blocktest.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. package tests
  2. import (
  3. "bytes"
  4. "encoding/hex"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "io/ioutil"
  9. "math/big"
  10. "runtime"
  11. "strconv"
  12. "strings"
  13. "github.com/ethereum/go-ethereum/core/types"
  14. "github.com/ethereum/go-ethereum/common"
  15. "github.com/ethereum/go-ethereum/rlp"
  16. "github.com/ethereum/go-ethereum/state"
  17. )
  18. // Block Test JSON Format
  19. type btJSON struct {
  20. Blocks []btBlock
  21. GenesisBlockHeader btHeader
  22. Pre map[string]btAccount
  23. }
  24. type btAccount struct {
  25. Balance string
  26. Code string
  27. Nonce string
  28. Storage map[string]string
  29. }
  30. type btHeader struct {
  31. Bloom string
  32. Coinbase string
  33. MixHash string
  34. Nonce string
  35. Number string
  36. ParentHash string
  37. ReceiptTrie string
  38. SeedHash string
  39. StateRoot string
  40. TransactionsTrie string
  41. UncleHash string
  42. ExtraData string
  43. Difficulty string
  44. GasLimit string
  45. GasUsed string
  46. Timestamp string
  47. }
  48. type btTransaction struct {
  49. Data string
  50. GasLimit string
  51. GasPrice string
  52. Nonce string
  53. R string
  54. S string
  55. To string
  56. V string
  57. Value string
  58. }
  59. type btBlock struct {
  60. BlockHeader *btHeader
  61. Rlp string
  62. Transactions []btTransaction
  63. UncleHeaders []string
  64. }
  65. type BlockTest struct {
  66. Genesis *types.Block
  67. Blocks []*types.Block
  68. preAccounts map[string]btAccount
  69. }
  70. // LoadBlockTests loads a block test JSON file.
  71. func LoadBlockTests(file string) (map[string]*BlockTest, error) {
  72. bt := make(map[string]*btJSON)
  73. if err := loadJSON(file, &bt); err != nil {
  74. return nil, err
  75. }
  76. out := make(map[string]*BlockTest)
  77. for name, in := range bt {
  78. var err error
  79. if out[name], err = convertTest(in); err != nil {
  80. return nil, fmt.Errorf("bad test %q: %v", err)
  81. }
  82. }
  83. return out, nil
  84. }
  85. // InsertPreState populates the given database with the genesis
  86. // accounts defined by the test.
  87. func (t *BlockTest) InsertPreState(db common.Database) error {
  88. statedb := state.New(nil, db)
  89. for addrString, acct := range t.preAccounts {
  90. // XXX: is is worth it checking for errors here?
  91. addr, _ := hex.DecodeString(addrString)
  92. code, _ := hex.DecodeString(strings.TrimPrefix(acct.Code, "0x"))
  93. balance, _ := new(big.Int).SetString(acct.Balance, 0)
  94. nonce, _ := strconv.ParseUint(acct.Nonce, 16, 64)
  95. obj := statedb.NewStateObject(addr)
  96. obj.SetCode(code)
  97. obj.SetBalance(balance)
  98. obj.SetNonce(nonce)
  99. // for k, v := range acct.Storage {
  100. // obj.SetState(k, v)
  101. // }
  102. }
  103. // sync objects to trie
  104. statedb.Update(nil)
  105. // sync trie to disk
  106. statedb.Sync()
  107. if !bytes.Equal(t.Genesis.Root(), statedb.Root()) {
  108. return errors.New("computed state root does not match genesis block")
  109. }
  110. return nil
  111. }
  112. func convertTest(in *btJSON) (out *BlockTest, err error) {
  113. // the conversion handles errors by catching panics.
  114. // you might consider this ugly, but the alternative (passing errors)
  115. // would be much harder to read.
  116. defer func() {
  117. if recovered := recover(); recovered != nil {
  118. buf := make([]byte, 64<<10)
  119. buf = buf[:runtime.Stack(buf, false)]
  120. err = fmt.Errorf("%v\n%s", recovered, buf)
  121. }
  122. }()
  123. out = &BlockTest{preAccounts: in.Pre}
  124. out.Genesis = mustConvertGenesis(in.GenesisBlockHeader)
  125. out.Blocks = mustConvertBlocks(in.Blocks)
  126. return out, err
  127. }
  128. func mustConvertGenesis(testGenesis btHeader) *types.Block {
  129. hdr := mustConvertHeader(testGenesis)
  130. hdr.Number = big.NewInt(0)
  131. b := types.NewBlockWithHeader(hdr)
  132. b.Td = new(big.Int)
  133. b.Reward = new(big.Int)
  134. return b
  135. }
  136. func mustConvertHeader(in btHeader) *types.Header {
  137. // hex decode these fields
  138. return &types.Header{
  139. //SeedHash: mustConvertBytes(in.SeedHash),
  140. MixDigest: mustConvertBytes(in.MixHash),
  141. Bloom: mustConvertBytes(in.Bloom),
  142. ReceiptHash: mustConvertBytes(in.ReceiptTrie),
  143. TxHash: mustConvertBytes(in.TransactionsTrie),
  144. Root: mustConvertBytes(in.StateRoot),
  145. Coinbase: mustConvertBytes(in.Coinbase),
  146. UncleHash: mustConvertBytes(in.UncleHash),
  147. ParentHash: mustConvertBytes(in.ParentHash),
  148. Nonce: mustConvertBytes(in.Nonce),
  149. Extra: string(mustConvertBytes(in.ExtraData)),
  150. GasUsed: mustConvertBigInt10(in.GasUsed),
  151. GasLimit: mustConvertBigInt10(in.GasLimit),
  152. Difficulty: mustConvertBigInt10(in.Difficulty),
  153. Time: mustConvertUint(in.Timestamp),
  154. }
  155. }
  156. func mustConvertBlocks(testBlocks []btBlock) []*types.Block {
  157. var out []*types.Block
  158. for i, inb := range testBlocks {
  159. var b types.Block
  160. r := bytes.NewReader(mustConvertBytes(inb.Rlp))
  161. if err := rlp.Decode(r, &b); err != nil {
  162. panic(fmt.Errorf("invalid block %d: %q", i, inb.Rlp))
  163. }
  164. out = append(out, &b)
  165. }
  166. return out
  167. }
  168. func mustConvertBytes(in string) []byte {
  169. out, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
  170. if err != nil {
  171. panic(fmt.Errorf("invalid hex: %q", in))
  172. }
  173. return out
  174. }
  175. func mustConvertBigInt10(in string) *big.Int {
  176. out, ok := new(big.Int).SetString(in, 10)
  177. if !ok {
  178. panic(fmt.Errorf("invalid integer: %q", in))
  179. }
  180. return out
  181. }
  182. func mustConvertUint(in string) uint64 {
  183. out, err := strconv.ParseUint(in, 0, 64)
  184. if err != nil {
  185. panic(fmt.Errorf("invalid integer: %q", in))
  186. }
  187. return out
  188. }
  189. // loadJSON reads the given file and unmarshals its content.
  190. func loadJSON(file string, val interface{}) error {
  191. content, err := ioutil.ReadFile(file)
  192. if err != nil {
  193. return err
  194. }
  195. if err := json.Unmarshal(content, val); err != nil {
  196. if syntaxerr, ok := err.(*json.SyntaxError); ok {
  197. line := findLine(content, syntaxerr.Offset)
  198. return fmt.Errorf("JSON syntax error at %v:%v: %v", file, line, err)
  199. }
  200. return fmt.Errorf("JSON unmarshal error in %v: %v", file, err)
  201. }
  202. return nil
  203. }
  204. // findLine returns the line number for the given offset into data.
  205. func findLine(data []byte, offset int64) (line int) {
  206. line = 1
  207. for i, r := range string(data) {
  208. if int64(i) >= offset {
  209. return
  210. }
  211. if r == '\n' {
  212. line++
  213. }
  214. }
  215. return
  216. }