block_test_util.go 15 KB

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