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 5993f5a36..13bb4e317 100644 --- a/statediff/db/migrations/00004_create_eth_header_cids_table.sql +++ b/statediff/db/migrations/00004_create_eth_header_cids_table.sql @@ -16,7 +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, + base_fee VARCHAR(38), UNIQUE (block_number, block_hash) ); diff --git a/statediff/indexer/indexer_legacy_test.go b/statediff/indexer/indexer_legacy_test.go new file mode 100644 index 000000000..bef319354 --- /dev/null +++ b/statediff/indexer/indexer_legacy_test.go @@ -0,0 +1,86 @@ +// VulcanizeDB +// Copyright © 2019 Vulcanize + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package indexer_test + +import ( + "testing" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/statediff/indexer" + "github.com/ethereum/go-ethereum/statediff/indexer/ipfs/ipld" + "github.com/ethereum/go-ethereum/statediff/indexer/mocks" + "github.com/ethereum/go-ethereum/statediff/indexer/shared" + "github.com/ipfs/go-cid" + "github.com/multiformats/go-multihash" + "github.com/stretchr/testify/require" +) + +var ( + legacyData = mocks.NewLegacyData() + mockLegacyBlock *types.Block + legacyHeaderCID cid.Cid +) + +func setupLegacy(t *testing.T) { + mockLegacyBlock = legacyData.MockBlock + legacyHeaderCID, _ = ipld.RawdataToCid(ipld.MEthHeader, legacyData.MockHeaderRlp, multihash.KECCAK_256) + + db, err = shared.SetupDB() + require.NoError(t, err) + + ind = indexer.NewStateDiffIndexer(legacyData.Config, db) + var tx *indexer.BlockTx + tx, err = ind.PushBlock( + mockLegacyBlock, + legacyData.MockReceipts, + legacyData.MockBlock.Difficulty()) + require.NoError(t, err) + + defer tx.Close(err) + for _, node := range legacyData.StateDiffs { + err = ind.PushStateNode(tx, node) + require.NoError(t, err) + } + + shared.ExpectEqual(t, tx.BlockNumber, legacyData.BlockNumber.Uint64()) +} + +func TestPublishAndIndexerLegacy(t *testing.T) { + t.Run("Publish and index header IPLDs in a legacy tx", func(t *testing.T) { + setupLegacy(t) + defer tearDown(t) + pgStr := `SELECT cid, td, reward, id, base_fee + FROM eth.header_cids + WHERE block_number = $1` + // check header was properly indexed + type res struct { + CID string + TD string + Reward string + ID int + BaseFee string `db:"base_fee"` + } + header := new(res) + err = db.QueryRowx(pgStr, legacyData.BlockNumber.Uint64()).StructScan(header) + require.NoError(t, err) + + shared.ExpectEqual(t, header.CID, legacyHeaderCID.String()) + shared.ExpectEqual(t, header.TD, legacyData.MockBlock.Difficulty().String()) + shared.ExpectEqual(t, header.Reward, "5000000000000011250") + shared.ExpectEqual(t, header.BaseFee, legacyData.MockHeader.BaseFee.String()) + }) +} diff --git a/statediff/indexer/mocks/test_data.go b/statediff/indexer/mocks/test_data.go index f132cd1fa..a8bd0430d 100644 --- a/statediff/indexer/mocks/test_data.go +++ b/statediff/indexer/mocks/test_data.go @@ -53,7 +53,7 @@ var ( Extra: []byte{}, BaseFee: big.NewInt(params.InitialBaseFee), } - MockTransactions, MockReceipts, SenderAddr = createTransactionsAndReceipts() + MockTransactions, MockReceipts, SenderAddr = createTransactionsAndReceipts(TestConfig, BlockNumber) MockBlock = types.NewBlock(&MockHeader, MockTransactions, nil, MockReceipts, new(trie.Trie)) MockHeaderRlp, _ = rlp.EncodeToBytes(MockBlock.Header()) Address = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476592") @@ -182,14 +182,132 @@ type AccessListTx struct { */ +type LegacyData struct { + Config *params.ChainConfig + BlockNumber *big.Int + MockHeader types.Header + MockTransactions types.Transactions + MockReceipts types.Receipts + SenderAddr common.Address + MockBlock *types.Block + MockHeaderRlp []byte + Address []byte + AnotherAddress []byte + ContractAddress common.Address + MockContractByteCode []byte + MockLog1 *types.Log + MockLog2 *types.Log + StorageLeafKey []byte + MockStorageLeafKey []byte + StorageLeafNode []byte + ContractLeafKey []byte + ContractAccount []byte + ContractPartialPath []byte + ContractLeafNode []byte + AccountRoot string + AccountLeafNode []byte + StateDiffs []sdtypes.StateNode +} + +func NewLegacyData() *LegacyData { + config := params.MainnetChainConfig + // Block number before london fork. + blockNumber := config.EIP155Block + + mockHeader := types.Header{ + Time: 0, + Number: new(big.Int).Set(blockNumber), + Root: common.HexToHash("0x0"), + TxHash: common.HexToHash("0x0"), + ReceiptHash: common.HexToHash("0x0"), + Difficulty: big.NewInt(5000000), + Extra: []byte{}, + } + + mockTransactions, mockReceipts, senderAddr := createLegacyTransactionsAndReceipts(config, blockNumber) + mockBlock := types.NewBlock(&mockHeader, mockTransactions, nil, mockReceipts, new(trie.Trie)) + mockHeaderRlp, _ := rlp.EncodeToBytes(mockBlock.Header()) + contractAddress := crypto.CreateAddress(senderAddr, mockTransactions[2].Nonce()) + + return &LegacyData{ + Config: config, + BlockNumber: blockNumber, + MockHeader: mockHeader, + MockTransactions: mockTransactions, + MockReceipts: mockReceipts, + SenderAddr: senderAddr, + MockBlock: mockBlock, + MockHeaderRlp: mockHeaderRlp, + ContractAddress: contractAddress, + MockContractByteCode: MockContractByteCode, + MockLog1: MockLog1, + MockLog2: MockLog2, + StorageLeafKey: StorageLeafKey, + MockStorageLeafKey: MockStorageLeafKey, + StorageLeafNode: StorageLeafNode, + ContractLeafKey: ContractLeafKey, + ContractAccount: ContractAccount, + ContractPartialPath: ContractPartialPath, + ContractLeafNode: ContractLeafNode, + AccountRoot: AccountRoot, + AccountLeafNode: AccountLeafKey, + StateDiffs: StateDiffs, + } +} + +// createLegacyTransactionsAndReceipts is a helper function to generate signed mock legacy transactions and mock receipts with mock logs +func createLegacyTransactionsAndReceipts(config *params.ChainConfig, blockNumber *big.Int) (types.Transactions, types.Receipts, common.Address) { + // make transactions + trx1 := types.NewTransaction(0, Address, big.NewInt(1000), 50, big.NewInt(100), []byte{}) + 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) + + transactionSigner := types.MakeSigner(config, blockNumber) + mockCurve := elliptic.P256() + mockPrvKey, err := ecdsa.GenerateKey(mockCurve, rand.Reader) + if err != nil { + log.Crit(err.Error()) + } + signedTrx1, err := types.SignTx(trx1, transactionSigner, mockPrvKey) + if err != nil { + log.Crit(err.Error()) + } + signedTrx2, err := types.SignTx(trx2, transactionSigner, mockPrvKey) + if err != nil { + log.Crit(err.Error()) + } + signedTrx3, err := types.SignTx(trx3, 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} + mockReceipt1.TxHash = signedTrx1.Hash() + mockReceipt2 := types.NewReceipt(common.HexToHash("0x1").Bytes(), false, 100) + mockReceipt2.Logs = []*types.Log{MockLog2} + mockReceipt2.TxHash = signedTrx2.Hash() + mockReceipt3 := types.NewReceipt(common.HexToHash("0x2").Bytes(), false, 75) + mockReceipt3.Logs = []*types.Log{} + mockReceipt3.TxHash = signedTrx3.Hash() + + return types.Transactions{signedTrx1, signedTrx2, signedTrx3}, types.Receipts{mockReceipt1, mockReceipt2, mockReceipt3}, senderAddr +} + // createTransactionsAndReceipts is a helper function to generate signed mock transactions and mock receipts with mock logs -func createTransactionsAndReceipts() (types.Transactions, types.Receipts, common.Address) { +func createTransactionsAndReceipts(config *params.ChainConfig, blockNumber *big.Int) (types.Transactions, types.Receipts, common.Address) { // make transactions trx1 := types.NewTransaction(0, Address, big.NewInt(1000), 50, big.NewInt(100), []byte{}) 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: TestConfig.ChainID, + ChainID: config.ChainID, Nonce: 0, GasPrice: big.NewInt(100), Gas: 50, @@ -202,7 +320,7 @@ func createTransactionsAndReceipts() (types.Transactions, types.Receipts, common }, }) trx5 := types.NewTx(&types.DynamicFeeTx{ - ChainID: TestConfig.ChainID, + ChainID: config.ChainID, Nonce: 0, GasTipCap: big.NewInt(100), GasFeeCap: big.NewInt(100), @@ -216,7 +334,7 @@ func createTransactionsAndReceipts() (types.Transactions, types.Receipts, common }, }) - transactionSigner := types.MakeSigner(TestConfig, BlockNumber) + transactionSigner := types.MakeSigner(config, blockNumber) mockCurve := elliptic.P256() mockPrvKey, err := ecdsa.GenerateKey(mockCurve, rand.Reader) if err != nil {