Add validation of post state accounts to block tests
This commit is contained in:
		| @@ -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) | ||||||
|   | |||||||
| @@ -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 | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user