From 93d16b962b959e4e516dc55af8fc485c4ee63a90 Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Thu, 17 Aug 2023 16:07:54 +0800 Subject: [PATCH 01/17] add: fix getTransactionFromBlockIndex interface --- eth/api.go | 2 +- internal/ethapi/api.go | 30 +++++++++++++++++++++--------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/eth/api.go b/eth/api.go index 8b96d1f31..b38630096 100644 --- a/eth/api.go +++ b/eth/api.go @@ -342,7 +342,7 @@ func (api *PrivateDebugAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs, } else { blockRlp = fmt.Sprintf("0x%x", rlpBytes) } - if blockJSON, err = ethapi.RPCMarshalBlock(block, true, true); err != nil { + if blockJSON, err = ethapi.RPCMarshalBlock(block, true, true, api.eth.chainDb); err != nil { blockJSON = map[string]interface{}{"error": err.Error()} } results = append(results, &BadBlockArgs{ diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index e8fa939e6..815350b5a 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -24,6 +24,8 @@ import ( "strings" "time" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/davecgh/go-spew/spew" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi" @@ -634,7 +636,7 @@ func (s *PublicBlockChainAPI) GetTransactionReceiptsByBlock(ctx context.Context, } if len(txs) != len(receipts) { - return nil, fmt.Errorf("txs length doesn't equal to receipts' length", len(txs), len(receipts)) + return nil, fmt.Errorf("txs length %d doesn't equal to receipts' length %d", len(txs), len(receipts)) } txReceipts := make([]map[string]interface{}, 0, len(txs)) @@ -1294,7 +1296,7 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} { // RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are // returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain // transaction hashes. -func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { +func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, db ethdb.Database) (map[string]interface{}, error) { fields := RPCMarshalHeader(block.Header()) fields["size"] = hexutil.Uint64(block.Size()) @@ -1304,7 +1306,7 @@ func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]i } if fullTx { formatTx = func(tx *types.Transaction) (interface{}, error) { - return newRPCTransactionFromBlockHash(block, tx.Hash()), nil + return newRPCTransactionFromBlockHash(block, tx.Hash(), db), nil } } txs := block.Transactions() @@ -1338,7 +1340,7 @@ func (s *PublicBlockChainAPI) rpcMarshalHeader(ctx context.Context, header *type // rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field, which requires // a `PublicBlockchainAPI`. func (s *PublicBlockChainAPI) rpcMarshalBlock(ctx context.Context, b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { - fields, err := RPCMarshalBlock(b, inclTx, fullTx) + fields, err := RPCMarshalBlock(b, inclTx, fullTx, s.b.ChainDb()) if err != nil { return nil, err } @@ -1438,8 +1440,18 @@ func newRPCPendingTransaction(tx *types.Transaction, current *types.Header, conf } // newRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation. -func newRPCTransactionFromBlockIndex(b *types.Block, index uint64) *RPCTransaction { +func newRPCTransactionFromBlockIndex(b *types.Block, index uint64, db ethdb.Database) *RPCTransaction { txs := b.Transactions() + + borReceipt := rawdb.ReadBorReceipt(db, b.Hash(), b.NumberU64()) + if borReceipt != nil { + tx, _, _, _ := rawdb.ReadBorTransaction(db, borReceipt.TxHash) + + if tx != nil { + txs = append(txs, tx) + } + } + if index >= uint64(len(txs)) { return nil } @@ -1457,10 +1469,10 @@ func newRPCRawTransactionFromBlockIndex(b *types.Block, index uint64) hexutil.By } // newRPCTransactionFromBlockHash returns a transaction that will serialize to the RPC representation. -func newRPCTransactionFromBlockHash(b *types.Block, hash common.Hash) *RPCTransaction { +func newRPCTransactionFromBlockHash(b *types.Block, hash common.Hash, db ethdb.Database) *RPCTransaction { for idx, tx := range b.Transactions() { if tx.Hash() == hash { - return newRPCTransactionFromBlockIndex(b, uint64(idx)) + return newRPCTransactionFromBlockIndex(b, uint64(idx), db) } } return nil @@ -1601,7 +1613,7 @@ func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByHash(ctx context.Co // GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index. func (s *PublicTransactionPoolAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) *RPCTransaction { if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { - return newRPCTransactionFromBlockIndex(block, uint64(index)) + return newRPCTransactionFromBlockIndex(block, uint64(index), s.b.ChainDb()) } return nil } @@ -1609,7 +1621,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionByBlockNumberAndIndex(ctx conte // GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index. func (s *PublicTransactionPoolAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *RPCTransaction { if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil { - return newRPCTransactionFromBlockIndex(block, uint64(index)) + return newRPCTransactionFromBlockIndex(block, uint64(index), s.b.ChainDb()) } return nil } From 0749135ce0b7924c7a835b148b321ab8379eefed Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Thu, 17 Aug 2023 17:07:18 +0800 Subject: [PATCH 02/17] add:statesync tx added to GetBlockTransactionCount rpc --- internal/ethapi/api.go | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 815350b5a..84a908f5f 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1592,10 +1592,31 @@ func NewPublicTransactionPoolAPI(b Backend, nonceLock *AddrLocker) *PublicTransa return &PublicTransactionPoolAPI{b, nonceLock, signer} } +// returns block transactions along with state-sync transaction if present +// nolint: unparam +func (api *PublicTransactionPoolAPI) getAllBlockTransactions(ctx context.Context, block *types.Block) (types.Transactions, bool) { + txs := block.Transactions() + + stateSyncPresent := false + + borReceipt := rawdb.ReadBorReceipt(api.b.ChainDb(), block.Hash(), block.NumberU64()) + if borReceipt != nil { + txHash := types.GetDerivedBorTxHash(types.BorReceiptKey(block.Number().Uint64(), block.Hash())) + if txHash != (common.Hash{}) { + borTx, _, _, _, _ := api.b.GetBorBlockTransactionWithBlockHash(ctx, txHash, block.Hash()) + txs = append(txs, borTx) + stateSyncPresent = true + } + } + + return txs, stateSyncPresent +} + // GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number. func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint { if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { - n := hexutil.Uint(len(block.Transactions())) + txs, _ := s.getAllBlockTransactions(ctx, block) + n := hexutil.Uint(len(txs)) return &n } return nil @@ -1604,7 +1625,8 @@ func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(ctx context. // GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash. func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint { if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil { - n := hexutil.Uint(len(block.Transactions())) + txs, _ := s.getAllBlockTransactions(ctx, block) + n := hexutil.Uint(len(txs)) return &n } return nil From d0105a074eb3c8837015435bb4c3c11a21b20756 Mon Sep 17 00:00:00 2001 From: clarkchenc <651044554@qq.com> Date: Thu, 24 Aug 2023 16:54:26 +0800 Subject: [PATCH 03/17] fix get block error when meeting state-sync txns --- ethclient/ethclient.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 8d904a772..e2f31e1c9 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -133,9 +133,6 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 { return nil, fmt.Errorf("server returned empty uncle list but block header indicates uncles") } - if head.TxHash == types.EmptyRootHash && len(body.Transactions) > 0 { - return nil, fmt.Errorf("server returned non-empty transaction list but block header indicates no transactions") - } if head.TxHash != types.EmptyRootHash && len(body.Transactions) == 0 { return nil, fmt.Errorf("server returned empty transaction list but block header indicates transactions") } From d829fbef03b2e4452a834f8a2d6164ecd545e149 Mon Sep 17 00:00:00 2001 From: clarkchenc <651044554@qq.com> Date: Thu, 24 Aug 2023 17:26:22 +0800 Subject: [PATCH 04/17] add GetSnapshotProposer and GetSnapshotProposerSequence --- consensus/bor/api.go | 50 +++++++++++++++++++++++++++++++++++++ internal/web3ext/bor_ext.go | 12 +++++++++ 2 files changed, 62 insertions(+) diff --git a/consensus/bor/api.go b/consensus/bor/api.go index 12841290a..f7f4de184 100644 --- a/consensus/bor/api.go +++ b/consensus/bor/api.go @@ -63,6 +63,56 @@ func (api *API) GetAuthor(number *rpc.BlockNumber) (*common.Address, error) { return &author, err } +type BlockSigners struct { + Signers map[common.Address]uint64 + Diff int + Author common.Address +} + +// GetSnapshotProposerSequence retrieves the in-turn signers of all sprints in a span +func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigners, error) { + + var difficulties = make(map[common.Address]uint64) + snap, err := api.GetSnapshot(number) + if err != nil { + return BlockSigners{}, err + } + proposer := snap.ValidatorSet.GetProposer().Address + proposerIndex, _ := snap.ValidatorSet.GetByAddress(proposer) + + signers := snap.signers() + for i := 0; i < len(signers); i++ { + tempIndex := i + if tempIndex < proposerIndex { + tempIndex = tempIndex + len(signers) + } + difficulties[signers[i]] = uint64(len(signers) - (tempIndex - proposerIndex)) + } + + author, err := api.GetAuthor(number) + if err != nil { + return BlockSigners{}, err + } + diff := int(difficulties[*author]) + blockSigners := &BlockSigners{ + Signers: difficulties, + Diff: diff, + Author: *author, + } + + return *blockSigners, nil +} + +// GetSnapshotProposer retrieves the in-turn signer at a given block. +func (api *API) GetSnapshotProposer(number *rpc.BlockNumber) (common.Address, error) { + *number -= 1 + snap, err := api.GetSnapshot(number) + if err != nil { + return common.Address{}, err + } + return snap.ValidatorSet.GetProposer().Address, nil +} + // GetSnapshotAtHash retrieves the state snapshot at a given block. func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) { header := api.chain.GetHeaderByHash(hash) diff --git a/internal/web3ext/bor_ext.go b/internal/web3ext/bor_ext.go index b7fe9b488..fe8b01da1 100644 --- a/internal/web3ext/bor_ext.go +++ b/internal/web3ext/bor_ext.go @@ -17,6 +17,18 @@ web3._extend({ params: 1, inputFormatter: [null] }), + new web3._extend.Method({ + name: 'getSnapshotProposer', + call: 'bor_getSnapshotProposer', + params: 1, + inputFormatter: [null] + }), + new web3._extend.Method({ + name: 'getSnapshotProposerSequence', + call: 'bor_getSnapshotProposerSequence', + params: 1, + inputFormatter: [null] + }), new web3._extend.Method({ name: 'getSnapshotAtHash', call: 'bor_getSnapshotAtHash', From 2065d2eee87f9e90ca43175127336e5df931cc5f Mon Sep 17 00:00:00 2001 From: clarkchenc <651044554@qq.com> Date: Thu, 24 Aug 2023 19:11:48 +0800 Subject: [PATCH 05/17] add fingerprint cmd --- cmd/geth/fingerprintcmd.go | 62 ++++++++++++++++++++++++++++++++++++++ cmd/geth/main.go | 1 + 2 files changed, 63 insertions(+) create mode 100644 cmd/geth/fingerprintcmd.go diff --git a/cmd/geth/fingerprintcmd.go b/cmd/geth/fingerprintcmd.go new file mode 100644 index 000000000..9acac6771 --- /dev/null +++ b/cmd/geth/fingerprintcmd.go @@ -0,0 +1,62 @@ +package main + +import ( + "fmt" + "math" + + "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/params" + "github.com/shirou/gopsutil/cpu" + "github.com/shirou/gopsutil/disk" + "github.com/shirou/gopsutil/host" + "github.com/shirou/gopsutil/mem" + "gopkg.in/urfave/cli.v1" +) + +var ( + fingerprintCommand = cli.Command{ + Name: "fingerprint", + Usage: "Display the system fingerprint", + ArgsUsage: "", + Action: utils.MigrateFlags(showFingerprint), + Category: "FINGERPRINT COMMANDS", + } +) + +func getCoresCount(cp []cpu.InfoStat) int { + cores := 0 + for i := 0; i < len(cp); i++ { + cores += int(cp[i].Cores) + } + return cores +} + +// Run implements the cli.Command interface +func showFingerprint(_ *cli.Context) error { + v, _ := mem.VirtualMemory() + h, _ := host.Info() + cp, _ := cpu.Info() + d, _ := disk.Usage("/") + + osName := h.OS + osVer := h.Platform + " - " + h.PlatformVersion + " - " + h.KernelArch + totalMem := math.Floor(float64(v.Total)/(1024*1024*1024)*100) / 100 + availableMem := math.Floor(float64(v.Available)/(1024*1024*1024)*100) / 100 + usedMem := math.Floor(float64(v.Used)/(1024*1024*1024)*100) / 100 + totalDisk := math.Floor(float64(d.Total)/(1024*1024*1024)*100) / 100 + availableDisk := math.Floor(float64(d.Free)/(1024*1024*1024)*100) / 100 + usedDisk := math.Floor(float64(d.Used)/(1024*1024*1024)*100) / 100 + + borDetails := fmt.Sprintf("Bor Version : %s", params.VersionWithMeta) + cpuDetails := fmt.Sprintf("CPU : %d cores", getCoresCount(cp)) + osDetails := fmt.Sprintf("OS : %s %s ", osName, osVer) + memDetails := fmt.Sprintf("RAM :: total : %v GB, free : %v GB, used : %v GB", totalMem, availableMem, usedMem) + diskDetails := fmt.Sprintf("STORAGE :: total : %v GB, free : %v GB, used : %v GB", totalDisk, availableDisk, usedDisk) + + fmt.Println(borDetails) + fmt.Println(cpuDetails) + fmt.Println(osDetails) + fmt.Println(memDetails) + fmt.Println(diskDetails) + return nil +} diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 5f69a1984..e4b96c834 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -241,6 +241,7 @@ func init() { utils.ShowDeprecated, // See snapshot.go snapshotCommand, + fingerprintCommand, } sort.Sort(cli.CommandsByName(app.Commands)) From 2e00f258b12aeef513dabc08b8303adb11f9412d Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Mon, 28 Aug 2023 15:03:56 +0800 Subject: [PATCH 06/17] add: add check for empty lists in txpool --- core/tx_list.go | 4 ++++ core/tx_pool.go | 3 +++ 2 files changed, 7 insertions(+) diff --git a/core/tx_list.go b/core/tx_list.go index ba7951100..d3b1fb563 100644 --- a/core/tx_list.go +++ b/core/tx_list.go @@ -240,6 +240,10 @@ func (m *txSortedMap) Flatten() types.Transactions { // transaction with the highest nonce func (m *txSortedMap) LastElement() *types.Transaction { cache := m.flatten() + ln := len(cache) + if ln == 0 { + return nil + } return cache[len(cache)-1] } diff --git a/core/tx_pool.go b/core/tx_pool.go index 1f4519768..4783183c1 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -1256,6 +1256,9 @@ func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirt // Update all accounts to the latest known pending nonce for addr, list := range pool.pending { highestPending := list.LastElement() + if highestPending == nil { + continue + } pool.pendingNonces.set(addr, highestPending.Nonce()+1) } dropBetweenReorgHistogram.Update(int64(pool.changesSinceReorg)) From c15349e95bda6af2db912e83674510b292a4151d Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Mon, 28 Aug 2023 15:32:17 +0800 Subject: [PATCH 07/17] add: add max code init size check in txpool --- core/error.go | 4 ++++ core/tx_pool.go | 6 ++++++ params/protocol_params.go | 3 ++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/core/error.go b/core/error.go index 33cf874d1..06e4f0ccd 100644 --- a/core/error.go +++ b/core/error.go @@ -57,6 +57,10 @@ var ( // have enough funds for transfer(topmost call only). ErrInsufficientFundsForTransfer = errors.New("insufficient funds for transfer") + // ErrMaxInitCodeSizeExceeded is returned if creation transaction provides the init code bigger + // than init code size limit. + ErrMaxInitCodeSizeExceeded = errors.New("max initcode size exceeded") + // ErrInsufficientFunds is returned if the total cost of executing a transaction // is higher than the balance of the user's account. ErrInsufficientFunds = errors.New("insufficient funds for gas * price + value") diff --git a/core/tx_pool.go b/core/tx_pool.go index 1f4519768..2e034583d 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -19,6 +19,7 @@ package core import ( "container/heap" "errors" + "fmt" "math" "math/big" "sort" @@ -600,6 +601,11 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { if uint64(tx.Size()) > txMaxSize { return ErrOversizedData } + // Check whether the init code size has been exceeded. + // (TODO): Add a hardfork check here while pulling upstream changes. + if tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { + return fmt.Errorf("%w: code size %v limit %v", ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize) + } // Transactions can't be negative. This may never happen using RLP decoded // transactions but may occur if you create a transaction using the RPC. if tx.Value().Sign() < 0 { diff --git a/params/protocol_params.go b/params/protocol_params.go index 7abb2441b..aae550e52 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -122,7 +122,8 @@ const ( ElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have. InitialBaseFee = 1000000000 // Initial base fee for EIP-1559 blocks. - MaxCodeSize = 24576 // Maximum bytecode to permit for a contract + MaxCodeSize = 24576 // Maximum bytecode to permit for a contract + MaxInitCodeSize = 2 * MaxCodeSize // Maximum initcode to permit in a creation transaction and create instructions // Precompiled contract gas prices From 626475942bacc00a34618a5b1667e3f44ab3af20 Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Mon, 28 Aug 2023 17:27:49 +0800 Subject: [PATCH 08/17] chg: only support full sync --- cmd/geth/main.go | 6 ++++++ cmd/utils/flags.go | 2 +- eth/ethconfig/config.go | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 5f69a1984..ff4948fc9 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -273,6 +273,12 @@ func main() { // prepare manipulates memory cache allowance and setups metric system. // This function should be called before launching devp2p stack. func prepare(ctx *cli.Context) { + //only support full sync + err := ctx.Set(utils.SyncModeFlag.Name, "full") + if err != nil { + log.Warn("Failed to set sync mode to full") + } + // If we're running a known preset, log it for convenience. switch { case ctx.GlobalIsSet(utils.RopstenFlag.Name): diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 957ed7abd..643e169cd 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -213,7 +213,7 @@ var ( defaultSyncMode = ethconfig.Defaults.SyncMode SyncModeFlag = TextMarshalerFlag{ Name: "syncmode", - Usage: `Blockchain sync mode ("fast", "full", "snap" or "light")`, + Usage: `Blockchain sync mode (only "full" sync supported)`, Value: &defaultSyncMode, } GCModeFlag = cli.StringFlag{ diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 8a34f7313..44e35cdef 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -63,7 +63,7 @@ var LightClientGPO = gasprice.Config{ // Defaults contains default settings for use on the Ethereum main net. var Defaults = Config{ - SyncMode: downloader.SnapSync, + SyncMode: downloader.FullSync, Ethash: ethash.Config{ CacheDir: "ethash", CachesInMem: 2, From e8e709a2461e07a5424e44bf6d10970e7fc25964 Mon Sep 17 00:00:00 2001 From: clarkchenc <651044554@qq.com> Date: Thu, 31 Aug 2023 21:28:27 +0800 Subject: [PATCH 09/17] optimize validatorset with map --- consensus/bor/bor.go | 4 +- consensus/bor/snapshot.go | 6 ++- consensus/bor/validator_set.go | 82 +++++++++++++++++++++++----------- 3 files changed, 63 insertions(+), 29 deletions(-) diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 60dcd7d6e..136ff18f5 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -590,7 +590,7 @@ func (c *Bor) verifySeal(chain consensus.ChainHeaderReader, header *types.Header if err != nil { return err } - if !snap.ValidatorSet.HasAddress(signer.Bytes()) { + if !snap.ValidatorSet.HasAddress(signer) { // Check the UnauthorizedSignerError.Error() msg to see why we pass number-1 return &UnauthorizedSignerError{number - 1, signer.Bytes()} } @@ -835,7 +835,7 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result } // Bail out if we're unauthorized to sign a block - if !snap.ValidatorSet.HasAddress(signer.Bytes()) { + if !snap.ValidatorSet.HasAddress(signer) { // Check the UnauthorizedSignerError.Error() msg to see why we pass number-1 return &UnauthorizedSignerError{number - 1, signer.Bytes()} } diff --git a/consensus/bor/snapshot.go b/consensus/bor/snapshot.go index 8405f34fb..d4c23e773 100644 --- a/consensus/bor/snapshot.go +++ b/consensus/bor/snapshot.go @@ -65,12 +65,14 @@ func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Dat if err := json.Unmarshal(blob, snap); err != nil { return nil, err } + + snap.ValidatorSet.UpdateValidatorMap() snap.config = config snap.sigcache = sigcache snap.ethAPI = ethAPI // update total voting power - if err := snap.ValidatorSet.updateTotalVotingPower(); err != nil { + if err := snap.ValidatorSet.UpdateTotalVotingPower(); err != nil { return nil, err } @@ -137,7 +139,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { } // check if signer is in validator set - if !snap.ValidatorSet.HasAddress(signer.Bytes()) { + if !snap.ValidatorSet.HasAddress(signer) { return nil, &UnauthorizedSignerError{number, signer.Bytes()} } diff --git a/consensus/bor/validator_set.go b/consensus/bor/validator_set.go index 0b5c10ebd..1671a2289 100644 --- a/consensus/bor/validator_set.go +++ b/consensus/bor/validator_set.go @@ -46,6 +46,7 @@ type ValidatorSet struct { // cached (unexported) totalVotingPower int64 + validatorsMap map[common.Address]int // address -> index } // NewValidatorSet initializes a ValidatorSet by copying over the @@ -54,7 +55,7 @@ type ValidatorSet struct { // The addresses of validators in `valz` must be unique otherwise the // function panics. func NewValidatorSet(valz []*Validator) *ValidatorSet { - vals := &ValidatorSet{} + vals := &ValidatorSet{validatorsMap: make(map[common.Address]int)} err := vals.updateWithChangeSet(valz, false) if err != nil { panic(fmt.Sprintf("cannot create validator set: %s", err)) @@ -212,43 +213,50 @@ func validatorListCopy(valsList []*Validator) []*Validator { // Copy each validator into a new ValidatorSet. func (vals *ValidatorSet) Copy() *ValidatorSet { + valCopy := validatorListCopy(vals.Validators) + validatorsMap := make(map[common.Address]int, len(vals.Validators)) + + for i, val := range valCopy { + validatorsMap[val.Address] = i + } + return &ValidatorSet{ Validators: validatorListCopy(vals.Validators), Proposer: vals.Proposer, totalVotingPower: vals.totalVotingPower, + validatorsMap: validatorsMap, } } // HasAddress returns true if address given is in the validator set, false - // otherwise. -func (vals *ValidatorSet) HasAddress(address []byte) bool { - idx := sort.Search(len(vals.Validators), func(i int) bool { - return bytes.Compare(address, vals.Validators[i].Address.Bytes()) <= 0 - }) - return idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address) +func (vals *ValidatorSet) HasAddress(address common.Address) bool { + _, ok := vals.validatorsMap[address] + + return ok } // GetByAddress returns an index of the validator with address and validator // itself if found. Otherwise, -1 and nil are returned. func (vals *ValidatorSet) GetByAddress(address common.Address) (index int, val *Validator) { - idx := sort.Search(len(vals.Validators), func(i int) bool { - return bytes.Compare(address.Bytes(), vals.Validators[i].Address.Bytes()) <= 0 - }) - if idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address.Bytes()) { + idx, ok := vals.validatorsMap[address] + if ok { return idx, vals.Validators[idx].Copy() } + return -1, nil } // GetByIndex returns the validator's address and validator itself by index. // It returns nil values if index is less than 0 or greater or equal to // len(ValidatorSet.Validators). -func (vals *ValidatorSet) GetByIndex(index int) (address []byte, val *Validator) { +func (vals *ValidatorSet) GetByIndex(index int) (address common.Address, val *Validator) { if index < 0 || index >= len(vals.Validators) { - return nil, nil + return common.Address{}, nil } val = vals.Validators[index] - return val.Address.Bytes(), val.Copy() + + return val.Address, val.Copy() } // Size returns the length of the validator set. @@ -257,7 +265,7 @@ func (vals *ValidatorSet) Size() int { } // Force recalculation of the set's total voting power. -func (vals *ValidatorSet) updateTotalVotingPower() error { +func (vals *ValidatorSet) UpdateTotalVotingPower() error { sum := int64(0) for _, val := range vals.Validators { @@ -276,7 +284,7 @@ func (vals *ValidatorSet) updateTotalVotingPower() error { func (vals *ValidatorSet) TotalVotingPower() int64 { if vals.totalVotingPower == 0 { log.Info("invoking updateTotalVotingPower before returning it") - if err := vals.updateTotalVotingPower(); err != nil { + if err := vals.UpdateTotalVotingPower(); err != nil { // Can/should we do better? panic(err) } @@ -299,7 +307,7 @@ func (vals *ValidatorSet) GetProposer() (proposer *Validator) { func (vals *ValidatorSet) findProposer() *Validator { var proposer *Validator for _, val := range vals.Validators { - if proposer == nil || !bytes.Equal(val.Address.Bytes(), proposer.Address.Bytes()) { + if proposer == nil || val.Address != proposer.Address { proposer = proposer.Cmp(val) } } @@ -341,13 +349,19 @@ func processChanges(origChanges []*Validator) (updates, removals []*Validator, e changes := validatorListCopy(origChanges) sort.Sort(ValidatorsByAddress(changes)) - removals = make([]*Validator, 0, len(changes)) - updates = make([]*Validator, 0, len(changes)) + sliceCap := len(changes) / 2 + if sliceCap == 0 { + sliceCap = 1 + } + + removals = make([]*Validator, 0, sliceCap) + updates = make([]*Validator, 0, sliceCap) + var prevAddr common.Address // Scan changes by address and append valid validators to updates or removals lists. for _, valUpdate := range changes { - if bytes.Equal(valUpdate.Address.Bytes(), prevAddr.Bytes()) { + if valUpdate.Address == prevAddr { err = fmt.Errorf("duplicate entry %v in %v", valUpdate, changes) return nil, nil, err } @@ -452,7 +466,7 @@ func (vals *ValidatorSet) applyUpdates(updates []*Validator) { } else { // Apply add or update. merged[i] = updates[0] - if bytes.Equal(existing[0].Address.Bytes(), updates[0].Address.Bytes()) { + if existing[0].Address == updates[0].Address { // Validator is present in both, advance existing. existing = existing[1:] } @@ -503,7 +517,7 @@ func (vals *ValidatorSet) applyRemovals(deletes []*Validator) { // Loop over deletes until we removed all of them. for len(deletes) > 0 { - if bytes.Equal(existing[0].Address.Bytes(), deletes[0].Address.Bytes()) { + if existing[0].Address == deletes[0].Address { deletes = deletes[1:] } else { // Leave it in the resulting slice. merged[i] = existing[0] @@ -561,10 +575,9 @@ func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes computeNewPriorities(updates, vals, updatedTotalVotingPower) // Apply updates and removals. - vals.applyUpdates(updates) - vals.applyRemovals(deletes) + vals.updateValidators(updates, deletes) - if err := vals.updateTotalVotingPower(); err != nil { + if err := vals.UpdateTotalVotingPower(); err != nil { return err } @@ -575,6 +588,21 @@ func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes return nil } +func (vals *ValidatorSet) updateValidators(updates []*Validator, deletes []*Validator) { + vals.applyUpdates(updates) + vals.applyRemovals(deletes) + + vals.UpdateValidatorMap() +} + +func (vals *ValidatorSet) UpdateValidatorMap() { + vals.validatorsMap = make(map[common.Address]int, len(vals.Validators)) + + for i, val := range vals.Validators { + vals.validatorsMap[val.Address] = i + } +} + // UpdateWithChangeSet attempts to update the validator set with 'changes'. // It performs the following steps: // - validates the changes making sure there are no duplicates and splits them in updates and deletes @@ -622,7 +650,7 @@ func (vals *ValidatorSet) StringIndented(indent string) string { if vals == nil { return "nil-ValidatorSet" } - var valStrings []string + valStrings := make([]string, 0, len(vals.Validators)) vals.Iterate(func(index int, val *Validator) bool { valStrings = append(valStrings, val.String()) return false @@ -639,6 +667,10 @@ func (vals *ValidatorSet) StringIndented(indent string) string { } +func (vals *ValidatorSet) SetMap(validatorsMap map[common.Address]int) { + vals.validatorsMap = validatorsMap +} + //------------------------------------- // Implements sort for sorting validators by address. From cbb2eac5aaf9fe05d5cd02326cc384e41022f2e9 Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Wed, 13 Sep 2023 16:37:24 +0800 Subject: [PATCH 10/17] add: pr tempalte --- .github/pull_request_template.md | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..715483ebe --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,42 @@ +# Description + +Please provide a detailed description of what was done in this PR + +# Changes + +- [ ] Bugfix (non-breaking change that solves an issue) +- [ ] Hotfix (change that solves an urgent issue, and requires immediate attention) +- [ ] New feature (non-breaking change that adds functionality) +- [ ] Breaking change (change that is not backwards-compatible and/or changes current functionality) + +# Breaking changes + +Please complete this section if any breaking changes have been made, otherwise delete it + +# Checklist + +- [ ] I have added at least 1 reviewer to this PR +- [ ] I have added sufficient documentation in code +- [ ] I will be resolving comments - if any - by pushing each fix in a separate commit and linking the commit hash in the comment reply + +# Cross repository changes + +- [ ] This PR requires changes to delivery + - In case link the PR here: + + +## Testing + +- [ ] I have added unit tests +- [ ] I have added tests to CI +- [ ] I have tested this code manually on local environment +- [ ] I have tested this code manually on remote devnet + + +### Manual tests + +Please complete this section with the steps you performed if you ran manual tests for this functionality, otherwise delete it + +# Additional comments + +Please post additional comments in this section if you have them, otherwise delete it \ No newline at end of file From da0b46b3aeff18738b88ffa4ccd2f8652f53dd8b Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Wed, 13 Sep 2023 17:05:44 +0800 Subject: [PATCH 11/17] fix : prevent panic --- internal/ethapi/api.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index e8fa939e6..574c40b02 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -614,6 +614,10 @@ func (s *PublicBlockChainAPI) GetTransactionReceiptsByBlock(ctx context.Context, return nil, err } + if block == nil { + return nil, errors.New("block not found") + } + receipts, err := s.b.GetReceipts(ctx, block.Hash()) if err != nil { return nil, err From e22bdc9df11d13f74cb75d1bd7164fca500dd23e Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Fri, 12 Jan 2024 10:37:58 +0800 Subject: [PATCH 12/17] add: batch limit in http --- cmd/geth/main.go | 1 + cmd/geth/usage.go | 1 + cmd/utils/flags.go | 9 +++++++ node/api.go | 3 +++ node/config.go | 4 +++ node/defaults.go | 1 + node/node.go | 9 ++++++- node/rpcstack.go | 6 +++++ rpc/client.go | 5 +++- rpc/errors.go | 2 ++ rpc/handler.go | 67 +++++++++++++++++++++++++++++++--------------- rpc/server.go | 20 ++++++++++---- 12 files changed, 99 insertions(+), 29 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 5f69a1984..b31b5c19f 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -185,6 +185,7 @@ var ( utils.RPCGlobalGasCapFlag, utils.RPCGlobalTxFeeCapFlag, utils.AllowUnprotectedTxs, + utils.BatchRequestLimit, } metricsFlags = []cli.Flag{ diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go index 52b4a1606..702a34b34 100644 --- a/cmd/geth/usage.go +++ b/cmd/geth/usage.go @@ -148,6 +148,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{ utils.WSApiFlag, utils.WSPathPrefixFlag, utils.WSAllowedOriginsFlag, + utils.BatchRequestLimit, utils.GraphQLEnabledFlag, utils.GraphQLCORSDomainFlag, utils.GraphQLVirtualHostsFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 957ed7abd..bf00b0395 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -621,6 +621,11 @@ var ( Name: "rpc.allow-unprotected-txs", Usage: "Allow for unprotected (non EIP155 signed) transactions to be submitted via RPC", } + BatchRequestLimit = &cli.IntFlag{ + Name: "rpc.batch-request-limit", + Usage: "Maximum number of requests in a batch(only supported in http)", + Value: node.DefaultConfig.BatchRequestLimit, + } // Network Settings MaxPeersFlag = cli.IntFlag{ @@ -995,6 +1000,10 @@ func setHTTP(ctx *cli.Context, cfg *node.Config) { if ctx.GlobalIsSet(AllowUnprotectedTxs.Name) { cfg.AllowUnprotectedTxs = ctx.GlobalBool(AllowUnprotectedTxs.Name) } + if ctx.IsSet(BatchRequestLimit.Name) { + cfg.BatchRequestLimit = ctx.Int(BatchRequestLimit.Name) + } + } // setGraphQL creates the GraphQL listener interface string from the set diff --git a/node/api.go b/node/api.go index be20b89d9..a03c2a26d 100644 --- a/node/api.go +++ b/node/api.go @@ -185,6 +185,9 @@ func (api *privateAdminAPI) StartHTTP(host *string, port *int, cors *string, api CorsAllowedOrigins: api.node.config.HTTPCors, Vhosts: api.node.config.HTTPVirtualHosts, Modules: api.node.config.HTTPModules, + rpcEndpointConfig: rpcEndpointConfig{ + batchItemLimit: api.node.config.BatchRequestLimit, + }, } if cors != nil { config.CorsAllowedOrigins = nil diff --git a/node/config.go b/node/config.go index 26f00cd67..eb898c5fc 100644 --- a/node/config.go +++ b/node/config.go @@ -190,6 +190,10 @@ type Config struct { // AllowUnprotectedTxs allows non EIP-155 protected transactions to be send over RPC. AllowUnprotectedTxs bool `toml:",omitempty"` + + // BatchRequestLimit is the maximum number of requests in a batch. + BatchRequestLimit int `toml:",omitempty"` + } // IPCEndpoint resolves an IPC endpoint based on a configured value, taking into diff --git a/node/defaults.go b/node/defaults.go index c685dde5d..1ffda8dea 100644 --- a/node/defaults.go +++ b/node/defaults.go @@ -45,6 +45,7 @@ var DefaultConfig = Config{ HTTPTimeouts: rpc.DefaultHTTPTimeouts, WSPort: DefaultWSPort, WSModules: []string{"net", "web3"}, + BatchRequestLimit: 1000, GraphQLVirtualHosts: []string{"localhost"}, P2P: p2p.Config{ ListenAddr: ":30303", diff --git a/node/node.go b/node/node.go index ceab1c909..5ad5af021 100644 --- a/node/node.go +++ b/node/node.go @@ -96,9 +96,11 @@ func New(conf *Config) (*Node, error) { return nil, errors.New(`Config.Name cannot end in ".ipc"`) } + server := rpc.NewServer() + server.SetBatchLimits(conf.BatchRequestLimit) node := &Node{ config: conf, - inprocHandler: rpc.NewServer(), + inprocHandler: server, eventmux: new(event.TypeMux), log: conf.Logger, stop: make(chan struct{}), @@ -350,6 +352,10 @@ func (n *Node) startRPC() error { } } + rpcConfig := rpcEndpointConfig{ + batchItemLimit: n.config.BatchRequestLimit, + } + // Configure HTTP. if n.config.HTTPHost != "" { config := httpConfig{ @@ -357,6 +363,7 @@ func (n *Node) startRPC() error { Vhosts: n.config.HTTPVirtualHosts, Modules: n.config.HTTPModules, prefix: n.config.HTTPPathPrefix, + rpcEndpointConfig: rpcConfig, } if err := n.http.setListenAddr(n.config.HTTPHost, n.config.HTTPPort); err != nil { return err diff --git a/node/rpcstack.go b/node/rpcstack.go index 2c55a070b..c641e10e4 100644 --- a/node/rpcstack.go +++ b/node/rpcstack.go @@ -40,6 +40,7 @@ type httpConfig struct { CorsAllowedOrigins []string Vhosts []string prefix string // path prefix on which to mount http handler + rpcEndpointConfig } // wsConfig is the JSON-RPC/Websocket configuration @@ -49,6 +50,10 @@ type wsConfig struct { prefix string // path prefix on which to mount ws handler } +type rpcEndpointConfig struct { + batchItemLimit int +} + type rpcHandler struct { http.Handler server *rpc.Server @@ -280,6 +285,7 @@ func (h *httpServer) enableRPC(apis []rpc.API, config httpConfig) error { // Create RPC server and handler. srv := rpc.NewServer() + srv.SetBatchLimits(config.batchItemLimit) if err := RegisterApis(apis, config.Modules, srv, false); err != nil { return err } diff --git a/rpc/client.go b/rpc/client.go index 198ce6357..77f144634 100644 --- a/rpc/client.go +++ b/rpc/client.go @@ -83,6 +83,9 @@ type Client struct { // This function, if non-nil, is called when the connection is lost. reconnectFunc reconnectFunc + // config fields + batchItemLimit int + // writeConn is used for writing to the connection on the caller's goroutine. It should // only be accessed outside of dispatch, with the write lock held. The write lock is // taken by sending on reqInit and released by sending on reqSent. @@ -111,7 +114,7 @@ type clientConn struct { func (c *Client) newClientConn(conn ServerCodec) *clientConn { ctx := context.WithValue(context.Background(), clientContextKey{}, c) - handler := newHandler(ctx, conn, c.idgen, c.services) + handler := newHandler(ctx, conn, c.idgen, c.services, c.batchItemLimit) return &clientConn{conn, handler} } diff --git a/rpc/errors.go b/rpc/errors.go index 4c06a745f..e58f6458c 100644 --- a/rpc/errors.go +++ b/rpc/errors.go @@ -58,6 +58,8 @@ var ( const defaultErrorCode = -32000 +const errMsgBatchTooLarge = "batch too large" + type methodNotFoundError struct{ method string } func (e *methodNotFoundError) ErrorCode() int { return -32601 } diff --git a/rpc/handler.go b/rpc/handler.go index 85f774a1b..884d26db4 100644 --- a/rpc/handler.go +++ b/rpc/handler.go @@ -50,17 +50,18 @@ import ( // } // type handler struct { - reg *serviceRegistry - unsubscribeCb *callback - idgen func() ID // subscription ID generator - respWait map[string]*requestOp // active client requests - clientSubs map[string]*ClientSubscription // active client subscriptions - callWG sync.WaitGroup // pending call goroutines - rootCtx context.Context // canceled by close() - cancelRoot func() // cancel function for rootCtx - conn jsonWriter // where responses will be sent - log log.Logger - allowSubscribe bool + reg *serviceRegistry + unsubscribeCb *callback + idgen func() ID // subscription ID generator + respWait map[string]*requestOp // active client requests + clientSubs map[string]*ClientSubscription // active client subscriptions + callWG sync.WaitGroup // pending call goroutines + rootCtx context.Context // canceled by close() + cancelRoot func() // cancel function for rootCtx + conn jsonWriter // where responses will be sent + log log.Logger + allowSubscribe bool + batchRequestLimit int subLock sync.Mutex serverSubs map[ID]*Subscription @@ -71,19 +72,20 @@ type callProc struct { notifiers []*Notifier } -func newHandler(connCtx context.Context, conn jsonWriter, idgen func() ID, reg *serviceRegistry) *handler { +func newHandler(connCtx context.Context, conn jsonWriter, idgen func() ID, reg *serviceRegistry, batchRequestLimit int) *handler { rootCtx, cancelRoot := context.WithCancel(connCtx) h := &handler{ - reg: reg, - idgen: idgen, - conn: conn, - respWait: make(map[string]*requestOp), - clientSubs: make(map[string]*ClientSubscription), - rootCtx: rootCtx, - cancelRoot: cancelRoot, - allowSubscribe: true, - serverSubs: make(map[ID]*Subscription), - log: log.Root(), + reg: reg, + idgen: idgen, + conn: conn, + respWait: make(map[string]*requestOp), + clientSubs: make(map[string]*ClientSubscription), + rootCtx: rootCtx, + cancelRoot: cancelRoot, + allowSubscribe: true, + serverSubs: make(map[ID]*Subscription), + log: log.Root(), + batchRequestLimit: batchRequestLimit, } if conn.remoteAddr() != "" { h.log = h.log.New("conn", conn.remoteAddr()) @@ -102,6 +104,14 @@ func (h *handler) handleBatch(msgs []*jsonrpcMessage) { return } + // Apply limit on total number of requests. + if h.batchRequestLimit != 0 && len(msgs) > h.batchRequestLimit { + h.startCallProc(func(cp *callProc) { + h.respondWithBatchTooLarge(cp, msgs) + }) + return + } + // Handle non-call messages first: calls := make([]*jsonrpcMessage, 0, len(msgs)) for _, msg := range msgs { @@ -129,6 +139,19 @@ func (h *handler) handleBatch(msgs []*jsonrpcMessage) { } }) } +func (h *handler) respondWithBatchTooLarge(cp *callProc, batch []*jsonrpcMessage) { + resp := errorMessage(&invalidRequestError{errMsgBatchTooLarge}) + // Find the first call and add its "id" field to the error. + // This is the best we can do, given that the protocol doesn't have a way + // of reporting an error for the entire batch. + for _, msg := range batch { + if msg.isCall() { + resp.ID = msg.ID + break + } + } + h.conn.writeJSON(cp.ctx, []*jsonrpcMessage{resp}) +} // handleMsg handles a single message. func (h *handler) handleMsg(msg *jsonrpcMessage) { diff --git a/rpc/server.go b/rpc/server.go index 64e078a7f..6294e201e 100644 --- a/rpc/server.go +++ b/rpc/server.go @@ -42,10 +42,11 @@ const ( // Server is an RPC server. type Server struct { - services serviceRegistry - idgen func() ID - run int32 - codecs mapset.Set + services serviceRegistry + idgen func() ID + run int32 + codecs mapset.Set + batchItemLimit int } // NewServer creates a new server instance with no registered handlers. @@ -58,6 +59,15 @@ func NewServer() *Server { return server } +// SetBatchLimits sets limits applied to batch requests. There are two limits: 'itemLimit' +// is the maximum number of items in a batch. +// +// This method should be called before processing any requests via ServeCodec, ServeHTTP, +// ServeListener etc. +func (s *Server) SetBatchLimits(itemLimit int) { + s.batchItemLimit = itemLimit +} + // RegisterName creates a service for the given receiver type under the given name. When no // methods on the given receiver match the criteria to be either a RPC method or a // subscription an error is returned. Otherwise a new service is created and added to the @@ -97,7 +107,7 @@ func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec) { return } - h := newHandler(ctx, codec, s.idgen, &s.services) + h := newHandler(ctx, codec, s.idgen, &s.services, s.batchItemLimit) h.allowSubscribe = false defer h.close(io.EOF, nil) From e283013d4442f4a9b23c9d0a1a3bdb377c3adb30 Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Wed, 6 Mar 2024 18:18:57 +0800 Subject: [PATCH 13/17] chg: fix lint --- cmd/utils/flags.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index bf00b0395..4f755c13a 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -621,12 +621,11 @@ var ( Name: "rpc.allow-unprotected-txs", Usage: "Allow for unprotected (non EIP155 signed) transactions to be submitted via RPC", } - BatchRequestLimit = &cli.IntFlag{ + BatchRequestLimit = cli.IntFlag{ //nolint:typecheck Name: "rpc.batch-request-limit", Usage: "Maximum number of requests in a batch(only supported in http)", Value: node.DefaultConfig.BatchRequestLimit, } - // Network Settings MaxPeersFlag = cli.IntFlag{ Name: "maxpeers", From 4c0cf76333dd5213142cb04544f75e43e20c481e Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Wed, 6 Mar 2024 18:45:54 +0800 Subject: [PATCH 14/17] chg:fix lint --- internal/ethapi/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index a38532521..782805b5d 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1603,7 +1603,7 @@ func (api *PublicTransactionPoolAPI) getAllBlockTransactions(ctx context.Context if borReceipt != nil { txHash := types.GetDerivedBorTxHash(types.BorReceiptKey(block.Number().Uint64(), block.Hash())) if txHash != (common.Hash{}) { - borTx, _, _, _, _ := api.b.GetBorBlockTransactionWithBlockHash(ctx, txHash, block.Hash()) + borTx, _, _, _, _ := api.b.GetBorBlockTransactionWithBlockHash(ctx, txHash, block.Hash()) //nolint:typecheck txs = append(txs, borTx) stateSyncPresent = true } From eeb1dc61d11d0a8508beea48f84c5b3b34cd4435 Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Mon, 1 Apr 2024 18:56:30 +0800 Subject: [PATCH 15/17] chg: fix txHash --- internal/ethapi/api.go | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index fc3c023b0..48e130904 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1446,20 +1446,31 @@ func newRPCPendingTransaction(tx *types.Transaction, current *types.Header, conf // newRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation. func newRPCTransactionFromBlockIndex(b *types.Block, index uint64, db ethdb.Database) *RPCTransaction { txs := b.Transactions() + var borReceipt *types.Receipt - borReceipt := rawdb.ReadBorReceipt(db, b.Hash(), b.NumberU64()) - if borReceipt != nil { - tx, _, _, _ := rawdb.ReadBorTransaction(db, borReceipt.TxHash) + // Read bor receipts if a state-sync transaction is requested + if index == uint64(len(txs)) { + borReceipt = rawdb.ReadBorReceipt(db, b.Hash(), b.NumberU64()) + if borReceipt != nil { + tx, _, _, _ := rawdb.ReadBorTransaction(db, borReceipt.TxHash) - if tx != nil { - txs = append(txs, tx) + if tx != nil { + txs = append(txs, tx) + } } } if index >= uint64(len(txs)) { return nil } - return newRPCTransaction(txs[index], b.Hash(), b.NumberU64(), index, b.BaseFee()) + rpcTx := newRPCTransaction(txs[index], b.Hash(), b.NumberU64(), index, b.BaseFee()) + + // If the transaction is a bor transaction, we need to set the hash to the derived bor tx hash. BorTx is always the last index. + if borReceipt != nil && index == uint64(len(txs)-1) { + rpcTx.Hash = borReceipt.TxHash + } + + return rpcTx } // newRPCRawTransactionFromBlockIndex returns the bytes of a transaction given a block and a transaction index. From b23e0a634658c51d6b5ac2b310a3010e33b95bf2 Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Tue, 2 Apr 2024 11:14:37 +0800 Subject: [PATCH 16/17] chg: add check --- internal/ethapi/api.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 48e130904..f52311762 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1452,10 +1452,12 @@ func newRPCTransactionFromBlockIndex(b *types.Block, index uint64, db ethdb.Data if index == uint64(len(txs)) { borReceipt = rawdb.ReadBorReceipt(db, b.Hash(), b.NumberU64()) if borReceipt != nil { - tx, _, _, _ := rawdb.ReadBorTransaction(db, borReceipt.TxHash) + if borReceipt.TxHash != (common.Hash{}) { + tx, _, _, _ := rawdb.ReadBorTransaction(db, borReceipt.TxHash) - if tx != nil { - txs = append(txs, tx) + if tx != nil { + txs = append(txs, tx) + } } } } From 9ce223e7cc5cd72dbc5b8c40e2fa9762dce536e9 Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Tue, 2 Apr 2024 12:09:58 +0800 Subject: [PATCH 17/17] chg: add check --- internal/ethapi/api.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index f52311762..355a31a01 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1448,12 +1448,16 @@ func newRPCTransactionFromBlockIndex(b *types.Block, index uint64, db ethdb.Data txs := b.Transactions() var borReceipt *types.Receipt + if index >= uint64(len(txs)+1) { + return nil + } + // Read bor receipts if a state-sync transaction is requested if index == uint64(len(txs)) { borReceipt = rawdb.ReadBorReceipt(db, b.Hash(), b.NumberU64()) if borReceipt != nil { if borReceipt.TxHash != (common.Hash{}) { - tx, _, _, _ := rawdb.ReadBorTransaction(db, borReceipt.TxHash) + tx, _, _, _ := rawdb.ReadBorTransactionWithBlockHash(db, borReceipt.TxHash, b.Hash()) if tx != nil { txs = append(txs, tx)