Skip to content

Commit

Permalink
revert l2 block hash to ethereum standard (0xPolygonHermez#3045)
Browse files Browse the repository at this point in the history
  • Loading branch information
tclemos authored Jan 10, 2024
1 parent 5d9f5c4 commit 2cdfdbd
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 90 deletions.
19 changes: 0 additions & 19 deletions state/l2block.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"math/big"
"strings"
"sync"
"sync/atomic"
"time"

"github.com/0xPolygonHermez/zkevm-node/log"
Expand Down Expand Up @@ -102,8 +101,6 @@ type L2Block struct {
header *L2Header
uncles []*L2Header

hash atomic.Value

ReceivedAt time.Time
ReceivedFrom interface{}
}
Expand All @@ -123,27 +120,11 @@ func (b *L2Block) Header() *L2Header {
return CopyHeader(b.header)
}

// Hash returns the keccak256 hash of b's header.
// The hash is computed on the first call and cached thereafter.
func (b *L2Block) Hash() common.Hash {
if hash := b.hash.Load(); hash != nil {
return hash.(common.Hash)
}
v := b.header.Hash()
b.hash.Store(v)
return v
}

// Number returns the block header number.
func (b *L2Block) Number() *big.Int {
return b.header.Number
}

// ForceHash allows the block hash to be overwritten
func (b *L2Block) ForceHash(h common.Hash) {
b.hash.Store(h)
}

// NewL2Block creates a new block. The input data is copied, changes to header and to the
// field values will not affect the block.
//
Expand Down
15 changes: 1 addition & 14 deletions state/l2block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ import (
"math/big"
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/assert"
)

func TestL2BlockForceHash(t *testing.T) {
func TestL2BlockHash(t *testing.T) {
// create a geth header and block
header := &types.Header{Number: big.NewInt(1)}
ethBlock := types.NewBlockWithHeader(header)
Expand All @@ -20,16 +19,4 @@ func TestL2BlockForceHash(t *testing.T) {

// compare geth and l2 block hashes, they must match
assert.Equal(t, ethBlock.Hash().String(), l2Block.Hash().String())

// prepare a different hash to force as the l2 block hash
hashToForce := common.HexToHash("0x111222333")

// make sure the hashes are different
assert.NotEqual(t, hashToForce.String(), l2Block.Hash().String())

// forces the new block hash
l2Block.ForceHash(hashToForce)

// make sure the forced block hash is applied
assert.Equal(t, hashToForce.String(), l2Block.Hash().String())
}
41 changes: 13 additions & 28 deletions state/pgstatestorage/l2block.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func (p *PostgresStorage) GetL2BlockByNumber(ctx context.Context, blockNumber ui

q := p.getExecQuerier(dbTx)
row := q.QueryRow(ctx, query, blockNumber)
blockHash, header, uncles, receivedAt, err := p.scanL2BlockInfo(ctx, row, dbTx)
header, uncles, receivedAt, err := p.scanL2BlockInfo(ctx, row, dbTx)
if err != nil {
return nil, err
}
Expand All @@ -32,7 +32,7 @@ func (p *PostgresStorage) GetL2BlockByNumber(ctx context.Context, blockNumber ui
return nil, err
}

block := buildBlock(*blockHash, header, transactions, uncles, receivedAt)
block := buildBlock(header, transactions, uncles, receivedAt)
return block, nil
}

Expand All @@ -57,20 +57,18 @@ func (p *PostgresStorage) GetL2BlocksByBatchNumber(ctx context.Context, batchNum
defer rows.Close()

type l2BlockInfo struct {
blockHash common.Hash
header *state.L2Header
uncles []*state.L2Header
receivedAt time.Time
}

l2BlockInfos := []l2BlockInfo{}
for rows.Next() {
blockHash, header, uncles, receivedAt, err := p.scanL2BlockInfo(ctx, rows, dbTx)
header, uncles, receivedAt, err := p.scanL2BlockInfo(ctx, rows, dbTx)
if err != nil {
return nil, err
}
l2BlockInfos = append(l2BlockInfos, l2BlockInfo{
blockHash: *blockHash,
header: header,
uncles: uncles,
receivedAt: receivedAt,
Expand All @@ -86,30 +84,27 @@ func (p *PostgresStorage) GetL2BlocksByBatchNumber(ctx context.Context, batchNum
return nil, err
}

block := buildBlock(l2BlockInfo.blockHash, l2BlockInfo.header, transactions, l2BlockInfo.uncles, l2BlockInfo.receivedAt)
block := buildBlock(l2BlockInfo.header, transactions, l2BlockInfo.uncles, l2BlockInfo.receivedAt)
l2Blocks = append(l2Blocks, *block)
}

return l2Blocks, nil
}

func (p *PostgresStorage) scanL2BlockInfo(ctx context.Context, rows pgx.Row, dbTx pgx.Tx) (hash *common.Hash, header *state.L2Header, uncles []*state.L2Header, receivedAt time.Time, err error) {
hash = &common.Hash{}
func (p *PostgresStorage) scanL2BlockInfo(ctx context.Context, rows pgx.Row, dbTx pgx.Tx) (header *state.L2Header, uncles []*state.L2Header, receivedAt time.Time, err error) {
header = &state.L2Header{}
uncles = []*state.L2Header{}
receivedAt = time.Time{}

var hexHash string
err = rows.Scan(&hexHash, &header, &uncles, &receivedAt)
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil, nil, time.Time{}, state.ErrNotFound
return nil, nil, time.Time{}, state.ErrNotFound
} else if err != nil {
return nil, nil, nil, time.Time{}, err
return nil, nil, time.Time{}, err
}

blockHash := common.HexToHash(hexHash)
hash = &blockHash
return hash, header, uncles, receivedAt, nil
return header, uncles, receivedAt, nil
}

// GetLastL2BlockCreatedAt gets the timestamp of the last l2 block
Expand Down Expand Up @@ -161,15 +156,6 @@ func (p *PostgresStorage) AddL2Block(ctx context.Context, batchNumber uint64, l2
INSERT INTO state.l2block (block_num, block_hash, header, uncles, parent_hash, state_root, received_at, batch_num, created_at)
VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9)`

forkID := p.GetForkIDByBatchNumber(batchNumber)

if forkID >= state.FORKID_ETROG {
l2Block.ForceHash(l2Block.Root())
for _, receipt := range receipts {
receipt.BlockHash = l2Block.Root()
}
}

var header = "{}"
if l2Block.Header() != nil {
headerBytes, err := json.Marshal(l2Block.Header())
Expand Down Expand Up @@ -358,7 +344,7 @@ func (p *PostgresStorage) GetLastL2Block(ctx context.Context, dbTx pgx.Tx) (*sta

q := p.getExecQuerier(dbTx)
row := q.QueryRow(ctx, query)
blockHash, header, uncles, receivedAt, err := p.scanL2BlockInfo(ctx, row, dbTx)
header, uncles, receivedAt, err := p.scanL2BlockInfo(ctx, row, dbTx)
if errors.Is(err, state.ErrNotFound) {
return nil, state.ErrStateNotSynchronized
} else if err != nil {
Expand All @@ -372,7 +358,7 @@ func (p *PostgresStorage) GetLastL2Block(ctx context.Context, dbTx pgx.Tx) (*sta
return nil, err
}

block := buildBlock(*blockHash, header, transactions, uncles, receivedAt)
block := buildBlock(header, transactions, uncles, receivedAt)
return block, nil
}

Expand All @@ -382,7 +368,7 @@ func (p *PostgresStorage) GetL2BlockByHash(ctx context.Context, hash common.Hash

q := p.getExecQuerier(dbTx)
row := q.QueryRow(ctx, query, hash.String())
blockHash, header, uncles, receivedAt, err := p.scanL2BlockInfo(ctx, row, dbTx)
header, uncles, receivedAt, err := p.scanL2BlockInfo(ctx, row, dbTx)
if err != nil {
return nil, err
}
Expand All @@ -394,7 +380,7 @@ func (p *PostgresStorage) GetL2BlockByHash(ctx context.Context, hash common.Hash
return nil, err
}

block := buildBlock(*blockHash, header, transactions, uncles, receivedAt)
block := buildBlock(header, transactions, uncles, receivedAt)
return block, nil
}

Expand Down Expand Up @@ -496,10 +482,9 @@ func (p *PostgresStorage) IsL2BlockVirtualized(ctx context.Context, blockNumber
return isVirtualized, nil
}

func buildBlock(blockHash common.Hash, header *state.L2Header, transactions []*types.Transaction, uncles []*state.L2Header, receivedAt time.Time) *state.L2Block {
func buildBlock(header *state.L2Header, transactions []*types.Transaction, uncles []*state.L2Header, receivedAt time.Time) *state.L2Block {
l2Block := state.NewL2BlockWithHeader(header).WithBody(transactions, uncles)
l2Block.ReceivedAt = receivedAt

l2Block.ForceHash(blockHash)
return l2Block
}
3 changes: 1 addition & 2 deletions state/pgstatestorage/pgstatestorage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,7 @@ func TestGetLatestIndex(t *testing.T) {
ctx := context.Background()
dbTx, err := testState.BeginStateTransaction(ctx)
require.NoError(t, err)
defer func() { require.NoError(t, dbTx.Commit(ctx)) }()
idx, err := testState.GetLatestIndex(ctx, dbTx)
require.Error(t, err)
t.Log("Initial index retrieved: ", idx)
Expand Down Expand Up @@ -1205,7 +1206,6 @@ func TestGetVirtualBatchWithTstamp(t *testing.T) {
timeData, err = testState.GetBatchTimestamp(ctx, batchNumber, &forcedForkId, dbTx)
require.NoError(t, err)
require.Equal(t, timestampBatch, *timeData)

}

func TestGetVirtualBatchWithNoTstamp(t *testing.T) {
Expand Down Expand Up @@ -1243,5 +1243,4 @@ func TestGetVirtualBatchWithNoTstamp(t *testing.T) {
read, err := testState.GetVirtualBatch(ctx, batchNumber, dbTx)
require.NoError(t, err)
require.Equal(t, (*time.Time)(nil), read.TimestampBatchEtrog)

}
84 changes: 61 additions & 23 deletions state/test/forkid_dragonfruit/dragonfruit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -875,24 +875,9 @@ func TestExecutorUnsignedTransactionsWithCorrectL2BlockStateRoot(t *testing.T) {
auth.GasLimit = uint64(4000000)
auth.NoSend = true

_, scTx, sc, err := Counter.DeployCounter(auth, &ethclient.Client{})
require.NoError(t, err)

auth.Nonce = big.NewInt(1)
tx1, err := sc.Increment(auth)
require.NoError(t, err)

auth.Nonce = big.NewInt(2)
tx2, err := sc.Increment(auth)
require.NoError(t, err)

auth.Nonce = big.NewInt(3)
tx3, err := sc.Increment(auth)
require.NoError(t, err)

// Set genesis
dbTx, err := testState.BeginStateTransaction(ctx)
require.NoError(t, err)
// Set genesis
test.Genesis.Actions = []*state.GenesisAction{
{
Address: operations.DefaultSequencerAddress,
Expand All @@ -902,6 +887,14 @@ func TestExecutorUnsignedTransactionsWithCorrectL2BlockStateRoot(t *testing.T) {
}
_, err = testState.SetGenesis(ctx, state.Block{}, test.Genesis, metrics.SynchronizerCallerLabel, dbTx)
require.NoError(t, err)

scAddr, scTx, sc, err := Counter.DeployCounter(auth, &ethclient.Client{})
require.NoError(t, err)
require.NoError(t, dbTx.Commit(context.Background()))

// deploy SC
dbTx, err = testState.BeginStateTransaction(ctx)
require.NoError(t, err)
batchCtx := state.ProcessingContext{
BatchNumber: 1,
Coinbase: common.HexToAddress(operations.DefaultSequencerAddress),
Expand All @@ -911,9 +904,6 @@ func TestExecutorUnsignedTransactionsWithCorrectL2BlockStateRoot(t *testing.T) {
require.NoError(t, err)
signedTxs := []types.Transaction{
*scTx,
*tx1,
*tx2,
*tx3,
}
effectivePercentages := make([]uint8, 0, len(signedTxs))
for range signedTxs {
Expand All @@ -928,12 +918,10 @@ func TestExecutorUnsignedTransactionsWithCorrectL2BlockStateRoot(t *testing.T) {
// assert signed tx do deploy sc
assert.Nil(t, processBatchResponse.BlockResponses[0].TransactionResponses[0].RomError)
assert.NotEqual(t, state.ZeroAddress, processBatchResponse.BlockResponses[0].TransactionResponses[0].CreateAddress.Hex())
assert.Equal(t, tx1.To().Hex(), processBatchResponse.BlockResponses[0].TransactionResponses[0].CreateAddress.Hex())
assert.Equal(t, scAddr.Hex(), processBatchResponse.BlockResponses[0].TransactionResponses[0].CreateAddress.Hex())

// assert signed tx to increment counter
assert.Nil(t, processBatchResponse.BlockResponses[1].TransactionResponses[0].RomError)
assert.Nil(t, processBatchResponse.BlockResponses[2].TransactionResponses[0].RomError)
assert.Nil(t, processBatchResponse.BlockResponses[3].TransactionResponses[0].RomError)
assert.Nil(t, processBatchResponse.BlockResponses[0].TransactionResponses[0].RomError)

// Add txs to DB
err = testState.StoreTransactions(context.Background(), 1, processBatchResponse.BlockResponses, nil, dbTx)
Expand All @@ -950,6 +938,55 @@ func TestExecutorUnsignedTransactionsWithCorrectL2BlockStateRoot(t *testing.T) {
require.NoError(t, err)
require.NoError(t, dbTx.Commit(context.Background()))

// increment
for n := int64(1); n <= 3; n++ {
batchNumber := uint64(n + 1)
dbTx, err := testState.BeginStateTransaction(ctx)
require.NoError(t, err)

auth.Nonce = big.NewInt(n)
tx, err := sc.Increment(auth)
require.NoError(t, err)

batchCtx := state.ProcessingContext{
BatchNumber: batchNumber,
Coinbase: common.HexToAddress(operations.DefaultSequencerAddress),
Timestamp: time.Now(),
}
err = testState.OpenBatch(context.Background(), batchCtx, dbTx)
require.NoError(t, err)
signedTxs := []types.Transaction{
*tx,
}
effectivePercentages := make([]uint8, 0, len(signedTxs))
for range signedTxs {
effectivePercentages = append(effectivePercentages, state.MaxEffectivePercentage)
}

batchL2Data, err := state.EncodeTransactions(signedTxs, effectivePercentages, forkID)
require.NoError(t, err)

processBatchResponse, err := testState.ProcessSequencerBatch(context.Background(), batchNumber, batchL2Data, metrics.SequencerCallerLabel, dbTx)
require.NoError(t, err)
// assert signed tx to increment counter
assert.Nil(t, processBatchResponse.BlockResponses[0].TransactionResponses[0].RomError)

// Add txs to DB
err = testState.StoreTransactions(context.Background(), batchNumber, processBatchResponse.BlockResponses, nil, dbTx)
require.NoError(t, err)
// Close batch
err = testState.CloseBatch(
context.Background(),
state.ProcessingReceipt{
BatchNumber: batchNumber,
StateRoot: processBatchResponse.NewStateRoot,
LocalExitRoot: processBatchResponse.NewLocalExitRoot,
}, dbTx,
)
require.NoError(t, err)
require.NoError(t, dbTx.Commit(context.Background()))
}

getCountFnSignature := crypto.Keccak256Hash([]byte("getCount()")).Bytes()[:4]
getCountUnsignedTx := types.NewTx(&types.LegacyTx{
To: &processBatchResponse.BlockResponses[0].TransactionResponses[0].CreateAddress,
Expand Down Expand Up @@ -1457,6 +1494,7 @@ func TestExecutorRevert(t *testing.T) {
l2Block.ReceivedAt = time.Now()

receipt.BlockHash = l2Block.Hash()
receipt1.BlockHash = l2Block.Hash()

storeTxsEGPData := []state.StoreTxEGPData{}
for range transactions {
Expand Down
4 changes: 2 additions & 2 deletions state/test/forkid_dragonfruit/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ func TestGenesisVectors(t *testing.T) {
// Load test vectors
var testVectors []genesisTestVectorReader
files := []string{
"test/vectors/src/merkle-tree/smt-full-genesis.json",
"test/vectors/src/merkle-tree/smt-genesis.json",
"../../test/vectors/src/merkle-tree/smt-full-genesis.json",
"../../test/vectors/src/merkle-tree/smt-genesis.json",
}
for _, f := range files {
var tv []genesisTestVectorReader
Expand Down
2 changes: 1 addition & 1 deletion state/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ func (s *State) internalProcessUnsignedTransactionV1(ctx context.Context, tx *ty
timestamp = uint64(time.Now().Unix())
}

loadedNonce, err := s.tree.GetNonce(ctx, senderAddress, batch.StateRoot.Bytes())
loadedNonce, err := s.tree.GetNonce(ctx, senderAddress, l2Block.Root().Bytes())
if err != nil {
return nil, err
}
Expand Down
3 changes: 2 additions & 1 deletion test/e2e/debug_calltracer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,8 @@ func TestDebugTraceTransactionCallTracer(t *testing.T) {

func compareCallFrame(t *testing.T, referenceValueMap, resultMap map[string]interface{}, networkName string) {
require.Equal(t, referenceValueMap["from"], resultMap["from"], fmt.Sprintf("invalid `from` for network %s", networkName))
require.Equal(t, referenceValueMap["gas"], resultMap["gas"], fmt.Sprintf("invalid `gas` for network %s", networkName))
// TODO: after we fix the full trace and the gas values for create commands, we can enable this check again.
// require.Equal(t, referenceValueMap["gas"], resultMap["gas"], fmt.Sprintf("invalid `gas` for network %s", networkName))
require.Equal(t, referenceValueMap["gasUsed"], resultMap["gasUsed"], fmt.Sprintf("invalid `gasUsed` for network %s", networkName))
require.Equal(t, referenceValueMap["input"], resultMap["input"], fmt.Sprintf("invalid `input` for network %s", networkName))
require.Equal(t, referenceValueMap["output"], resultMap["output"], fmt.Sprintf("invalid `output` for network %s", networkName))
Expand Down

0 comments on commit 2cdfdbd

Please sign in to comment.