/* This file is part of go-ethereum go-ethereum is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. go-ethereum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with go-ethereum. If not, see . */ /** * @authors * Gustav Simonsson * @date 2015 * */ package main import ( "bytes" "encoding/hex" "encoding/json" "flag" "fmt" "io/ioutil" "log" "math/big" "os" "runtime" "strings" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/core" types "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/rlp" ) type Account struct { Balance string Code string Nonce string Storage map[string]string } type BlockHeader struct { Bloom string Coinbase string Difficulty string ExtraData string GasLimit string GasUsed string MixHash string Nonce string Number string ParentHash string ReceiptTrie string SeedHash string StateRoot string Timestamp string TransactionsTrie string UncleHash string } type Tx struct { Data string GasLimit string GasPrice string Nonce string R string S string To string V string Value string } type Block struct { BlockHeader BlockHeader Rlp string Transactions []Tx UncleHeaders []string } type Test struct { Blocks []Block GenesisBlockHeader BlockHeader Pre map[string]Account } func main() { flag.Usage = func() { fmt.Fprintf(os.Stderr, "%s \n", os.Args[0]) flag.PrintDefaults() } flag.Parse() runtime.GOMAXPROCS(runtime.NumCPU()) logger.AddLogSystem(logger.NewStdLogSystem(os.Stderr, log.LstdFlags, logger.DebugDetailLevel)) defer func() { logger.Flush() }() if len(os.Args) < 2 { utils.Fatalf("Please specify a test file as the first argument.") } blocks, err := loadBlocksFromTestFile(os.Args[1]) if err != nil { utils.Fatalf("Could not load blocks: %v", err) } chain := memchain() chain.ResetWithGenesisBlock(blocks[0]) if err = chain.InsertChain(types.Blocks{blocks[1]}); err != nil { utils.Fatalf("Error: %v", err) } else { fmt.Println("PASS") } } func memchain() *core.ChainManager { db, err := ethdb.NewMemDatabase() if err != nil { utils.Fatalf("Could not create in-memory database: %v", err) } return core.NewChainManager(db, new(event.TypeMux)) } func loadBlocksFromTestFile(filePath string) (blocks types.Blocks, err error) { fileContent, err := ioutil.ReadFile(filePath) if err != nil { return } bt := make(map[string]Test) if err = json.Unmarshal(fileContent, &bt); err != nil { return } // TODO: support multiple blocks; loop over all blocks gbh := new(types.Header) // Let's use slighlty different namings for the same things, because that's awesome. gbh.ParentHash, err = hex_decode(bt["SimpleTx"].GenesisBlockHeader.ParentHash) gbh.UncleHash, err = hex_decode(bt["SimpleTx"].GenesisBlockHeader.UncleHash) gbh.Coinbase, err = hex_decode(bt["SimpleTx"].GenesisBlockHeader.Coinbase) gbh.Root, err = hex_decode(bt["SimpleTx"].GenesisBlockHeader.StateRoot) gbh.TxHash, err = hex_decode(bt["SimpleTx"].GenesisBlockHeader.TransactionsTrie) gbh.ReceiptHash, err = hex_decode(bt["SimpleTx"].GenesisBlockHeader.ReceiptTrie) gbh.Bloom, err = hex_decode(bt["SimpleTx"].GenesisBlockHeader.Bloom) gbh.MixDigest, err = hex_decode(bt["SimpleTx"].GenesisBlockHeader.MixHash) gbh.SeedHash, err = hex_decode(bt["SimpleTx"].GenesisBlockHeader.SeedHash) d, _ := new(big.Int).SetString(bt["SimpleTx"].GenesisBlockHeader.Difficulty, 10) gbh.Difficulty = d n, _ := new(big.Int).SetString(bt["SimpleTx"].GenesisBlockHeader.Number, 10) gbh.Number = n gl, _ := new(big.Int).SetString(bt["SimpleTx"].GenesisBlockHeader.GasLimit, 10) gbh.GasLimit = gl gu, _ := new(big.Int).SetString(bt["SimpleTx"].GenesisBlockHeader.GasUsed, 10) gbh.GasUsed = gu ts, _ := new(big.Int).SetString(bt["SimpleTx"].GenesisBlockHeader.Timestamp, 0) gbh.Time = ts.Uint64() extra, err := hex_decode(bt["SimpleTx"].GenesisBlockHeader.ExtraData) gbh.Extra = string(extra) // TODO: change ExtraData to byte array nonce, _ := hex_decode(bt["SimpleTx"].GenesisBlockHeader.Nonce) gbh.Nonce = nonce if err != nil { return } gb := types.NewBlockWithHeader(gbh) gb.Reward = new(big.Int) testBlock := new(types.Block) rlpBytes, err := hex_decode(bt["SimpleTx"].Blocks[0].Rlp) err = rlp.Decode(bytes.NewReader(rlpBytes), &testBlock) if err != nil { return } blocks = types.Blocks{ gb, testBlock, } return } func hex_decode(s string) (res []byte, err error) { return hex.DecodeString(strings.TrimPrefix(s, "0x")) }