github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/tests/block_test_util.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //
    10  //
    11  //
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  
    25  //
    26  package tests
    27  
    28  import (
    29  	"bytes"
    30  	"encoding/hex"
    31  	"encoding/json"
    32  	"fmt"
    33  	"math/big"
    34  
    35  	"github.com/ethereum/go-ethereum/common"
    36  	"github.com/ethereum/go-ethereum/common/hexutil"
    37  	"github.com/ethereum/go-ethereum/common/math"
    38  	"github.com/ethereum/go-ethereum/consensus/ethash"
    39  	"github.com/ethereum/go-ethereum/core"
    40  	"github.com/ethereum/go-ethereum/core/state"
    41  	"github.com/ethereum/go-ethereum/core/types"
    42  	"github.com/ethereum/go-ethereum/core/vm"
    43  	"github.com/ethereum/go-ethereum/ethdb"
    44  	"github.com/ethereum/go-ethereum/params"
    45  	"github.com/ethereum/go-ethereum/rlp"
    46  )
    47  
    48  //
    49  type BlockTest struct {
    50  	json btJSON
    51  }
    52  
    53  //
    54  func (t *BlockTest) UnmarshalJSON(in []byte) error {
    55  	return json.Unmarshal(in, &t.json)
    56  }
    57  
    58  type btJSON struct {
    59  	Blocks    []btBlock             `json:"blocks"`
    60  	Genesis   btHeader              `json:"genesisBlockHeader"`
    61  	Pre       core.GenesisAlloc     `json:"pre"`
    62  	Post      core.GenesisAlloc     `json:"postState"`
    63  	BestBlock common.UnprefixedHash `json:"lastblockhash"`
    64  	Network   string                `json:"network"`
    65  }
    66  
    67  type btBlock struct {
    68  	BlockHeader  *btHeader
    69  	Rlp          string
    70  	UncleHeaders []*btHeader
    71  }
    72  
    73  //
    74  
    75  type btHeader struct {
    76  	Bloom            types.Bloom
    77  	Coinbase         common.Address
    78  	MixHash          common.Hash
    79  	Nonce            types.BlockNonce
    80  	Number           *big.Int
    81  	Hash             common.Hash
    82  	ParentHash       common.Hash
    83  	ReceiptTrie      common.Hash
    84  	StateRoot        common.Hash
    85  	TransactionsTrie common.Hash
    86  	UncleHash        common.Hash
    87  	ExtraData        []byte
    88  	Difficulty       *big.Int
    89  	GasLimit         uint64
    90  	GasUsed          uint64
    91  	Timestamp        *big.Int
    92  }
    93  
    94  type btHeaderMarshaling struct {
    95  	ExtraData  hexutil.Bytes
    96  	Number     *math.HexOrDecimal256
    97  	Difficulty *math.HexOrDecimal256
    98  	GasLimit   math.HexOrDecimal64
    99  	GasUsed    math.HexOrDecimal64
   100  	Timestamp  *math.HexOrDecimal256
   101  }
   102  
   103  func (t *BlockTest) Run() error {
   104  	config, ok := Forks[t.json.Network]
   105  	if !ok {
   106  		return UnsupportedForkError{t.json.Network}
   107  	}
   108  
   109  //
   110  	db := ethdb.NewMemDatabase()
   111  	gblock, err := t.genesis(config).Commit(db)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	if gblock.Hash() != t.json.Genesis.Hash {
   116  		return fmt.Errorf("genesis block hash doesn't match test: computed=%x, test=%x", gblock.Hash().Bytes()[:6], t.json.Genesis.Hash[:6])
   117  	}
   118  	if gblock.Root() != t.json.Genesis.StateRoot {
   119  		return fmt.Errorf("genesis block state root does not match test: computed=%x, test=%x", gblock.Root().Bytes()[:6], t.json.Genesis.StateRoot[:6])
   120  	}
   121  
   122  	chain, err := core.NewBlockChain(db, nil, config, ethash.NewShared(), vm.Config{})
   123  	if err != nil {
   124  		return err
   125  	}
   126  	defer chain.Stop()
   127  
   128  	validBlocks, err := t.insertBlocks(chain)
   129  	if err != nil {
   130  		return err
   131  	}
   132  	cmlast := chain.CurrentBlock().Hash()
   133  	if common.Hash(t.json.BestBlock) != cmlast {
   134  		return fmt.Errorf("last block hash validation mismatch: want: %x, have: %x", t.json.BestBlock, cmlast)
   135  	}
   136  	newDB, err := chain.State()
   137  	if err != nil {
   138  		return err
   139  	}
   140  	if err = t.validatePostState(newDB); err != nil {
   141  		return fmt.Errorf("post state validation failed: %v", err)
   142  	}
   143  	return t.validateImportedHeaders(chain, validBlocks)
   144  }
   145  
   146  func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis {
   147  	return &core.Genesis{
   148  		Config:     config,
   149  		Nonce:      t.json.Genesis.Nonce.Uint64(),
   150  		Timestamp:  t.json.Genesis.Timestamp.Uint64(),
   151  		ParentHash: t.json.Genesis.ParentHash,
   152  		ExtraData:  t.json.Genesis.ExtraData,
   153  		GasLimit:   t.json.Genesis.GasLimit,
   154  		GasUsed:    t.json.Genesis.GasUsed,
   155  		Difficulty: t.json.Genesis.Difficulty,
   156  		Mixhash:    t.json.Genesis.MixHash,
   157  		Coinbase:   t.json.Genesis.Coinbase,
   158  		Alloc:      t.json.Pre,
   159  	}
   160  }
   161  
   162  /*
   163  
   164     
   165     
   166     
   167  
   168     
   169  
   170     
   171     
   172     
   173  */
   174  
   175  func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error) {
   176  	validBlocks := make([]btBlock, 0)
   177  //
   178  	for _, b := range t.json.Blocks {
   179  		cb, err := b.decode()
   180  		if err != nil {
   181  			if b.BlockHeader == nil {
   182  continue //
   183  			} else {
   184  				return nil, fmt.Errorf("Block RLP decoding failed when expected to succeed: %v", err)
   185  			}
   186  		}
   187  //
   188  		blocks := types.Blocks{cb}
   189  		i, err := blockchain.InsertChain(blocks)
   190  		if err != nil {
   191  			if b.BlockHeader == nil {
   192  continue //
   193  			} else {
   194  				return nil, fmt.Errorf("Block #%v insertion into chain failed: %v", blocks[i].Number(), err)
   195  			}
   196  		}
   197  		if b.BlockHeader == nil {
   198  			return nil, fmt.Errorf("Block insertion should have failed")
   199  		}
   200  
   201  //
   202  		if err = validateHeader(b.BlockHeader, cb.Header()); err != nil {
   203  			return nil, fmt.Errorf("Deserialised block header validation failed: %v", err)
   204  		}
   205  		validBlocks = append(validBlocks, b)
   206  	}
   207  	return validBlocks, nil
   208  }
   209  
   210  func validateHeader(h *btHeader, h2 *types.Header) error {
   211  	if h.Bloom != h2.Bloom {
   212  		return fmt.Errorf("Bloom: want: %x have: %x", h.Bloom, h2.Bloom)
   213  	}
   214  	if h.Coinbase != h2.Coinbase {
   215  		return fmt.Errorf("Coinbase: want: %x have: %x", h.Coinbase, h2.Coinbase)
   216  	}
   217  	if h.MixHash != h2.MixDigest {
   218  		return fmt.Errorf("MixHash: want: %x have: %x", h.MixHash, h2.MixDigest)
   219  	}
   220  	if h.Nonce != h2.Nonce {
   221  		return fmt.Errorf("Nonce: want: %x have: %x", h.Nonce, h2.Nonce)
   222  	}
   223  	if h.Number.Cmp(h2.Number) != 0 {
   224  		return fmt.Errorf("Number: want: %v have: %v", h.Number, h2.Number)
   225  	}
   226  	if h.ParentHash != h2.ParentHash {
   227  		return fmt.Errorf("Parent hash: want: %x have: %x", h.ParentHash, h2.ParentHash)
   228  	}
   229  	if h.ReceiptTrie != h2.ReceiptHash {
   230  		return fmt.Errorf("Receipt hash: want: %x have: %x", h.ReceiptTrie, h2.ReceiptHash)
   231  	}
   232  	if h.TransactionsTrie != h2.TxHash {
   233  		return fmt.Errorf("Tx hash: want: %x have: %x", h.TransactionsTrie, h2.TxHash)
   234  	}
   235  	if h.StateRoot != h2.Root {
   236  		return fmt.Errorf("State hash: want: %x have: %x", h.StateRoot, h2.Root)
   237  	}
   238  	if h.UncleHash != h2.UncleHash {
   239  		return fmt.Errorf("Uncle hash: want: %x have: %x", h.UncleHash, h2.UncleHash)
   240  	}
   241  	if !bytes.Equal(h.ExtraData, h2.Extra) {
   242  		return fmt.Errorf("Extra data: want: %x have: %x", h.ExtraData, h2.Extra)
   243  	}
   244  	if h.Difficulty.Cmp(h2.Difficulty) != 0 {
   245  		return fmt.Errorf("Difficulty: want: %v have: %v", h.Difficulty, h2.Difficulty)
   246  	}
   247  	if h.GasLimit != h2.GasLimit {
   248  		return fmt.Errorf("GasLimit: want: %d have: %d", h.GasLimit, h2.GasLimit)
   249  	}
   250  	if h.GasUsed != h2.GasUsed {
   251  		return fmt.Errorf("GasUsed: want: %d have: %d", h.GasUsed, h2.GasUsed)
   252  	}
   253  	if h.Timestamp.Cmp(h2.Time) != 0 {
   254  		return fmt.Errorf("Timestamp: want: %v have: %v", h.Timestamp, h2.Time)
   255  	}
   256  	return nil
   257  }
   258  
   259  func (t *BlockTest) validatePostState(statedb *state.StateDB) error {
   260  //
   261  	for addr, acct := range t.json.Post {
   262  //
   263  		code2 := statedb.GetCode(addr)
   264  		balance2 := statedb.GetBalance(addr)
   265  		nonce2 := statedb.GetNonce(addr)
   266  		if !bytes.Equal(code2, acct.Code) {
   267  			return fmt.Errorf("account code mismatch for addr: %s want: %v have: %s", addr, acct.Code, hex.EncodeToString(code2))
   268  		}
   269  		if balance2.Cmp(acct.Balance) != 0 {
   270  			return fmt.Errorf("account balance mismatch for addr: %s, want: %d, have: %d", addr, acct.Balance, balance2)
   271  		}
   272  		if nonce2 != acct.Nonce {
   273  			return fmt.Errorf("account nonce mismatch for addr: %s want: %d have: %d", addr, acct.Nonce, nonce2)
   274  		}
   275  	}
   276  	return nil
   277  }
   278  
   279  func (t *BlockTest) validateImportedHeaders(cm *core.BlockChain, validBlocks []btBlock) error {
   280  //
   281  	bmap := make(map[common.Hash]btBlock, len(t.json.Blocks))
   282  	for _, b := range validBlocks {
   283  		bmap[b.BlockHeader.Hash] = b
   284  	}
   285  //
   286  //
   287  //
   288  //
   289  //
   290  	for b := cm.CurrentBlock(); b != nil && b.NumberU64() != 0; b = cm.GetBlockByHash(b.Header().ParentHash) {
   291  		if err := validateHeader(bmap[b.Hash()].BlockHeader, b.Header()); err != nil {
   292  			return fmt.Errorf("Imported block header validation failed: %v", err)
   293  		}
   294  	}
   295  	return nil
   296  }
   297  
   298  func (bb *btBlock) decode() (*types.Block, error) {
   299  	data, err := hexutil.Decode(bb.Rlp)
   300  	if err != nil {
   301  		return nil, err
   302  	}
   303  	var b types.Block
   304  	err = rlp.DecodeBytes(data, &b)
   305  	return &b, err
   306  }