From 2ce21cefdc0b8f9a4942a4a337b73b3ca131c2cd Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 17 Apr 2015 16:28:44 +0200 Subject: eth: use NewDB hook also for extra DB (cherry picked from commit d5083033f15bb815a6212eddae16a7125db58738) --- eth/backend.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/eth/backend.go b/eth/backend.go index 264753aba..5798e641a 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -171,7 +171,10 @@ func New(config *Config) (*Ethereum, error) { if err != nil { return nil, err } - extraDb, err := ethdb.NewLDBDatabase(path.Join(config.DataDir, "extra")) + extraDb, err := newdb(path.Join(config.DataDir, "extra")) + if err != nil { + return nil, err + } // Perform database sanity checks d, _ := blockDb.Get([]byte("ProtocolVersion")) -- cgit v1.2.3 From 235ed7ecb92527ce0029c2a6f5ace06707db9b28 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 17 Apr 2015 16:30:15 +0200 Subject: cmd/geth, tests: enable running multiple tests from a single file This commit also changes the block test loading so tests containing invalid RLP blocks can be loaded and return an error only when they are run. (cherry picked from commit 898ba87984791249586b97c9ce340dd087b79d67) --- cmd/geth/blocktest.go | 89 +++++++++++++++++++++++++++++++++++++-------------- tests/blocktest.go | 49 ++++++++++++++++++++++------ 2 files changed, 105 insertions(+), 33 deletions(-) diff --git a/cmd/geth/blocktest.go b/cmd/geth/blocktest.go index f0b6bb1a2..792981ec0 100644 --- a/cmd/geth/blocktest.go +++ b/cmd/geth/blocktest.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "os" "github.com/codegangsta/cli" "github.com/ethereum/go-ethereum/cmd/utils" @@ -12,7 +13,7 @@ import ( ) var blocktestCmd = cli.Command{ - Action: runblocktest, + Action: runBlockTest, Name: "blocktest", Usage: `loads a block test file`, Description: ` @@ -25,27 +26,78 @@ be able to interact with the chain defined by the test. `, } -func runblocktest(ctx *cli.Context) { - if len(ctx.Args()) != 3 { - utils.Fatalf("Usage: ethereum blocktest {rpc, norpc}") +func runBlockTest(ctx *cli.Context) { + var ( + file, testname string + rpc bool + ) + args := ctx.Args() + switch { + case len(args) == 1: + file = args[0] + case len(args) == 2: + file, testname = args[0], args[1] + case len(args) == 3: + file, testname = args[0], args[1] + rpc = true + default: + utils.Fatalf(`Usage: ethereum blocktest [ [ "rpc" ] ]`) } - file, testname, startrpc := ctx.Args()[0], ctx.Args()[1], ctx.Args()[2] - bt, err := tests.LoadBlockTests(file) if err != nil { utils.Fatalf("%v", err) } + + // run all tests if no test name is specified + if testname == "" { + ecode := 0 + for name, test := range bt { + fmt.Printf("----------------- Running Block Test %q\n", name) + ethereum, err := runOneBlockTest(ctx, test) + if err != nil { + fmt.Println(err) + fmt.Println("FAIL") + ecode = 1 + } + if ethereum != nil { + ethereum.Stop() + ethereum.WaitForShutdown() + } + } + os.Exit(ecode) + return + } + // otherwise, run the given test test, ok := bt[testname] if !ok { utils.Fatalf("Test file does not contain test named %q", testname) } + ethereum, err := runOneBlockTest(ctx, test) + if err != nil { + utils.Fatalf("%v", err) + } + defer ethereum.Stop() + if rpc { + fmt.Println("Block Test post state validated, starting RPC interface.") + startEth(ctx, ethereum) + utils.StartRPC(ethereum, ctx) + ethereum.WaitForShutdown() + } +} +func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, error) { cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx) cfg.NewDB = func(path string) (common.Database, error) { return ethdb.NewMemDatabase() } cfg.MaxPeers = 0 // disable network + cfg.Shh = false // disable whisper + cfg.NAT = nil // disable port mapping + ethereum, err := eth.New(cfg) if err != nil { - utils.Fatalf("%v", err) + return nil, err + } + if err := ethereum.Start(); err != nil { + return nil, err } // import the genesis block @@ -54,27 +106,16 @@ func runblocktest(ctx *cli.Context) { // import pre accounts statedb, err := test.InsertPreState(ethereum.StateDb()) if err != nil { - utils.Fatalf("could not insert genesis accounts: %v", err) + return ethereum, fmt.Errorf("InsertPreState: %v", err) } // insert the test blocks, which will execute all transactions - chain := ethereum.ChainManager() - if err := chain.InsertChain(test.Blocks); err != nil { - utils.Fatalf("Block Test load error: %v %T", err, err) - } else { - fmt.Println("Block Test chain loaded") + if err := test.InsertBlocks(ethereum.ChainManager()); err != nil { + return ethereum, fmt.Errorf("Block Test load error: %v %T", err, err) } - + fmt.Println("chain loaded") if err := test.ValidatePostState(statedb); err != nil { - utils.Fatalf("post state validation failed: %v", err) - } - fmt.Println("Block Test post state validated, starting ethereum.") - - if startrpc == "rpc" { - startEth(ctx, ethereum) - utils.StartRPC(ethereum, ctx) - ethereum.WaitForShutdown() - } else { - startEth(ctx, ethereum) + return ethereum, fmt.Errorf("post state validation failed: %v", err) } + return ethereum, nil } diff --git a/tests/blocktest.go b/tests/blocktest.go index 2d6b11944..37fd9e494 100644 --- a/tests/blocktest.go +++ b/tests/blocktest.go @@ -12,6 +12,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" @@ -73,8 +74,8 @@ type btBlock struct { type BlockTest struct { Genesis *types.Block - Blocks []*types.Block + json *btJSON preAccounts map[string]btAccount } @@ -88,7 +89,7 @@ func LoadBlockTests(file string) (map[string]*BlockTest, error) { for name, in := range bt { var err error if out[name], err = convertTest(in); err != nil { - return nil, fmt.Errorf("bad test %q: %v", err) + return out, fmt.Errorf("bad test %q: %v", name, err) } } return out, nil @@ -124,6 +125,15 @@ func (t *BlockTest) InsertPreState(db common.Database) (*state.StateDB, error) { return statedb, nil } +// InsertBlocks loads the test's blocks into the given chain. +func (t *BlockTest) InsertBlocks(chain *core.ChainManager) error { + blocks, err := t.convertBlocks() + if err != nil { + return err + } + return chain.InsertChain(blocks) +} + func (t *BlockTest) ValidatePostState(statedb *state.StateDB) error { for addrString, acct := range t.preAccounts { // XXX: is is worth it checking for errors here? @@ -149,6 +159,21 @@ func (t *BlockTest) ValidatePostState(statedb *state.StateDB) error { return nil } +func (t *BlockTest) convertBlocks() (blocks []*types.Block, err error) { + // the conversion handles errors by catching panics. + // you might consider this ugly, but the alternative (passing errors) + // would be much harder to read. + defer func() { + if recovered := recover(); recovered != nil { + buf := make([]byte, 64<<10) + buf = buf[:runtime.Stack(buf, false)] + err = fmt.Errorf("%v\n%s", recovered, buf) + } + }() + blocks = mustConvertBlocks(t.json.Blocks) + return blocks, nil +} + func convertTest(in *btJSON) (out *BlockTest, err error) { // the conversion handles errors by catching panics. // you might consider this ugly, but the alternative (passing errors) @@ -160,9 +185,8 @@ func convertTest(in *btJSON) (out *BlockTest, err error) { err = fmt.Errorf("%v\n%s", recovered, buf) } }() - out = &BlockTest{preAccounts: in.Pre} + out = &BlockTest{preAccounts: in.Pre, json: in} out.Genesis = mustConvertGenesis(in.GenesisBlockHeader) - out.Blocks = mustConvertBlocks(in.Blocks) return out, err } @@ -203,7 +227,7 @@ func mustConvertBlocks(testBlocks []btBlock) []*types.Block { var b types.Block r := bytes.NewReader(mustConvertBytes(inb.Rlp)) if err := rlp.Decode(r, &b); err != nil { - panic(fmt.Errorf("invalid block %d: %q", i, inb.Rlp)) + panic(fmt.Errorf("invalid block %d: %q\nerror: %v", i, inb.Rlp, err)) } out = append(out, &b) } @@ -293,11 +317,18 @@ func findLine(data []byte, offset int64) (line int) { } func unfuckCPPHexInts(s string) string { - if s == "0x" { // no respect for the empty value :( + switch { + case s == "0x": + // no respect for the empty value :( return "0x00" - } - if (len(s) % 2) != 0 { // motherfucking nibbles + case len(s) == 0: + return "0x00" + case len(s) == 1: + return "0x0" + s[:1] + case len(s)%2 != 0: + // motherfucking nibbles return "0x0" + s[2:] + default: + return s } - return s } -- cgit v1.2.3 From c453f1f37093445ba1d9eba5a075169ef0566c19 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 17 Apr 2015 18:20:32 +0200 Subject: tests: hopefully improve test conversion helpers (cherry picked from commit 035a30acbefb5eeadc1fc8dbd567775d5688f8a9) --- tests/blocktest.go | 55 +++++++++++++++++++++++------------------- tests/transaction_test_util.go | 10 ++++---- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/tests/blocktest.go b/tests/blocktest.go index 37fd9e494..d0a910336 100644 --- a/tests/blocktest.go +++ b/tests/blocktest.go @@ -211,13 +211,13 @@ func mustConvertHeader(in btHeader) *types.Header { UncleHash: mustConvertHash(in.UncleHash), ParentHash: mustConvertHash(in.ParentHash), Extra: mustConvertBytes(in.ExtraData), - GasUsed: mustConvertBigInt(in.GasUsed), - GasLimit: mustConvertBigInt(in.GasLimit), - Difficulty: mustConvertBigInt(in.Difficulty), - Time: mustConvertUint(in.Timestamp), + GasUsed: mustConvertBigInt(in.GasUsed, 10), + GasLimit: mustConvertBigInt(in.GasLimit, 10), + Difficulty: mustConvertBigInt(in.Difficulty, 10), + Time: mustConvertUint(in.Timestamp, 10), } // XXX cheats? :-) - header.SetNonce(common.BytesToHash(mustConvertBytes(in.Nonce)).Big().Uint64()) + header.SetNonce(mustConvertUint(in.Nonce, 16)) return header } @@ -238,7 +238,7 @@ func mustConvertBytes(in string) []byte { if in == "0x" { return []byte{} } - h := strings.TrimPrefix(unfuckCPPHexInts(in), "0x") + h := nibbleFix(strings.TrimPrefix(in, "0x")) out, err := hex.DecodeString(h) if err != nil { panic(fmt.Errorf("invalid hex: %q", h)) @@ -255,7 +255,7 @@ func mustConvertHash(in string) common.Hash { } func mustConvertAddress(in string) common.Address { - out, err := hex.DecodeString(strings.TrimPrefix(in, "0x")) + out, err := hex.DecodeString(nibbleFix(strings.TrimPrefix(in, "0x"))) if err != nil { panic(fmt.Errorf("invalid hex: %q", in)) } @@ -270,16 +270,18 @@ func mustConvertBloom(in string) types.Bloom { return types.BytesToBloom(out) } -func mustConvertBigInt(in string) *big.Int { - out, ok := new(big.Int).SetString(unfuckCPPHexInts(in), 0) +func mustConvertBigInt(in string, base int) *big.Int { + in = prepInt(base, in) + out, ok := new(big.Int).SetString(in, base) if !ok { panic(fmt.Errorf("invalid integer: %q", in)) } return out } -func mustConvertUint(in string) uint64 { - out, err := strconv.ParseUint(unfuckCPPHexInts(in), 0, 64) +func mustConvertUint(in string, base int) uint64 { + in = prepInt(base, in) + out, err := strconv.ParseUint(in, base, 64) if err != nil { panic(fmt.Errorf("invalid integer: %q", in)) } @@ -316,19 +318,22 @@ func findLine(data []byte, offset int64) (line int) { return } -func unfuckCPPHexInts(s string) string { - switch { - case s == "0x": - // no respect for the empty value :( - return "0x00" - case len(s) == 0: - return "0x00" - case len(s) == 1: - return "0x0" + s[:1] - case len(s)%2 != 0: - // motherfucking nibbles - return "0x0" + s[2:] - default: - return s +func prepInt(base int, s string) string { + if base == 16 { + if strings.HasPrefix(s, "0x") { + s = s[2:] + } + if len(s) == 0 { + s = "00" + } + s = nibbleFix(s) + } + return s +} + +func nibbleFix(s string) string { + if len(s)%2 != 0 { + s = "0" + s } + return s } diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index 567aba66f..d82946e20 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -127,15 +127,15 @@ func convertTestTypes(txTest TransactionTest) (sender, to common.Address, txInputData = mustConvertBytes(txTest.Transaction.Data) rlpBytes = mustConvertBytes(txTest.Rlp) - gasLimit = mustConvertBigInt(txTest.Transaction.GasLimit) - gasPrice = mustConvertBigInt(txTest.Transaction.GasPrice) - value = mustConvertBigInt(txTest.Transaction.Value) + gasLimit = mustConvertBigInt(txTest.Transaction.GasLimit, 16) + gasPrice = mustConvertBigInt(txTest.Transaction.GasPrice, 16) + value = mustConvertBigInt(txTest.Transaction.Value, 16) r = common.Bytes2Big(mustConvertBytes(txTest.Transaction.R)) s = common.Bytes2Big(mustConvertBytes(txTest.Transaction.S)) - nonce = mustConvertUint(txTest.Transaction.Nonce) - v = mustConvertUint(txTest.Transaction.V) + nonce = mustConvertUint(txTest.Transaction.Nonce, 16) + v = mustConvertUint(txTest.Transaction.V, 16) return sender, to, txInputData, rlpBytes, gasLimit, gasPrice, value, r, s, nonce, v, nil } -- cgit v1.2.3 From 805345d13594b41e5dd2e4fed471c58c3775be9e Mon Sep 17 00:00:00 2001 From: Gustav Simonsson Date: Sun, 19 Apr 2015 00:35:48 +0200 Subject: Add block tests wrapper and fixes for tx tests * Add fixes to parsing and converting of fields in tx tests * Correct logic in tx tests; validation of fields and correct logic for when RLP decoding works/fails and when this is expected or not * Rename files for consistency * Add block tests wrapper to run block tests with go test --- cmd/geth/block_go_test.go | 80 ++++++++++ tests/block_test_util.go | 345 +++++++++++++++++++++++++++++++++++++++++ tests/blocktest.go | 339 ---------------------------------------- tests/transaction_test_util.go | 143 +++++++++-------- 4 files changed, 506 insertions(+), 401 deletions(-) create mode 100644 cmd/geth/block_go_test.go create mode 100644 tests/block_test_util.go delete mode 100644 tests/blocktest.go diff --git a/cmd/geth/block_go_test.go b/cmd/geth/block_go_test.go new file mode 100644 index 000000000..1980e4798 --- /dev/null +++ b/cmd/geth/block_go_test.go @@ -0,0 +1,80 @@ +package main + +import ( + "path" + "testing" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/tests" +) + +// TODO: refactor test setup & execution to better align with vm and tx tests +// TODO: refactor to avoid duplication with cmd/geth/blocktest.go +func TestBcValidBlockTests(t *testing.T) { + runBlockTestsInFile("../../tests/files/BlockTests/bcValidBlockTest.json", t) +} + +/* +func TestBcUncleTests(t *testing.T) { + runBlockTestsInFile("../../tests/files/BlockTests/bcUncleTest.json", t) +} +*/ + +func runBlockTestsInFile(filepath string, t *testing.T) { + bt, err := tests.LoadBlockTests(filepath) + if err != nil { + t.Fatal(err) + } + for name, test := range bt { + runTest(name, test, t) + } +} + +func runTest(name string, test *tests.BlockTest, t *testing.T) { + t.Log("Running test: ", name) + cfg := testEthConfig() + ethereum, err := eth.New(cfg) + if err != nil { + t.Fatalf("%v", err) + } + + err = ethereum.Start() + if err != nil { + t.Fatalf("%v", err) + } + + // import the genesis block + ethereum.ResetWithGenesisBlock(test.Genesis) + + // import pre accounts + statedb, err := test.InsertPreState(ethereum.StateDb()) + if err != nil { + t.Fatalf("InsertPreState: %v", err) + } + + // insert the test blocks, which will execute all transactions + if err := test.InsertBlocks(ethereum.ChainManager()); err != nil { + t.Fatalf("Block Test load error: %v %T", err, err) + } + + if err := test.ValidatePostState(statedb); err != nil { + t.Fatal("post state validation failed: %v", err) + } + t.Log("Test passed: ", name) +} + +func testEthConfig() *eth.Config { + ks := crypto.NewKeyStorePassphrase(path.Join(common.DefaultDataDir(), "keys")) + + return ð.Config{ + DataDir: common.DefaultDataDir(), + LogLevel: 5, + Etherbase: "primary", + AccountManager: accounts.NewManager(ks), + NewDB: func(path string) (common.Database, error) { return ethdb.NewMemDatabase() }, + } +} diff --git a/tests/block_test_util.go b/tests/block_test_util.go new file mode 100644 index 000000000..5c42ae18c --- /dev/null +++ b/tests/block_test_util.go @@ -0,0 +1,345 @@ +package tests + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "io/ioutil" + "math/big" + "runtime" + "strconv" + "strings" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" +) + +// Block Test JSON Format +type btJSON struct { + Blocks []btBlock + GenesisBlockHeader btHeader + Pre map[string]btAccount + PostState map[string]btAccount +} + +type btAccount struct { + Balance string + Code string + Nonce string + Storage map[string]string +} + +type btHeader struct { + Bloom string + Coinbase string + MixHash string + Nonce string + Number string + ParentHash string + ReceiptTrie string + SeedHash string + StateRoot string + TransactionsTrie string + UncleHash string + + ExtraData string + Difficulty string + GasLimit string + GasUsed string + Timestamp string +} + +type btTransaction struct { + Data string + GasLimit string + GasPrice string + Nonce string + R string + S string + To string + V string + Value string +} + +type btBlock struct { + BlockHeader *btHeader + Rlp string + Transactions []btTransaction + UncleHeaders []*btHeader +} + +type BlockTest struct { + Genesis *types.Block + + json *btJSON + preAccounts map[string]btAccount +} + +// LoadBlockTests loads a block test JSON file. +func LoadBlockTests(file string) (map[string]*BlockTest, error) { + bt := make(map[string]*btJSON) + if err := LoadJSON(file, &bt); err != nil { + return nil, err + } + out := make(map[string]*BlockTest) + for name, in := range bt { + var err error + if out[name], err = convertTest(in); err != nil { + return out, fmt.Errorf("bad test %q: %v", name, err) + } + } + return out, nil +} + +// InsertPreState populates the given database with the genesis +// accounts defined by the test. +func (t *BlockTest) InsertPreState(db common.Database) (*state.StateDB, error) { + statedb := state.New(common.Hash{}, db) + for addrString, acct := range t.preAccounts { + // XXX: is is worth it checking for errors here? + //addr, _ := hex.DecodeString(addrString) + code, _ := hex.DecodeString(strings.TrimPrefix(acct.Code, "0x")) + balance, _ := new(big.Int).SetString(acct.Balance, 0) + nonce, _ := strconv.ParseUint(acct.Nonce, 16, 64) + + obj := statedb.CreateAccount(common.HexToAddress(addrString)) + obj.SetCode(code) + obj.SetBalance(balance) + obj.SetNonce(nonce) + for k, v := range acct.Storage { + statedb.SetState(common.HexToAddress(addrString), common.HexToHash(k), common.FromHex(v)) + } + } + // sync objects to trie + statedb.Update() + // sync trie to disk + statedb.Sync() + + if !bytes.Equal(t.Genesis.Root().Bytes(), statedb.Root().Bytes()) { + return nil, fmt.Errorf("computed state root does not match genesis block %x %x", t.Genesis.Root().Bytes()[:4], statedb.Root().Bytes()[:4]) + } + return statedb, nil +} + +// InsertBlocks loads the test's blocks into the given chain. +func (t *BlockTest) InsertBlocks(chain *core.ChainManager) error { + blocks, err := t.convertBlocks() + if err != nil { + return err + } + return chain.InsertChain(blocks) +} + +func (t *BlockTest) ValidatePostState(statedb *state.StateDB) error { + for addrString, acct := range t.preAccounts { + // XXX: is is worth it checking for errors here? + addr, _ := hex.DecodeString(addrString) + code, _ := hex.DecodeString(strings.TrimPrefix(acct.Code, "0x")) + balance, _ := new(big.Int).SetString(acct.Balance, 0) + nonce, _ := strconv.ParseUint(acct.Nonce, 16, 64) + + // address is indirectly verified by the other fields, as it's the db key + code2 := statedb.GetCode(common.BytesToAddress(addr)) + balance2 := statedb.GetBalance(common.BytesToAddress(addr)) + nonce2 := statedb.GetNonce(common.BytesToAddress(addr)) + if !bytes.Equal(code2, code) { + return fmt.Errorf("account code mismatch, addr, found, expected: ", addrString, hex.EncodeToString(code2), hex.EncodeToString(code)) + } + if balance2.Cmp(balance) != 0 { + return fmt.Errorf("account balance mismatch, addr, found, expected: ", addrString, balance2, balance) + } + if nonce2 != nonce { + return fmt.Errorf("account nonce mismatch, addr, found, expected: ", addrString, nonce2, nonce) + } + } + return nil +} + +func (t *BlockTest) convertBlocks() (blocks []*types.Block, err error) { + // the conversion handles errors by catching panics. + // you might consider this ugly, but the alternative (passing errors) + // would be much harder to read. + defer func() { + if recovered := recover(); recovered != nil { + buf := make([]byte, 64<<10) + buf = buf[:runtime.Stack(buf, false)] + err = fmt.Errorf("%v\n%s", recovered, buf) + } + }() + blocks = mustConvertBlocks(t.json.Blocks) + return blocks, nil +} + +func convertTest(in *btJSON) (out *BlockTest, err error) { + // the conversion handles errors by catching panics. + // you might consider this ugly, but the alternative (passing errors) + // would be much harder to read. + defer func() { + if recovered := recover(); recovered != nil { + buf := make([]byte, 64<<10) + buf = buf[:runtime.Stack(buf, false)] + err = fmt.Errorf("%v\n%s", recovered, buf) + } + }() + out = &BlockTest{preAccounts: in.Pre, json: in} + out.Genesis = mustConvertGenesis(in.GenesisBlockHeader) + return out, err +} + +func mustConvertGenesis(testGenesis btHeader) *types.Block { + hdr := mustConvertHeader(testGenesis) + hdr.Number = big.NewInt(0) + b := types.NewBlockWithHeader(hdr) + b.Td = new(big.Int) + return b +} + +func mustConvertHeader(in btHeader) *types.Header { + // hex decode these fields + header := &types.Header{ + //SeedHash: mustConvertBytes(in.SeedHash), + MixDigest: mustConvertHash(in.MixHash), + Bloom: mustConvertBloom(in.Bloom), + ReceiptHash: mustConvertHash(in.ReceiptTrie), + TxHash: mustConvertHash(in.TransactionsTrie), + Root: mustConvertHash(in.StateRoot), + Coinbase: mustConvertAddress(in.Coinbase), + UncleHash: mustConvertHash(in.UncleHash), + ParentHash: mustConvertHash(in.ParentHash), + Extra: mustConvertBytes(in.ExtraData), + GasUsed: mustConvertBigInt(in.GasUsed, 10), + GasLimit: mustConvertBigInt(in.GasLimit, 10), + Difficulty: mustConvertBigInt(in.Difficulty, 10), + Time: mustConvertUint(in.Timestamp, 10), + } + // XXX cheats? :-) + header.SetNonce(mustConvertUint(in.Nonce, 16)) + return header +} + +func mustConvertBlocks(testBlocks []btBlock) []*types.Block { + var out []*types.Block + for i, inb := range testBlocks { + var b types.Block + r := bytes.NewReader(mustConvertBytes(inb.Rlp)) + if err := rlp.Decode(r, &b); err != nil { + panic(fmt.Errorf("invalid block %d: %q\nerror: %v", i, inb.Rlp, err)) + } + out = append(out, &b) + } + return out +} + +func mustConvertBytes(in string) []byte { + if in == "0x" { + return []byte{} + } + h := unfuckFuckedHex(strings.TrimPrefix(in, "0x")) + out, err := hex.DecodeString(h) + if err != nil { + panic(fmt.Errorf("invalid hex: %q: ", h, err)) + } + return out +} + +func mustConvertHash(in string) common.Hash { + out, err := hex.DecodeString(strings.TrimPrefix(in, "0x")) + if err != nil { + panic(fmt.Errorf("invalid hex: %q", in)) + } + return common.BytesToHash(out) +} + +func mustConvertAddress(in string) common.Address { + out, err := hex.DecodeString(strings.TrimPrefix(in, "0x")) + if err != nil { + panic(fmt.Errorf("invalid hex: %q", in)) + } + return common.BytesToAddress(out) +} + +func mustConvertBloom(in string) types.Bloom { + out, err := hex.DecodeString(strings.TrimPrefix(in, "0x")) + if err != nil { + panic(fmt.Errorf("invalid hex: %q", in)) + } + return types.BytesToBloom(out) +} + +func mustConvertBigInt(in string, base int) *big.Int { + in = prepInt(base, in) + out, ok := new(big.Int).SetString(in, base) + if !ok { + panic(fmt.Errorf("invalid integer: %q", in)) + } + return out +} + +func mustConvertUint(in string, base int) uint64 { + in = prepInt(base, in) + out, err := strconv.ParseUint(in, base, 64) + if err != nil { + panic(fmt.Errorf("invalid integer: %q", in)) + } + return out +} + +// LoadJSON reads the given file and unmarshals its content. +func LoadJSON(file string, val interface{}) error { + content, err := ioutil.ReadFile(file) + if err != nil { + return err + } + if err := json.Unmarshal(content, val); err != nil { + if syntaxerr, ok := err.(*json.SyntaxError); ok { + line := findLine(content, syntaxerr.Offset) + return fmt.Errorf("JSON syntax error at %v:%v: %v", file, line, err) + } + return fmt.Errorf("JSON unmarshal error in %v: %v", file, err) + } + return nil +} + +// findLine returns the line number for the given offset into data. +func findLine(data []byte, offset int64) (line int) { + line = 1 + for i, r := range string(data) { + if int64(i) >= offset { + return + } + if r == '\n' { + line++ + } + } + return +} + +// Nothing to see here, please move along... +func prepInt(base int, s string) string { + if base == 16 { + if strings.HasPrefix(s, "0x") { + s = s[2:] + } + if len(s) == 0 { + s = "00" + } + s = nibbleFix(s) + } + return s +} + +// don't ask +func unfuckFuckedHex(almostHex string) string { + return nibbleFix(strings.Replace(almostHex, "v", "", -1)) +} + +func nibbleFix(s string) string { + if len(s)%2 != 0 { + s = "0" + s + } + return s +} diff --git a/tests/blocktest.go b/tests/blocktest.go deleted file mode 100644 index d0a910336..000000000 --- a/tests/blocktest.go +++ /dev/null @@ -1,339 +0,0 @@ -package tests - -import ( - "bytes" - "encoding/hex" - "encoding/json" - "fmt" - "io/ioutil" - "math/big" - "runtime" - "strconv" - "strings" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" -) - -// Block Test JSON Format -type btJSON struct { - Blocks []btBlock - GenesisBlockHeader btHeader - Pre map[string]btAccount - PostState map[string]btAccount -} - -type btAccount struct { - Balance string - Code string - Nonce string - Storage map[string]string -} - -type btHeader struct { - Bloom string - Coinbase string - MixHash string - Nonce string - Number string - ParentHash string - ReceiptTrie string - SeedHash string - StateRoot string - TransactionsTrie string - UncleHash string - - ExtraData string - Difficulty string - GasLimit string - GasUsed string - Timestamp string -} - -type btTransaction struct { - Data string - GasLimit string - GasPrice string - Nonce string - R string - S string - To string - V string - Value string -} - -type btBlock struct { - BlockHeader *btHeader - Rlp string - Transactions []btTransaction - UncleHeaders []*btHeader -} - -type BlockTest struct { - Genesis *types.Block - - json *btJSON - preAccounts map[string]btAccount -} - -// LoadBlockTests loads a block test JSON file. -func LoadBlockTests(file string) (map[string]*BlockTest, error) { - bt := make(map[string]*btJSON) - if err := LoadJSON(file, &bt); err != nil { - return nil, err - } - out := make(map[string]*BlockTest) - for name, in := range bt { - var err error - if out[name], err = convertTest(in); err != nil { - return out, fmt.Errorf("bad test %q: %v", name, err) - } - } - return out, nil -} - -// InsertPreState populates the given database with the genesis -// accounts defined by the test. -func (t *BlockTest) InsertPreState(db common.Database) (*state.StateDB, error) { - statedb := state.New(common.Hash{}, db) - for addrString, acct := range t.preAccounts { - // XXX: is is worth it checking for errors here? - //addr, _ := hex.DecodeString(addrString) - code, _ := hex.DecodeString(strings.TrimPrefix(acct.Code, "0x")) - balance, _ := new(big.Int).SetString(acct.Balance, 0) - nonce, _ := strconv.ParseUint(acct.Nonce, 16, 64) - - obj := statedb.CreateAccount(common.HexToAddress(addrString)) - obj.SetCode(code) - obj.SetBalance(balance) - obj.SetNonce(nonce) - for k, v := range acct.Storage { - statedb.SetState(common.HexToAddress(addrString), common.HexToHash(k), common.FromHex(v)) - } - } - // sync objects to trie - statedb.Update() - // sync trie to disk - statedb.Sync() - - if !bytes.Equal(t.Genesis.Root().Bytes(), statedb.Root().Bytes()) { - return nil, fmt.Errorf("computed state root does not match genesis block %x %x", t.Genesis.Root().Bytes()[:4], statedb.Root().Bytes()[:4]) - } - return statedb, nil -} - -// InsertBlocks loads the test's blocks into the given chain. -func (t *BlockTest) InsertBlocks(chain *core.ChainManager) error { - blocks, err := t.convertBlocks() - if err != nil { - return err - } - return chain.InsertChain(blocks) -} - -func (t *BlockTest) ValidatePostState(statedb *state.StateDB) error { - for addrString, acct := range t.preAccounts { - // XXX: is is worth it checking for errors here? - addr, _ := hex.DecodeString(addrString) - code, _ := hex.DecodeString(strings.TrimPrefix(acct.Code, "0x")) - balance, _ := new(big.Int).SetString(acct.Balance, 0) - nonce, _ := strconv.ParseUint(acct.Nonce, 16, 64) - - // address is indirectly verified by the other fields, as it's the db key - code2 := statedb.GetCode(common.BytesToAddress(addr)) - balance2 := statedb.GetBalance(common.BytesToAddress(addr)) - nonce2 := statedb.GetNonce(common.BytesToAddress(addr)) - if !bytes.Equal(code2, code) { - return fmt.Errorf("account code mismatch, addr, found, expected: ", addrString, hex.EncodeToString(code2), hex.EncodeToString(code)) - } - if balance2.Cmp(balance) != 0 { - return fmt.Errorf("account balance mismatch, addr, found, expected: ", addrString, balance2, balance) - } - if nonce2 != nonce { - return fmt.Errorf("account nonce mismatch, addr, found, expected: ", addrString, nonce2, nonce) - } - } - return nil -} - -func (t *BlockTest) convertBlocks() (blocks []*types.Block, err error) { - // the conversion handles errors by catching panics. - // you might consider this ugly, but the alternative (passing errors) - // would be much harder to read. - defer func() { - if recovered := recover(); recovered != nil { - buf := make([]byte, 64<<10) - buf = buf[:runtime.Stack(buf, false)] - err = fmt.Errorf("%v\n%s", recovered, buf) - } - }() - blocks = mustConvertBlocks(t.json.Blocks) - return blocks, nil -} - -func convertTest(in *btJSON) (out *BlockTest, err error) { - // the conversion handles errors by catching panics. - // you might consider this ugly, but the alternative (passing errors) - // would be much harder to read. - defer func() { - if recovered := recover(); recovered != nil { - buf := make([]byte, 64<<10) - buf = buf[:runtime.Stack(buf, false)] - err = fmt.Errorf("%v\n%s", recovered, buf) - } - }() - out = &BlockTest{preAccounts: in.Pre, json: in} - out.Genesis = mustConvertGenesis(in.GenesisBlockHeader) - return out, err -} - -func mustConvertGenesis(testGenesis btHeader) *types.Block { - hdr := mustConvertHeader(testGenesis) - hdr.Number = big.NewInt(0) - b := types.NewBlockWithHeader(hdr) - b.Td = new(big.Int) - return b -} - -func mustConvertHeader(in btHeader) *types.Header { - // hex decode these fields - header := &types.Header{ - //SeedHash: mustConvertBytes(in.SeedHash), - MixDigest: mustConvertHash(in.MixHash), - Bloom: mustConvertBloom(in.Bloom), - ReceiptHash: mustConvertHash(in.ReceiptTrie), - TxHash: mustConvertHash(in.TransactionsTrie), - Root: mustConvertHash(in.StateRoot), - Coinbase: mustConvertAddress(in.Coinbase), - UncleHash: mustConvertHash(in.UncleHash), - ParentHash: mustConvertHash(in.ParentHash), - Extra: mustConvertBytes(in.ExtraData), - GasUsed: mustConvertBigInt(in.GasUsed, 10), - GasLimit: mustConvertBigInt(in.GasLimit, 10), - Difficulty: mustConvertBigInt(in.Difficulty, 10), - Time: mustConvertUint(in.Timestamp, 10), - } - // XXX cheats? :-) - header.SetNonce(mustConvertUint(in.Nonce, 16)) - return header -} - -func mustConvertBlocks(testBlocks []btBlock) []*types.Block { - var out []*types.Block - for i, inb := range testBlocks { - var b types.Block - r := bytes.NewReader(mustConvertBytes(inb.Rlp)) - if err := rlp.Decode(r, &b); err != nil { - panic(fmt.Errorf("invalid block %d: %q\nerror: %v", i, inb.Rlp, err)) - } - out = append(out, &b) - } - return out -} - -func mustConvertBytes(in string) []byte { - if in == "0x" { - return []byte{} - } - h := nibbleFix(strings.TrimPrefix(in, "0x")) - out, err := hex.DecodeString(h) - if err != nil { - panic(fmt.Errorf("invalid hex: %q", h)) - } - return out -} - -func mustConvertHash(in string) common.Hash { - out, err := hex.DecodeString(strings.TrimPrefix(in, "0x")) - if err != nil { - panic(fmt.Errorf("invalid hex: %q", in)) - } - return common.BytesToHash(out) -} - -func mustConvertAddress(in string) common.Address { - out, err := hex.DecodeString(nibbleFix(strings.TrimPrefix(in, "0x"))) - if err != nil { - panic(fmt.Errorf("invalid hex: %q", in)) - } - return common.BytesToAddress(out) -} - -func mustConvertBloom(in string) types.Bloom { - out, err := hex.DecodeString(strings.TrimPrefix(in, "0x")) - if err != nil { - panic(fmt.Errorf("invalid hex: %q", in)) - } - return types.BytesToBloom(out) -} - -func mustConvertBigInt(in string, base int) *big.Int { - in = prepInt(base, in) - out, ok := new(big.Int).SetString(in, base) - if !ok { - panic(fmt.Errorf("invalid integer: %q", in)) - } - return out -} - -func mustConvertUint(in string, base int) uint64 { - in = prepInt(base, in) - out, err := strconv.ParseUint(in, base, 64) - if err != nil { - panic(fmt.Errorf("invalid integer: %q", in)) - } - return out -} - -// LoadJSON reads the given file and unmarshals its content. -func LoadJSON(file string, val interface{}) error { - content, err := ioutil.ReadFile(file) - if err != nil { - return err - } - if err := json.Unmarshal(content, val); err != nil { - if syntaxerr, ok := err.(*json.SyntaxError); ok { - line := findLine(content, syntaxerr.Offset) - return fmt.Errorf("JSON syntax error at %v:%v: %v", file, line, err) - } - return fmt.Errorf("JSON unmarshal error in %v: %v", file, err) - } - return nil -} - -// findLine returns the line number for the given offset into data. -func findLine(data []byte, offset int64) (line int) { - line = 1 - for i, r := range string(data) { - if int64(i) >= offset { - return - } - if r == '\n' { - line++ - } - } - return -} - -func prepInt(base int, s string) string { - if base == 16 { - if strings.HasPrefix(s, "0x") { - s = s[2:] - } - if len(s) == 0 { - s = "00" - } - s = nibbleFix(s) - } - return s -} - -func nibbleFix(s string) string { - if len(s)%2 != 0 { - s = "0" + s - } - return s -} diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index d82946e20..23ec375e3 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -2,8 +2,8 @@ package tests import ( "bytes" + "errors" "fmt" - "math/big" "runtime" "github.com/ethereum/go-ethereum/common" @@ -49,93 +49,112 @@ func RunTransactionTests(file string, notWorking map[string]bool) error { } func runTest(txTest TransactionTest) (err error) { - expectedSender, expectedTo, expectedData, rlpBytes, expectedGasLimit, expectedGasPrice, expectedValue, expectedR, expectedS, expectedNonce, expectedV, err := convertTestTypes(txTest) + tx := new(types.Transaction) + err = rlp.DecodeBytes(mustConvertBytes(txTest.Rlp), tx) if err != nil { - if txTest.Sender == "" { // tx is invalid and this is expected (test OK) + if txTest.Sender == "" { + // RLP decoding failed and this is expected (test OK) return nil } else { - return err // tx is invalid and this is NOT expected (test FAIL) + // RLP decoding failed but is expected to succeed (test FAIL) + return errors.New("RLP decoding failed when expected to succeed") } } - tx := new(types.Transaction) - rlp.DecodeBytes(rlpBytes, tx) - //fmt.Println("HURR tx: %v", tx) - sender, err := tx.From() + + validationError := verifyTxFields(txTest, tx) + if txTest.Sender == "" { + if validationError != nil { + // RLP decoding works but validation should fail (test OK) + return nil + } else { + // RLP decoding works but validation should fail (test FAIL) + // (this should not be possible but added here for completeness) + return errors.New("Field validations succeeded but should fail") + } + } + + if txTest.Sender != "" { + if validationError == nil { + // RLP decoding works and validations pass (test OK) + return nil + } else { + // RLP decoding works and validations pass (test FAIL) + return errors.New("Field validations failed after RLP decoding") + } + } + return errors.New("Should not happen: verify RLP decoding and field validation") +} + +func verifyTxFields(txTest TransactionTest, decodedTx *types.Transaction) (err error) { + defer func() { + if recovered := recover(); recovered != nil { + buf := make([]byte, 64<<10) + buf = buf[:runtime.Stack(buf, false)] + err = fmt.Errorf("%v\n%s", recovered, buf) + } + }() + + decodedSender, err := decodedTx.From() if err != nil { return err } - if expectedSender != sender { - return fmt.Errorf("Sender mismatch: %v %v", expectedSender, sender) + expectedSender := mustConvertAddress(txTest.Sender) + if expectedSender != decodedSender { + return fmt.Errorf("Sender mismatch: %v %v", expectedSender, decodedSender) } - if !bytes.Equal(expectedData, tx.Payload) { - return fmt.Errorf("Tx input data mismatch: %#v %#v", expectedData, tx.Payload) + + expectedData := mustConvertBytes(txTest.Transaction.Data) + if !bytes.Equal(expectedData, decodedTx.Payload) { + return fmt.Errorf("Tx input data mismatch: %#v %#v", expectedData, decodedTx.Payload) } - if expectedGasLimit.Cmp(tx.GasLimit) != 0 { - return fmt.Errorf("GasLimit mismatch: %v %v", expectedGasLimit, tx.GasLimit) + + expectedGasLimit := mustConvertBigInt(txTest.Transaction.GasLimit, 16) + if expectedGasLimit.Cmp(decodedTx.GasLimit) != 0 { + return fmt.Errorf("GasLimit mismatch: %v %v", expectedGasLimit, decodedTx.GasLimit) } - if expectedGasPrice.Cmp(tx.Price) != 0 { - return fmt.Errorf("GasPrice mismatch: %v %v", expectedGasPrice, tx.Price) + + expectedGasPrice := mustConvertBigInt(txTest.Transaction.GasPrice, 16) + if expectedGasPrice.Cmp(decodedTx.Price) != 0 { + return fmt.Errorf("GasPrice mismatch: %v %v", expectedGasPrice, decodedTx.Price) } - if expectedNonce != tx.AccountNonce { - return fmt.Errorf("Nonce mismatch: %v %v", expectedNonce, tx.AccountNonce) + + expectedNonce := mustConvertUint(txTest.Transaction.Nonce, 16) + if expectedNonce != decodedTx.AccountNonce { + return fmt.Errorf("Nonce mismatch: %v %v", expectedNonce, decodedTx.AccountNonce) } - if expectedR.Cmp(tx.R) != 0 { - return fmt.Errorf("R mismatch: %v %v", expectedR, tx.R) + + expectedR := common.Bytes2Big(mustConvertBytes(txTest.Transaction.R)) + if expectedR.Cmp(decodedTx.R) != 0 { + return fmt.Errorf("R mismatch: %v %v", expectedR, decodedTx.R) } - if expectedS.Cmp(tx.S) != 0 { - return fmt.Errorf("S mismatch: %v %v", expectedS, tx.S) + + expectedS := common.Bytes2Big(mustConvertBytes(txTest.Transaction.S)) + if expectedS.Cmp(decodedTx.S) != 0 { + return fmt.Errorf("S mismatch: %v %v", expectedS, decodedTx.S) } - if expectedV != uint64(tx.V) { - return fmt.Errorf("V mismatch: %v %v", expectedV, uint64(tx.V)) + + expectedV := mustConvertUint(txTest.Transaction.V, 16) + if expectedV != uint64(decodedTx.V) { + return fmt.Errorf("V mismatch: %v %v", expectedV, uint64(decodedTx.V)) } - if tx.Recipient == nil { + + expectedTo := mustConvertAddress(txTest.Transaction.To) + if decodedTx.Recipient == nil { if expectedTo != common.BytesToAddress([]byte{}) { // "empty" or "zero" address return fmt.Errorf("To mismatch when recipient is nil (contract creation): %v", expectedTo) } } else { - if expectedTo != *tx.Recipient { - return fmt.Errorf("To mismatch: %v %v", expectedTo, *tx.Recipient) + if expectedTo != *decodedTx.Recipient { + return fmt.Errorf("To mismatch: %v %v", expectedTo, *decodedTx.Recipient) } } - if expectedValue.Cmp(tx.Amount) != 0 { - return fmt.Errorf("Value mismatch: %v %v", expectedValue, tx.Amount) + expectedValue := mustConvertBigInt(txTest.Transaction.Value, 16) + if expectedValue.Cmp(decodedTx.Amount) != 0 { + return fmt.Errorf("Value mismatch: %v %v", expectedValue, decodedTx.Amount) } return nil } - -func convertTestTypes(txTest TransactionTest) (sender, to common.Address, - txInputData, rlpBytes []byte, - gasLimit, gasPrice, value, r, s *big.Int, - nonce, v uint64, - err error) { - - defer func() { - if recovered := recover(); recovered != nil { - buf := make([]byte, 64<<10) - buf = buf[:runtime.Stack(buf, false)] - err = fmt.Errorf("%v\n%s", recovered, buf) - } - }() - - sender = mustConvertAddress(txTest.Sender) - to = mustConvertAddress(txTest.Transaction.To) - - txInputData = mustConvertBytes(txTest.Transaction.Data) - rlpBytes = mustConvertBytes(txTest.Rlp) - - gasLimit = mustConvertBigInt(txTest.Transaction.GasLimit, 16) - gasPrice = mustConvertBigInt(txTest.Transaction.GasPrice, 16) - value = mustConvertBigInt(txTest.Transaction.Value, 16) - - r = common.Bytes2Big(mustConvertBytes(txTest.Transaction.R)) - s = common.Bytes2Big(mustConvertBytes(txTest.Transaction.S)) - - nonce = mustConvertUint(txTest.Transaction.Nonce, 16) - v = mustConvertUint(txTest.Transaction.V, 16) - - return sender, to, txInputData, rlpBytes, gasLimit, gasPrice, value, r, s, nonce, v, nil -} -- cgit v1.2.3 From 59a7405a8072b735472de885c33c2a82fcf7a162 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 20 Apr 2015 14:47:12 -0600 Subject: Broken link for detailed go build instructions #661 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 75547e09b..f79ae3d29 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ godep go build -v ./cmd/geth Instead of `build`, you can use `install` which will also install the resulting binary. -For prerequisites and detailed build instructions please see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)) +For prerequisites and detailed build instructions please see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum) If you intend to develop on go-ethereum, check the [Developers' Guide](https://github.com/ethereum/go-ethereum/wiki/Developers'-Guide) -- cgit v1.2.3 From 3ef1cd43f6f582bb23863292eb1d0c2de88a7a29 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 20 Apr 2015 22:08:50 -0600 Subject: fix for: Please remove the "minGasPrice" from block returns #754 --- rpc/responses.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/rpc/responses.go b/rpc/responses.go index 5d1be8f34..884b7e69b 100644 --- a/rpc/responses.go +++ b/rpc/responses.go @@ -24,7 +24,6 @@ type BlockRes struct { Size *hexnum `json:"size"` ExtraData *hexdata `json:"extraData"` GasLimit *hexnum `json:"gasLimit"` - MinGasPrice *hexnum `json:"minGasPrice"` GasUsed *hexnum `json:"gasUsed"` UnixTimestamp *hexnum `json:"timestamp"` Transactions []*TransactionRes `json:"transactions"` @@ -48,7 +47,6 @@ func (b *BlockRes) MarshalJSON() ([]byte, error) { Size *hexnum `json:"size"` ExtraData *hexdata `json:"extraData"` GasLimit *hexnum `json:"gasLimit"` - MinGasPrice *hexnum `json:"minGasPrice"` GasUsed *hexnum `json:"gasUsed"` UnixTimestamp *hexnum `json:"timestamp"` Transactions []*TransactionRes `json:"transactions"` @@ -69,7 +67,6 @@ func (b *BlockRes) MarshalJSON() ([]byte, error) { ext.Size = b.Size ext.ExtraData = b.ExtraData ext.GasLimit = b.GasLimit - ext.MinGasPrice = b.MinGasPrice ext.GasUsed = b.GasUsed ext.UnixTimestamp = b.UnixTimestamp ext.Transactions = b.Transactions @@ -94,7 +91,6 @@ func (b *BlockRes) MarshalJSON() ([]byte, error) { Size *hexnum `json:"size"` ExtraData *hexdata `json:"extraData"` GasLimit *hexnum `json:"gasLimit"` - MinGasPrice *hexnum `json:"minGasPrice"` GasUsed *hexnum `json:"gasUsed"` UnixTimestamp *hexnum `json:"timestamp"` Transactions []*hexdata `json:"transactions"` @@ -115,7 +111,6 @@ func (b *BlockRes) MarshalJSON() ([]byte, error) { ext.Size = b.Size ext.ExtraData = b.ExtraData ext.GasLimit = b.GasLimit - ext.MinGasPrice = b.MinGasPrice ext.GasUsed = b.GasUsed ext.UnixTimestamp = b.UnixTimestamp ext.Transactions = make([]*hexdata, len(b.Transactions)) @@ -151,7 +146,6 @@ func NewBlockRes(block *types.Block, fullTx bool) *BlockRes { res.Size = newHexNum(block.Size().Int64()) res.ExtraData = newHexData(block.Header().Extra) res.GasLimit = newHexNum(block.GasLimit()) - // res.MinGasPrice = res.GasUsed = newHexNum(block.GasUsed()) res.UnixTimestamp = newHexNum(block.Time()) -- cgit v1.2.3