From 96b78908d4fd896131948fe089b8e46d13fb549b Mon Sep 17 00:00:00 2001 From: Max Planck Date: Thu, 25 Aug 2022 19:34:26 -0400 Subject: [PATCH] refactor database models for scribe --- scribe/db/datastore/sql/base/base_store.go | 2 +- scribe/db/datastore/sql/base/model.go | 24 +---- scribe/db/datastore/sql/base/transaction.go | 109 +------------------- scribe/db/event.go | 9 +- scribe/db/transaction_test.go | 31 +----- 5 files changed, 9 insertions(+), 166 deletions(-) diff --git a/scribe/db/datastore/sql/base/base_store.go b/scribe/db/datastore/sql/base/base_store.go index 9fcffb114e..830ea6a648 100644 --- a/scribe/db/datastore/sql/base/base_store.go +++ b/scribe/db/datastore/sql/base/base_store.go @@ -24,7 +24,7 @@ func (s Store) DB() *gorm.DB { // see: https://medium.com/@SaifAbid/slice-interfaces-8c78f8b6345d for an explanation of why we can't do this at initialization time func GetAllModels() (allModels []interface{}) { allModels = append(allModels, - &Log{}, &Receipt{}, &RawEthTX{}, &ProcessedEthTx{}, &LastIndexedInfo{}, + &Log{}, &Receipt{}, &EthTx{}, &LastIndexedInfo{}, ) return allModels } diff --git a/scribe/db/datastore/sql/base/model.go b/scribe/db/datastore/sql/base/model.go index 169f756979..76075f1646 100644 --- a/scribe/db/datastore/sql/base/model.go +++ b/scribe/db/datastore/sql/base/model.go @@ -87,31 +87,11 @@ type Receipt struct { TransactionIndex uint64 `gorm:"transaction_index"` } -// RawEthTX contains a raw evm transaction that is unsigned -// note: idx_id contains a composite index of (chain_id,nonce) -type RawEthTX struct { - gorm.Model - // From is the sender of the transaction - From string `gorm:"from"` - // To is the contract address the transaction was sent to. - To string `gorm:"index"` - // ChainID is the chain id the transaction hash will be sent on - ChainID uint64 `gorm:"column:chain_id;uniqueIndex:idx_id"` - // Nonce is the nonce of the raw evm tx - Nonce uint64 `gorm:"column:nonce;uniqueIndex:idx_id"` - // RawTx is the raw serialized transaction - RawTx []byte `gorm:"column:raw_tx"` -} - -// ProcessedEthTx contains a processed ethereum transaction. -type ProcessedEthTx struct { +// EthTx contains a processed ethereum transaction. +type EthTx struct { TxHash string `gorm:"tx_hash"` // RawTx is the raw serialized transaction RawTx []byte `gorm:"column:raw_tx"` - // RawEthTx is the txid that caused the event - RawEthTx uint - // OriginatingEvent is the event that originated the tx - EthTx RawEthTX `gorm:"foreignkey:RawEthTx"` // GasFeeCap contains the gas fee cap stored in wei GasFeeCap uint64 // GasTipCap contains the gas tip cap stored in wei diff --git a/scribe/db/datastore/sql/base/transaction.go b/scribe/db/datastore/sql/base/transaction.go index 2b9d2ead6b..a1669d0dfd 100644 --- a/scribe/db/datastore/sql/base/transaction.go +++ b/scribe/db/datastore/sql/base/transaction.go @@ -2,37 +2,22 @@ package base import ( "context" - "database/sql" "fmt" - "github.com/synapsecns/sanguine/agents/db" "math/big" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" ) -// StoreProcessedTx stores a processed text. -func (s Store) StoreProcessedTx(ctx context.Context, tx *types.Transaction) error { +// StoreEthTx stores a processed text. +func (s Store) StoreEthTx(ctx context.Context, tx *types.Transaction) error { marshalledTx, err := tx.MarshalBinary() if err != nil { return fmt.Errorf("could not marshall tx to binary: %w", err) } - signer := types.LatestSignerForChainID(tx.ChainId()) - sender, err := types.Sender(signer, tx) - if err != nil { - return fmt.Errorf("could not get sender for tx: %s: %w", tx.Hash(), err) - } - - parentID, err := s.getRawTXIDByParams(ctx, tx.Nonce(), tx.ChainId(), sender) - if err != nil { - return fmt.Errorf("could not get parent tx: %w", err) - } - - dbTx := s.DB().WithContext(ctx).Create(&ProcessedEthTx{ + dbTx := s.DB().WithContext(ctx).Create(&EthTx{ TxHash: tx.Hash().String(), RawTx: marshalledTx, - RawEthTx: parentID, GasFeeCap: tx.GasFeeCap().Uint64(), GasTipCap: tx.GasTipCap().Uint64(), }) @@ -44,62 +29,6 @@ func (s Store) StoreProcessedTx(ctx context.Context, tx *types.Transaction) erro return nil } -// StoreRawTx stores a raw transaction. -func (s Store) StoreRawTx(ctx context.Context, tx *types.Transaction, chainID *big.Int, from common.Address) error { - toAddress := "" - if tx != nil { - toAddress = tx.To().String() - } - - // sanity check for making sure transaction marshaled chainid matches derived chain id (if present) - hasID, newID := getChainID(tx) - if hasID { - if newID.Cmp(chainID) != 0 { - return fmt.Errorf("chainid mismatch, expected %d, got %d", chainID, newID) - } - } - - marshalledTx, err := tx.MarshalBinary() - if err != nil { - return fmt.Errorf("could not marshall tx to binary: %w", err) - } - - dbTx := s.DB().WithContext(ctx).Create(&RawEthTX{ - From: from.String(), - To: toAddress, - ChainID: chainID.Uint64(), - Nonce: tx.Nonce(), - RawTx: marshalledTx, - }) - - if dbTx.Error != nil { - return fmt.Errorf("could not create raw tx: %w", dbTx.Error) - } - - return nil -} - -// getRawTXIDByParams by nonce/chain id gets the raw transaction id by a combination of the nonce and chain id -// this is used for storing processed txes. -func (s Store) getRawTXIDByParams(ctx context.Context, nonce uint64, chainID *big.Int, sender common.Address) (id uint, err error) { - var res RawEthTX - dbTx := s.DB().Select("ID").WithContext(ctx).Model(&RawEthTX{}).Where(RawEthTX{ - ChainID: chainID.Uint64(), - Nonce: nonce, - From: sender.String(), - }).Find(&res) - - if dbTx.RowsAffected == 0 { - return 0, db.ErrNotFound - } - - if dbTx.Error != nil { - return 0, fmt.Errorf("could not get %T by chainID: %d and nonce: %d. error: %w", &RawEthTX{}, chainID.Uint64(), nonce, dbTx.Error) - } - - return res.ID, nil -} - // getChainID gets the chain id from non-legacy transaction types // it is used to check chainids against the chainid passed in the raw id. func getChainID(tx *types.Transaction) (hasType bool, chainID *big.Int) { @@ -115,35 +44,3 @@ func getChainID(tx *types.Transaction) (hasType bool, chainID *big.Int) { return true, tx.ChainId() } } - -// GetNonceForChainID gets a nonce for a chainid. -func (s Store) GetNonceForChainID(ctx context.Context, fromAddress common.Address, chainID *big.Int) (nonce uint64, err error) { - var newNonce sql.NullInt64 - - selectMaxNonce := "max(`nonce`)" - - dbTx := s.DB().WithContext(ctx).Model(&RawEthTX{}).Select(selectMaxNonce).Where(RawEthTX{ - From: fromAddress.String(), - ChainID: chainID.Uint64(), - }).Scan(&newNonce) - - if dbTx.Error != nil { - return 0, fmt.Errorf("could not get nonce for chain id: %w", dbTx.Error) - } - - // if no nonces, return the corresponding error. - if newNonce.Int64 == 0 { - // we need to check if any nonces exist first - var count int64 - dbTx = s.DB().WithContext(ctx).Model(&RawEthTX{}).Where(RawEthTX{ChainID: chainID.Uint64(), From: fromAddress.String()}).Count(&count) - if dbTx.Error != nil { - return 0, fmt.Errorf("error getting count on %T: %w", &RawEthTX{}, dbTx.Error) - } - - if count == 0 { - return 0, db.ErrNoNonceForChain - } - } - - return uint64(newNonce.Int64), nil -} diff --git a/scribe/db/event.go b/scribe/db/event.go index 3e517798eb..118f07e3ab 100644 --- a/scribe/db/event.go +++ b/scribe/db/event.go @@ -2,7 +2,6 @@ package db import ( "context" - "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -18,12 +17,8 @@ type EventDB interface { StoreReceipt(ctx context.Context, receipt types.Receipt) error // RetrieveReceiptByTxHash retrieves a receipt by tx hash RetrieveReceiptByTxHash(ctx context.Context, txHash common.Hash) (receipt types.Receipt, err error) - // StoreRawTx stores a raw transaction - StoreRawTx(ctx context.Context, tx *types.Transaction, chainID *big.Int, from common.Address) error - // StoreProcessedTx stores a processed transaction - StoreProcessedTx(ctx context.Context, tx *types.Transaction) error - // GetNonceForChainID returns the nonce for a chain id - GetNonceForChainID(ctx context.Context, fromAddress common.Address, chainID *big.Int) (nonce uint64, err error) + // StoreEthTx stores a processed transaction + StoreEthTx(ctx context.Context, tx *types.Transaction) error // StoreLastIndexed stores the last indexed for a contract address StoreLastIndexed(ctx context.Context, contractAddress common.Address, chainID uint32, blockNumber uint64) error // RetrieveLastIndexed retrieves the last indexed for a contract address diff --git a/scribe/db/transaction_test.go b/scribe/db/transaction_test.go index 7a9c7dc3ad..3a44fe45f9 100644 --- a/scribe/db/transaction_test.go +++ b/scribe/db/transaction_test.go @@ -70,44 +70,15 @@ func (t *DBSuite) TestTxInsertion() { t.RunOnAllDBs(func(testDB db.EventDB) { for _, testTx := range testTxes { - err := testDB.StoreRawTx(t.GetTestContext(), testTx, testTx.ChainId(), signer.Address()) - Nil(t.T(), err) - - // TODO: retrieve raw tx - transactor, err := signer.GetTransactor(testTx.ChainId()) Nil(t.T(), err) signedTx, err := transactor.Signer(signer.Address(), testTx) Nil(t.T(), err) - err = testDB.StoreProcessedTx(t.GetTestContext(), signedTx) + err = testDB.StoreEthTx(t.GetTestContext(), signedTx) Nil(t.T(), err) // TODO: retrieve the processed tx } }) } - -// / make sure tx doesn't conflict on both chains. -func (t *DBSuite) TestTxNonceQueryMultiChain() { - fakeTx := testTxes[0] - fakeTx2 := testTxes[1] - - t.RunOnAllDBs(func(testDB db.EventDB) { - from := common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64())) - - err := testDB.StoreRawTx(t.GetTestContext(), fakeTx, fakeTx.ChainId(), from) - Nil(t.T(), err) - - err = testDB.StoreRawTx(t.GetTestContext(), fakeTx2, fakeTx2.ChainId(), from) - Nil(t.T(), err) - - nonce1, err := testDB.GetNonceForChainID(t.GetTestContext(), from, fakeTx.ChainId()) - Nil(t.T(), err) - Equal(t.T(), nonce1, fakeTx.Nonce()) - - nonce2, err := testDB.GetNonceForChainID(t.GetTestContext(), from, fakeTx2.ChainId()) - Nil(t.T(), err) - Equal(t.T(), nonce2, fakeTx2.Nonce()) - }) -}