zksync-sdk / zksync2-go

zksync2-go is a geth library adapted to work with the zkSync Era.
Apache License 2.0
87 stars 36 forks source link

BlockByNumber gives various errors #7

Closed bdehri closed 1 year ago

bdehri commented 1 year ago

When using BlockByNumber function, it either gives server returned empty transaction list but block header indicates transactions or invalid transaction v, r, s values. Code Snippet:

    client, err := zksync2.NewDefaultProvider("https://mainnet.era.zksync.io")
    if err != nil {
        return 0, 0, err
    }

    latestBlock, err := client.BlockNumber(context.TODO())
    if err != nil {
        return 0, 0, err
    }

    startBlock, err := client.BlockByNumber(context.TODO(), big.NewInt(int64(latestBlock)))
    if err != nil {
        return 0, 0, err
    }
VickMellon commented 1 year ago

.BlockByNumber() is native ethclient's method, it's not working for ZkSync nodes. Use custom .GetBlockByNumber() method of zksync2.Provider interface.

bdehri commented 1 year ago
client, err := zksync2.NewDefaultProvider(rpcUrl)
if err != nil {
    return 0, 0, err
}

startBlock, err := client.GetBlockByNumber(zksync2.BlockNumber(fmt.Sprintf("%d", 100)))
if err != nil {
    return 0, 0, err
}

This snippet still returns invalid transaction v, r, s values

tacshi commented 1 year ago
client, err := zksync2.NewDefaultProvider(rpcUrl)
if err != nil {
  return 0, 0, err
}

startBlock, err := client.GetBlockByNumber(zksync2.BlockNumber(fmt.Sprintf("%d", 100)))
if err != nil {
  return 0, 0, err
}

This snippet still returns invalid transaction v, r, s values

same error

danijelTxFusion commented 1 year ago

The eth_getBlockByNumber and eth_getBlockByHash methods for blocks that contain transactions return transactions of type 0x0, which indicates that they are legacy transactions. The problem occurs with the V value, which can be either 0 or 1 and is intended to be used as a recovery ID. The signature validation using the V, R, S values obtained from the RPC method is valid, but the issue arises because SDKs perform a pre-calculation of the V value before validating the signature. For legacy transactions in Ethereum implementation, the V value can be used as a recovery ID, where the value is 27 (if the first possible key is used for signing) or 28 (if the second possible key is used for signing). SDKs, before validating the signature for legacy transactions, decrease the value by 27. Therefore, the V value is either 0 (27-27) or 1 (28-27). Decresing 0 or 1 value by 27 gives gives wrong numbers which cause signature to be invalid.

So this computation of V from Ethereum implementatin should be dropped in next release.

danijelTxFusion commented 1 year ago

Fixed in v0.3.0 version.