diff --git a/statediff/db/migrations/00004_create_eth_header_cids_table.sql b/statediff/db/migrations/00004_create_eth_header_cids_table.sql index 339eb427b..5993f5a36 100644 --- a/statediff/db/migrations/00004_create_eth_header_cids_table.sql +++ b/statediff/db/migrations/00004_create_eth_header_cids_table.sql @@ -16,6 +16,7 @@ CREATE TABLE eth.header_cids ( bloom BYTEA NOT NULL, timestamp NUMERIC NOT NULL, times_validated INTEGER NOT NULL DEFAULT 1, + base_fee BIGINT NOT NULL, UNIQUE (block_number, block_hash) ); diff --git a/statediff/indexer/indexer.go b/statediff/indexer/indexer.go index 942bf1952..85d0018d0 100644 --- a/statediff/indexer/indexer.go +++ b/statediff/indexer/indexer.go @@ -229,6 +229,7 @@ func (sdi *StateDiffIndexer) processHeader(tx *sqlx.Tx, header *types.Header, he TxRoot: header.TxHash.String(), UncleRoot: header.UncleHash.String(), Timestamp: header.Time, + BaseFee: header.BaseFee.String(), }) } diff --git a/statediff/indexer/indexer_test.go b/statediff/indexer/indexer_test.go index faa178197..9d4901e09 100644 --- a/statediff/indexer/indexer_test.go +++ b/statediff/indexer/indexer_test.go @@ -25,7 +25,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/statediff/indexer" "github.com/ethereum/go-ethereum/statediff/indexer/ipfs/ipld" "github.com/ethereum/go-ethereum/statediff/indexer/mocks" @@ -45,11 +44,11 @@ var ( ind *indexer.StateDiffIndexer ipfsPgGet = `SELECT data FROM public.blocks WHERE key = $1` - tx1, tx2, tx3, tx4, rct1, rct2, rct3, rct4 []byte - mockBlock *types.Block - headerCID, trx1CID, trx2CID, trx3CID, trx4CID cid.Cid - rct1CID, rct2CID, rct3CID, rct4CID cid.Cid - state1CID, state2CID, storageCID cid.Cid + tx1, tx2, tx3, tx4, tx5, rct1, rct2, rct3, rct4, rct5 []byte + mockBlock *types.Block + headerCID, trx1CID, trx2CID, trx3CID, trx4CID, trx5CID cid.Cid + rct1CID, rct2CID, rct3CID, rct4CID, rct5CID cid.Cid + state1CID, state2CID, storageCID cid.Cid ) func expectTrue(t *testing.T, value bool) { @@ -88,6 +87,11 @@ func init() { copy(tx4, buf.Bytes()) buf.Reset() + txs.EncodeIndex(4, buf) + tx5 = make([]byte, buf.Len()) + copy(tx5, buf.Bytes()) + buf.Reset() + rcts.EncodeIndex(0, buf) rct1 = make([]byte, buf.Len()) copy(rct1, buf.Bytes()) @@ -108,15 +112,22 @@ func init() { copy(rct4, buf.Bytes()) buf.Reset() + rcts.EncodeIndex(4, buf) + rct5 = make([]byte, buf.Len()) + copy(rct5, buf.Bytes()) + buf.Reset() + headerCID, _ = ipld.RawdataToCid(ipld.MEthHeader, mocks.MockHeaderRlp, multihash.KECCAK_256) trx1CID, _ = ipld.RawdataToCid(ipld.MEthTx, tx1, multihash.KECCAK_256) trx2CID, _ = ipld.RawdataToCid(ipld.MEthTx, tx2, multihash.KECCAK_256) trx3CID, _ = ipld.RawdataToCid(ipld.MEthTx, tx3, multihash.KECCAK_256) trx4CID, _ = ipld.RawdataToCid(ipld.MEthTx, tx4, multihash.KECCAK_256) + trx5CID, _ = ipld.RawdataToCid(ipld.MEthTx, tx5, multihash.KECCAK_256) rct1CID, _ = ipld.RawdataToCid(ipld.MEthTxReceipt, rct1, multihash.KECCAK_256) rct2CID, _ = ipld.RawdataToCid(ipld.MEthTxReceipt, rct2, multihash.KECCAK_256) rct3CID, _ = ipld.RawdataToCid(ipld.MEthTxReceipt, rct3, multihash.KECCAK_256) rct4CID, _ = ipld.RawdataToCid(ipld.MEthTxReceipt, rct4, multihash.KECCAK_256) + rct5CID, _ = ipld.RawdataToCid(ipld.MEthTxReceipt, rct5, multihash.KECCAK_256) state1CID, _ = ipld.RawdataToCid(ipld.MEthStateTrie, mocks.ContractLeafNode, multihash.KECCAK_256) state2CID, _ = ipld.RawdataToCid(ipld.MEthStateTrie, mocks.AccountLeafNode, multihash.KECCAK_256) storageCID, _ = ipld.RawdataToCid(ipld.MEthStorageTrie, mocks.StorageLeafNode, multihash.KECCAK_256) @@ -127,7 +138,7 @@ func setup(t *testing.T) { if err != nil { t.Fatal(err) } - ind = indexer.NewStateDiffIndexer(params.MainnetChainConfig, db) + ind = indexer.NewStateDiffIndexer(mocks.TestConfig, db) var tx *indexer.BlockTx tx, err = ind.PushBlock( mockBlock, @@ -198,11 +209,12 @@ func TestPublishAndIndexer(t *testing.T) { if err != nil { t.Fatal(err) } - shared.ExpectEqual(t, len(trxs), 4) + shared.ExpectEqual(t, len(trxs), 5) expectTrue(t, shared.ListContainsString(trxs, trx1CID.String())) expectTrue(t, shared.ListContainsString(trxs, trx2CID.String())) expectTrue(t, shared.ListContainsString(trxs, trx3CID.String())) expectTrue(t, shared.ListContainsString(trxs, trx4CID.String())) + expectTrue(t, shared.ListContainsString(trxs, trx5CID.String())) // and published for _, c := range trxs { dc, err := cid.Decode(c) @@ -281,6 +293,17 @@ func TestPublishAndIndexer(t *testing.T) { } shared.ExpectEqual(t, model1, mocks.AccessListEntry1Model) shared.ExpectEqual(t, model2, mocks.AccessListEntry2Model) + case trx5CID.String(): + shared.ExpectEqual(t, data, tx5) + var txType *uint8 + pgStr = `SELECT tx_type FROM eth.transaction_cids WHERE cid = $1` + err = db.Get(&txType, pgStr, c) + if err != nil { + t.Fatal(err) + } + if *txType != types.DynamicFeeTxType { + t.Fatalf("expected DynamicFeeTxType (2), got %d", *txType) + } } } }) @@ -298,11 +321,12 @@ func TestPublishAndIndexer(t *testing.T) { if err != nil { t.Fatal(err) } - shared.ExpectEqual(t, len(rcts), 4) + shared.ExpectEqual(t, len(rcts), 5) expectTrue(t, shared.ListContainsString(rcts, rct1CID.String())) expectTrue(t, shared.ListContainsString(rcts, rct2CID.String())) expectTrue(t, shared.ListContainsString(rcts, rct3CID.String())) expectTrue(t, shared.ListContainsString(rcts, rct4CID.String())) + expectTrue(t, shared.ListContainsString(rcts, rct5CID.String())) // and published for _, c := range rcts { dc, err := cid.Decode(c) @@ -353,6 +377,15 @@ func TestPublishAndIndexer(t *testing.T) { t.Fatal(err) } shared.ExpectEqual(t, postState, mocks.ExpectedPostState3) + case rct5CID.String(): + shared.ExpectEqual(t, data, rct5) + var postState string + pgStr = `SELECT post_state FROM eth.receipt_cids WHERE cid = $1` + err = db.Get(&postState, pgStr, c) + if err != nil { + t.Fatal(err) + } + shared.ExpectEqual(t, postState, mocks.ExpectedPostState3) } } }) diff --git a/statediff/indexer/mocks/test_data.go b/statediff/indexer/mocks/test_data.go index d0b693fba..f132cd1fa 100644 --- a/statediff/indexer/mocks/test_data.go +++ b/statediff/indexer/mocks/test_data.go @@ -40,7 +40,9 @@ import ( // Test variables var ( // block data - BlockNumber = big.NewInt(12244001) + // TODO: Update this to `MainnetChainConfig` when `LondonBlock` is added + TestConfig = params.RinkebyChainConfig + BlockNumber = TestConfig.LondonBlock MockHeader = types.Header{ Time: 0, Number: new(big.Int).Set(BlockNumber), @@ -49,6 +51,7 @@ var ( ReceiptHash: common.HexToHash("0x0"), Difficulty: big.NewInt(5000000), Extra: []byte{}, + BaseFee: big.NewInt(params.InitialBaseFee), } MockTransactions, MockReceipts, SenderAddr = createTransactionsAndReceipts() MockBlock = types.NewBlock(&MockHeader, MockTransactions, nil, MockReceipts, new(trie.Trie)) @@ -186,7 +189,7 @@ func createTransactionsAndReceipts() (types.Transactions, types.Receipts, common trx2 := types.NewTransaction(1, AnotherAddress, big.NewInt(2000), 100, big.NewInt(200), []byte{}) trx3 := types.NewContractCreation(2, big.NewInt(1500), 75, big.NewInt(150), MockContractByteCode) trx4 := types.NewTx(&types.AccessListTx{ - ChainID: big.NewInt(1), + ChainID: TestConfig.ChainID, Nonce: 0, GasPrice: big.NewInt(100), Gas: 50, @@ -198,8 +201,22 @@ func createTransactionsAndReceipts() (types.Transactions, types.Receipts, common AccessListEntry2, }, }) + trx5 := types.NewTx(&types.DynamicFeeTx{ + ChainID: TestConfig.ChainID, + Nonce: 0, + GasTipCap: big.NewInt(100), + GasFeeCap: big.NewInt(100), + Gas: 50, + To: &AnotherAddress, + Value: big.NewInt(1000), + Data: []byte{}, + AccessList: types.AccessList{ + AccessListEntry1, + AccessListEntry2, + }, + }) - transactionSigner := types.NewEIP2930Signer(params.MainnetChainConfig.ChainID) + transactionSigner := types.MakeSigner(TestConfig, BlockNumber) mockCurve := elliptic.P256() mockPrvKey, err := ecdsa.GenerateKey(mockCurve, rand.Reader) if err != nil { @@ -219,13 +236,18 @@ func createTransactionsAndReceipts() (types.Transactions, types.Receipts, common } signedTrx4, err := types.SignTx(trx4, transactionSigner, mockPrvKey) if err != nil { - println(err.Error()) log.Crit(err.Error()) } + signedTrx5, err := types.SignTx(trx5, transactionSigner, mockPrvKey) + if err != nil { + log.Crit(err.Error()) + } + senderAddr, err := types.Sender(transactionSigner, signedTrx1) // same for both trx if err != nil { log.Crit(err.Error()) } + // make receipts mockReceipt1 := types.NewReceipt(nil, false, 50) mockReceipt1.Logs = []*types.Log{MockLog1} @@ -244,6 +266,14 @@ func createTransactionsAndReceipts() (types.Transactions, types.Receipts, common Logs: []*types.Log{}, TxHash: signedTrx4.Hash(), } + mockReceipt5 := &types.Receipt{ + Type: types.DynamicFeeTxType, + PostState: common.HexToHash("0x3").Bytes(), + Status: types.ReceiptStatusSuccessful, + CumulativeGasUsed: 175, + Logs: []*types.Log{}, + TxHash: signedTrx5.Hash(), + } - return types.Transactions{signedTrx1, signedTrx2, signedTrx3, signedTrx4}, types.Receipts{mockReceipt1, mockReceipt2, mockReceipt3, mockReceipt4}, senderAddr + return types.Transactions{signedTrx1, signedTrx2, signedTrx3, signedTrx4, signedTrx5}, types.Receipts{mockReceipt1, mockReceipt2, mockReceipt3, mockReceipt4, mockReceipt5}, senderAddr } diff --git a/statediff/indexer/models/models.go b/statediff/indexer/models/models.go index 604cf6b62..2855c5889 100644 --- a/statediff/indexer/models/models.go +++ b/statediff/indexer/models/models.go @@ -36,6 +36,7 @@ type HeaderModel struct { Bloom []byte `db:"bloom"` Timestamp uint64 `db:"timestamp"` TimesValidated int64 `db:"times_validated"` + BaseFee string `db:"base_fee"` } // UncleModel is the db model for eth.uncle_cids @@ -63,7 +64,7 @@ type TxModel struct { Type *uint8 `db:"tx_type"` } -// AccessListEntryModel is the db model for eth.access_list_entry +// AccessListElementModel is the db model for eth.access_list_entry type AccessListElementModel struct { ID int64 `db:"id"` Index int64 `db:"index"` diff --git a/statediff/indexer/writer.go b/statediff/indexer/writer.go index e8c0a0398..79ffbed8c 100644 --- a/statediff/indexer/writer.go +++ b/statediff/indexer/writer.go @@ -44,12 +44,12 @@ func NewPostgresCIDWriter(db *postgres.DB) *PostgresCIDWriter { func (in *PostgresCIDWriter) upsertHeaderCID(tx *sqlx.Tx, header models.HeaderModel) (int64, error) { var headerID int64 - err := tx.QueryRowx(`INSERT INTO eth.header_cids (block_number, block_hash, parent_hash, cid, td, node_id, reward, state_root, tx_root, receipt_root, uncle_root, bloom, timestamp, mh_key, times_validated) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) - ON CONFLICT (block_number, block_hash) DO UPDATE SET (parent_hash, cid, td, node_id, reward, state_root, tx_root, receipt_root, uncle_root, bloom, timestamp, mh_key, times_validated) = ($3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, eth.header_cids.times_validated + 1) + err := tx.QueryRowx(`INSERT INTO eth.header_cids (block_number, block_hash, parent_hash, cid, td, node_id, reward, state_root, tx_root, receipt_root, uncle_root, bloom, timestamp, mh_key, times_validated, base_fee) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) + ON CONFLICT (block_number, block_hash) DO UPDATE SET (parent_hash, cid, td, node_id, reward, state_root, tx_root, receipt_root, uncle_root, bloom, timestamp, mh_key, times_validated, base_fee) = ($3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, eth.header_cids.times_validated + 1, $16) RETURNING id`, header.BlockNumber, header.BlockHash, header.ParentHash, header.CID, header.TotalDifficulty, in.db.NodeID, header.Reward, header.StateRoot, header.TxRoot, - header.RctRoot, header.UncleRoot, header.Bloom, header.Timestamp, header.MhKey, 1).Scan(&headerID) + header.RctRoot, header.UncleRoot, header.Bloom, header.Timestamp, header.MhKey, 1, header.BaseFee).Scan(&headerID) if err != nil { return 0, fmt.Errorf("error upserting header_cids entry: %v", err) }