From 26fcfda87caa458f164ed2e27f5db8128c35f80d Mon Sep 17 00:00:00 2001 From: screwyprof Date: Tue, 17 Oct 2017 00:54:56 +0300 Subject: [PATCH] Introduced a private Ethereum network for testing purposes (#397) 1. A new private testing network (StatusChain) is introduced. 2. An example test case implemented (TestSendEtherOnStatusChainTx) 3. Genesis file added static/config/status-chain-genesis.json --- e2e/transactions/transactions_test.go | 81 +++++++++++++++++++++++++ geth/params/config.go | 20 ++++++ geth/params/defaults.go | 3 + static/bindata.go | 59 ++++++++++++------ static/config/status-chain-genesis.json | 22 +++++++ testing/testing.go | 7 ++- 6 files changed, 171 insertions(+), 21 deletions(-) create mode 100644 static/config/status-chain-genesis.json diff --git a/e2e/transactions/transactions_test.go b/e2e/transactions/transactions_test.go index ef2f19b6a..00e487ebb 100644 --- a/e2e/transactions/transactions_test.go +++ b/e2e/transactions/transactions_test.go @@ -314,6 +314,87 @@ func (s *TransactionsTestSuite) TestSendEtherTx() { s.Zero(s.Backend.TxQueueManager().TransactionQueue().Count(), "tx queue must be empty at this point") } +func (s *TransactionsTestSuite) TestSendEtherOnStatusChainTx() { + s.StartTestBackend(params.StatusChainNetworkID) + defer s.StopTestBackend() + + backend := s.LightEthereumService().StatusBackend + s.NotNil(backend) + + // create an account + sampleAddress, _, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password) + s.NoError(err) + + completeQueuedTransaction := make(chan struct{}) + + // replace transaction notification handler + var txHash = gethcommon.Hash{} + signal.SetDefaultNodeNotificationHandler(func(jsonEvent string) { // nolint: dupl + var envelope signal.Envelope + err := json.Unmarshal([]byte(jsonEvent), &envelope) + s.NoError(err, fmt.Sprintf("cannot unmarshal JSON: %s", jsonEvent)) + + if envelope.Type == txqueue.EventTransactionQueued { + event := envelope.Event.(map[string]interface{}) + log.Info("transaction queued (will be completed shortly)", "id", event["id"].(string)) + + // the first call will fail (we are not logged in, but trying to complete tx) + log.Info("trying to complete with no user logged in") + txHash, err = s.Backend.CompleteTransaction( + common.QueuedTxID(event["id"].(string)), + TestConfig.Account1.Password, + ) + s.EqualError( + err, + account.ErrNoAccountSelected.Error(), + fmt.Sprintf("expected error on queued transaction[%v] not thrown", event["id"]), + ) + + // the second call will also fail (we are logged in as different user) + log.Info("trying to complete with invalid user") + err = s.Backend.AccountManager().SelectAccount(sampleAddress, TestConfig.Account1.Password) + s.NoError(err) + txHash, err = s.Backend.CompleteTransaction( + common.QueuedTxID(event["id"].(string)), TestConfig.Account1.Password) + s.EqualError( + err, + txqueue.ErrInvalidCompleteTxSender.Error(), + fmt.Sprintf("expected error on queued transaction[%v] not thrown", event["id"]), + ) + + // the third call will work as expected (as we are logged in with correct credentials) + log.Info("trying to complete with correct user, this should succeed") + s.NoError(s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)) + txHash, err = s.Backend.CompleteTransaction( + common.QueuedTxID(event["id"].(string)), + TestConfig.Account1.Password, + ) + s.NoError(err, fmt.Sprintf("cannot complete queued transaction[%v]", event["id"])) + + close(completeQueuedTransaction) + return + } + }) + + // this call blocks, up until Complete Transaction is called + txHashCheck, err := s.Backend.SendTransaction(nil, common.SendTxArgs{ + From: common.FromAddress(TestConfig.Account1.Address), + To: common.ToAddress(TestConfig.Account2.Address), + Value: (*hexutil.Big)(big.NewInt(1000000000000)), + }) + s.NoError(err, "cannot send transaction") + + select { + case <-completeQueuedTransaction: + case <-time.After(2 * time.Minute): + s.FailNow("completing transaction timed out") + } + + s.Equal(txHashCheck.Hex(), txHash.Hex(), "transaction hash returned from SendTransaction is invalid") + s.False(reflect.DeepEqual(txHashCheck, gethcommon.Hash{}), "transaction was never queued or completed") + s.Zero(s.Backend.TxQueueManager().TransactionQueue().Count(), "tx queue must be empty at this point") +} + func (s *TransactionsTestSuite) TestSendEtherTxUpstream() { s.StartTestBackend( params.RopstenNetworkID, diff --git a/geth/params/config.go b/geth/params/config.go index 96a1bae0c..10a8e240b 100644 --- a/geth/params/config.go +++ b/geth/params/config.go @@ -497,6 +497,12 @@ func (c *NodeConfig) updateGenesisConfig() error { genesis = core.DefaultTestnetGenesisBlock() case RinkebyNetworkID: genesis = core.DefaultRinkebyGenesisBlock() + case StatusChainNetworkID: + var err error + genesis, err = c.DefaultStatusChainGenesisBlock() + if err != nil { + return err + } default: return nil } @@ -511,6 +517,20 @@ func (c *NodeConfig) updateGenesisConfig() error { return nil } +// DefaultStatusChainGenesisBlock returns the StatusChain network genesis block. +func (c *NodeConfig) DefaultStatusChainGenesisBlock() (*core.Genesis, error) { + genesisJSON, err := static.Asset("config/status-chain-genesis.json") + if err != nil { + return nil, fmt.Errorf("status-chain-genesis.json could not be loaded: %s", err) + } + + var genesis *core.Genesis + if err := json.Unmarshal([]byte(genesisJSON), &genesis); err != nil { + return nil, fmt.Errorf("cannot unmarshal status-chain-genesis.json: %s", err) + } + return genesis, nil +} + // updateUpstreamConfig sets the proper UpstreamConfig.URL for the network id being used. func (c *NodeConfig) updateUpstreamConfig() error { diff --git a/geth/params/defaults.go b/geth/params/defaults.go index adc0e7815..2a7212147 100644 --- a/geth/params/defaults.go +++ b/geth/params/defaults.go @@ -99,4 +99,7 @@ const ( // RinkebyNetworkID is id of a test network (on PoA) RinkebyNetworkID = 4 + + // StatusChainNetworkID is id of a test network (private chain) + StatusChainNetworkID = 777 ) diff --git a/static/bindata.go b/static/bindata.go index bdbc2c434..bc2c626ee 100644 --- a/static/bindata.go +++ b/static/bindata.go @@ -4,6 +4,7 @@ // scripts/web3.js // config/cht.json // config/linter_exclude_list.txt +// config/status-chain-genesis.json // config/test-data.json // keys/firebaseauthkey // keys/test-account1-before-eip55.pk @@ -100,7 +101,7 @@ func scriptsReadmeMd() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "scripts/README.md", size: 133, mode: os.FileMode(420), modTime: time.Unix(1498222808, 0)} + info := bindataFileInfo{name: "scripts/README.md", size: 133, mode: os.FileMode(420), modTime: time.Unix(1506194117, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -120,7 +121,7 @@ func scriptsWeb3Js() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "scripts/web3.js", size: 497689, mode: os.FileMode(420), modTime: time.Unix(1507747781, 0)} + info := bindataFileInfo{name: "scripts/web3.js", size: 497689, mode: os.FileMode(420), modTime: time.Unix(1508188203, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -140,7 +141,7 @@ func configChtJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "config/cht.json", size: 7624, mode: os.FileMode(420), modTime: time.Unix(1507747773, 0)} + info := bindataFileInfo{name: "config/cht.json", size: 7624, mode: os.FileMode(420), modTime: time.Unix(1507816211, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -160,7 +161,27 @@ func configLinter_exclude_listTxt() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "config/linter_exclude_list.txt", size: 2258, mode: os.FileMode(420), modTime: time.Unix(1498222808, 0)} + info := bindataFileInfo{name: "config/linter_exclude_list.txt", size: 2258, mode: os.FileMode(420), modTime: time.Unix(1506194117, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _configStatusChainGenesisJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\x91\x4b\x8e\xdb\x30\x0c\x86\xf7\x39\x85\xa0\x75\x17\xd4\x83\xa4\xe4\x9d\xed\x38\x68\x81\xee\x7a\x02\x5a\x92\x27\xc6\x38\x71\x90\x38\xc0\x4c\x8b\xb9\x7b\x91\x47\xd3\xa0\xe8\x78\x63\x48\x1f\xf9\x7f\x94\xf4\x6b\xa5\x94\x96\x69\x9a\x93\xae\xd4\x65\xa1\x94\xd2\x75\xae\x07\x83\xd0\x47\xc0\x76\xc0\x8e\x6a\xe6\xd0\x21\xba\xce\x60\x6d\x5c\x6c\x88\x4c\x68\xfa\x86\xff\xb6\x28\xdd\xcb\x24\xfb\x54\x74\xa5\x34\xbc\x19\xd8\x40\xbb\x01\xf2\xeb\x35\x46\x0b\x97\x4f\x5f\x0b\x3f\xbe\x5c\x7f\x9a\xb0\x05\x83\x81\x44\xa0\x2d\x06\x6d\x70\x98\x38\x04\x69\x0b\x11\x96\x68\xea\xde\xa1\xe5\x3e\x7c\x6e\x68\x4c\xdd\xf9\x35\x75\xb6\xdb\xe0\xb3\x60\x75\x97\xe8\x34\xef\x87\xf1\xe5\x11\xa0\xd3\x56\xc6\xfd\xb7\xac\x2b\xc5\xcc\xf7\x31\xb6\xf3\xae\x9c\x96\x22\xb9\x99\xe6\xf4\xaa\x2b\x05\x77\x90\x65\xde\xcc\xc7\xd7\x1f\xe7\xc3\x61\x3e\x2e\xba\x52\xcb\xf1\x5c\xee\xac\x7f\xff\x29\xfb\x65\x3c\xef\xfe\x6d\x2a\xe3\xc1\x20\x7c\x95\xd3\xf6\x36\xa3\x37\xd1\x1b\xb0\x8e\x02\x44\xeb\x0a\x0c\xc5\x67\xf6\xe2\x7c\x9f\x25\x05\xe3\xcd\x60\xd1\x43\x71\x52\x22\x90\x75\x6c\x42\xf1\x9c\x89\xb2\x49\xe2\xc5\x66\xfd\x9c\x8b\xff\xb5\x85\xc7\xee\xe3\xdc\x79\x1c\x86\x31\x9d\xa7\xe5\xfd\xcf\x5b\x5c\x6f\xe7\xca\xca\xdb\x72\x94\xb5\x2c\x72\x43\xe8\xd8\x93\x61\xcf\xc8\xce\x3b\x0a\x64\x28\x52\xb1\x80\xc0\x96\x22\xd3\x85\x11\x5a\x40\x4f\xc8\x97\xda\x48\x85\xd8\x82\x2f\x84\xec\x99\x69\x60\x4b\xfd\x2d\xfa\x45\x4e\xdf\xc7\xdd\xb8\x3c\x4b\x41\xaf\x3e\x56\xbf\x03\x00\x00\xff\xff\xf1\x46\x63\xd8\x62\x02\x00\x00") + +func configStatusChainGenesisJsonBytes() ([]byte, error) { + return bindataRead( + _configStatusChainGenesisJson, + "config/status-chain-genesis.json", + ) +} + +func configStatusChainGenesisJson() (*asset, error) { + bytes, err := configStatusChainGenesisJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "config/status-chain-genesis.json", size: 610, mode: os.FileMode(420), modTime: time.Unix(1508185315, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -180,7 +201,7 @@ func configTestDataJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "config/test-data.json", size: 302, mode: os.FileMode(420), modTime: time.Unix(1507747350, 0)} + info := bindataFileInfo{name: "config/test-data.json", size: 302, mode: os.FileMode(420), modTime: time.Unix(1507638424, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -200,7 +221,7 @@ func keysFirebaseauthkey() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/firebaseauthkey", size: 153, mode: os.FileMode(420), modTime: time.Unix(1498222808, 0)} + info := bindataFileInfo{name: "keys/firebaseauthkey", size: 153, mode: os.FileMode(420), modTime: time.Unix(1506194117, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -220,7 +241,7 @@ func keysTestAccount1BeforeEip55Pk() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/test-account1-before-eip55.pk", size: 638, mode: os.FileMode(420), modTime: time.Unix(1507747350, 0)} + info := bindataFileInfo{name: "keys/test-account1-before-eip55.pk", size: 638, mode: os.FileMode(420), modTime: time.Unix(1507638424, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -240,7 +261,7 @@ func keysTestAccount1Pk() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/test-account1.pk", size: 638, mode: os.FileMode(420), modTime: time.Unix(1507747350, 0)} + info := bindataFileInfo{name: "keys/test-account1.pk", size: 638, mode: os.FileMode(420), modTime: time.Unix(1507638424, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -260,7 +281,7 @@ func keysTestAccount2Pk() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/test-account2.pk", size: 1074, mode: os.FileMode(420), modTime: time.Unix(1507747350, 0)} + info := bindataFileInfo{name: "keys/test-account2.pk", size: 1074, mode: os.FileMode(420), modTime: time.Unix(1507638424, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -280,7 +301,7 @@ func keysWnodekey() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/wnodekey", size: 65, mode: os.FileMode(420), modTime: time.Unix(1498222808, 0)} + info := bindataFileInfo{name: "keys/wnodekey", size: 65, mode: os.FileMode(420), modTime: time.Unix(1506194117, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -300,7 +321,7 @@ func keysWnodepassword() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/wnodepassword", size: 9, mode: os.FileMode(420), modTime: time.Unix(1498222808, 0)} + info := bindataFileInfo{name: "keys/wnodepassword", size: 9, mode: os.FileMode(420), modTime: time.Unix(1506194117, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -320,7 +341,7 @@ func testdataJailCommandsJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "testdata/jail/commands.js", size: 7677, mode: os.FileMode(420), modTime: time.Unix(1500264813, 0)} + info := bindataFileInfo{name: "testdata/jail/commands.js", size: 7677, mode: os.FileMode(420), modTime: time.Unix(1506194117, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -340,7 +361,7 @@ func testdataJailStatusJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "testdata/jail/status.js", size: 3402, mode: os.FileMode(420), modTime: time.Unix(1500264813, 0)} + info := bindataFileInfo{name: "testdata/jail/status.js", size: 3402, mode: os.FileMode(420), modTime: time.Unix(1506194117, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -360,7 +381,7 @@ func testdataJailTxSendContextNoMessageIdJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "testdata/jail/tx-send/context-no-message-id.js", size: 1793, mode: os.FileMode(420), modTime: time.Unix(1500821837, 0)} + info := bindataFileInfo{name: "testdata/jail/tx-send/context-no-message-id.js", size: 1793, mode: os.FileMode(420), modTime: time.Unix(1506194117, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -380,7 +401,7 @@ func testdataJailTxSendMessageIdNoContextJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "testdata/jail/tx-send/message-id-no-context.js", size: 1875, mode: os.FileMode(420), modTime: time.Unix(1500264813, 0)} + info := bindataFileInfo{name: "testdata/jail/tx-send/message-id-no-context.js", size: 1875, mode: os.FileMode(420), modTime: time.Unix(1506194117, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -400,7 +421,7 @@ func testdataJailTxSendNoMessageIdOrContextJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "testdata/jail/tx-send/no-message-id-or-context.js", size: 1354, mode: os.FileMode(420), modTime: time.Unix(1500264813, 0)} + info := bindataFileInfo{name: "testdata/jail/tx-send/no-message-id-or-context.js", size: 1354, mode: os.FileMode(420), modTime: time.Unix(1506194117, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -420,7 +441,7 @@ func testdataJailTxSendTxSendJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "testdata/jail/tx-send/tx-send.js", size: 3343, mode: os.FileMode(420), modTime: time.Unix(1507647025, 0)} + info := bindataFileInfo{name: "testdata/jail/tx-send/tx-send.js", size: 3343, mode: os.FileMode(420), modTime: time.Unix(1506194117, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -440,7 +461,7 @@ func testdataNodeTestSol() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "testdata/node/test.sol", size: 119, mode: os.FileMode(420), modTime: time.Unix(1500264813, 0)} + info := bindataFileInfo{name: "testdata/node/test.sol", size: 119, mode: os.FileMode(420), modTime: time.Unix(1506194117, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -501,6 +522,7 @@ var _bindata = map[string]func() (*asset, error){ "scripts/web3.js": scriptsWeb3Js, "config/cht.json": configChtJson, "config/linter_exclude_list.txt": configLinter_exclude_listTxt, + "config/status-chain-genesis.json": configStatusChainGenesisJson, "config/test-data.json": configTestDataJson, "keys/firebaseauthkey": keysFirebaseauthkey, "keys/test-account1-before-eip55.pk": keysTestAccount1BeforeEip55Pk, @@ -560,6 +582,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "config": &bintree{nil, map[string]*bintree{ "cht.json": &bintree{configChtJson, map[string]*bintree{}}, "linter_exclude_list.txt": &bintree{configLinter_exclude_listTxt, map[string]*bintree{}}, + "status-chain-genesis.json": &bintree{configStatusChainGenesisJson, map[string]*bintree{}}, "test-data.json": &bintree{configTestDataJson, map[string]*bintree{}}, }}, "keys": &bintree{nil, map[string]*bintree{ diff --git a/static/config/status-chain-genesis.json b/static/config/status-chain-genesis.json new file mode 100644 index 000000000..e620c8870 --- /dev/null +++ b/static/config/status-chain-genesis.json @@ -0,0 +1,22 @@ +{ + "alloc": { + "AdAf150b905Cf5E6A778E553E15A139B6618BbB7": { + "balance": "0x10F0CF064DD59200000" + }, + "65C01586aa0Ce152835c788aCe665e91Ab3527b8": { + "balance": "0x1B1AE4D6E2EF500000" + } + }, + "config": { + "chainId": 777, + "homesteadBlock": 0, + "daoForkSupport": true, + "byzantiumBlock": 0, + "eip150Hash": "0x28c4da1cca48d0107ea5ea29a40ac15fca86899c52d02309fa12ea39b86d219c", + "eip155Block": 0, + "eip158Block": 0 + }, + "difficulty": "0x100000", + "extraData": "0x537461747573436861696e20507269766174652054657374696e67204e6574776f726b", + "gasLimit": "0x1000000" +} diff --git a/testing/testing.go b/testing/testing.go index 2384c80b3..cd02a8141 100644 --- a/testing/testing.go +++ b/testing/testing.go @@ -23,9 +23,10 @@ var ( // TestNetworkNames network ID to name mapping TestNetworkNames = map[int]string{ - params.MainNetworkID: "Mainnet", - params.RopstenNetworkID: "Ropsten", - params.RinkebyNetworkID: "Rinkeby", + params.MainNetworkID: "Mainnet", + params.RopstenNetworkID: "Ropsten", + params.RinkebyNetworkID: "Rinkeby", + params.StatusChainNetworkID: "StatusChain", } )