mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 05:06:43 +00:00
Merge remote-tracking branch 'felix/blocktest-parsing-fix' into HEAD
* felix/blocktest-parsing-fix: tests: hopefully improve test conversion helpers blockpool: add missing shutdown synchronization core, eth: add missing shutdown synchronization to ChainManager cmd/geth, tests: enable running multiple tests from a single file eth: honour config.Shh eth: use NewDB hook also for extra DB Conflicts: eth/backend.go
This commit is contained in:
commit
7c3319f4d7
6 changed files with 146 additions and 57 deletions
|
|
@ -184,6 +184,7 @@ type BlockPool struct {
|
||||||
wg sync.WaitGroup //
|
wg sync.WaitGroup //
|
||||||
quit chan bool // chan used for quitting parallel routines
|
quit chan bool // chan used for quitting parallel routines
|
||||||
running bool //
|
running bool //
|
||||||
|
evloopdone chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// public constructor
|
// public constructor
|
||||||
|
|
@ -204,6 +205,7 @@ func New(
|
||||||
verifyPoW: verifyPoW,
|
verifyPoW: verifyPoW,
|
||||||
chainEvents: chainEvents,
|
chainEvents: chainEvents,
|
||||||
td: td,
|
td: td,
|
||||||
|
evloopdone: make(chan struct{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -244,6 +246,7 @@ func (self *BlockPool) Start() {
|
||||||
// status update interval
|
// status update interval
|
||||||
timer := time.NewTicker(self.Config.StatusUpdateInterval)
|
timer := time.NewTicker(self.Config.StatusUpdateInterval)
|
||||||
go func() {
|
go func() {
|
||||||
|
defer close(self.evloopdone)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-self.quit:
|
case <-self.quit:
|
||||||
|
|
@ -290,6 +293,7 @@ func (self *BlockPool) Stop() {
|
||||||
|
|
||||||
self.tdSub.Unsubscribe()
|
self.tdSub.Unsubscribe()
|
||||||
close(self.quit)
|
close(self.quit)
|
||||||
|
<-self.evloopdone
|
||||||
|
|
||||||
self.lock.Lock()
|
self.lock.Lock()
|
||||||
self.peers = nil
|
self.peers = nil
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
|
|
@ -12,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var blocktestCmd = cli.Command{
|
var blocktestCmd = cli.Command{
|
||||||
Action: runblocktest,
|
Action: runBlockTest,
|
||||||
Name: "blocktest",
|
Name: "blocktest",
|
||||||
Usage: `loads a block test file`,
|
Usage: `loads a block test file`,
|
||||||
Description: `
|
Description: `
|
||||||
|
|
@ -25,27 +26,78 @@ be able to interact with the chain defined by the test.
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
func runblocktest(ctx *cli.Context) {
|
func runBlockTest(ctx *cli.Context) {
|
||||||
if len(ctx.Args()) != 3 {
|
var (
|
||||||
utils.Fatalf("Usage: ethereum blocktest <path-to-test-file> <test-name> {rpc, norpc}")
|
file, testname string
|
||||||
|
rpc bool
|
||||||
|
)
|
||||||
|
args := ctx.Args()
|
||||||
|
switch {
|
||||||
|
case len(args) == 1:
|
||||||
|
file = args[0]
|
||||||
|
case len(args) == 2:
|
||||||
|
file, testname = args[0], args[1]
|
||||||
|
case len(args) == 3:
|
||||||
|
file, testname = args[0], args[1]
|
||||||
|
rpc = true
|
||||||
|
default:
|
||||||
|
utils.Fatalf(`Usage: ethereum blocktest <path-to-test-file> [ <test-name> [ "rpc" ] ]`)
|
||||||
}
|
}
|
||||||
file, testname, startrpc := ctx.Args()[0], ctx.Args()[1], ctx.Args()[2]
|
|
||||||
|
|
||||||
bt, err := tests.LoadBlockTests(file)
|
bt, err := tests.LoadBlockTests(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("%v", err)
|
utils.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// run all tests if no test name is specified
|
||||||
|
if testname == "" {
|
||||||
|
ecode := 0
|
||||||
|
for name, test := range bt {
|
||||||
|
fmt.Printf("----------------- Running Block Test %q\n", name)
|
||||||
|
ethereum, err := runOneBlockTest(ctx, test)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Println("FAIL")
|
||||||
|
ecode = 1
|
||||||
|
}
|
||||||
|
if ethereum != nil {
|
||||||
|
ethereum.Stop()
|
||||||
|
ethereum.WaitForShutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os.Exit(ecode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// otherwise, run the given test
|
||||||
test, ok := bt[testname]
|
test, ok := bt[testname]
|
||||||
if !ok {
|
if !ok {
|
||||||
utils.Fatalf("Test file does not contain test named %q", testname)
|
utils.Fatalf("Test file does not contain test named %q", testname)
|
||||||
}
|
}
|
||||||
|
ethereum, err := runOneBlockTest(ctx, test)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
defer ethereum.Stop()
|
||||||
|
if rpc {
|
||||||
|
fmt.Println("Block Test post state validated, starting RPC interface.")
|
||||||
|
startEth(ctx, ethereum)
|
||||||
|
utils.StartRPC(ethereum, ctx)
|
||||||
|
ethereum.WaitForShutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, error) {
|
||||||
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
|
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
|
||||||
cfg.NewDB = func(path string) (common.Database, error) { return ethdb.NewMemDatabase() }
|
cfg.NewDB = func(path string) (common.Database, error) { return ethdb.NewMemDatabase() }
|
||||||
cfg.MaxPeers = 0 // disable network
|
cfg.MaxPeers = 0 // disable network
|
||||||
|
cfg.Shh = false // disable whisper
|
||||||
|
cfg.NAT = nil // disable port mapping
|
||||||
|
|
||||||
ethereum, err := eth.New(cfg)
|
ethereum, err := eth.New(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("%v", err)
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := ethereum.Start(); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// import the genesis block
|
// import the genesis block
|
||||||
|
|
@ -54,27 +106,16 @@ func runblocktest(ctx *cli.Context) {
|
||||||
// import pre accounts
|
// import pre accounts
|
||||||
statedb, err := test.InsertPreState(ethereum.StateDb())
|
statedb, err := test.InsertPreState(ethereum.StateDb())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("could not insert genesis accounts: %v", err)
|
return ethereum, fmt.Errorf("InsertPreState: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert the test blocks, which will execute all transactions
|
// insert the test blocks, which will execute all transactions
|
||||||
chain := ethereum.ChainManager()
|
if err := test.InsertBlocks(ethereum.ChainManager()); err != nil {
|
||||||
if err := chain.InsertChain(test.Blocks); err != nil {
|
return ethereum, fmt.Errorf("Block Test load error: %v %T", err, err)
|
||||||
utils.Fatalf("Block Test load error: %v %T", err, err)
|
|
||||||
} else {
|
|
||||||
fmt.Println("Block Test chain loaded")
|
|
||||||
}
|
}
|
||||||
|
fmt.Println("chain loaded")
|
||||||
if err := test.ValidatePostState(statedb); err != nil {
|
if err := test.ValidatePostState(statedb); err != nil {
|
||||||
utils.Fatalf("post state validation failed: %v", err)
|
return ethereum, fmt.Errorf("post state validation failed: %v", err)
|
||||||
}
|
|
||||||
fmt.Println("Block Test post state validated, starting ethereum.")
|
|
||||||
|
|
||||||
if startrpc == "rpc" {
|
|
||||||
startEth(ctx, ethereum)
|
|
||||||
utils.StartRPC(ethereum, ctx)
|
|
||||||
ethereum.WaitForShutdown()
|
|
||||||
} else {
|
|
||||||
startEth(ctx, ethereum)
|
|
||||||
}
|
}
|
||||||
|
return ethereum, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ type ChainManager struct {
|
||||||
futureBlocks *BlockCache
|
futureBlocks *BlockCache
|
||||||
|
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
|
wg sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewChainManager(blockDb, stateDb common.Database, mux *event.TypeMux) *ChainManager {
|
func NewChainManager(blockDb, stateDb common.Database, mux *event.TypeMux) *ChainManager {
|
||||||
|
|
@ -104,6 +105,7 @@ func NewChainManager(blockDb, stateDb common.Database, mux *event.TypeMux) *Chai
|
||||||
bc.futureBlocks = NewBlockCache(254)
|
bc.futureBlocks = NewBlockCache(254)
|
||||||
bc.makeCache()
|
bc.makeCache()
|
||||||
|
|
||||||
|
bc.wg.Add(1)
|
||||||
go bc.update()
|
go bc.update()
|
||||||
|
|
||||||
return bc
|
return bc
|
||||||
|
|
@ -428,6 +430,7 @@ func (self *ChainManager) CalcTotalDiff(block *types.Block) (*big.Int, error) {
|
||||||
|
|
||||||
func (bc *ChainManager) Stop() {
|
func (bc *ChainManager) Stop() {
|
||||||
close(bc.quit)
|
close(bc.quit)
|
||||||
|
bc.wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
type queueEvent struct {
|
type queueEvent struct {
|
||||||
|
|
@ -593,6 +596,9 @@ func (self *ChainManager) merge(oldBlock, newBlock *types.Block) {
|
||||||
func (self *ChainManager) update() {
|
func (self *ChainManager) update() {
|
||||||
events := self.eventMux.Subscribe(queueEvent{})
|
events := self.eventMux.Subscribe(queueEvent{})
|
||||||
futureTimer := time.NewTicker(5 * time.Second)
|
futureTimer := time.NewTicker(5 * time.Second)
|
||||||
|
defer self.wg.Done()
|
||||||
|
defer futureTimer.Stop()
|
||||||
|
|
||||||
out:
|
out:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,10 @@ func New(config *Config) (*Ethereum, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
extraDb, err := ethdb.NewLDBDatabase(path.Join(config.DataDir, "extra"))
|
extraDb, err := newdb(path.Join(config.DataDir, "extra"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Perform database sanity checks
|
// Perform database sanity checks
|
||||||
d, _ := blockDb.Get([]byte("ProtocolVersion"))
|
d, _ := blockDb.Get([]byte("ProtocolVersion"))
|
||||||
|
|
@ -213,8 +216,6 @@ func New(config *Config) (*Ethereum, error) {
|
||||||
eth.txPool = core.NewTxPool(eth.EventMux(), eth.chainManager.State)
|
eth.txPool = core.NewTxPool(eth.EventMux(), eth.chainManager.State)
|
||||||
eth.blockProcessor = core.NewBlockProcessor(stateDb, extraDb, eth.pow, eth.txPool, eth.chainManager, eth.EventMux())
|
eth.blockProcessor = core.NewBlockProcessor(stateDb, extraDb, eth.pow, eth.txPool, eth.chainManager, eth.EventMux())
|
||||||
eth.chainManager.SetProcessor(eth.blockProcessor)
|
eth.chainManager.SetProcessor(eth.blockProcessor)
|
||||||
eth.whisper = whisper.New()
|
|
||||||
eth.shhVersionId = int(eth.whisper.Version())
|
|
||||||
eth.miner = miner.New(eth, eth.pow, config.MinerThreads)
|
eth.miner = miner.New(eth, eth.pow, config.MinerThreads)
|
||||||
eth.protocolManager = NewProtocolManager(config.ProtocolVersion, config.NetworkId, eth.txPool, eth.chainManager, eth.downloader)
|
eth.protocolManager = NewProtocolManager(config.ProtocolVersion, config.NetworkId, eth.txPool, eth.chainManager, eth.downloader)
|
||||||
|
|
||||||
|
|
@ -419,6 +420,7 @@ func (s *Ethereum) Stop() {
|
||||||
s.txSub.Unsubscribe() // quits txBroadcastLoop
|
s.txSub.Unsubscribe() // quits txBroadcastLoop
|
||||||
s.minedBlockSub.Unsubscribe() // quits blockBroadcastLoop
|
s.minedBlockSub.Unsubscribe() // quits blockBroadcastLoop
|
||||||
|
|
||||||
|
s.chainManager.Stop()
|
||||||
s.txPool.Stop()
|
s.txPool.Stop()
|
||||||
s.eventMux.Stop()
|
s.eventMux.Stop()
|
||||||
if s.whisper != nil {
|
if s.whisper != nil {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
|
@ -73,8 +74,8 @@ type btBlock struct {
|
||||||
|
|
||||||
type BlockTest struct {
|
type BlockTest struct {
|
||||||
Genesis *types.Block
|
Genesis *types.Block
|
||||||
Blocks []*types.Block
|
|
||||||
|
|
||||||
|
json *btJSON
|
||||||
preAccounts map[string]btAccount
|
preAccounts map[string]btAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,7 +89,7 @@ func LoadBlockTests(file string) (map[string]*BlockTest, error) {
|
||||||
for name, in := range bt {
|
for name, in := range bt {
|
||||||
var err error
|
var err error
|
||||||
if out[name], err = convertTest(in); err != nil {
|
if out[name], err = convertTest(in); err != nil {
|
||||||
return nil, fmt.Errorf("bad test %q: %v", err)
|
return out, fmt.Errorf("bad test %q: %v", name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
|
|
@ -124,6 +125,15 @@ func (t *BlockTest) InsertPreState(db common.Database) (*state.StateDB, error) {
|
||||||
return statedb, nil
|
return statedb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InsertBlocks loads the test's blocks into the given chain.
|
||||||
|
func (t *BlockTest) InsertBlocks(chain *core.ChainManager) error {
|
||||||
|
blocks, err := t.convertBlocks()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return chain.InsertChain(blocks)
|
||||||
|
}
|
||||||
|
|
||||||
func (t *BlockTest) ValidatePostState(statedb *state.StateDB) error {
|
func (t *BlockTest) ValidatePostState(statedb *state.StateDB) error {
|
||||||
for addrString, acct := range t.preAccounts {
|
for addrString, acct := range t.preAccounts {
|
||||||
// XXX: is is worth it checking for errors here?
|
// XXX: is is worth it checking for errors here?
|
||||||
|
|
@ -149,6 +159,21 @@ func (t *BlockTest) ValidatePostState(statedb *state.StateDB) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *BlockTest) convertBlocks() (blocks []*types.Block, err error) {
|
||||||
|
// the conversion handles errors by catching panics.
|
||||||
|
// you might consider this ugly, but the alternative (passing errors)
|
||||||
|
// would be much harder to read.
|
||||||
|
defer func() {
|
||||||
|
if recovered := recover(); recovered != nil {
|
||||||
|
buf := make([]byte, 64<<10)
|
||||||
|
buf = buf[:runtime.Stack(buf, false)]
|
||||||
|
err = fmt.Errorf("%v\n%s", recovered, buf)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
blocks = mustConvertBlocks(t.json.Blocks)
|
||||||
|
return blocks, nil
|
||||||
|
}
|
||||||
|
|
||||||
func convertTest(in *btJSON) (out *BlockTest, err error) {
|
func convertTest(in *btJSON) (out *BlockTest, err error) {
|
||||||
// the conversion handles errors by catching panics.
|
// the conversion handles errors by catching panics.
|
||||||
// you might consider this ugly, but the alternative (passing errors)
|
// you might consider this ugly, but the alternative (passing errors)
|
||||||
|
|
@ -160,9 +185,8 @@ func convertTest(in *btJSON) (out *BlockTest, err error) {
|
||||||
err = fmt.Errorf("%v\n%s", recovered, buf)
|
err = fmt.Errorf("%v\n%s", recovered, buf)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
out = &BlockTest{preAccounts: in.Pre}
|
out = &BlockTest{preAccounts: in.Pre, json: in}
|
||||||
out.Genesis = mustConvertGenesis(in.GenesisBlockHeader)
|
out.Genesis = mustConvertGenesis(in.GenesisBlockHeader)
|
||||||
out.Blocks = mustConvertBlocks(in.Blocks)
|
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,13 +211,13 @@ func mustConvertHeader(in btHeader) *types.Header {
|
||||||
UncleHash: mustConvertHash(in.UncleHash),
|
UncleHash: mustConvertHash(in.UncleHash),
|
||||||
ParentHash: mustConvertHash(in.ParentHash),
|
ParentHash: mustConvertHash(in.ParentHash),
|
||||||
Extra: mustConvertBytes(in.ExtraData),
|
Extra: mustConvertBytes(in.ExtraData),
|
||||||
GasUsed: mustConvertBigInt(in.GasUsed),
|
GasUsed: mustConvertBigInt(in.GasUsed, 10),
|
||||||
GasLimit: mustConvertBigInt(in.GasLimit),
|
GasLimit: mustConvertBigInt(in.GasLimit, 10),
|
||||||
Difficulty: mustConvertBigInt(in.Difficulty),
|
Difficulty: mustConvertBigInt(in.Difficulty, 10),
|
||||||
Time: mustConvertUint(in.Timestamp),
|
Time: mustConvertUint(in.Timestamp, 10),
|
||||||
}
|
}
|
||||||
// XXX cheats? :-)
|
// XXX cheats? :-)
|
||||||
header.SetNonce(common.BytesToHash(mustConvertBytes(in.Nonce)).Big().Uint64())
|
header.SetNonce(mustConvertUint(in.Nonce, 16))
|
||||||
return header
|
return header
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -203,7 +227,7 @@ func mustConvertBlocks(testBlocks []btBlock) []*types.Block {
|
||||||
var b types.Block
|
var b types.Block
|
||||||
r := bytes.NewReader(mustConvertBytes(inb.Rlp))
|
r := bytes.NewReader(mustConvertBytes(inb.Rlp))
|
||||||
if err := rlp.Decode(r, &b); err != nil {
|
if err := rlp.Decode(r, &b); err != nil {
|
||||||
panic(fmt.Errorf("invalid block %d: %q", i, inb.Rlp))
|
panic(fmt.Errorf("invalid block %d: %q\nerror: %v", i, inb.Rlp, err))
|
||||||
}
|
}
|
||||||
out = append(out, &b)
|
out = append(out, &b)
|
||||||
}
|
}
|
||||||
|
|
@ -214,7 +238,7 @@ func mustConvertBytes(in string) []byte {
|
||||||
if in == "0x" {
|
if in == "0x" {
|
||||||
return []byte{}
|
return []byte{}
|
||||||
}
|
}
|
||||||
h := strings.TrimPrefix(unfuckCPPHexInts(in), "0x")
|
h := nibbleFix(strings.TrimPrefix(in, "0x"))
|
||||||
out, err := hex.DecodeString(h)
|
out, err := hex.DecodeString(h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("invalid hex: %q", h))
|
panic(fmt.Errorf("invalid hex: %q", h))
|
||||||
|
|
@ -231,7 +255,7 @@ func mustConvertHash(in string) common.Hash {
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustConvertAddress(in string) common.Address {
|
func mustConvertAddress(in string) common.Address {
|
||||||
out, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
|
out, err := hex.DecodeString(nibbleFix(strings.TrimPrefix(in, "0x")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("invalid hex: %q", in))
|
panic(fmt.Errorf("invalid hex: %q", in))
|
||||||
}
|
}
|
||||||
|
|
@ -246,16 +270,18 @@ func mustConvertBloom(in string) types.Bloom {
|
||||||
return types.BytesToBloom(out)
|
return types.BytesToBloom(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustConvertBigInt(in string) *big.Int {
|
func mustConvertBigInt(in string, base int) *big.Int {
|
||||||
out, ok := new(big.Int).SetString(unfuckCPPHexInts(in), 0)
|
in = prepInt(base, in)
|
||||||
|
out, ok := new(big.Int).SetString(in, base)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Errorf("invalid integer: %q", in))
|
panic(fmt.Errorf("invalid integer: %q", in))
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustConvertUint(in string) uint64 {
|
func mustConvertUint(in string, base int) uint64 {
|
||||||
out, err := strconv.ParseUint(unfuckCPPHexInts(in), 0, 64)
|
in = prepInt(base, in)
|
||||||
|
out, err := strconv.ParseUint(in, base, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("invalid integer: %q", in))
|
panic(fmt.Errorf("invalid integer: %q", in))
|
||||||
}
|
}
|
||||||
|
|
@ -292,12 +318,22 @@ func findLine(data []byte, offset int64) (line int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func unfuckCPPHexInts(s string) string {
|
func prepInt(base int, s string) string {
|
||||||
if s == "0x" { // no respect for the empty value :(
|
if base == 16 {
|
||||||
return "0x00"
|
if strings.HasPrefix(s, "0x") {
|
||||||
|
s = s[2:]
|
||||||
}
|
}
|
||||||
if (len(s) % 2) != 0 { // motherfucking nibbles
|
if len(s) == 0 {
|
||||||
return "0x0" + s[2:]
|
s = "00"
|
||||||
|
}
|
||||||
|
s = nibbleFix(s)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func nibbleFix(s string) string {
|
||||||
|
if len(s)%2 != 0 {
|
||||||
|
s = "0" + s
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,15 +127,15 @@ func convertTestTypes(txTest TransactionTest) (sender, to common.Address,
|
||||||
txInputData = mustConvertBytes(txTest.Transaction.Data)
|
txInputData = mustConvertBytes(txTest.Transaction.Data)
|
||||||
rlpBytes = mustConvertBytes(txTest.Rlp)
|
rlpBytes = mustConvertBytes(txTest.Rlp)
|
||||||
|
|
||||||
gasLimit = mustConvertBigInt(txTest.Transaction.GasLimit)
|
gasLimit = mustConvertBigInt(txTest.Transaction.GasLimit, 16)
|
||||||
gasPrice = mustConvertBigInt(txTest.Transaction.GasPrice)
|
gasPrice = mustConvertBigInt(txTest.Transaction.GasPrice, 16)
|
||||||
value = mustConvertBigInt(txTest.Transaction.Value)
|
value = mustConvertBigInt(txTest.Transaction.Value, 16)
|
||||||
|
|
||||||
r = common.Bytes2Big(mustConvertBytes(txTest.Transaction.R))
|
r = common.Bytes2Big(mustConvertBytes(txTest.Transaction.R))
|
||||||
s = common.Bytes2Big(mustConvertBytes(txTest.Transaction.S))
|
s = common.Bytes2Big(mustConvertBytes(txTest.Transaction.S))
|
||||||
|
|
||||||
nonce = mustConvertUint(txTest.Transaction.Nonce)
|
nonce = mustConvertUint(txTest.Transaction.Nonce, 16)
|
||||||
v = mustConvertUint(txTest.Transaction.V)
|
v = mustConvertUint(txTest.Transaction.V, 16)
|
||||||
|
|
||||||
return sender, to, txInputData, rlpBytes, gasLimit, gasPrice, value, r, s, nonce, v, nil
|
return sender, to, txInputData, rlpBytes, gasLimit, gasPrice, value, r, s, nonce, v, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue