Add validation of post state accounts to block tests

This commit is contained in:
Gustav Simonsson 2015-03-20 09:10:13 +01:00
parent 33c5186fd0
commit 08bb472c91
2 changed files with 40 additions and 6 deletions

View File

@ -52,7 +52,8 @@ func runblocktest(ctx *cli.Context) {
ethereum.ResetWithGenesisBlock(test.Genesis) ethereum.ResetWithGenesisBlock(test.Genesis)
// import pre accounts // import pre accounts
if err := test.InsertPreState(ethereum.StateDb()); err != nil { statedb, err := test.InsertPreState(ethereum.StateDb())
if err != nil {
utils.Fatalf("could not insert genesis accounts: %v", err) utils.Fatalf("could not insert genesis accounts: %v", err)
} }
@ -61,8 +62,14 @@ func runblocktest(ctx *cli.Context) {
if err := chain.InsertChain(test.Blocks); err != nil { if err := chain.InsertChain(test.Blocks); err != nil {
utils.Fatalf("Block Test load error: %v", err) utils.Fatalf("Block Test load error: %v", err)
} else { } else {
fmt.Println("Block Test chain loaded, starting ethereum.") fmt.Println("Block Test 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" { if startrpc == "rpc" {
startEth(ctx, ethereum) startEth(ctx, ethereum)
utils.StartRPC(ethereum, ctx) utils.StartRPC(ethereum, ctx)

View File

@ -19,11 +19,11 @@ import (
) )
// Block Test JSON Format // Block Test JSON Format
type btJSON struct { type btJSON struct {
Blocks []btBlock Blocks []btBlock
GenesisBlockHeader btHeader GenesisBlockHeader btHeader
Pre map[string]btAccount Pre map[string]btAccount
PostState map[string]btAccount
} }
type btAccount struct { type btAccount struct {
@ -97,7 +97,7 @@ func LoadBlockTests(file string) (map[string]*BlockTest, error) {
// InsertPreState populates the given database with the genesis // InsertPreState populates the given database with the genesis
// accounts defined by the test. // accounts defined by the test.
func (t *BlockTest) InsertPreState(db common.Database) error { func (t *BlockTest) InsertPreState(db common.Database) (*state.StateDB, error) {
statedb := state.New(common.Hash{}, db) statedb := state.New(common.Hash{}, db)
for addrString, acct := range t.preAccounts { for addrString, acct := range t.preAccounts {
// XXX: is is worth it checking for errors here? // XXX: is is worth it checking for errors here?
@ -119,8 +119,35 @@ func (t *BlockTest) InsertPreState(db common.Database) error {
// sync trie to disk // sync trie to disk
statedb.Sync() statedb.Sync()
if t.Genesis.Root() != statedb.Root() { if !bytes.Equal(t.Genesis.Root(), statedb.Root()) {
return errors.New("computed state root does not match genesis block") return nil, errors.New("computed state root does not match genesis block")
}
return statedb, nil
}
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(addr)
balance2 := statedb.GetBalance(addr)
nonce2 := statedb.GetNonce(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)
}
>>>>>>> Add validation of post state accounts to block tests
} }
return nil return nil
} }