block_test_util.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. package tests
  2. import (
  3. "bytes"
  4. "encoding/hex"
  5. "fmt"
  6. "io"
  7. "math/big"
  8. "path/filepath"
  9. "runtime"
  10. "strconv"
  11. "strings"
  12. "time"
  13. "github.com/ethereum/go-ethereum/accounts"
  14. "github.com/ethereum/go-ethereum/common"
  15. "github.com/ethereum/go-ethereum/core"
  16. "github.com/ethereum/go-ethereum/core/state"
  17. "github.com/ethereum/go-ethereum/core/types"
  18. "github.com/ethereum/go-ethereum/crypto"
  19. "github.com/ethereum/go-ethereum/eth"
  20. "github.com/ethereum/go-ethereum/ethdb"
  21. "github.com/ethereum/go-ethereum/logger/glog"
  22. "github.com/ethereum/go-ethereum/rlp"
  23. )
  24. // Block Test JSON Format
  25. type BlockTest struct {
  26. Genesis *types.Block
  27. Json *btJSON
  28. preAccounts map[string]btAccount
  29. }
  30. type btJSON struct {
  31. Blocks []btBlock
  32. GenesisBlockHeader btHeader
  33. Pre map[string]btAccount
  34. PostState map[string]btAccount
  35. }
  36. type btBlock struct {
  37. BlockHeader *btHeader
  38. Rlp string
  39. Transactions []btTransaction
  40. UncleHeaders []*btHeader
  41. }
  42. type btAccount struct {
  43. Balance string
  44. Code string
  45. Nonce string
  46. Storage map[string]string
  47. PrivateKey string
  48. }
  49. type btHeader struct {
  50. Bloom string
  51. Coinbase string
  52. MixHash string
  53. Nonce string
  54. Number string
  55. ParentHash string
  56. ReceiptTrie string
  57. SeedHash string
  58. StateRoot string
  59. TransactionsTrie string
  60. UncleHash string
  61. ExtraData string
  62. Difficulty string
  63. GasLimit string
  64. GasUsed string
  65. Timestamp string
  66. }
  67. type btTransaction struct {
  68. Data string
  69. GasLimit string
  70. GasPrice string
  71. Nonce string
  72. R string
  73. S string
  74. To string
  75. V string
  76. Value string
  77. }
  78. func RunBlockTestWithReader(r io.Reader, skipTests []string) error {
  79. btjs := make(map[string]*btJSON)
  80. if err := readJson(r, &btjs); err != nil {
  81. return err
  82. }
  83. bt, err := convertBlockTests(btjs)
  84. if err != nil {
  85. return err
  86. }
  87. if err := runBlockTests(bt, skipTests); err != nil {
  88. return err
  89. }
  90. return nil
  91. }
  92. func RunBlockTest(file string, skipTests []string) error {
  93. btjs := make(map[string]*btJSON)
  94. if err := readJsonFile(file, &btjs); err != nil {
  95. return err
  96. }
  97. bt, err := convertBlockTests(btjs)
  98. if err != nil {
  99. return err
  100. }
  101. if err := runBlockTests(bt, skipTests); err != nil {
  102. return err
  103. }
  104. return nil
  105. }
  106. func runBlockTests(bt map[string]*BlockTest, skipTests []string) error {
  107. skipTest := make(map[string]bool, len(skipTests))
  108. for _, name := range skipTests {
  109. skipTest[name] = true
  110. }
  111. for name, test := range bt {
  112. // if the test should be skipped, return
  113. if skipTest[name] {
  114. glog.Infoln("Skipping block test", name)
  115. continue
  116. }
  117. // test the block
  118. if err := runBlockTest(test); err != nil {
  119. return err
  120. }
  121. glog.Infoln("Block test passed: ", name)
  122. }
  123. return nil
  124. }
  125. func runBlockTest(test *BlockTest) error {
  126. cfg := test.makeEthConfig()
  127. ethereum, err := eth.New(cfg)
  128. if err != nil {
  129. return err
  130. }
  131. err = ethereum.Start()
  132. if err != nil {
  133. return err
  134. }
  135. // import the genesis block
  136. ethereum.ResetWithGenesisBlock(test.Genesis)
  137. // import pre accounts
  138. statedb, err := test.InsertPreState(ethereum)
  139. if err != nil {
  140. return fmt.Errorf("InsertPreState: %v", err)
  141. }
  142. err = test.TryBlocksInsert(ethereum.ChainManager())
  143. if err != nil {
  144. return err
  145. }
  146. if err = test.ValidatePostState(statedb); err != nil {
  147. return fmt.Errorf("post state validation failed: %v", err)
  148. }
  149. return nil
  150. }
  151. func (test *BlockTest) makeEthConfig() *eth.Config {
  152. ks := crypto.NewKeyStorePassphrase(filepath.Join(common.DefaultDataDir(), "keystore"))
  153. return &eth.Config{
  154. DataDir: common.DefaultDataDir(),
  155. Verbosity: 5,
  156. Etherbase: "primary",
  157. AccountManager: accounts.NewManager(ks),
  158. NewDB: func(path string) (common.Database, error) { return ethdb.NewMemDatabase() },
  159. }
  160. }
  161. // InsertPreState populates the given database with the genesis
  162. // accounts defined by the test.
  163. func (t *BlockTest) InsertPreState(ethereum *eth.Ethereum) (*state.StateDB, error) {
  164. db := ethereum.StateDb()
  165. statedb := state.New(common.Hash{}, db)
  166. for addrString, acct := range t.preAccounts {
  167. addr, _ := hex.DecodeString(addrString)
  168. code, _ := hex.DecodeString(strings.TrimPrefix(acct.Code, "0x"))
  169. balance, _ := new(big.Int).SetString(acct.Balance, 0)
  170. nonce, _ := strconv.ParseUint(acct.Nonce, 16, 64)
  171. if acct.PrivateKey != "" {
  172. privkey, err := hex.DecodeString(strings.TrimPrefix(acct.PrivateKey, "0x"))
  173. err = crypto.ImportBlockTestKey(privkey)
  174. err = ethereum.AccountManager().TimedUnlock(common.BytesToAddress(addr), "", 999999*time.Second)
  175. if err != nil {
  176. return nil, err
  177. }
  178. }
  179. obj := statedb.CreateAccount(common.HexToAddress(addrString))
  180. obj.SetCode(code)
  181. obj.SetBalance(balance)
  182. obj.SetNonce(nonce)
  183. for k, v := range acct.Storage {
  184. statedb.SetState(common.HexToAddress(addrString), common.HexToHash(k), common.HexToHash(v))
  185. }
  186. }
  187. // sync objects to trie
  188. statedb.SyncObjects()
  189. // sync trie to disk
  190. statedb.Sync()
  191. if !bytes.Equal(t.Genesis.Root().Bytes(), statedb.Root().Bytes()) {
  192. return nil, fmt.Errorf("computed state root does not match genesis block %x %x", t.Genesis.Root().Bytes()[:4], statedb.Root().Bytes()[:4])
  193. }
  194. return statedb, nil
  195. }
  196. /* See https://github.com/ethereum/tests/wiki/Blockchain-Tests-II
  197. Whether a block is valid or not is a bit subtle, it's defined by presence of
  198. blockHeader, transactions and uncleHeaders fields. If they are missing, the block is
  199. invalid and we must verify that we do not accept it.
  200. Since some tests mix valid and invalid blocks we need to check this for every block.
  201. If a block is invalid it does not necessarily fail the test, if it's invalidness is
  202. expected we are expected to ignore it and continue processing and then validate the
  203. post state.
  204. */
  205. func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error {
  206. // insert the test blocks, which will execute all transactions
  207. for _, b := range t.Json.Blocks {
  208. cb, err := mustConvertBlock(b)
  209. if err != nil {
  210. if b.BlockHeader == nil {
  211. continue // OK - block is supposed to be invalid, continue with next block
  212. } else {
  213. return fmt.Errorf("Block RLP decoding failed when expected to succeed: %v", err)
  214. }
  215. }
  216. // RLP decoding worked, try to insert into chain:
  217. _, err = chainManager.InsertChain(types.Blocks{cb})
  218. if err != nil {
  219. if b.BlockHeader == nil {
  220. continue // OK - block is supposed to be invalid, continue with next block
  221. } else {
  222. return fmt.Errorf("Block insertion into chain failed: %v", err)
  223. }
  224. }
  225. if b.BlockHeader == nil {
  226. return fmt.Errorf("Block insertion should have failed")
  227. }
  228. err = t.validateBlockHeader(b.BlockHeader, cb.Header())
  229. if err != nil {
  230. return fmt.Errorf("Block header validation failed: %v", err)
  231. }
  232. }
  233. return nil
  234. }
  235. func (s *BlockTest) validateBlockHeader(h *btHeader, h2 *types.Header) error {
  236. expectedBloom := mustConvertBytes(h.Bloom)
  237. if !bytes.Equal(expectedBloom, h2.Bloom.Bytes()) {
  238. return fmt.Errorf("Bloom: expected: %v, decoded: %v", expectedBloom, h2.Bloom.Bytes())
  239. }
  240. expectedCoinbase := mustConvertBytes(h.Coinbase)
  241. if !bytes.Equal(expectedCoinbase, h2.Coinbase.Bytes()) {
  242. return fmt.Errorf("Coinbase: expected: %v, decoded: %v", expectedCoinbase, h2.Coinbase.Bytes())
  243. }
  244. expectedMixHashBytes := mustConvertBytes(h.MixHash)
  245. if !bytes.Equal(expectedMixHashBytes, h2.MixDigest.Bytes()) {
  246. return fmt.Errorf("MixHash: expected: %v, decoded: %v", expectedMixHashBytes, h2.MixDigest.Bytes())
  247. }
  248. expectedNonce := mustConvertBytes(h.Nonce)
  249. if !bytes.Equal(expectedNonce, h2.Nonce[:]) {
  250. return fmt.Errorf("Nonce: expected: %v, decoded: %v", expectedNonce, h2.Nonce)
  251. }
  252. expectedNumber := mustConvertBigInt(h.Number, 16)
  253. if expectedNumber.Cmp(h2.Number) != 0 {
  254. return fmt.Errorf("Number: expected: %v, decoded: %v", expectedNumber, h2.Number)
  255. }
  256. expectedParentHash := mustConvertBytes(h.ParentHash)
  257. if !bytes.Equal(expectedParentHash, h2.ParentHash.Bytes()) {
  258. return fmt.Errorf("Parent hash: expected: %v, decoded: %v", expectedParentHash, h2.ParentHash.Bytes())
  259. }
  260. expectedReceiptHash := mustConvertBytes(h.ReceiptTrie)
  261. if !bytes.Equal(expectedReceiptHash, h2.ReceiptHash.Bytes()) {
  262. return fmt.Errorf("Receipt hash: expected: %v, decoded: %v", expectedReceiptHash, h2.ReceiptHash.Bytes())
  263. }
  264. expectedTxHash := mustConvertBytes(h.TransactionsTrie)
  265. if !bytes.Equal(expectedTxHash, h2.TxHash.Bytes()) {
  266. return fmt.Errorf("Tx hash: expected: %v, decoded: %v", expectedTxHash, h2.TxHash.Bytes())
  267. }
  268. expectedStateHash := mustConvertBytes(h.StateRoot)
  269. if !bytes.Equal(expectedStateHash, h2.Root.Bytes()) {
  270. return fmt.Errorf("State hash: expected: %v, decoded: %v", expectedStateHash, h2.Root.Bytes())
  271. }
  272. expectedUncleHash := mustConvertBytes(h.UncleHash)
  273. if !bytes.Equal(expectedUncleHash, h2.UncleHash.Bytes()) {
  274. return fmt.Errorf("Uncle hash: expected: %v, decoded: %v", expectedUncleHash, h2.UncleHash.Bytes())
  275. }
  276. expectedExtraData := mustConvertBytes(h.ExtraData)
  277. if !bytes.Equal(expectedExtraData, h2.Extra) {
  278. return fmt.Errorf("Extra data: expected: %v, decoded: %v", expectedExtraData, h2.Extra)
  279. }
  280. expectedDifficulty := mustConvertBigInt(h.Difficulty, 16)
  281. if expectedDifficulty.Cmp(h2.Difficulty) != 0 {
  282. return fmt.Errorf("Difficulty: expected: %v, decoded: %v", expectedDifficulty, h2.Difficulty)
  283. }
  284. expectedGasLimit := mustConvertBigInt(h.GasLimit, 16)
  285. if expectedGasLimit.Cmp(h2.GasLimit) != 0 {
  286. return fmt.Errorf("GasLimit: expected: %v, decoded: %v", expectedGasLimit, h2.GasLimit)
  287. }
  288. expectedGasUsed := mustConvertBigInt(h.GasUsed, 16)
  289. if expectedGasUsed.Cmp(h2.GasUsed) != 0 {
  290. return fmt.Errorf("GasUsed: expected: %v, decoded: %v", expectedGasUsed, h2.GasUsed)
  291. }
  292. expectedTimestamp := mustConvertUint(h.Timestamp, 16)
  293. if expectedTimestamp != h2.Time {
  294. return fmt.Errorf("Timestamp: expected: %v, decoded: %v", expectedTimestamp, h2.Time)
  295. }
  296. return nil
  297. }
  298. func (t *BlockTest) ValidatePostState(statedb *state.StateDB) error {
  299. for addrString, acct := range t.preAccounts {
  300. // XXX: is is worth it checking for errors here?
  301. addr, _ := hex.DecodeString(addrString)
  302. code, _ := hex.DecodeString(strings.TrimPrefix(acct.Code, "0x"))
  303. balance, _ := new(big.Int).SetString(acct.Balance, 0)
  304. nonce, _ := strconv.ParseUint(acct.Nonce, 16, 64)
  305. // address is indirectly verified by the other fields, as it's the db key
  306. code2 := statedb.GetCode(common.BytesToAddress(addr))
  307. balance2 := statedb.GetBalance(common.BytesToAddress(addr))
  308. nonce2 := statedb.GetNonce(common.BytesToAddress(addr))
  309. if !bytes.Equal(code2, code) {
  310. return fmt.Errorf("account code mismatch, addr, found, expected: ", addrString, hex.EncodeToString(code2), hex.EncodeToString(code))
  311. }
  312. if balance2.Cmp(balance) != 0 {
  313. return fmt.Errorf("account balance mismatch, addr, found, expected: ", addrString, balance2, balance)
  314. }
  315. if nonce2 != nonce {
  316. return fmt.Errorf("account nonce mismatch, addr, found, expected: ", addrString, nonce2, nonce)
  317. }
  318. }
  319. return nil
  320. }
  321. func convertBlockTests(in map[string]*btJSON) (map[string]*BlockTest, error) {
  322. out := make(map[string]*BlockTest)
  323. for name, test := range in {
  324. var err error
  325. if out[name], err = convertBlockTest(test); err != nil {
  326. return out, fmt.Errorf("bad test %q: %v", name, err)
  327. }
  328. }
  329. return out, nil
  330. }
  331. func convertBlockTest(in *btJSON) (out *BlockTest, err error) {
  332. // the conversion handles errors by catching panics.
  333. // you might consider this ugly, but the alternative (passing errors)
  334. // would be much harder to read.
  335. defer func() {
  336. if recovered := recover(); recovered != nil {
  337. buf := make([]byte, 64<<10)
  338. buf = buf[:runtime.Stack(buf, false)]
  339. err = fmt.Errorf("%v\n%s", recovered, buf)
  340. }
  341. }()
  342. out = &BlockTest{preAccounts: in.Pre, Json: in}
  343. out.Genesis = mustConvertGenesis(in.GenesisBlockHeader)
  344. return out, err
  345. }
  346. func mustConvertGenesis(testGenesis btHeader) *types.Block {
  347. hdr := mustConvertHeader(testGenesis)
  348. hdr.Number = big.NewInt(0)
  349. b := types.NewBlockWithHeader(hdr)
  350. b.Td = new(big.Int)
  351. return b
  352. }
  353. func mustConvertHeader(in btHeader) *types.Header {
  354. // hex decode these fields
  355. header := &types.Header{
  356. //SeedHash: mustConvertBytes(in.SeedHash),
  357. MixDigest: mustConvertHash(in.MixHash),
  358. Bloom: mustConvertBloom(in.Bloom),
  359. ReceiptHash: mustConvertHash(in.ReceiptTrie),
  360. TxHash: mustConvertHash(in.TransactionsTrie),
  361. Root: mustConvertHash(in.StateRoot),
  362. Coinbase: mustConvertAddress(in.Coinbase),
  363. UncleHash: mustConvertHash(in.UncleHash),
  364. ParentHash: mustConvertHash(in.ParentHash),
  365. Extra: mustConvertBytes(in.ExtraData),
  366. GasUsed: mustConvertBigInt(in.GasUsed, 16),
  367. GasLimit: mustConvertBigInt(in.GasLimit, 16),
  368. Difficulty: mustConvertBigInt(in.Difficulty, 16),
  369. Time: mustConvertUint(in.Timestamp, 16),
  370. Nonce: types.EncodeNonce(mustConvertUint(in.Nonce, 16)),
  371. }
  372. return header
  373. }
  374. func mustConvertBlock(testBlock btBlock) (*types.Block, error) {
  375. var b types.Block
  376. r := bytes.NewReader(mustConvertBytes(testBlock.Rlp))
  377. err := rlp.Decode(r, &b)
  378. return &b, err
  379. }
  380. func mustConvertBytes(in string) []byte {
  381. if in == "0x" {
  382. return []byte{}
  383. }
  384. h := unfuckFuckedHex(strings.TrimPrefix(in, "0x"))
  385. out, err := hex.DecodeString(h)
  386. if err != nil {
  387. panic(fmt.Errorf("invalid hex: %q: ", h, err))
  388. }
  389. return out
  390. }
  391. func mustConvertHash(in string) common.Hash {
  392. out, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
  393. if err != nil {
  394. panic(fmt.Errorf("invalid hex: %q", in))
  395. }
  396. return common.BytesToHash(out)
  397. }
  398. func mustConvertAddress(in string) common.Address {
  399. out, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
  400. if err != nil {
  401. panic(fmt.Errorf("invalid hex: %q", in))
  402. }
  403. return common.BytesToAddress(out)
  404. }
  405. func mustConvertBloom(in string) types.Bloom {
  406. out, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
  407. if err != nil {
  408. panic(fmt.Errorf("invalid hex: %q", in))
  409. }
  410. return types.BytesToBloom(out)
  411. }
  412. func mustConvertBigInt(in string, base int) *big.Int {
  413. in = prepInt(base, in)
  414. out, ok := new(big.Int).SetString(in, base)
  415. if !ok {
  416. panic(fmt.Errorf("invalid integer: %q", in))
  417. }
  418. return out
  419. }
  420. func mustConvertUint(in string, base int) uint64 {
  421. in = prepInt(base, in)
  422. out, err := strconv.ParseUint(in, base, 64)
  423. if err != nil {
  424. panic(fmt.Errorf("invalid integer: %q", in))
  425. }
  426. return out
  427. }
  428. func LoadBlockTests(file string) (map[string]*BlockTest, error) {
  429. btjs := make(map[string]*btJSON)
  430. if err := readJsonFile(file, &btjs); err != nil {
  431. return nil, err
  432. }
  433. return convertBlockTests(btjs)
  434. }
  435. // Nothing to see here, please move along...
  436. func prepInt(base int, s string) string {
  437. if base == 16 {
  438. if strings.HasPrefix(s, "0x") {
  439. s = s[2:]
  440. }
  441. if len(s) == 0 {
  442. s = "00"
  443. }
  444. s = nibbleFix(s)
  445. }
  446. return s
  447. }
  448. // don't ask
  449. func unfuckFuckedHex(almostHex string) string {
  450. return nibbleFix(strings.Replace(almostHex, "v", "", -1))
  451. }
  452. func nibbleFix(s string) string {
  453. if len(s)%2 != 0 {
  454. s = "0" + s
  455. }
  456. return s
  457. }