diff --git a/core/tx_pool.go b/core/tx_pool.go index eb5bd5595..660e80d46 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -225,12 +225,11 @@ type TxPool struct { wg sync.WaitGroup // for shutdown sync homestead bool - EnodeId string } // NewTxPool creates a new transaction pool to gather, sort and filter inbound // transactions from the network. -func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain blockChain, id string) *TxPool { +func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain blockChain) *TxPool { // Sanitize the input to ensure no vulnerable gas prices are set config = (&config).sanitize() @@ -246,7 +245,6 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block all: newTxLookup(), chainHeadCh: make(chan ChainHeadEvent, chainHeadChanSize), gasPrice: new(big.Int).SetUint64(config.PriceLimit), - EnodeId: id, } pool.locals = newAccountSet(pool.signer) for _, addr := range config.Locals { diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go index 5e80859f9..0048ff4ae 100644 --- a/core/tx_pool_test.go +++ b/core/tx_pool_test.go @@ -84,7 +84,7 @@ func setupTxPool() (*TxPool, *ecdsa.PrivateKey) { blockchain := &testBlockChain{statedb, statedb, 1000000, new(event.Feed)} key, _ := crypto.GenerateKey() - pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, "") + pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) return pool, key } @@ -95,7 +95,7 @@ func setupQuorumTxPool() (*TxPool, *ecdsa.PrivateKey) { blockchain := &testBlockChain{statedb, statedb, 1000000, new(event.Feed)} key, _ := crypto.GenerateKey() - pool := NewTxPool(testTxPoolConfig, params.QuorumTestChainConfig, blockchain, "") + pool := NewTxPool(testTxPoolConfig, params.QuorumTestChainConfig, blockchain) return pool, key } @@ -205,7 +205,7 @@ func TestStateChangeDuringTransactionPoolReset(t *testing.T) { tx0 := transaction(0, 100000, key) tx1 := transaction(1, 100000, key) - pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, "") + pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) defer pool.Stop() nonce := pool.State().GetNonce(address) @@ -287,7 +287,7 @@ func TestInvalidTransactions(t *testing.T) { statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) blockchain := &testBlockChain{statedb, statedb, 1000000, new(event.Feed)} params.TestChainConfig.TransactionSizeLimit = 128 - pool2 := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, "") + pool2 := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) pool2.currentState.AddBalance(from, big.NewInt(0xffffffffffffff)) data2 := make([]byte, (127 * 1024)) @@ -691,7 +691,7 @@ func TestTransactionPostponing(t *testing.T) { statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) blockchain := &testBlockChain{statedb, statedb, 1000000, new(event.Feed)} - pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, "") + pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) defer pool.Stop() // Create two test accounts to produce different gap profiles with @@ -910,7 +910,7 @@ func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) { config.NoLocals = nolocals config.GlobalQueue = config.AccountQueue*3 - 1 // reduce the queue limits to shorten test time (-1 to make it non divisible) - pool := NewTxPool(config, params.TestChainConfig, blockchain, "") + pool := NewTxPool(config, params.TestChainConfig, blockchain) defer pool.Stop() // Create a number of test accounts and fund them (last one will be the local) @@ -998,7 +998,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { config.Lifetime = time.Second config.NoLocals = nolocals - pool := NewTxPool(config, params.TestChainConfig, blockchain, "") + pool := NewTxPool(config, params.TestChainConfig, blockchain) defer pool.Stop() // Create two test accounts to ensure remotes expire but locals do not @@ -1157,7 +1157,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) { config := testTxPoolConfig config.GlobalSlots = config.AccountSlots * 10 - pool := NewTxPool(config, params.TestChainConfig, blockchain, "") + pool := NewTxPool(config, params.TestChainConfig, blockchain) defer pool.Stop() // Create a number of test accounts and fund them @@ -1205,7 +1205,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) { config.AccountQueue = 2 config.GlobalSlots = 8 - pool := NewTxPool(config, params.TestChainConfig, blockchain, "") + pool := NewTxPool(config, params.TestChainConfig, blockchain) defer pool.Stop() // Create a number of test accounts and fund them @@ -1237,7 +1237,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) { config := testTxPoolConfig config.GlobalSlots = 0 - pool := NewTxPool(config, params.TestChainConfig, blockchain, "") + pool := NewTxPool(config, params.TestChainConfig, blockchain) defer pool.Stop() // Create a number of test accounts and fund them @@ -1282,7 +1282,7 @@ func TestTransactionPoolRepricing(t *testing.T) { statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) blockchain := &testBlockChain{statedb, statedb, 1000000, new(event.Feed)} - pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, "") + pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) defer pool.Stop() // Keep track of transaction events to ensure all executables get announced @@ -1403,7 +1403,7 @@ func TestTransactionPoolRepricingKeepsLocals(t *testing.T) { statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) blockchain := &testBlockChain{statedb, statedb, 1000000, new(event.Feed)} - pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, "") + pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) defer pool.Stop() // Create a number of test accounts and fund them @@ -1469,7 +1469,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) { config.GlobalSlots = 2 config.GlobalQueue = 2 - pool := NewTxPool(config, params.TestChainConfig, blockchain, "") + pool := NewTxPool(config, params.TestChainConfig, blockchain) defer pool.Stop() // Keep track of transaction events to ensure all executables get announced @@ -1575,7 +1575,7 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) { config.GlobalSlots = 128 config.GlobalQueue = 0 - pool := NewTxPool(config, params.TestChainConfig, blockchain, "") + pool := NewTxPool(config, params.TestChainConfig, blockchain) defer pool.Stop() // Keep track of transaction events to ensure all executables get announced @@ -1637,7 +1637,7 @@ func TestTransactionReplacement(t *testing.T) { statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) blockchain := &testBlockChain{statedb, statedb, 1000000, new(event.Feed)} - pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, "") + pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) defer pool.Stop() // Keep track of transaction events to ensure all executables get announced @@ -1736,7 +1736,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) { config.Journal = journal config.Rejournal = time.Second - pool := NewTxPool(config, params.TestChainConfig, blockchain, "") + pool := NewTxPool(config, params.TestChainConfig, blockchain) // Create two test accounts to ensure remotes expire but locals do not local, _ := crypto.GenerateKey() @@ -1773,7 +1773,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) { statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) blockchain = &testBlockChain{statedb, statedb, 1000000, new(event.Feed)} - pool = NewTxPool(config, params.TestChainConfig, blockchain, "") + pool = NewTxPool(config, params.TestChainConfig, blockchain) pending, queued = pool.Stats() if queued != 0 { @@ -1799,7 +1799,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) { statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) blockchain = &testBlockChain{statedb, statedb, 1000000, new(event.Feed)} - pool = NewTxPool(config, params.TestChainConfig, blockchain, "") + pool = NewTxPool(config, params.TestChainConfig, blockchain) pending, queued = pool.Stats() if pending != 0 { @@ -1829,7 +1829,7 @@ func TestTransactionStatusCheck(t *testing.T) { statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) blockchain := &testBlockChain{statedb, statedb, 1000000, new(event.Feed)} - pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, "") + pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) defer pool.Stop() // Create the test accounts to check various transaction statuses with @@ -2007,7 +2007,7 @@ func TestEIP155SignerOnTxPool(t *testing.T) { Ethash: new(params.EthashConfig), } - pool := NewTxPool(testTxPoolConfig, chainconfig, blockchain, "") + pool := NewTxPool(testTxPoolConfig, chainconfig, blockchain) if reflect.TypeOf(types.EIP155Signer{}) != reflect.TypeOf(pool.signer) { t.Fail() diff --git a/core/types/permissions_cache_test.go b/core/types/permissions_cache_test.go index 4613b7c65..54fb87bb0 100644 --- a/core/types/permissions_cache_test.go +++ b/core/types/permissions_cache_test.go @@ -2,17 +2,19 @@ package types import ( "fmt" - "github.com/ethereum/go-ethereum/common" - testifyassert "github.com/stretchr/testify/assert" "math/big" "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + testifyassert "github.com/stretchr/testify/assert" ) var ( NETWORKADMIN = "NWADMIN" - ORGADMIN = "OADMIN" - NODE1 = "enode://ac6b1096ca56b9f6d004b779ae3728bf83f8e22453404cc3cef16a3d9b96608bc67c4b30db88e0a5a6c6390213f7acbe1153ff6d23ce57380104288ae19373ef@127.0.0.1:21000?discport=0&raftport=50401" - NODE2 = "enode://0ba6b9f606a43a95edc6247cdb1c1e105145817be7bcafd6b2c0ba15d58145f0dc1a194f70ba73cd6f4cdd6864edc7687f311254c7555cc32e4d45aeb1b80416@127.0.0.1:21001?discport=0&raftport=50402" + ORGADMIN = "OADMIN" + NODE1 = "enode://ac6b1096ca56b9f6d004b779ae3728bf83f8e22453404cc3cef16a3d9b96608bc67c4b30db88e0a5a6c6390213f7acbe1153ff6d23ce57380104288ae19373ef@127.0.0.1:21000?discport=0&raftport=50401" + NODE2 = "enode://0ba6b9f606a43a95edc6247cdb1c1e105145817be7bcafd6b2c0ba15d58145f0dc1a194f70ba73cd6f4cdd6864edc7687f311254c7555cc32e4d45aeb1b80416@127.0.0.1:21001?discport=0&raftport=50402" ) var Acct1 = common.BytesToAddress([]byte("permission")) @@ -98,19 +100,19 @@ func TestRoleCache_UpsertRole(t *testing.T) { assert := testifyassert.New(t) // add a role into the cache and validate - RoleInfoMap.UpsertRole(NETWORKADMIN, NETWORKADMIN, true, true, FullAccess, true ) + RoleInfoMap.UpsertRole(NETWORKADMIN, NETWORKADMIN, true, true, FullAccess, true) roleInfo := RoleInfoMap.GetRole(NETWORKADMIN, NETWORKADMIN) assert.False(roleInfo == nil, fmt.Sprintf("Expected role details, got nil")) assert.True(roleInfo.OrgId == NETWORKADMIN, fmt.Sprintf("Expected org id for node %v, got %v", NETWORKADMIN, roleInfo.OrgId)) assert.True(roleInfo.RoleId == NETWORKADMIN, fmt.Sprintf("Expected node id %v, got %v", NETWORKADMIN, roleInfo.RoleId)) // add another role and validate the list function - RoleInfoMap.UpsertRole(ORGADMIN, ORGADMIN, true, true, FullAccess, true ) + RoleInfoMap.UpsertRole(ORGADMIN, ORGADMIN, true, true, FullAccess, true) roleList := RoleInfoMap.GetRoleList() assert.True(len(roleList) == 2, fmt.Sprintf("Expected 2 entries, got %v", len(roleList))) // update role status and validate - RoleInfoMap.UpsertRole(ORGADMIN, ORGADMIN, true, true, FullAccess, false ) + RoleInfoMap.UpsertRole(ORGADMIN, ORGADMIN, true, true, FullAccess, false) roleInfo = RoleInfoMap.GetRole(ORGADMIN, ORGADMIN) assert.True(roleInfo.Active == false, fmt.Sprintf("Expected role active status to be %v, got %v", true, roleInfo.Active)) } @@ -119,19 +121,19 @@ func TestAcctCache_UpsertAccount(t *testing.T) { assert := testifyassert.New(t) // add an account into the cache and validate - AcctInfoMap.UpsertAccount(NETWORKADMIN, NETWORKADMIN, Acct1, true, AcctActive ) + AcctInfoMap.UpsertAccount(NETWORKADMIN, NETWORKADMIN, Acct1, true, AcctActive) acctInfo := AcctInfoMap.GetAccount(Acct1) assert.False(acctInfo == nil, fmt.Sprintf("Expected account details, got nil")) assert.True(acctInfo.OrgId == NETWORKADMIN, fmt.Sprintf("Expected org id for the account to be %v, got %v", NETWORKADMIN, acctInfo.OrgId)) assert.True(acctInfo.AcctId == Acct1, fmt.Sprintf("Expected account id %x, got %x", Acct1, acctInfo.AcctId)) // add a second account and validate the list function - AcctInfoMap.UpsertAccount(ORGADMIN, ORGADMIN, Acct2, true, AcctActive ) + AcctInfoMap.UpsertAccount(ORGADMIN, ORGADMIN, Acct2, true, AcctActive) acctList := AcctInfoMap.GetAcctList() assert.True(len(acctList) == 2, fmt.Sprintf("Expected 2 entries, got %v", len(acctList))) // update account status and validate - AcctInfoMap.UpsertAccount(ORGADMIN, ORGADMIN, Acct2, true, AcctBlacklisted ) + AcctInfoMap.UpsertAccount(ORGADMIN, ORGADMIN, Acct2, true, AcctBlacklisted) acctInfo = AcctInfoMap.GetAccount(Acct2) assert.True(acctInfo.Status == AcctBlacklisted, fmt.Sprintf("Expected account status to be %v, got %v", AcctBlacklisted, acctInfo.Status)) @@ -152,10 +154,10 @@ func TestGetAcctAccess(t *testing.T) { // Create an org with two roles and two accounts linked to different roles. Validate account access OrgInfoMap.UpsertOrg(NETWORKADMIN, "", NETWORKADMIN, big.NewInt(1), OrgApproved) - RoleInfoMap.UpsertRole(NETWORKADMIN, NETWORKADMIN, true, true, FullAccess, true ) - RoleInfoMap.UpsertRole(NETWORKADMIN, "ROLE1", true, true, FullAccess, true ) - AcctInfoMap.UpsertAccount(NETWORKADMIN, NETWORKADMIN, Acct1, true, AcctActive ) - AcctInfoMap.UpsertAccount(NETWORKADMIN, "ROLE1", Acct2, true, AcctActive ) + RoleInfoMap.UpsertRole(NETWORKADMIN, NETWORKADMIN, true, true, FullAccess, true) + RoleInfoMap.UpsertRole(NETWORKADMIN, "ROLE1", true, true, FullAccess, true) + AcctInfoMap.UpsertAccount(NETWORKADMIN, NETWORKADMIN, Acct1, true, AcctActive) + AcctInfoMap.UpsertAccount(NETWORKADMIN, "ROLE1", Acct2, true, AcctActive) access = GetAcctAccess(Acct1) assert.True(access == FullAccess, fmt.Sprintf("Expected account access to be %v, got %v", FullAccess, access)) @@ -172,7 +174,7 @@ func TestGetAcctAccess(t *testing.T) { // mark the role as inactive and account access should now nbe read only OrgInfoMap.UpsertOrg(NETWORKADMIN, "", NETWORKADMIN, big.NewInt(1), OrgApproved) - RoleInfoMap.UpsertRole(NETWORKADMIN, "ROLE1", true, true, FullAccess, false ) + RoleInfoMap.UpsertRole(NETWORKADMIN, "ROLE1", true, true, FullAccess, false) access = GetAcctAccess(Acct2) assert.True(access == ReadOnly, fmt.Sprintf("Expected account access to be %v, got %v", ReadOnly, access)) } @@ -195,14 +197,27 @@ func TestValidateNodeForTxn(t *testing.T) { // populate an org, account and node. validate access OrgInfoMap.UpsertOrg(NETWORKADMIN, "", NETWORKADMIN, big.NewInt(1), OrgApproved) NodeInfoMap.UpsertNode(NETWORKADMIN, NODE1, NodeApproved) - AcctInfoMap.UpsertAccount(NETWORKADMIN, NETWORKADMIN, Acct1, true, AcctActive ) + AcctInfoMap.UpsertAccount(NETWORKADMIN, NETWORKADMIN, Acct1, true, AcctActive) txnAllowed = ValidateNodeForTxn(NODE1, Acct1) assert.True(txnAllowed == true, "Expected access %v, got %v", true, txnAllowed) // test access from a node not linked to the org. should return false OrgInfoMap.UpsertOrg(ORGADMIN, "", ORGADMIN, big.NewInt(1), OrgApproved) NodeInfoMap.UpsertNode(ORGADMIN, NODE2, NodeApproved) - AcctInfoMap.UpsertAccount(ORGADMIN, ORGADMIN, Acct2, true, AcctActive ) + AcctInfoMap.UpsertAccount(ORGADMIN, ORGADMIN, Acct2, true, AcctActive) txnAllowed = ValidateNodeForTxn(NODE1, Acct2) assert.True(txnAllowed == false, "Expected access %v, got %v", true, txnAllowed) -} \ No newline at end of file +} + +// This is to make sure enode.ParseV4() honors single hexNodeId value eventhough it does follow enode URI scheme +func TestValidateNodeForTxn_whenUsingOnlyHexNodeId(t *testing.T) { + OrgInfoMap.UpsertOrg(NETWORKADMIN, "", NETWORKADMIN, big.NewInt(1), OrgApproved) + NodeInfoMap.UpsertNode(NETWORKADMIN, NODE1, NodeApproved) + AcctInfoMap.UpsertAccount(NETWORKADMIN, NETWORKADMIN, Acct1, true, AcctActive) + arbitraryPrivateKey, _ := crypto.GenerateKey() + hexNodeId := fmt.Sprintf("%x", crypto.FromECDSAPub(&arbitraryPrivateKey.PublicKey)[1:]) + + txnAllowed := ValidateNodeForTxn(hexNodeId, Acct1) + + testifyassert.False(t, txnAllowed) +} diff --git a/eth/api_backend.go b/eth/api_backend.go index c8741b58a..733db6280 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -41,6 +41,11 @@ import ( type EthAPIBackend struct { eth *Ethereum gpo *gasprice.Oracle + + // Quorum + // + // hex node id from node public key + hexNodeId string } // ChainConfig returns the active chain configuration. @@ -184,7 +189,7 @@ func (b *EthAPIBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscri func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { // validation for node need to happen here and cannot be done as a part of // validateTx in tx_pool.go as tx_pool validation will happen in every node - if b.eth.txPool.EnodeId != "" && !types.ValidateNodeForTxn(b.eth.txPool.EnodeId, signedTx.From()) { + if b.hexNodeId != "" && !types.ValidateNodeForTxn(b.hexNodeId, signedTx.From()) { return errors.New("cannot send transaction from this node") } return b.eth.txPool.AddLocal(signedTx) diff --git a/eth/backend.go b/eth/backend.go index 47cf8465f..467da50f1 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -197,7 +197,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { if config.TxPool.Journal != "" { config.TxPool.Journal = ctx.ResolvePath(config.TxPool.Journal) } - eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain, fmt.Sprintf("%x", crypto.FromECDSAPub(&ctx.NodeKey().PublicKey)[1:])) + eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain) if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb, config.RaftMode); err != nil { return nil, err @@ -206,7 +206,8 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine, config.MinerRecommit, config.MinerGasFloor, config.MinerGasCeil, eth.isLocalBlock) eth.miner.SetExtra(makeExtraData(config.MinerExtraData, eth.chainConfig.IsQuorum)) - eth.APIBackend = &EthAPIBackend{eth, nil} + hexNodeId := fmt.Sprintf("%x", crypto.FromECDSAPub(&ctx.NodeKey().PublicKey)[1:]) // Quorum + eth.APIBackend = &EthAPIBackend{eth, nil, hexNodeId} gpoParams := config.GPO if gpoParams.Default == nil { gpoParams.Default = config.MinerGasPrice diff --git a/les/handler_test.go b/les/handler_test.go index d4c9c7b0c..43be7f41b 100644 --- a/les/handler_test.go +++ b/les/handler_test.go @@ -498,7 +498,7 @@ func TestTransactionStatusLes2(t *testing.T) { chain := pm.blockchain.(*core.BlockChain) config := core.DefaultTxPoolConfig config.Journal = "" - txpool := core.NewTxPool(config, params.TestChainConfig, chain, "") + txpool := core.NewTxPool(config, params.TestChainConfig, chain) pm.txpool = txpool peer, _ := newTestPeer(t, "peer", 2, pm, true) defer peer.close() diff --git a/miner/worker_test.go b/miner/worker_test.go index 2bdbecdf1..bda4f17c3 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -97,7 +97,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine genesis := gspec.MustCommit(db) chain, _ := core.NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil) - txpool := core.NewTxPool(testTxPoolConfig, chainConfig, chain, "") + txpool := core.NewTxPool(testTxPoolConfig, chainConfig, chain) // Generate a small n-block chain and an uncle block for it if n > 0 {