From 2ead9d7d336ce94ff302ae76f2c3c8fc28484445 Mon Sep 17 00:00:00 2001 From: Daniel Van Der Maden Date: Sat, 31 Oct 2020 12:17:27 -0700 Subject: [PATCH] Tx submission epoch checks (#3421) * [node] Add Cx epoch check * Report invalid epoch for staking tx Signed-off-by: Daniel Van Der Maden * [rosetta] Add Cx epoch check in Metadata request Signed-off-by: Daniel Van Der Maden * [node] Fix lint Signed-off-by: Daniel Van Der Maden --- node/node.go | 52 +++++++++++++++++--------- rosetta/services/construction_check.go | 14 +++++++ 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/node/node.go b/node/node.go index 2111fa0ee..59b82aa1a 100644 --- a/node/node.go +++ b/node/node.go @@ -204,10 +204,16 @@ func (node *Node) tryBroadcastStaking(stakingTx *staking.StakingTransaction) { // Add new transactions to the pending transaction list. func (node *Node) addPendingTransactions(newTxs types.Transactions) []error { poolTxs := types.PoolTransactions{} + errs := []error{} + acceptCx := node.Blockchain().Config().AcceptsCrossTx(node.Blockchain().CurrentHeader().Epoch()) for _, tx := range newTxs { + if tx.ShardID() != tx.ToShardID() && !acceptCx { + errs = append(errs, errors.WithMessage(errInvalidEpoch, "cross-shard tx not accepted yet")) + continue + } poolTxs = append(poolTxs, tx) } - errs := node.TxPool.AddRemotes(poolTxs) + errs = append(errs, node.TxPool.AddRemotes(poolTxs)...) pendingCount, queueCount := node.TxPool.Stats() utils.Logger().Info(). @@ -221,22 +227,28 @@ func (node *Node) addPendingTransactions(newTxs types.Transactions) []error { // Add new staking transactions to the pending staking transaction list. func (node *Node) addPendingStakingTransactions(newStakingTxs staking.StakingTransactions) []error { - if node.NodeConfig.ShardID == shard.BeaconChainShardID && - node.Blockchain().Config().IsPreStaking(node.Blockchain().CurrentHeader().Epoch()) { - poolTxs := types.PoolTransactions{} - for _, tx := range newStakingTxs { - poolTxs = append(poolTxs, tx) + if node.NodeConfig.ShardID == shard.BeaconChainShardID { + if node.Blockchain().Config().IsPreStaking(node.Blockchain().CurrentHeader().Epoch()) { + poolTxs := types.PoolTransactions{} + for _, tx := range newStakingTxs { + poolTxs = append(poolTxs, tx) + } + errs := node.TxPool.AddRemotes(poolTxs) + pendingCount, queueCount := node.TxPool.Stats() + utils.Logger().Info(). + Int("length of newStakingTxs", len(poolTxs)). + Int("totalPending", pendingCount). + Int("totalQueued", queueCount). + Msg("Got more staking transactions") + return errs } - errs := node.TxPool.AddRemotes(poolTxs) - pendingCount, queueCount := node.TxPool.Stats() - utils.Logger().Info(). - Int("length of newStakingTxs", len(poolTxs)). - Int("totalPending", pendingCount). - Int("totalQueued", queueCount). - Msg("Got more staking transactions") - return errs + return []error{ + errors.WithMessage(errInvalidEpoch, "staking txs not accepted yet"), + } + } + return []error{ + errors.WithMessage(errInvalidShard, fmt.Sprintf("txs only valid on shard %v", shard.BeaconChainShardID)), } - return make([]error, len(newStakingTxs)) } // AddPendingStakingTransaction staking transactions @@ -248,13 +260,17 @@ func (node *Node) AddPendingStakingTransaction( var err error for i := range errs { if errs[i] != nil { - utils.Logger().Info().Err(errs[i]).Msg("[AddPendingStakingTransaction] Failed adding new staking transaction") + utils.Logger().Info(). + Err(errs[i]). + Msg("[AddPendingStakingTransaction] Failed adding new staking transaction") err = errs[i] break } } if err == nil || node.BroadcastInvalidTx { - utils.Logger().Info().Str("Hash", newStakingTx.Hash().Hex()).Msg("Broadcasting Staking Tx") + utils.Logger().Info(). + Str("Hash", newStakingTx.Hash().Hex()). + Msg("Broadcasting Staking Tx") node.tryBroadcastStaking(newStakingTx) } return err @@ -361,6 +377,8 @@ var ( errWrongShardID = errors.New("wrong shard id") errInvalidNodeMsg = errors.New("invalid node message") errIgnoreBeaconMsg = errors.New("ignore beacon sync block") + errInvalidEpoch = errors.New("invalid epoch for transaction") + errInvalidShard = errors.New("invalid shard") ) // validateNodeMessage validate node message diff --git a/rosetta/services/construction_check.go b/rosetta/services/construction_check.go index 9b96ea70a..53d1b5f2a 100644 --- a/rosetta/services/construction_check.go +++ b/rosetta/services/construction_check.go @@ -172,6 +172,20 @@ func (s *ConstructAPI) ConstructionMetadata( }) } + currBlock, err := s.hmy.BlockByNumber(ctx, ethRpc.LatestBlockNumber) + if err != nil { + return nil, common.NewError(common.CatchAllError, map[string]interface{}{ + "message": err.Error(), + }) + } + + if options.OperationType == common.NativeCrossShardTransferOperation && + !s.hmy.BlockChain.Config().AcceptsCrossTx(currBlock.Epoch()) { + return nil, common.NewError(common.InvalidTransactionConstructionError, map[string]interface{}{ + "message": "cross-shard transaction is not accepted yet", + }) + } + data := hexutil.Bytes{} if options.TransactionMetadata.Data != nil { var err error