Merge pull request #537 from Gustav-Simonsson/blocktests2

Add post state validation to block tests and disable network, add RPC
This commit is contained in:
Jeffrey Wilcke 2015-03-23 16:39:26 +01:00
commit 9562a9840f
5 changed files with 56 additions and 15 deletions

View File

@ -5,9 +5,9 @@ import (
"github.com/codegangsta/cli"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/tests"
)
@ -26,10 +26,10 @@ be able to interact with the chain defined by the test.
}
func runblocktest(ctx *cli.Context) {
if len(ctx.Args()) != 2 {
utils.Fatalf("This command requires two arguments.")
if len(ctx.Args()) != 3 {
utils.Fatalf("Usage: ethereum blocktest <path-to-test-file> <test-name> {rpc, norpc}")
}
file, testname := ctx.Args()[0], ctx.Args()[1]
file, testname, startrpc := ctx.Args()[0], ctx.Args()[1], ctx.Args()[2]
bt, err := tests.LoadBlockTests(file)
if err != nil {
@ -42,6 +42,7 @@ func runblocktest(ctx *cli.Context) {
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
cfg.NewDB = func(path string) (common.Database, error) { return ethdb.NewMemDatabase() }
cfg.MaxPeers = 0 // disable network
ethereum, err := eth.New(cfg)
if err != nil {
utils.Fatalf("%v", err)
@ -51,7 +52,8 @@ func runblocktest(ctx *cli.Context) {
ethereum.ResetWithGenesisBlock(test.Genesis)
// 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)
}
@ -60,7 +62,19 @@ func runblocktest(ctx *cli.Context) {
if err := chain.InsertChain(test.Blocks); err != nil {
utils.Fatalf("Block Test load error: %v", err)
} 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" {
startEth(ctx, ethereum)
utils.StartRPC(ethereum, ctx)
ethereum.WaitForShutdown()
} else {
startEth(ctx, ethereum)
}
startEth(ctx, ethereum)
}

View File

@ -219,7 +219,7 @@ func RunVmTest(r io.Reader) (failed int) {
}
func main() {
helper.Logger.SetLogLevel(5)
//helper.Logger.SetLogLevel(5)
vm.Debug = true
if len(os.Args) > 1 {

View File

@ -256,7 +256,7 @@ func StartRPC(eth *eth.Ethereum, ctx *cli.Context) {
addr := ctx.GlobalString(RPCListenAddrFlag.Name)
port := ctx.GlobalInt(RPCPortFlag.Name)
dataDir := ctx.GlobalString(DataDirFlag.Name)
fmt.Println("Starting RPC on port: ", port)
l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, port))
if err != nil {
Fatalf("Can't listen on %s:%d: %v", addr, port, err)

View File

@ -32,8 +32,10 @@ type StateQuery interface {
func CalcDifficulty(block, parent *types.Header) *big.Int {
diff := new(big.Int)
min := big.NewInt(2048)
adjust := new(big.Int).Div(parent.Difficulty, min)
diffBoundDiv := big.NewInt(2048)
min := big.NewInt(131072)
adjust := new(big.Int).Div(parent.Difficulty, diffBoundDiv)
if (block.Time - parent.Time) < 8 {
diff.Add(parent.Difficulty, adjust)
} else {

View File

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