diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000000..cc9834bb9f --- /dev/null +++ b/.mailmap @@ -0,0 +1,12 @@ +Jeffrey Wilcke +Jeffrey Wilcke +Jeffrey Wilcke +Jeffrey Wilcke + +Viktor Trón + +Joseph Goulden + +Nick Savers + +Maran Hidskes \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index d09cbcdb09..21c15068b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: go go: - - 1.3 + - tip before_install: - sudo add-apt-repository ppa:ubuntu-sdk-team/ppa -y - sudo apt-get update -qq @@ -8,10 +8,10 @@ before_install: install: - go get code.google.com/p/go.tools/cmd/goimports - go get github.com/golang/lint/golint - # - go get code.google.com/p/go.tools/cmd/vet - - go get code.google.com/p/go.tools/cmd/cover + # - go get golang.org/x/tools/cmd/vet + - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi - go get github.com/mattn/goveralls - - ./install_deps.sh + - ETH_DEPS=$(go list -f '{{.Imports}} {{.TestImports}} {{.XTestImports}}' github.com/ethereum/go-ethereum/... | sed -e 's/\[//g' | sed -e 's/\]//g' | sed -e 's/C //g'); if [ "$ETH_DEPS" ]; then go get $ETH_DEPS; fi before_script: - gofmt -l -w . - goimports -l -w . @@ -19,7 +19,7 @@ before_script: # - go vet ./... # - go test -race ./... script: - - ./gocoverage.sh && goveralls -coverprofile=profile.cov -service=travis-ci -repotoken $COVERALLS_TOKEN + - ./gocoverage.sh env: - secure: "U2U1AmkU4NJBgKR/uUAebQY87cNL0+1JHjnLOmmXwxYYyj5ralWb1aSuSH3qSXiT93qLBmtaUkuv9fberHVqrbAeVlztVdUsKAq7JMQH+M99iFkC9UiRMqHmtjWJ0ok4COD1sRYixxi21wb/JrMe3M1iL4QJVS61iltjHhVdM64=" diff --git a/Dockerfile b/Dockerfile index 1f37ce892a..82ce9f7fc4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,14 +25,14 @@ RUN apt-get install -y qtbase5-private-dev qtdeclarative5-private-dev libqt5open ## Fetch and install serpent-go RUN go get -v -d github.com/ethereum/serpent-go WORKDIR $GOPATH/src/github.com/ethereum/serpent-go -RUN git checkout master +# RUN git checkout master RUN git submodule update --init RUN go install -v # Fetch and install go-ethereum RUN go get -v -d github.com/ethereum/go-ethereum/... WORKDIR $GOPATH/src/github.com/ethereum/go-ethereum -RUN git checkout poc8 +# RUN git checkout develop RUN ETH_DEPS=$(go list -f '{{.Imports}} {{.TestImports}} {{.XTestImports}}' github.com/ethereum/go-ethereum/... | sed -e 's/\[//g' | sed -e 's/\]//g' | sed -e 's/C //g'); if [ "$ETH_DEPS" ]; then go get $ETH_DEPS; fi RUN go install -v ./cmd/ethereum diff --git a/README.md b/README.md index 564e5c56dd..4830d93032 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,11 @@ Ethereum [![Build Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20master%20branch)](http://build.ethdev.com:8010/builders/Linux%20Go%20master%20branch/builds/-1) master [![Build Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](http://build.ethdev.com:8010/builders/Linux%20Go%20develop%20branch/builds/-1) develop +[![Coverage Status](https://coveralls.io/repos/ethereum/go-ethereum/badge.png?branch=tests)](https://coveralls.io/r/ethereum/go-ethereum?branch=tests) tests Ethereum Go Client © 2014 Jeffrey Wilcke. -Current state: Proof of Concept 0.7 +Current state: Proof of Concept 0.8 Ethereum is currently in its testing phase. diff --git a/_data/chain1 b/_data/chain1 deleted file mode 100755 index ef392e001e..0000000000 Binary files a/_data/chain1 and /dev/null differ diff --git a/_data/chain2 b/_data/chain2 deleted file mode 100755 index 48ed4d5ea9..0000000000 Binary files a/_data/chain2 and /dev/null differ diff --git a/_data/invalid1 b/_data/invalid1 new file mode 100755 index 0000000000..9c24b13e8e Binary files /dev/null and b/_data/invalid1 differ diff --git a/_data/valid1 b/_data/valid1 new file mode 100755 index 0000000000..809a55f1a6 Binary files /dev/null and b/_data/valid1 differ diff --git a/_data/valid2 b/_data/valid2 new file mode 100755 index 0000000000..3e9d2971a9 Binary files /dev/null and b/_data/valid2 differ diff --git a/_data/valid3 b/_data/valid3 new file mode 100755 index 0000000000..685bc9fd7b Binary files /dev/null and b/_data/valid3 differ diff --git a/_data/valid4 b/_data/valid4 new file mode 100755 index 0000000000..fc016057fa Binary files /dev/null and b/_data/valid4 differ diff --git a/cmd/ethereum/cmd.go b/cmd/ethereum/cmd.go index d8b9ea4875..8ffd868ed0 100644 --- a/cmd/ethereum/cmd.go +++ b/cmd/ethereum/cmd.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 General Public License -// along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package main import ( diff --git a/cmd/ethereum/flags.go b/cmd/ethereum/flags.go index 5567354912..f829744dc9 100644 --- a/cmd/ethereum/flags.go +++ b/cmd/ethereum/flags.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 General Public License -// along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package main import ( @@ -58,6 +61,10 @@ var ( DumpHash string DumpNumber int VmType int + ImportChain string + SHH bool + Dial bool + PrintVersion bool ) // flags specific to cli client @@ -87,12 +94,14 @@ func Init() { flag.StringVar(&OutboundPort, "port", "30303", "listening port") flag.StringVar(&NatType, "nat", "", "NAT support (UPNP|PMP) (none)") flag.StringVar(&PMPGateway, "pmp", "", "Gateway IP for PMP") - flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers") + flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers") flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on") flag.BoolVar(&StartRpc, "rpc", false, "start rpc server") flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server") flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)") flag.BoolVar(&UseSeed, "seed", true, "seed peers") + flag.BoolVar(&SHH, "shh", true, "whisper protocol (on)") + flag.BoolVar(&Dial, "dial", true, "dial out connections (on)") flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key") flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)") flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given") @@ -104,6 +113,7 @@ func Init() { flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0") flag.StringVar(&DiffType, "diff", "all", "sets the level of diff output [vm, all]. Has no effect if difftool=false") flag.BoolVar(&ShowGenesis, "genesis", false, "Dump the genesis block") + flag.StringVar(&ImportChain, "chain", "", "Imports given chain") flag.BoolVar(&Dump, "dump", false, "output the ethereum state in JSON format. Sub args [number, hash]") flag.StringVar(&DumpHash, "hash", "", "specify arg in hex") @@ -111,6 +121,7 @@ func Init() { flag.BoolVar(&StartMining, "mine", false, "start dagger mining") flag.BoolVar(&StartJsConsole, "js", false, "launches javascript console") + flag.BoolVar(&PrintVersion, "version", false, "prints version number") flag.Parse() diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go index da09e0b588..b816c678e7 100644 --- a/cmd/ethereum/main.go +++ b/cmd/ethereum/main.go @@ -1,36 +1,42 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 General Public License -// along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package main import ( "fmt" "os" "runtime" + "time" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/state" ) const ( ClientIdentifier = "Ethereum(G)" - Version = "0.7.9" + Version = "0.8.1" ) var clilogger = logger.NewLogger("CLI") @@ -38,40 +44,44 @@ var clilogger = logger.NewLogger("CLI") func main() { runtime.GOMAXPROCS(runtime.NumCPU()) + defer func() { + logger.Flush() + }() + utils.HandleInterrupt() // precedence: code-internal flag default < config file < environment variables < command line Init() // parsing command line - // If the difftool option is selected ignore all other log output - if DiffTool || Dump { - LogLevel = 0 + if PrintVersion { + printVersion() + return } utils.InitConfig(VmType, ConfigFile, Datadir, "ETH") - ethutil.Config.Diff = DiffTool - ethutil.Config.DiffType = DiffType - utils.InitDataDir(Datadir) + ethereum, err := eth.New(ð.Config{ + Name: ClientIdentifier, + Version: Version, + KeyStore: KeyStore, + DataDir: Datadir, + LogFile: LogFile, + LogLevel: LogLevel, + Identifier: Identifier, + MaxPeers: MaxPeer, + Port: OutboundPort, + NATType: PMPGateway, + PMPGateway: PMPGateway, + KeyRing: KeyRing, + Shh: SHH, + Dial: Dial, + }) - utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile) - - db := utils.NewDatabase() - err := utils.DBSanityCheck(db) if err != nil { - fmt.Println(err) - - os.Exit(1) + clilogger.Fatalln(err) } - keyManager := utils.NewKeyManager(KeyStore, Datadir, db) - - // create, import, export keys - utils.KeyTasks(keyManager, KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive) - - clientIdentity := utils.NewClientIdentity(ClientIdentifier, Version, Identifier, string(keyManager.PublicKey())) - - ethereum := utils.NewEthereum(db, clientIdentity, keyManager, utils.NatType(NatType, PMPGateway), OutboundPort, MaxPeer) + utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive) if Dump { var block *types.Block @@ -93,30 +103,27 @@ func main() { os.Exit(1) } - // block.GetRoot() does not exist - //fmt.Printf("RLP: %x\nstate: %x\nhash: %x\n", ethutil.Rlp(block), block.GetRoot(), block.Hash()) - // Leave the Println. This needs clean output for piping - fmt.Printf("%s\n", block.State().Dump()) + statedb := state.New(block.Root(), ethereum.Db()) + fmt.Printf("%s\n", statedb.Dump()) fmt.Println(block) - os.Exit(0) - } - - if ShowGenesis { - utils.ShowGenesis(ethereum) + return } if StartMining { utils.StartMining(ethereum) } - // better reworked as cases - if StartJsConsole { - InitJsConsole(ethereum) - } else if len(InputFile) > 0 { - ExecJsFile(ethereum, InputFile) + if len(ImportChain) > 0 { + start := time.Now() + err := utils.ImportChain(ethereum, ImportChain) + if err != nil { + clilogger.Infoln(err) + } + clilogger.Infoln("import done in", time.Since(start)) + return } if StartRpc { @@ -129,7 +136,21 @@ func main() { utils.StartEthereum(ethereum, UseSeed) + if StartJsConsole { + InitJsConsole(ethereum) + } else if len(InputFile) > 0 { + ExecJsFile(ethereum, InputFile) + } // this blocks the thread ethereum.WaitForShutdown() - logger.Flush() +} + +func printVersion() { + fmt.Printf(`%v %v +PV=%d +GOOS=%s +GO=%s +GOPATH=%s +GOROOT=%s +`, ClientIdentifier, Version, eth.ProtocolVersion, runtime.GOOS, runtime.Version(), os.Getenv("GOPATH"), runtime.GOROOT()) } diff --git a/cmd/ethereum/repl/repl.go b/cmd/ethereum/repl/repl.go index 4a7880ff42..78bb19cecf 100644 --- a/cmd/ethereum/repl/repl.go +++ b/cmd/ethereum/repl/repl.go @@ -86,11 +86,6 @@ func (self *JSRepl) Stop() { } func (self *JSRepl) parseInput(code string) { - defer func() { - if r := recover(); r != nil { - fmt.Println("[native] error", r) - } - }() value, err := self.re.Run(code) if err != nil { diff --git a/cmd/ethtest/.bowerrc b/cmd/ethtest/.bowerrc new file mode 100644 index 0000000000..c3a8813e8b --- /dev/null +++ b/cmd/ethtest/.bowerrc @@ -0,0 +1,5 @@ +{ + "directory": "example/js/", + "cwd": "./", + "analytics": false +} \ No newline at end of file diff --git a/cmd/ethtest/.editorconfig b/cmd/ethtest/.editorconfig new file mode 100644 index 0000000000..60a2751d33 --- /dev/null +++ b/cmd/ethtest/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false \ No newline at end of file diff --git a/cmd/mist/assets/ext/eth.js/.gitignore b/cmd/ethtest/.gitignore similarity index 85% rename from cmd/mist/assets/ext/eth.js/.gitignore rename to cmd/ethtest/.gitignore index de3a847ace..399b6dc882 100644 --- a/cmd/mist/assets/ext/eth.js/.gitignore +++ b/cmd/ethtest/.gitignore @@ -4,6 +4,7 @@ # or operating system, you probably want to add a global ignore instead: # git config --global core.excludesfile ~/.gitignore_global +*.swp /tmp */**/*un~ *un~ @@ -11,4 +12,7 @@ */**/.DS_Store ethereum/ethereum ethereal/ethereal - +example/js +node_modules +bower_components +npm-debug.log diff --git a/cmd/ethtest/.jshintrc b/cmd/ethtest/.jshintrc new file mode 100644 index 0000000000..c0ec5f89d1 --- /dev/null +++ b/cmd/ethtest/.jshintrc @@ -0,0 +1,50 @@ +{ + "predef": [ + "console", + "require", + "equal", + "test", + "testBoth", + "testWithDefault", + "raises", + "deepEqual", + "start", + "stop", + "ok", + "strictEqual", + "module", + "expect", + "reject", + "impl" + ], + + "esnext": true, + "proto": true, + "node" : true, + "browser" : true, + "browserify" : true, + + "boss" : true, + "curly": false, + "debug": true, + "devel": true, + "eqeqeq": true, + "evil": true, + "forin": false, + "immed": false, + "laxbreak": false, + "newcap": true, + "noarg": true, + "noempty": false, + "nonew": false, + "nomen": false, + "onevar": false, + "plusplus": false, + "regexp": false, + "undef": true, + "sub": true, + "strict": false, + "white": false, + "shadow": true, + "eqnull": true +} \ No newline at end of file diff --git a/cmd/ethtest/.npmignore b/cmd/ethtest/.npmignore new file mode 100644 index 0000000000..5bbffe4fd3 --- /dev/null +++ b/cmd/ethtest/.npmignore @@ -0,0 +1,9 @@ +example/js +node_modules +test +.gitignore +.editorconfig +.travis.yml +.npmignore +component.json +testling.html \ No newline at end of file diff --git a/cmd/ethtest/.travis.yml b/cmd/ethtest/.travis.yml new file mode 100644 index 0000000000..fafacbd5a1 --- /dev/null +++ b/cmd/ethtest/.travis.yml @@ -0,0 +1,11 @@ +language: node_js +node_js: + - "0.11" + - "0.10" +before_script: + - npm install + - npm install jshint +script: + - "jshint *.js lib" +after_script: + - npm run-script gulp diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go index 94ab779dba..ac473d58c0 100644 --- a/cmd/ethtest/main.go +++ b/cmd/ethtest/main.go @@ -17,8 +17,6 @@ /** * @authors: * Jeffrey Wilcke - * @date 2014 - * */ package main @@ -26,11 +24,13 @@ package main import ( "bytes" "encoding/json" + "io" "io/ioutil" "log" "os" "strings" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/tests/helper" @@ -43,8 +43,8 @@ type Account struct { Storage map[string]string } -func StateObjectFromAccount(addr string, account Account) *state.StateObject { - obj := state.NewStateObject(ethutil.Hex2Bytes(addr)) +func StateObjectFromAccount(db ethutil.Database, addr string, account Account) *state.StateObject { + obj := state.NewStateObject(ethutil.Hex2Bytes(addr), db) obj.SetBalance(ethutil.Big(account.Balance)) if ethutil.IsHex(account.Code) { @@ -66,19 +66,20 @@ type VmTest struct { Pre map[string]Account } -func RunVmTest(js string) (failed int) { +func RunVmTest(r io.Reader) (failed int) { tests := make(map[string]VmTest) - data, _ := ioutil.ReadAll(strings.NewReader(js)) + data, _ := ioutil.ReadAll(r) err := json.Unmarshal(data, &tests) if err != nil { log.Fatalln(err) } for name, test := range tests { - state := state.New(helper.NewTrie()) + db, _ := ethdb.NewMemDatabase() + state := state.New(nil, db) for addr, account := range test.Pre { - obj := StateObjectFromAccount(addr, account) + obj := StateObjectFromAccount(db, addr, account) state.SetStateObject(obj) } @@ -95,10 +96,15 @@ func RunVmTest(js string) (failed int) { failed = 1 } - gexp := ethutil.Big(test.Gas) - if gexp.Cmp(gas) != 0 { - log.Printf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas) + if len(test.Gas) == 0 && err == nil { + log.Printf("0 gas indicates error but no error given by VM") failed = 1 + } else { + gexp := ethutil.Big(test.Gas) + if gexp.Cmp(gas) != 0 { + log.Printf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas) + failed = 1 + } } for addr, account := range test.Post { @@ -120,9 +126,10 @@ func RunVmTest(js string) (failed int) { func main() { helper.Logger.SetLogLevel(5) - if len(os.Args) == 1 { - log.Fatalln("no json supplied") - } - os.Exit(RunVmTest(os.Args[1])) + if len(os.Args) > 1 { + os.Exit(RunVmTest(strings.NewReader(os.Args[1]))) + } else { + os.Exit(RunVmTest(os.Stdin)) + } } diff --git a/cmd/evm/main.go b/cmd/evm/main.go index c6c986a04a..f819386fe0 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -17,8 +17,6 @@ /** * @authors * Jeffrey Wilcke - * @date 2014 - * */ package main @@ -38,7 +36,6 @@ import ( "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/state" - "github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/vm" ) @@ -65,7 +62,7 @@ func main() { ethutil.ReadConfig("/tmp/evmtest", "/tmp/evm", "") db, _ := ethdb.NewMemDatabase() - statedb := state.New(trie.New(db, "")) + statedb := state.New(nil, db) sender := statedb.NewStateObject([]byte("sender")) receiver := statedb.NewStateObject([]byte("receiver")) //receiver.SetCode([]byte(*code)) @@ -133,6 +130,12 @@ func (self *VMEnv) Value() *big.Int { return self.value } func (self *VMEnv) GasLimit() *big.Int { return big.NewInt(1000000000) } func (self *VMEnv) Depth() int { return 0 } func (self *VMEnv) SetDepth(i int) { self.depth = i } +func (self *VMEnv) GetHash(n uint64) []byte { + if self.block.Number().Cmp(big.NewInt(int64(n))) == 0 { + return self.block.Hash() + } + return nil +} func (self *VMEnv) AddLog(log state.Log) { self.state.AddLog(log) } @@ -141,24 +144,22 @@ func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error { } func (self *VMEnv) vm(addr, data []byte, gas, price, value *big.Int) *core.Execution { - evm := vm.New(self, vm.DebugVmTy) - - return core.NewExecution(evm, addr, data, gas, price, value) + return core.NewExecution(self, addr, data, gas, price, value) } -func (self *VMEnv) Call(caller vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { +func (self *VMEnv) Call(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { exe := self.vm(addr, data, gas, price, value) ret, err := exe.Call(addr, caller) self.Gas = exe.Gas return ret, err } -func (self *VMEnv) CallCode(caller vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { +func (self *VMEnv) CallCode(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { exe := self.vm(caller.Address(), data, gas, price, value) return exe.Call(addr, caller) } -func (self *VMEnv) Create(caller vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ClosureRef) { +func (self *VMEnv) Create(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { exe := self.vm(addr, data, gas, price, value) return exe.Create(caller) } diff --git a/cmd/mist/assets/ext/eth.js/README.md b/cmd/mist/assets/ext/eth.js/README.md deleted file mode 100644 index 86e2969bef..0000000000 --- a/cmd/mist/assets/ext/eth.js/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Ethereum JavaScript API - -This is the Ethereum compatible JavaScript API using `Promise`s -which implements the [Generic JSON RPC](https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC) spec. - -For an example see `index.html`. - -**Please note this repo is in it's early stage.** - -If you'd like to run a WebSocket ethereum node check out -[go-ethereum](https://github.com/ethereum/go-ethereum). - -To install ethereum and spawn a node: - -``` -go get github.com/ethereum/go-ethereum/ethereum -ethereum -ws -loglevel=4 -``` diff --git a/cmd/mist/assets/ext/eth.js/httprpc.js b/cmd/mist/assets/ext/eth.js/httprpc.js deleted file mode 100644 index 085b4693d4..0000000000 --- a/cmd/mist/assets/ext/eth.js/httprpc.js +++ /dev/null @@ -1,70 +0,0 @@ -(function () { - var HttpRpcProvider = function (host) { - this.handlers = []; - this.host = host; - }; - - function formatJsonRpcObject(object) { - return { - jsonrpc: '2.0', - method: object.call, - params: object.args, - id: object._id - } - }; - - function formatJsonRpcMessage(message) { - var object = JSON.parse(message); - - return { - _id: object.id, - data: object.result - }; - }; - - HttpRpcProvider.prototype.sendRequest = function (payload, cb) { - var data = formatJsonRpcObject(payload); - - var request = new XMLHttpRequest(); - request.open("POST", this.host, true); - request.send(JSON.stringify(data)); - request.onreadystatechange = function () { - if (request.readyState === 4 && cb) { - cb(request); - } - } - }; - - HttpRpcProvider.prototype.send = function (payload) { - var self = this; - this.sendRequest(payload, function (request) { - self.handlers.forEach(function (handler) { - handler.call(self, formatJsonRpcMessage(request.responseText)); - }); - }); - }; - - HttpRpcProvider.prototype.poll = function (payload, id) { - var self = this; - this.sendRequest(payload, function (request) { - var parsed = JSON.parse(request.responseText); - if (parsed.result instanceof Array ? parsed.result.length === 0 : !parsed.result) { - return; - } - self.handlers.forEach(function (handler) { - handler.call(self, {_event: payload.call, _id: id, data: parsed.result}); - }); - }); - }; - - Object.defineProperty(HttpRpcProvider.prototype, "onmessage", { - set: function (handler) { - this.handlers.push(handler); - } - }); - - if (typeof(web3) !== "undefined" && web3.providers !== undefined) { - web3.providers.HttpRpcProvider = HttpRpcProvider; - } -})(); - diff --git a/cmd/mist/assets/ext/eth.js/index.html b/cmd/mist/assets/ext/eth.js/index.html deleted file mode 100644 index 2b3f50a141..0000000000 --- a/cmd/mist/assets/ext/eth.js/index.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - -

std::name_reg

- - -
- - - - diff --git a/cmd/mist/assets/ext/eth.js/main.js b/cmd/mist/assets/ext/eth.js/main.js deleted file mode 100644 index 5c7ca06034..0000000000 --- a/cmd/mist/assets/ext/eth.js/main.js +++ /dev/null @@ -1,432 +0,0 @@ -(function(window) { - function isPromise(o) { - return o instanceof Promise - } - - function flattenPromise (obj) { - if (obj instanceof Promise) { - return Promise.resolve(obj); - } - - if (obj instanceof Array) { - return new Promise(function (resolve) { - var promises = obj.map(function (o) { - return flattenPromise(o); - }); - - return Promise.all(promises).then(function (res) { - for (var i = 0; i < obj.length; i++) { - obj[i] = res[i]; - } - resolve(obj); - }); - }); - } - - if (obj instanceof Object) { - return new Promise(function (resolve) { - var keys = Object.keys(obj); - var promises = keys.map(function (key) { - return flattenPromise(obj[key]); - }); - - return Promise.all(promises).then(function (res) { - for (var i = 0; i < keys.length; i++) { - obj[keys[i]] = res[i]; - } - resolve(obj); - }); - }); - } - - return Promise.resolve(obj); - }; - - var ethMethods = function () { - var blockCall = function (args) { - return typeof args[0] === "string" ? "blockByHash" : "blockByNumber"; - }; - - var transactionCall = function (args) { - return typeof args[0] === "string" ? 'transactionByHash' : 'transactionByNumber'; - }; - - var uncleCall = function (args) { - return typeof args[0] === "string" ? 'uncleByHash' : 'uncleByNumber'; - }; - - var methods = [ - { name: 'balanceAt', call: 'balanceAt' }, - { name: 'stateAt', call: 'stateAt' }, - { name: 'countAt', call: 'countAt'}, - { name: 'codeAt', call: 'codeAt' }, - { name: 'transact', call: 'transact' }, - { name: 'call', call: 'call' }, - { name: 'block', call: blockCall }, - { name: 'transaction', call: transactionCall }, - { name: 'uncle', call: uncleCall }, - { name: 'compile', call: 'compile' } - ]; - return methods; - }; - - var ethProperties = function () { - return [ - { name: 'coinbase', getter: 'coinbase', setter: 'setCoinbase' }, - { name: 'listening', getter: 'listening', setter: 'setListening' }, - { name: 'mining', getter: 'mining', setter: 'setMining' }, - { name: 'gasPrice', getter: 'gasPrice' }, - { name: 'account', getter: 'account' }, - { name: 'accounts', getter: 'accounts' }, - { name: 'peerCount', getter: 'peerCount' }, - { name: 'defaultBlock', getter: 'defaultBlock', setter: 'setDefaultBlock' }, - { name: 'number', getter: 'number'} - ]; - }; - - var dbMethods = function () { - return [ - { name: 'put', call: 'put' }, - { name: 'get', call: 'get' }, - { name: 'putString', call: 'putString' }, - { name: 'getString', call: 'getString' } - ]; - }; - - var shhMethods = function () { - return [ - { name: 'post', call: 'post' }, - { name: 'newIdentity', call: 'newIdentity' }, - { name: 'haveIdentity', call: 'haveIdentity' }, - { name: 'newGroup', call: 'newGroup' }, - { name: 'addToGroup', call: 'addToGroup' } - ]; - }; - - var ethWatchMethods = function () { - var newFilter = function (args) { - return typeof args[0] === 'string' ? 'newFilterString' : 'newFilter'; - }; - - return [ - { name: 'newFilter', call: newFilter }, - { name: 'uninstallFilter', call: 'uninstallFilter' }, - { name: 'getMessages', call: 'getMessages' } - ]; - }; - - var shhWatchMethods = function () { - return [ - { name: 'newFilter', call: 'shhNewFilter' }, - { name: 'uninstallFilter', call: 'shhUninstallFilter' }, - { name: 'getMessage', call: 'shhGetMessages' } - ]; - }; - - var setupMethods = function (obj, methods) { - methods.forEach(function (method) { - obj[method.name] = function () { - return flattenPromise(Array.prototype.slice.call(arguments)).then(function (args) { - var call = typeof method.call === "function" ? method.call(args) : method.call; - return {call: call, args: args}; - }).then(function (request) { - return new Promise(function (resolve, reject) { - web3.provider.send(request, function (result) { - //if (result || typeof result === "boolean") { - resolve(result); - return; - //} - //reject(result); - }); - }); - }).catch(function( err) { - console.error(err); - }); - }; - }); - }; - - var setupProperties = function (obj, properties) { - properties.forEach(function (property) { - var proto = {}; - proto.get = function () { - return new Promise(function(resolve, reject) { - web3.provider.send({call: property.getter}, function(result) { - resolve(result); - }); - }); - }; - if (property.setter) { - proto.set = function (val) { - return flattenPromise([val]).then(function (args) { - return new Promise(function (resolve) { - web3.provider.send({call: property.setter, args: args}, function (result) { - resolve(result); - }); - }); - }).catch(function (err) { - console.error(err); - }); - } - } - Object.defineProperty(obj, property.name, proto); - }); - }; - - var web3 = { - _callbacks: {}, - _events: {}, - providers: {}, - toHex: function(str) { - var hex = ""; - for(var i = 0; i < str.length; i++) { - var n = str.charCodeAt(i).toString(16); - hex += n.length < 2 ? '0' + n : n; - } - - return hex; - }, - - toAscii: function(hex) { - // Find termination - var str = ""; - var i = 0, l = hex.length; - for(; i < l; i+=2) { - var code = hex.charCodeAt(i) - if(code == 0) { - break; - } - - str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); - } - - return str; - }, - - toDecimal: function (val) { - return parseInt(val, 16); - }, - - fromAscii: function(str, pad) { - pad = pad === undefined ? 32 : pad; - var hex = this.toHex(str); - while(hex.length < pad*2) - hex += "00"; - return hex - }, - - eth: { - prototype: Object(), - watch: function (params) { - return new Filter(params, ethWatch); - }, - }, - - db: { - prototype: Object() - }, - - shh: { - prototype: Object(), - watch: function (params) { - return new Filter(params, shhWatch); - } - }, - - on: function(event, id, cb) { - if(web3._events[event] === undefined) { - web3._events[event] = {}; - } - - web3._events[event][id] = cb; - return this - }, - - off: function(event, id) { - if(web3._events[event] !== undefined) { - delete web3._events[event][id]; - } - - return this - }, - - trigger: function(event, id, data) { - var callbacks = web3._events[event]; - if (!callbacks || !callbacks[id]) { - return; - } - var cb = callbacks[id]; - cb(data); - }, - }; - - var eth = web3.eth; - setupMethods(eth, ethMethods()); - setupProperties(eth, ethProperties()); - setupMethods(web3.db, dbMethods()); - setupMethods(web3.shh, shhMethods()); - - var ethWatch = { - changed: 'changed' - }; - setupMethods(ethWatch, ethWatchMethods()); - var shhWatch = { - changed: 'shhChanged' - }; - setupMethods(shhWatch, shhWatchMethods()); - - var ProviderManager = function() { - this.queued = []; - this.polls = []; - this.ready = false; - this.provider = undefined; - this.id = 1; - - var self = this; - var poll = function () { - if (self.provider && self.provider.poll) { - self.polls.forEach(function (data) { - data.data._id = self.id; - self.id++; - self.provider.poll(data.data, data.id); - }); - } - setTimeout(poll, 12000); - }; - poll(); - }; - - ProviderManager.prototype.send = function(data, cb) { - data._id = this.id; - if (cb) { - web3._callbacks[data._id] = cb; - } - - data.args = data.args || []; - this.id++; - - if(this.provider !== undefined) { - this.provider.send(data); - } else { - console.warn("provider is not set"); - this.queued.push(data); - } - }; - - ProviderManager.prototype.set = function(provider) { - if(this.provider !== undefined && this.provider.unload !== undefined) { - this.provider.unload(); - } - - this.provider = provider; - this.ready = true; - }; - - ProviderManager.prototype.sendQueued = function() { - for(var i = 0; this.queued.length; i++) { - // Resend - this.send(this.queued[i]); - } - }; - - ProviderManager.prototype.installed = function() { - return this.provider !== undefined; - }; - - ProviderManager.prototype.startPolling = function (data, pollId) { - if (!this.provider || !this.provider.poll) { - return; - } - this.polls.push({data: data, id: pollId}); - }; - - ProviderManager.prototype.stopPolling = function (pollId) { - for (var i = this.polls.length; i--;) { - var poll = this.polls[i]; - if (poll.id === pollId) { - this.polls.splice(i, 1); - } - } - }; - - web3.provider = new ProviderManager(); - - web3.setProvider = function(provider) { - provider.onmessage = messageHandler; - web3.provider.set(provider); - web3.provider.sendQueued(); - }; - - var Filter = function(options, impl) { - this.impl = impl; - this.callbacks = []; - - var self = this; - this.promise = impl.newFilter(options); - this.promise.then(function (id) { - self.id = id; - web3.on(impl.changed, id, self.trigger.bind(self)); - web3.provider.startPolling({call: impl.changed, args: [id]}, id); - }); - }; - - Filter.prototype.arrived = function(callback) { - this.changed(callback); - } - - Filter.prototype.changed = function(callback) { - var self = this; - this.promise.then(function(id) { - self.callbacks.push(callback); - }); - }; - - Filter.prototype.trigger = function(messages) { - for(var i = 0; i < this.callbacks.length; i++) { - this.callbacks[i].call(this, messages); - } - }; - - Filter.prototype.uninstall = function() { - var self = this; - this.promise.then(function (id) { - self.impl.uninstallFilter(id); - web3.provider.stopPolling(id); - web3.off(impl.changed, id); - }); - }; - - Filter.prototype.messages = function() { - var self = this; - return this.promise.then(function (id) { - return self.impl.getMessages(id); - }); - }; - - function messageHandler(data) { - if(data._event !== undefined) { - web3.trigger(data._event, data._id, data.data); - return; - } - - if(data._id) { - var cb = web3._callbacks[data._id]; - if (cb) { - cb.call(this, data.data) - delete web3._callbacks[data._id]; - } - } - } - - /* - // Install default provider - if(!web3.provider.installed()) { - var sock = new web3.WebSocket("ws://localhost:40404/eth"); - - web3.setProvider(sock); - } - */ - - window.web3 = web3; - -})(this); diff --git a/cmd/mist/assets/ext/eth.js/qt.js b/cmd/mist/assets/ext/eth.js/qt.js deleted file mode 100644 index 644c377378..0000000000 --- a/cmd/mist/assets/ext/eth.js/qt.js +++ /dev/null @@ -1,27 +0,0 @@ -(function() { - var QtProvider = function() { - this.handlers = []; - - var self = this; - navigator.qt.onmessage = function (message) { - self.handlers.forEach(function (handler) { - handler.call(self, JSON.parse(message.data)); - }); - } - }; - - QtProvider.prototype.send = function(payload) { - navigator.qt.postMessage(JSON.stringify(payload)); - }; - - Object.defineProperty(QtProvider.prototype, "onmessage", { - set: function(handler) { - this.handlers.push(handler); - }, - }); - - if(typeof(web3) !== "undefined" && web3.providers !== undefined) { - web3.providers.QtProvider = QtProvider; - } -})(); - diff --git a/cmd/mist/assets/ext/eth.js/websocket.js b/cmd/mist/assets/ext/eth.js/websocket.js deleted file mode 100644 index 732a086f29..0000000000 --- a/cmd/mist/assets/ext/eth.js/websocket.js +++ /dev/null @@ -1,51 +0,0 @@ -(function() { - var WebSocketProvider = function(host) { - // onmessage handlers - this.handlers = []; - // queue will be filled with messages if send is invoked before the ws is ready - this.queued = []; - this.ready = false; - - this.ws = new WebSocket(host); - - var self = this; - this.ws.onmessage = function(event) { - for(var i = 0; i < self.handlers.length; i++) { - self.handlers[i].call(self, JSON.parse(event.data), event) - } - }; - - this.ws.onopen = function() { - self.ready = true; - - for(var i = 0; i < self.queued.length; i++) { - // Resend - self.send(self.queued[i]); - } - }; - }; - WebSocketProvider.prototype.send = function(payload) { - if(this.ready) { - var data = JSON.stringify(payload); - - this.ws.send(data); - } else { - this.queued.push(payload); - } - }; - - WebSocketProvider.prototype.onMessage = function(handler) { - this.handlers.push(handler); - }; - - WebSocketProvider.prototype.unload = function() { - this.ws.close(); - }; - Object.defineProperty(WebSocketProvider.prototype, "onmessage", { - set: function(provider) { this.onMessage(provider); } - }); - - if(typeof(web3) !== "undefined" && web3.providers !== undefined) { - web3.providers.WebSocketProvider = WebSocketProvider; - } -})(); diff --git a/cmd/mist/assets/ext/ethereum.js b/cmd/mist/assets/ext/ethereum.js deleted file mode 100644 index aeb79e488d..0000000000 --- a/cmd/mist/assets/ext/ethereum.js +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 General Public License -// along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA - -// Main Ethereum library -window.eth = { - prototype: Object(), - _callbacks: {}, - _onCallbacks: {}, - - test: function() { - var t = undefined; - postData({call: "test"}) - navigator.qt.onmessage = function(d) {console.log("onmessage called"); t = d; } - for(;;) { - if(t !== undefined) { - return t - } - } - }, - - mutan: function(code, cb) { - postData({call: "mutan", args: [code]}, cb) - }, - - toHex: function(str) { - var hex = ""; - for(var i = 0; i < str.length; i++) { - var n = str.charCodeAt(i).toString(16); - hex += n.length < 2 ? '0' + n : n; - } - - return hex; - }, - - toAscii: function(hex) { - // Find termination - var str = ""; - var i = 0, l = hex.length; - for(; i < l; i+=2) { - var code = hex.charCodeAt(i) - if(code == 0) { - break; - } - - str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); - } - - return str; - }, - - fromAscii: function(str, pad) { - if(pad === undefined) { - pad = 32 - } - - var hex = this.toHex(str); - - while(hex.length < pad*2) - hex += "00"; - - return hex - }, - - - // Retrieve block - // - // Either supply a number or a string. Type is determent for the lookup method - // string - Retrieves the block by looking up the hash - // number - Retrieves the block by looking up the block number - getBlock: function(numberOrHash, cb) { - var func; - if(typeof numberOrHash == "string") { - func = "getBlockByHash"; - } else { - func = "getBlockByNumber"; - } - postData({call: func, args: [numberOrHash]}, cb); - }, - - // Create transaction - // - // Transact between two state objects - transact: function(params, cb) { - if(params === undefined) { - params = {}; - } - - if(params.endowment !== undefined) - params.value = params.endowment; - if(params.code !== undefined) - params.data = params.code; - - // Make sure everything is string - var fields = ["to", "from", "value", "gas", "gasPrice"]; - for(var i = 0; i < fields.length; i++) { - if(params[fields[i]] === undefined) { - params[fields[i]] = ""; - } - params[fields[i]] = params[fields[i]].toString(); - } - - var data; - if(typeof params.data === "object") { - data = ""; - for(var i = 0; i < params.data.length; i++) { - data += params.data[i] - } - } else { - data = params.data; - } - - postData({call: "transact", args: [params.from, params.to, params.value, params.gas, params.gasPrice, "0x"+data]}, cb); - }, - - getMessages: function(filter, cb) { - postData({call: "messages", args: [filter]}, cb); - }, - - getStorageAt: function(address, storageAddress, cb) { - postData({call: "getStorage", args: [address, storageAddress]}, cb); - }, - - getEachStorageAt: function(address, cb){ - postData({call: "getEachStorage", args: [address]}, cb); - }, - - getKey: function(cb) { - postData({call: "getKey"}, cb); - }, - - getTxCountAt: function(address, cb) { - postData({call: "getTxCountAt", args: [address]}, cb); - }, - getIsMining: function(cb){ - postData({call: "getIsMining"}, cb) - }, - getIsListening: function(cb){ - postData({call: "getIsListening"}, cb) - }, - getCoinBase: function(cb){ - postData({call: "getCoinBase"}, cb); - }, - getPeerCount: function(cb){ - postData({call: "getPeerCount"}, cb); - }, - getBalanceAt: function(address, cb) { - postData({call: "getBalance", args: [address]}, cb); - }, - getTransactionsFor: function(address, cb) { - postData({call: "getTransactionsFor", args: [address]}, cb); - }, - - getSecretToAddress: function(sec, cb) { - postData({call: "getSecretToAddress", args: [sec]}, cb); - }, - - /* - watch: function(address, storageAddrOrCb, cb) { - var ev; - if(cb === undefined) { - cb = storageAddrOrCb; - storageAddrOrCb = ""; - ev = "object:"+address; - } else { - ev = "storage:"+address+":"+storageAddrOrCb; - } - - eth.on(ev, cb) - - postData({call: "watch", args: [address, storageAddrOrCb]}); - }, - - disconnect: function(address, storageAddrOrCb, cb) { - var ev; - if(cb === undefined) { - cb = storageAddrOrCb; - storageAddrOrCb = ""; - ev = "object:"+address; - } else { - ev = "storage:"+address+":"+storageAddrOrCb; - } - - eth.off(ev, cb) - - postData({call: "disconnect", args: [address, storageAddrOrCb]}); - }, - */ - - watch: function(options) { - var filter = new Filter(options); - filter.number = newWatchNum().toString() - - postData({call: "watch", args: [options, filter.number]}) - - return filter; - }, - - set: function(props) { - postData({call: "set", args: props}); - }, - - on: function(event, cb) { - if(eth._onCallbacks[event] === undefined) { - eth._onCallbacks[event] = []; - } - - eth._onCallbacks[event].push(cb); - - return this - }, - - off: function(event, cb) { - if(eth._onCallbacks[event] !== undefined) { - var callbacks = eth._onCallbacks[event]; - for(var i = 0; i < callbacks.length; i++) { - if(callbacks[i] === cb) { - delete callbacks[i]; - } - } - } - - return this - }, - - trigger: function(event, data) { - var callbacks = eth._onCallbacks[event]; - if(callbacks !== undefined) { - for(var i = 0; i < callbacks.length; i++) { - // Figure out whether the returned data was an array - // array means multiple return arguments (multiple params) - if(data instanceof Array) { - callbacks[i].apply(this, data); - } else { - callbacks[i].call(this, data); - } - } - } - }, -} - - -var Filter = function(options) { - this.options = options; -}; -Filter.prototype.changed = function(callback) { - // Register the watched:. Qml will call the appropriate event if anything - // interesting happens in the land of Go. - eth.on("watched:"+this.number, callback) -} -Filter.prototype.getMessages = function(cb) { - return eth.getMessages(this.options, cb) -} - -var watchNum = 0; -function newWatchNum() { - return watchNum++; -} - -function postData(data, cb) { - data._seed = Math.floor(Math.random() * 1000000) - if(cb) { - eth._callbacks[data._seed] = cb; - } - - if(data.args === undefined) { - data.args = []; - } - - navigator.qt.postMessage(JSON.stringify(data)); -} - -navigator.qt.onmessage = function(ev) { - var data = JSON.parse(ev.data) - - if(data._event !== undefined) { - eth.trigger(data._event, data.data); - } else { - if(data._seed) { - var cb = eth._callbacks[data._seed]; - if(cb) { - cb.call(this, data.data) - - // Remove the "trigger" callback - delete eth._callbacks[ev._seed]; - } - } - } -} - -eth.on("chain:changed", function() { -}) - -eth.on("messages", { /* filters */}, function(messages){ -}) - -eth.on("pending:changed", function() { -}) - diff --git a/cmd/mist/assets/ext/ethereum.js/.bowerrc b/cmd/mist/assets/ext/ethereum.js/.bowerrc new file mode 100644 index 0000000000..c3a8813e8b --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/.bowerrc @@ -0,0 +1,5 @@ +{ + "directory": "example/js/", + "cwd": "./", + "analytics": false +} \ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/.editorconfig b/cmd/mist/assets/ext/ethereum.js/.editorconfig new file mode 100644 index 0000000000..60a2751d33 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false \ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/.gitignore b/cmd/mist/assets/ext/ethereum.js/.gitignore new file mode 100644 index 0000000000..399b6dc882 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/.gitignore @@ -0,0 +1,18 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. +# +# If you find yourself ignoring temporary files generated by your text editor +# or operating system, you probably want to add a global ignore instead: +# git config --global core.excludesfile ~/.gitignore_global + +*.swp +/tmp +*/**/*un~ +*un~ +.DS_Store +*/**/.DS_Store +ethereum/ethereum +ethereal/ethereal +example/js +node_modules +bower_components +npm-debug.log diff --git a/cmd/mist/assets/ext/ethereum.js/.jshintrc b/cmd/mist/assets/ext/ethereum.js/.jshintrc new file mode 100644 index 0000000000..c0ec5f89d1 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/.jshintrc @@ -0,0 +1,50 @@ +{ + "predef": [ + "console", + "require", + "equal", + "test", + "testBoth", + "testWithDefault", + "raises", + "deepEqual", + "start", + "stop", + "ok", + "strictEqual", + "module", + "expect", + "reject", + "impl" + ], + + "esnext": true, + "proto": true, + "node" : true, + "browser" : true, + "browserify" : true, + + "boss" : true, + "curly": false, + "debug": true, + "devel": true, + "eqeqeq": true, + "evil": true, + "forin": false, + "immed": false, + "laxbreak": false, + "newcap": true, + "noarg": true, + "noempty": false, + "nonew": false, + "nomen": false, + "onevar": false, + "plusplus": false, + "regexp": false, + "undef": true, + "sub": true, + "strict": false, + "white": false, + "shadow": true, + "eqnull": true +} \ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/.npmignore b/cmd/mist/assets/ext/ethereum.js/.npmignore new file mode 100644 index 0000000000..5bbffe4fd3 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/.npmignore @@ -0,0 +1,9 @@ +example/js +node_modules +test +.gitignore +.editorconfig +.travis.yml +.npmignore +component.json +testling.html \ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/.travis.yml b/cmd/mist/assets/ext/ethereum.js/.travis.yml new file mode 100644 index 0000000000..fafacbd5a1 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/.travis.yml @@ -0,0 +1,11 @@ +language: node_js +node_js: + - "0.11" + - "0.10" +before_script: + - npm install + - npm install jshint +script: + - "jshint *.js lib" +after_script: + - npm run-script gulp diff --git a/cmd/mist/assets/ext/ethereum.js/LICENSE b/cmd/mist/assets/ext/ethereum.js/LICENSE new file mode 100644 index 0000000000..0f187b8736 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/LICENSE @@ -0,0 +1,14 @@ +This file is part of ethereum.js. + +ethereum.js 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. + +ethereum.js 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with ethereum.js. If not, see . \ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/README.md b/cmd/mist/assets/ext/ethereum.js/README.md new file mode 100644 index 0000000000..865b62c6b1 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/README.md @@ -0,0 +1,79 @@ +# Ethereum JavaScript API + +This is the Ethereum compatible JavaScript API using `Promise`s +which implements the [Generic JSON RPC](https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC) spec. It's available on npm as a node module and also for bower and component as an embeddable js + +[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![dependency status][dep-image]][dep-url] [![dev dependency status][dep-dev-image]][dep-dev-url] + + + +## Installation + +### Node.js + + npm install ethereum.js + +### For browser +Bower + + bower install ethereum.js + +Component + + component install ethereum/ethereum.js + +* Include `ethereum.min.js` in your html file. +* Include [es6-promise](https://github.com/jakearchibald/es6-promise) or another ES6-Shim if your browser doesn't support ECMAScript 6. + +## Usage +Require the library: + + var web3 = require('web3'); + +Set a provider (QtProvider, WebSocketProvider, HttpRpcProvider) + + var web3.setProvider(new web3.providers.WebSocketProvider('ws://localhost:40404/eth')); + +There you go, now you can use it: + +``` +web3.eth.coinbase.then(function(result){ + console.log(result); + return web3.eth.balanceAt(result); +}).then(function(balance){ + console.log(web3.toDecimal(balance)); +}).catch(function(err){ + console.log(err); +}); +``` + + +For another example see `example/index.html`. + +## Building + +* `gulp build` + + +### Testing + +**Please note this repo is in it's early stage.** + +If you'd like to run a WebSocket ethereum node check out +[go-ethereum](https://github.com/ethereum/go-ethereum). + +To install ethereum and spawn a node: + +``` +go get github.com/ethereum/go-ethereum/ethereum +ethereum -ws -loglevel=4 +``` + +[npm-image]: https://badge.fury.io/js/ethereum.js.png +[npm-url]: https://npmjs.org/package/ethereum.js +[travis-image]: https://travis-ci.org/ethereum/ethereum.js.svg +[travis-url]: https://travis-ci.org/ethereum/ethereum.js +[dep-image]: https://david-dm.org/ethereum/ethereum.js.svg +[dep-url]: https://david-dm.org/ethereum/ethereum.js +[dep-dev-image]: https://david-dm.org/ethereum/ethereum.js/dev-status.svg +[dep-dev-url]: https://david-dm.org/ethereum/ethereum.js#info=devDependencies \ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/bower.json b/cmd/mist/assets/ext/ethereum.js/bower.json new file mode 100644 index 0000000000..cedae9023d --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/bower.json @@ -0,0 +1,51 @@ +{ + "name": "ethereum.js", + "namespace": "ethereum", + "version": "0.0.3", + "description": "Ethereum Compatible JavaScript API", + "main": ["./dist/ethereum.js", "./dist/ethereum.min.js"], + "dependencies": { + "es6-promise": "#master" + }, + "repository": { + "type": "git", + "url": "https://github.com/ethereum/ethereum.js.git" + }, + "homepage": "https://github.com/ethereum/ethereum.js", + "bugs": { + "url": "https://github.com/ethereum/ethereum.js/issues" + }, + "keywords": [ + "ethereum", + "javascript", + "API" + ], + "authors": [ + { + "name": "Marek Kotewicz", + "email": "marek@ethdev.com", + "homepage": "https://github.com/debris" + }, + { + "name": "Marian Oancea", + "email": "marian@ethdev.com", + "homepage": "https://github.com/cubedro" + } + ], + "license": "LGPL-3.0", + "ignore": [ + "example", + "lib", + "node_modules", + "package.json", + ".bowerrc", + ".editorconfig", + ".gitignore", + ".jshintrc", + ".npmignore", + ".travis.yml", + "gulpfile.js", + "index.js", + "**/*.txt" + ] +} \ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js new file mode 100644 index 0000000000..4f4b5d3265 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js @@ -0,0 +1,1184 @@ +require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o. +*/ +/** @file abi.js + * @authors: + * Marek Kotewicz + * Gav Wood + * @date 2014 + */ + +// TODO: is these line is supposed to be here? +if ("build" !== 'build') {/* + var web3 = require('./web3'); // jshint ignore:line +*/} + +// TODO: make these be actually accurate instead of falling back onto JS's doubles. +var hexToDec = function (hex) { + return parseInt(hex, 16).toString(); +}; + +var decToHex = function (dec) { + return parseInt(dec).toString(16); +}; + +var findIndex = function (array, callback) { + var end = false; + var i = 0; + for (; i < array.length && !end; i++) { + end = callback(array[i]); + } + return end ? i - 1 : -1; +}; + +var findMethodIndex = function (json, methodName) { + return findIndex(json, function (method) { + return method.name === methodName; + }); +}; + +var padLeft = function (string, chars) { + return new Array(chars - string.length + 1).join("0") + string; +}; + +var calcBitPadding = function (type, expected) { + var value = type.slice(expected.length); + if (value === "") { + return 32; + } + return parseInt(value) / 8; +}; + +var calcBytePadding = function (type, expected) { + var value = type.slice(expected.length); + if (value === "") { + return 32; + } + return parseInt(value); +}; + +var calcRealPadding = function (type, expected) { + var value = type.slice(expected.length); + if (value === "") { + return 32; + } + var sizes = value.split('x'); + for (var padding = 0, i = 0; i < sizes; i++) { + padding += (sizes[i] / 8); + } + return padding; +}; + +var setupInputTypes = function () { + + var prefixedType = function (prefix, calcPadding) { + return function (type, value) { + var expected = prefix; + if (type.indexOf(expected) !== 0) { + return false; + } + + var padding = calcPadding(type, expected); + if (typeof value === "number") + value = value.toString(16); + else if (typeof value === "string") + value = web3.toHex(value); + else if (value.indexOf('0x') === 0) + value = value.substr(2); + else + value = (+value).toString(16); + return padLeft(value, padding * 2); + }; + }; + + var namedType = function (name, padding, formatter) { + return function (type, value) { + if (type !== name) { + return false; + } + + return padLeft(formatter ? formatter(value) : value, padding * 2); + }; + }; + + var formatBool = function (value) { + return value ? '0x1' : '0x0'; + }; + + return [ + prefixedType('uint', calcBitPadding), + prefixedType('int', calcBitPadding), + prefixedType('hash', calcBitPadding), + prefixedType('string', calcBytePadding), + prefixedType('real', calcRealPadding), + prefixedType('ureal', calcRealPadding), + namedType('address', 20), + namedType('bool', 1, formatBool), + ]; +}; + +var inputTypes = setupInputTypes(); + +var toAbiInput = function (json, methodName, params) { + var bytes = ""; + var index = findMethodIndex(json, methodName); + + if (index === -1) { + return; + } + + bytes = "0x" + padLeft(index.toString(16), 2); + var method = json[index]; + + for (var i = 0; i < method.inputs.length; i++) { + var found = false; + for (var j = 0; j < inputTypes.length && !found; j++) { + found = inputTypes[j](method.inputs[i].type, params[i]); + } + if (!found) { + console.error('unsupported json type: ' + method.inputs[i].type); + } + bytes += found; + } + return bytes; +}; + +var setupOutputTypes = function () { + + var prefixedType = function (prefix, calcPadding) { + return function (type) { + var expected = prefix; + if (type.indexOf(expected) !== 0) { + return -1; + } + + var padding = calcPadding(type, expected); + return padding * 2; + }; + }; + + var namedType = function (name, padding) { + return function (type) { + return name === type ? padding * 2 : -1; + }; + }; + + var formatInt = function (value) { + return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value); + }; + + var formatHash = function (value) { + return "0x" + value; + }; + + var formatBool = function (value) { + return value === '1' ? true : false; + }; + + var formatString = function (value) { + return web3.toAscii(value); + }; + + return [ + { padding: prefixedType('uint', calcBitPadding), format: formatInt }, + { padding: prefixedType('int', calcBitPadding), format: formatInt }, + { padding: prefixedType('hash', calcBitPadding), format: formatHash }, + { padding: prefixedType('string', calcBytePadding), format: formatString }, + { padding: prefixedType('real', calcRealPadding), format: formatInt }, + { padding: prefixedType('ureal', calcRealPadding), format: formatInt }, + { padding: namedType('address', 20) }, + { padding: namedType('bool', 1), format: formatBool } + ]; +}; + +var outputTypes = setupOutputTypes(); + +var fromAbiOutput = function (json, methodName, output) { + var index = findMethodIndex(json, methodName); + + if (index === -1) { + return; + } + + output = output.slice(2); + + var result = []; + var method = json[index]; + for (var i = 0; i < method.outputs.length; i++) { + var padding = -1; + for (var j = 0; j < outputTypes.length && padding === -1; j++) { + padding = outputTypes[j].padding(method.outputs[i].type); + } + + if (padding === -1) { + // not found output parsing + continue; + } + var res = output.slice(0, padding); + var formatter = outputTypes[j - 1].format; + result.push(formatter ? formatter(res) : ("0x" + res)); + output = output.slice(padding); + } + + return result; +}; + +var inputParser = function (json) { + var parser = {}; + json.forEach(function (method) { + parser[method.name] = function () { + var params = Array.prototype.slice.call(arguments); + return toAbiInput(json, method.name, params); + }; + }); + + return parser; +}; + +var outputParser = function (json) { + var parser = {}; + json.forEach(function (method) { + parser[method.name] = function (output) { + return fromAbiOutput(json, method.name, output); + }; + }); + + return parser; +}; + +module.exports = { + inputParser: inputParser, + outputParser: outputParser +}; + +},{}],2:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js 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. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file autoprovider.js + * @authors: + * Marek Kotewicz + * Marian Oancea + * @date 2014 + */ + +/* + * @brief if qt object is available, uses QtProvider, + * if not tries to connect over websockets + * if it fails, it uses HttpRpcProvider + */ + +// TODO: is these line is supposed to be here? +if ("build" !== 'build') {/* + var WebSocket = require('ws'); // jshint ignore:line + var web3 = require('./web3'); // jshint ignore:line +*/} + +var AutoProvider = function (userOptions) { + if (web3.haveProvider()) { + return; + } + + // before we determine what provider we are, we have to cache request + this.sendQueue = []; + this.onmessageQueue = []; + + if (navigator.qt) { + this.provider = new web3.providers.QtProvider(); + return; + } + + userOptions = userOptions || {}; + var options = { + httprpc: userOptions.httprpc || 'http://localhost:8080', + websockets: userOptions.websockets || 'ws://localhost:40404/eth' + }; + + var self = this; + var closeWithSuccess = function (success) { + ws.close(); + if (success) { + self.provider = new web3.providers.WebSocketProvider(options.websockets); + } else { + self.provider = new web3.providers.HttpRpcProvider(options.httprpc); + self.poll = self.provider.poll.bind(self.provider); + } + self.sendQueue.forEach(function (payload) { + self.provider(payload); + }); + self.onmessageQueue.forEach(function (handler) { + self.provider.onmessage = handler; + }); + }; + + var ws = new WebSocket(options.websockets); + + ws.onopen = function() { + closeWithSuccess(true); + }; + + ws.onerror = function() { + closeWithSuccess(false); + }; +}; + +AutoProvider.prototype.send = function (payload) { + if (this.provider) { + this.provider.send(payload); + return; + } + this.sendQueue.push(payload); +}; + +Object.defineProperty(AutoProvider.prototype, 'onmessage', { + set: function (handler) { + if (this.provider) { + this.provider.onmessage = handler; + return; + } + this.onmessageQueue.push(handler); + } +}); + +module.exports = AutoProvider; + +},{}],3:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js 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. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file contract.js + * @authors: + * Marek Kotewicz + * @date 2014 + */ + +// TODO: is these line is supposed to be here? +if ("build" !== 'build') {/* + var web3 = require('./web3'); // jshint ignore:line +*/} + +var abi = require('./abi'); + +var contract = function (address, desc) { + var inputParser = abi.inputParser(desc); + var outputParser = abi.outputParser(desc); + + var contract = {}; + + desc.forEach(function (method) { + contract[method.name] = function () { + var params = Array.prototype.slice.call(arguments); + var parsed = inputParser[method.name].apply(null, params); + + var onSuccess = function (result) { + return outputParser[method.name](result); + }; + + return { + call: function (extra) { + extra = extra || {}; + extra.to = address; + extra.data = parsed; + return web3.eth.call(extra).then(onSuccess); + }, + transact: function (extra) { + extra = extra || {}; + extra.to = address; + extra.data = parsed; + return web3.eth.transact(extra).then(onSuccess); + } + }; + }; + }); + + return contract; +}; + +module.exports = contract; + +},{"./abi":1}],4:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js 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. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file httprpc.js + * @authors: + * Marek Kotewicz + * Marian Oancea + * @date 2014 + */ + +// TODO: is these line is supposed to be here? +if ("build" !== 'build') {/* + var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line +*/} + +var HttpRpcProvider = function (host) { + this.handlers = []; + this.host = host; +}; + +function formatJsonRpcObject(object) { + return { + jsonrpc: '2.0', + method: object.call, + params: object.args, + id: object._id + }; +} + +function formatJsonRpcMessage(message) { + var object = JSON.parse(message); + + return { + _id: object.id, + data: object.result, + error: object.error + }; +} + +HttpRpcProvider.prototype.sendRequest = function (payload, cb) { + var data = formatJsonRpcObject(payload); + + var request = new XMLHttpRequest(); + request.open("POST", this.host, true); + request.send(JSON.stringify(data)); + request.onreadystatechange = function () { + if (request.readyState === 4 && cb) { + cb(request); + } + }; +}; + +HttpRpcProvider.prototype.send = function (payload) { + var self = this; + this.sendRequest(payload, function (request) { + self.handlers.forEach(function (handler) { + handler.call(self, formatJsonRpcMessage(request.responseText)); + }); + }); +}; + +HttpRpcProvider.prototype.poll = function (payload, id) { + var self = this; + this.sendRequest(payload, function (request) { + var parsed = JSON.parse(request.responseText); + if (parsed.error || (parsed.result instanceof Array ? parsed.result.length === 0 : !parsed.result)) { + return; + } + self.handlers.forEach(function (handler) { + handler.call(self, {_event: payload.call, _id: id, data: parsed.result}); + }); + }); +}; + +Object.defineProperty(HttpRpcProvider.prototype, "onmessage", { + set: function (handler) { + this.handlers.push(handler); + } +}); + +module.exports = HttpRpcProvider; + +},{}],5:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js 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. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file qt.js + * @authors: + * Jeffrey Wilcke + * Marek Kotewicz + * @date 2014 + */ + +var QtProvider = function() { + this.handlers = []; + + var self = this; + navigator.qt.onmessage = function (message) { + self.handlers.forEach(function (handler) { + handler.call(self, JSON.parse(message.data)); + }); + }; +}; + +QtProvider.prototype.send = function(payload) { + navigator.qt.postMessage(JSON.stringify(payload)); +}; + +Object.defineProperty(QtProvider.prototype, "onmessage", { + set: function(handler) { + this.handlers.push(handler); + } +}); + +module.exports = QtProvider; + +},{}],6:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js 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. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file main.js + * @authors: + * Jeffrey Wilcke + * Marek Kotewicz + * Marian Oancea + * Gav Wood + * @date 2014 + */ + +function flattenPromise (obj) { + if (obj instanceof Promise) { + return Promise.resolve(obj); + } + + if (obj instanceof Array) { + return new Promise(function (resolve) { + var promises = obj.map(function (o) { + return flattenPromise(o); + }); + + return Promise.all(promises).then(function (res) { + for (var i = 0; i < obj.length; i++) { + obj[i] = res[i]; + } + resolve(obj); + }); + }); + } + + if (obj instanceof Object) { + return new Promise(function (resolve) { + var keys = Object.keys(obj); + var promises = keys.map(function (key) { + return flattenPromise(obj[key]); + }); + + return Promise.all(promises).then(function (res) { + for (var i = 0; i < keys.length; i++) { + obj[keys[i]] = res[i]; + } + resolve(obj); + }); + }); + } + + return Promise.resolve(obj); +} + +var web3Methods = function () { + return [ + { name: 'sha3', call: 'web3_sha3' } + ]; +}; + +var ethMethods = function () { + var blockCall = function (args) { + return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber"; + }; + + var transactionCall = function (args) { + return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber'; + }; + + var uncleCall = function (args) { + return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber'; + }; + + var methods = [ + { name: 'balanceAt', call: 'eth_balanceAt' }, + { name: 'stateAt', call: 'eth_stateAt' }, + { name: 'storageAt', call: 'eth_storageAt' }, + { name: 'countAt', call: 'eth_countAt'}, + { name: 'codeAt', call: 'eth_codeAt' }, + { name: 'transact', call: 'eth_transact' }, + { name: 'call', call: 'eth_call' }, + { name: 'block', call: blockCall }, + { name: 'transaction', call: transactionCall }, + { name: 'uncle', call: uncleCall }, + { name: 'compilers', call: 'eth_compilers' }, + { name: 'lll', call: 'eth_lll' }, + { name: 'solidity', call: 'eth_solidity' }, + { name: 'serpent', call: 'eth_serpent' }, + { name: 'logs', call: 'eth_logs' } + ]; + return methods; +}; + +var ethProperties = function () { + return [ + { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' }, + { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' }, + { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' }, + { name: 'gasPrice', getter: 'eth_gasPrice' }, + { name: 'account', getter: 'eth_account' }, + { name: 'accounts', getter: 'eth_accounts' }, + { name: 'peerCount', getter: 'eth_peerCount' }, + { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' }, + { name: 'number', getter: 'eth_number'} + ]; +}; + +var dbMethods = function () { + return [ + { name: 'put', call: 'db_put' }, + { name: 'get', call: 'db_get' }, + { name: 'putString', call: 'db_putString' }, + { name: 'getString', call: 'db_getString' } + ]; +}; + +var shhMethods = function () { + return [ + { name: 'post', call: 'shh_post' }, + { name: 'newIdentity', call: 'shh_newIdentity' }, + { name: 'haveIdentity', call: 'shh_haveIdentity' }, + { name: 'newGroup', call: 'shh_newGroup' }, + { name: 'addToGroup', call: 'shh_addToGroup' } + ]; +}; + +var ethWatchMethods = function () { + var newFilter = function (args) { + return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter'; + }; + + return [ + { name: 'newFilter', call: newFilter }, + { name: 'uninstallFilter', call: 'eth_uninstallFilter' }, + { name: 'getMessages', call: 'eth_filterLogs' } + ]; +}; + +var shhWatchMethods = function () { + return [ + { name: 'newFilter', call: 'shh_newFilter' }, + { name: 'uninstallFilter', call: 'shh_uninstallFilter' }, + { name: 'getMessage', call: 'shh_getMessages' } + ]; +}; + +var setupMethods = function (obj, methods) { + methods.forEach(function (method) { + obj[method.name] = function () { + return flattenPromise(Array.prototype.slice.call(arguments)).then(function (args) { + var call = typeof method.call === "function" ? method.call(args) : method.call; + return {call: call, args: args}; + }).then(function (request) { + return new Promise(function (resolve, reject) { + web3.provider.send(request, function (err, result) { + if (!err) { + resolve(result); + return; + } + reject(err); + }); + }); + }).catch(function(err) { + console.error(err); + }); + }; + }); +}; + +var setupProperties = function (obj, properties) { + properties.forEach(function (property) { + var proto = {}; + proto.get = function () { + return new Promise(function(resolve, reject) { + web3.provider.send({call: property.getter}, function(err, result) { + if (!err) { + resolve(result); + return; + } + reject(err); + }); + }); + }; + if (property.setter) { + proto.set = function (val) { + return flattenPromise([val]).then(function (args) { + return new Promise(function (resolve) { + web3.provider.send({call: property.setter, args: args}, function (err, result) { + if (!err) { + resolve(result); + return; + } + reject(err); + }); + }); + }).catch(function (err) { + console.error(err); + }); + }; + } + Object.defineProperty(obj, property.name, proto); + }); +}; + +// TODO: import from a dependency, don't duplicate. +var hexToDec = function (hex) { + return parseInt(hex, 16).toString(); +}; + +var decToHex = function (dec) { + return parseInt(dec).toString(16); +}; + + +var web3 = { + _callbacks: {}, + _events: {}, + providers: {}, + + toHex: function(str) { + var hex = ""; + for(var i = 0; i < str.length; i++) { + var n = str.charCodeAt(i).toString(16); + hex += n.length < 2 ? '0' + n : n; + } + + return hex; + }, + + toAscii: function(hex) { + // Find termination + var str = ""; + var i = 0, l = hex.length; + if (hex.substring(0, 2) === '0x') + i = 2; + for(; i < l; i+=2) { + var code = hex.charCodeAt(i); + if(code === 0) { + break; + } + + str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); + } + + return str; + }, + + fromAscii: function(str, pad) { + pad = pad === undefined ? 32 : pad; + var hex = this.toHex(str); + while(hex.length < pad*2) + hex += "00"; + return "0x" + hex; + }, + + toDecimal: function (val) { + return hexToDec(val.substring(2)); + }, + + fromDecimal: function (val) { + return "0x" + decToHex(val); + }, + + toEth: function(str) { + var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str; + var unit = 0; + var units = [ 'wei', 'Kwei', 'Mwei', 'Gwei', 'szabo', 'finney', 'ether', 'grand', 'Mether', 'Gether', 'Tether', 'Pether', 'Eether', 'Zether', 'Yether', 'Nether', 'Dether', 'Vether', 'Uether' ]; + while (val > 3000 && unit < units.length - 1) + { + val /= 1000; + unit++; + } + var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2); + var replaceFunction = function($0, $1, $2) { + return $1 + ',' + $2; + }; + + while (true) { + var o = s; + s = s.replace(/(\d)(\d\d\d[\.\,])/, replaceFunction); + if (o === s) + break; + } + return s + ' ' + units[unit]; + }, + + eth: { + prototype: Object(), // jshint ignore:line + watch: function (params) { + return new Filter(params, ethWatch); + } + }, + + db: { + prototype: Object() // jshint ignore:line + }, + + shh: { + prototype: Object(), // jshint ignore:line + watch: function (params) { + return new Filter(params, shhWatch); + } + }, + + on: function(event, id, cb) { + if(web3._events[event] === undefined) { + web3._events[event] = {}; + } + + web3._events[event][id] = cb; + return this; + }, + + off: function(event, id) { + if(web3._events[event] !== undefined) { + delete web3._events[event][id]; + } + + return this; + }, + + trigger: function(event, id, data) { + var callbacks = web3._events[event]; + if (!callbacks || !callbacks[id]) { + return; + } + var cb = callbacks[id]; + cb(data); + } +}; + +setupMethods(web3, web3Methods()); +setupMethods(web3.eth, ethMethods()); +setupProperties(web3.eth, ethProperties()); +setupMethods(web3.db, dbMethods()); +setupMethods(web3.shh, shhMethods()); + +var ethWatch = { + changed: 'eth_changed' +}; +setupMethods(ethWatch, ethWatchMethods()); +var shhWatch = { + changed: 'shh_changed' +}; +setupMethods(shhWatch, shhWatchMethods()); + +var ProviderManager = function() { + this.queued = []; + this.polls = []; + this.ready = false; + this.provider = undefined; + this.id = 1; + + var self = this; + var poll = function () { + if (self.provider && self.provider.poll) { + self.polls.forEach(function (data) { + data.data._id = self.id; + self.id++; + self.provider.poll(data.data, data.id); + }); + } + setTimeout(poll, 12000); + }; + poll(); +}; + +ProviderManager.prototype.send = function(data, cb) { + data._id = this.id; + if (cb) { + web3._callbacks[data._id] = cb; + } + + data.args = data.args || []; + this.id++; + + if(this.provider !== undefined) { + this.provider.send(data); + } else { + console.warn("provider is not set"); + this.queued.push(data); + } +}; + +ProviderManager.prototype.set = function(provider) { + if(this.provider !== undefined && this.provider.unload !== undefined) { + this.provider.unload(); + } + + this.provider = provider; + this.ready = true; +}; + +ProviderManager.prototype.sendQueued = function() { + for(var i = 0; this.queued.length; i++) { + // Resend + this.send(this.queued[i]); + } +}; + +ProviderManager.prototype.installed = function() { + return this.provider !== undefined; +}; + +ProviderManager.prototype.startPolling = function (data, pollId) { + if (!this.provider || !this.provider.poll) { + return; + } + this.polls.push({data: data, id: pollId}); +}; + +ProviderManager.prototype.stopPolling = function (pollId) { + for (var i = this.polls.length; i--;) { + var poll = this.polls[i]; + if (poll.id === pollId) { + this.polls.splice(i, 1); + } + } +}; + +web3.provider = new ProviderManager(); + +web3.setProvider = function(provider) { + provider.onmessage = messageHandler; + web3.provider.set(provider); + web3.provider.sendQueued(); +}; + +web3.haveProvider = function() { + return !!web3.provider.provider; +}; + +var Filter = function(options, impl) { + this.impl = impl; + this.callbacks = []; + + var self = this; + this.promise = impl.newFilter(options); + this.promise.then(function (id) { + self.id = id; + web3.on(impl.changed, id, self.trigger.bind(self)); + web3.provider.startPolling({call: impl.changed, args: [id]}, id); + }); +}; + +Filter.prototype.arrived = function(callback) { + this.changed(callback); +}; + +Filter.prototype.changed = function(callback) { + var self = this; + this.promise.then(function(id) { + self.callbacks.push(callback); + }); +}; + +Filter.prototype.trigger = function(messages) { + for(var i = 0; i < this.callbacks.length; i++) { + this.callbacks[i].call(this, messages); + } +}; + +Filter.prototype.uninstall = function() { + var self = this; + this.promise.then(function (id) { + self.impl.uninstallFilter(id); + web3.provider.stopPolling(id); + web3.off(impl.changed, id); + }); +}; + +Filter.prototype.messages = function() { + var self = this; + return this.promise.then(function (id) { + return self.impl.getMessages(id); + }); +}; + +Filter.prototype.logs = function () { + return this.messages(); +}; + +function messageHandler(data) { + if(data._event !== undefined) { + web3.trigger(data._event, data._id, data.data); + return; + } + + if(data._id) { + var cb = web3._callbacks[data._id]; + if (cb) { + cb.call(this, data.error, data.data); + delete web3._callbacks[data._id]; + } + } +} + +module.exports = web3; + +},{}],7:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js 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. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file websocket.js + * @authors: + * Jeffrey Wilcke + * Marek Kotewicz + * Marian Oancea + * @date 2014 + */ + +// TODO: is these line is supposed to be here? +if ("build" !== 'build') {/* + var WebSocket = require('ws'); // jshint ignore:line +*/} + +var WebSocketProvider = function(host) { + // onmessage handlers + this.handlers = []; + // queue will be filled with messages if send is invoked before the ws is ready + this.queued = []; + this.ready = false; + + this.ws = new WebSocket(host); + + var self = this; + this.ws.onmessage = function(event) { + for(var i = 0; i < self.handlers.length; i++) { + self.handlers[i].call(self, JSON.parse(event.data), event); + } + }; + + this.ws.onopen = function() { + self.ready = true; + + for(var i = 0; i < self.queued.length; i++) { + // Resend + self.send(self.queued[i]); + } + }; +}; + +WebSocketProvider.prototype.send = function(payload) { + if(this.ready) { + var data = JSON.stringify(payload); + + this.ws.send(data); + } else { + this.queued.push(payload); + } +}; + +WebSocketProvider.prototype.onMessage = function(handler) { + this.handlers.push(handler); +}; + +WebSocketProvider.prototype.unload = function() { + this.ws.close(); +}; +Object.defineProperty(WebSocketProvider.prototype, "onmessage", { + set: function(provider) { this.onMessage(provider); } +}); + +module.exports = WebSocketProvider; + +},{}],"web3":[function(require,module,exports){ +var web3 = require('./lib/web3'); +web3.providers.WebSocketProvider = require('./lib/websocket'); +web3.providers.HttpRpcProvider = require('./lib/httprpc'); +web3.providers.QtProvider = require('./lib/qt'); +web3.providers.AutoProvider = require('./lib/autoprovider'); +web3.contract = require('./lib/contract'); + +module.exports = web3; + +},{"./lib/autoprovider":2,"./lib/contract":3,"./lib/httprpc":4,"./lib/qt":5,"./lib/web3":6,"./lib/websocket":7}]},{},["web3"]) + + +//# sourceMappingURL=ethereum.js.map \ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js.map b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js.map new file mode 100644 index 0000000000..9886b70ce0 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js.map @@ -0,0 +1,29 @@ +{ + "version": 3, + "sources": [ + "node_modules/browserify/node_modules/browser-pack/_prelude.js", + "lib/abi.js", + "lib/autoprovider.js", + "lib/contract.js", + "lib/httprpc.js", + "lib/qt.js", + "lib/web3.js", + "lib/websocket.js", + "index.js" + ], + "names": [], + "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5fA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", + "file": "generated.js", + "sourceRoot": "", + "sourcesContent": [ + "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o.\n*/\n/** @file abi.js\n * @authors:\n * Marek Kotewicz \n * Gav Wood \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\n// TODO: make these be actually accurate instead of falling back onto JS's doubles.\nvar hexToDec = function (hex) {\n return parseInt(hex, 16).toString();\n};\n\nvar decToHex = function (dec) {\n return parseInt(dec).toString(16);\n};\n\nvar findIndex = function (array, callback) {\n var end = false;\n var i = 0;\n for (; i < array.length && !end; i++) {\n end = callback(array[i]);\n }\n return end ? i - 1 : -1;\n};\n\nvar findMethodIndex = function (json, methodName) {\n return findIndex(json, function (method) {\n return method.name === methodName;\n });\n};\n\nvar padLeft = function (string, chars) {\n return new Array(chars - string.length + 1).join(\"0\") + string;\n};\n\nvar calcBitPadding = function (type, expected) {\n var value = type.slice(expected.length);\n if (value === \"\") {\n return 32;\n }\n return parseInt(value) / 8;\n};\n\nvar calcBytePadding = function (type, expected) {\n var value = type.slice(expected.length);\n if (value === \"\") {\n return 32;\n }\n return parseInt(value);\n};\n\nvar calcRealPadding = function (type, expected) {\n var value = type.slice(expected.length);\n if (value === \"\") {\n return 32;\n }\n var sizes = value.split('x');\n for (var padding = 0, i = 0; i < sizes; i++) {\n padding += (sizes[i] / 8);\n }\n return padding;\n};\n\nvar setupInputTypes = function () {\n \n var prefixedType = function (prefix, calcPadding) {\n return function (type, value) {\n var expected = prefix;\n if (type.indexOf(expected) !== 0) {\n return false;\n }\n\n var padding = calcPadding(type, expected);\n if (typeof value === \"number\")\n value = value.toString(16);\n else if (typeof value === \"string\")\n value = web3.toHex(value); \n else if (value.indexOf('0x') === 0)\n value = value.substr(2);\n else\n value = (+value).toString(16);\n return padLeft(value, padding * 2);\n };\n };\n\n var namedType = function (name, padding, formatter) {\n return function (type, value) {\n if (type !== name) {\n return false;\n }\n\n return padLeft(formatter ? formatter(value) : value, padding * 2);\n };\n };\n\n var formatBool = function (value) {\n return value ? '0x1' : '0x0';\n };\n\n return [\n prefixedType('uint', calcBitPadding),\n prefixedType('int', calcBitPadding),\n prefixedType('hash', calcBitPadding),\n prefixedType('string', calcBytePadding),\n prefixedType('real', calcRealPadding),\n prefixedType('ureal', calcRealPadding),\n namedType('address', 20),\n namedType('bool', 1, formatBool),\n ];\n};\n\nvar inputTypes = setupInputTypes();\n\nvar toAbiInput = function (json, methodName, params) {\n var bytes = \"\";\n var index = findMethodIndex(json, methodName);\n\n if (index === -1) {\n return;\n }\n\n bytes = \"0x\" + padLeft(index.toString(16), 2);\n var method = json[index];\n\n for (var i = 0; i < method.inputs.length; i++) {\n var found = false;\n for (var j = 0; j < inputTypes.length && !found; j++) {\n found = inputTypes[j](method.inputs[i].type, params[i]);\n }\n if (!found) {\n console.error('unsupported json type: ' + method.inputs[i].type);\n }\n bytes += found;\n }\n return bytes;\n};\n\nvar setupOutputTypes = function () {\n\n var prefixedType = function (prefix, calcPadding) {\n return function (type) {\n var expected = prefix;\n if (type.indexOf(expected) !== 0) {\n return -1;\n }\n\n var padding = calcPadding(type, expected);\n return padding * 2;\n };\n };\n\n var namedType = function (name, padding) {\n return function (type) {\n return name === type ? padding * 2 : -1;\n };\n };\n\n var formatInt = function (value) {\n return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value);\n };\n\n var formatHash = function (value) {\n return \"0x\" + value;\n };\n\n var formatBool = function (value) {\n return value === '1' ? true : false;\n };\n\n var formatString = function (value) {\n return web3.toAscii(value);\n };\n\n return [\n { padding: prefixedType('uint', calcBitPadding), format: formatInt },\n { padding: prefixedType('int', calcBitPadding), format: formatInt },\n { padding: prefixedType('hash', calcBitPadding), format: formatHash },\n { padding: prefixedType('string', calcBytePadding), format: formatString },\n { padding: prefixedType('real', calcRealPadding), format: formatInt },\n { padding: prefixedType('ureal', calcRealPadding), format: formatInt },\n { padding: namedType('address', 20) },\n { padding: namedType('bool', 1), format: formatBool }\n ];\n};\n\nvar outputTypes = setupOutputTypes();\n\nvar fromAbiOutput = function (json, methodName, output) {\n var index = findMethodIndex(json, methodName);\n\n if (index === -1) {\n return;\n }\n\n output = output.slice(2);\n\n var result = [];\n var method = json[index];\n for (var i = 0; i < method.outputs.length; i++) {\n var padding = -1;\n for (var j = 0; j < outputTypes.length && padding === -1; j++) {\n padding = outputTypes[j].padding(method.outputs[i].type);\n }\n\n if (padding === -1) {\n // not found output parsing\n continue;\n }\n var res = output.slice(0, padding);\n var formatter = outputTypes[j - 1].format;\n result.push(formatter ? formatter(res) : (\"0x\" + res));\n output = output.slice(padding);\n }\n\n return result;\n};\n\nvar inputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n parser[method.name] = function () {\n var params = Array.prototype.slice.call(arguments);\n return toAbiInput(json, method.name, params);\n };\n });\n\n return parser;\n};\n\nvar outputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n parser[method.name] = function (output) {\n return fromAbiOutput(json, method.name, output);\n };\n });\n\n return parser;\n};\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser\n};\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file autoprovider.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\n/*\n * @brief if qt object is available, uses QtProvider,\n * if not tries to connect over websockets\n * if it fails, it uses HttpRpcProvider\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var WebSocket = require('ws'); // jshint ignore:line\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\nvar AutoProvider = function (userOptions) {\n if (web3.haveProvider()) {\n return;\n }\n\n // before we determine what provider we are, we have to cache request\n this.sendQueue = [];\n this.onmessageQueue = [];\n\n if (navigator.qt) {\n this.provider = new web3.providers.QtProvider();\n return;\n }\n\n userOptions = userOptions || {};\n var options = {\n httprpc: userOptions.httprpc || 'http://localhost:8080',\n websockets: userOptions.websockets || 'ws://localhost:40404/eth'\n };\n\n var self = this;\n var closeWithSuccess = function (success) {\n ws.close();\n if (success) {\n self.provider = new web3.providers.WebSocketProvider(options.websockets);\n } else {\n self.provider = new web3.providers.HttpRpcProvider(options.httprpc);\n self.poll = self.provider.poll.bind(self.provider);\n }\n self.sendQueue.forEach(function (payload) {\n self.provider(payload);\n });\n self.onmessageQueue.forEach(function (handler) {\n self.provider.onmessage = handler;\n });\n };\n\n var ws = new WebSocket(options.websockets);\n\n ws.onopen = function() {\n closeWithSuccess(true);\n };\n\n ws.onerror = function() {\n closeWithSuccess(false);\n };\n};\n\nAutoProvider.prototype.send = function (payload) {\n if (this.provider) {\n this.provider.send(payload);\n return;\n }\n this.sendQueue.push(payload);\n};\n\nObject.defineProperty(AutoProvider.prototype, 'onmessage', {\n set: function (handler) {\n if (this.provider) {\n this.provider.onmessage = handler;\n return;\n }\n this.onmessageQueue.push(handler);\n }\n});\n\nmodule.exports = AutoProvider;\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file contract.js\n * @authors:\n * Marek Kotewicz \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\nvar abi = require('./abi');\n\nvar contract = function (address, desc) {\n var inputParser = abi.inputParser(desc);\n var outputParser = abi.outputParser(desc);\n\n var contract = {};\n\n desc.forEach(function (method) {\n contract[method.name] = function () {\n var params = Array.prototype.slice.call(arguments);\n var parsed = inputParser[method.name].apply(null, params);\n\n var onSuccess = function (result) {\n return outputParser[method.name](result);\n };\n\n return {\n call: function (extra) {\n extra = extra || {};\n extra.to = address;\n extra.data = parsed;\n return web3.eth.call(extra).then(onSuccess);\n },\n transact: function (extra) {\n extra = extra || {};\n extra.to = address;\n extra.data = parsed;\n return web3.eth.transact(extra).then(onSuccess);\n }\n };\n };\n });\n\n return contract;\n};\n\nmodule.exports = contract;\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file httprpc.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\n*/}\n\nvar HttpRpcProvider = function (host) {\n this.handlers = [];\n this.host = host;\n};\n\nfunction formatJsonRpcObject(object) {\n return {\n jsonrpc: '2.0',\n method: object.call,\n params: object.args,\n id: object._id\n };\n}\n\nfunction formatJsonRpcMessage(message) {\n var object = JSON.parse(message);\n\n return {\n _id: object.id,\n data: object.result,\n error: object.error\n };\n}\n\nHttpRpcProvider.prototype.sendRequest = function (payload, cb) {\n var data = formatJsonRpcObject(payload);\n\n var request = new XMLHttpRequest();\n request.open(\"POST\", this.host, true);\n request.send(JSON.stringify(data));\n request.onreadystatechange = function () {\n if (request.readyState === 4 && cb) {\n cb(request);\n }\n };\n};\n\nHttpRpcProvider.prototype.send = function (payload) {\n var self = this;\n this.sendRequest(payload, function (request) {\n self.handlers.forEach(function (handler) {\n handler.call(self, formatJsonRpcMessage(request.responseText));\n });\n });\n};\n\nHttpRpcProvider.prototype.poll = function (payload, id) {\n var self = this;\n this.sendRequest(payload, function (request) {\n var parsed = JSON.parse(request.responseText);\n if (parsed.error || (parsed.result instanceof Array ? parsed.result.length === 0 : !parsed.result)) {\n return;\n }\n self.handlers.forEach(function (handler) {\n handler.call(self, {_event: payload.call, _id: id, data: parsed.result});\n });\n });\n};\n\nObject.defineProperty(HttpRpcProvider.prototype, \"onmessage\", {\n set: function (handler) {\n this.handlers.push(handler);\n }\n});\n\nmodule.exports = HttpRpcProvider;\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file qt.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * @date 2014\n */\n\nvar QtProvider = function() {\n this.handlers = [];\n\n var self = this;\n navigator.qt.onmessage = function (message) {\n self.handlers.forEach(function (handler) {\n handler.call(self, JSON.parse(message.data));\n });\n };\n};\n\nQtProvider.prototype.send = function(payload) {\n navigator.qt.postMessage(JSON.stringify(payload));\n};\n\nObject.defineProperty(QtProvider.prototype, \"onmessage\", {\n set: function(handler) {\n this.handlers.push(handler);\n }\n});\n\nmodule.exports = QtProvider;\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file main.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \n * @date 2014\n */\n\nfunction flattenPromise (obj) {\n if (obj instanceof Promise) {\n return Promise.resolve(obj);\n }\n\n if (obj instanceof Array) {\n return new Promise(function (resolve) {\n var promises = obj.map(function (o) {\n return flattenPromise(o);\n });\n\n return Promise.all(promises).then(function (res) {\n for (var i = 0; i < obj.length; i++) {\n obj[i] = res[i];\n }\n resolve(obj);\n });\n });\n }\n\n if (obj instanceof Object) {\n return new Promise(function (resolve) {\n var keys = Object.keys(obj);\n var promises = keys.map(function (key) {\n return flattenPromise(obj[key]);\n });\n\n return Promise.all(promises).then(function (res) {\n for (var i = 0; i < keys.length; i++) {\n obj[keys[i]] = res[i];\n }\n resolve(obj);\n });\n });\n }\n\n return Promise.resolve(obj);\n}\n\nvar web3Methods = function () {\n return [\n { name: 'sha3', call: 'web3_sha3' }\n ];\n};\n\nvar ethMethods = function () {\n var blockCall = function (args) {\n return typeof args[0] === \"string\" ? \"eth_blockByHash\" : \"eth_blockByNumber\";\n };\n\n var transactionCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_transactionByHash' : 'eth_transactionByNumber';\n };\n\n var uncleCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_uncleByHash' : 'eth_uncleByNumber';\n };\n\n var methods = [\n { name: 'balanceAt', call: 'eth_balanceAt' },\n { name: 'stateAt', call: 'eth_stateAt' },\n { name: 'storageAt', call: 'eth_storageAt' },\n { name: 'countAt', call: 'eth_countAt'},\n { name: 'codeAt', call: 'eth_codeAt' },\n { name: 'transact', call: 'eth_transact' },\n { name: 'call', call: 'eth_call' },\n { name: 'block', call: blockCall },\n { name: 'transaction', call: transactionCall },\n { name: 'uncle', call: uncleCall },\n { name: 'compilers', call: 'eth_compilers' },\n { name: 'lll', call: 'eth_lll' },\n { name: 'solidity', call: 'eth_solidity' },\n { name: 'serpent', call: 'eth_serpent' },\n { name: 'logs', call: 'eth_logs' }\n ];\n return methods;\n};\n\nvar ethProperties = function () {\n return [\n { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },\n { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },\n { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },\n { name: 'gasPrice', getter: 'eth_gasPrice' },\n { name: 'account', getter: 'eth_account' },\n { name: 'accounts', getter: 'eth_accounts' },\n { name: 'peerCount', getter: 'eth_peerCount' },\n { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },\n { name: 'number', getter: 'eth_number'}\n ];\n};\n\nvar dbMethods = function () {\n return [\n { name: 'put', call: 'db_put' },\n { name: 'get', call: 'db_get' },\n { name: 'putString', call: 'db_putString' },\n { name: 'getString', call: 'db_getString' }\n ];\n};\n\nvar shhMethods = function () {\n return [\n { name: 'post', call: 'shh_post' },\n { name: 'newIdentity', call: 'shh_newIdentity' },\n { name: 'haveIdentity', call: 'shh_haveIdentity' },\n { name: 'newGroup', call: 'shh_newGroup' },\n { name: 'addToGroup', call: 'shh_addToGroup' }\n ];\n};\n\nvar ethWatchMethods = function () {\n var newFilter = function (args) {\n return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter';\n };\n\n return [\n { name: 'newFilter', call: newFilter },\n { name: 'uninstallFilter', call: 'eth_uninstallFilter' },\n { name: 'getMessages', call: 'eth_filterLogs' }\n ];\n};\n\nvar shhWatchMethods = function () {\n return [\n { name: 'newFilter', call: 'shh_newFilter' },\n { name: 'uninstallFilter', call: 'shh_uninstallFilter' },\n { name: 'getMessage', call: 'shh_getMessages' }\n ];\n};\n\nvar setupMethods = function (obj, methods) {\n methods.forEach(function (method) {\n obj[method.name] = function () {\n return flattenPromise(Array.prototype.slice.call(arguments)).then(function (args) {\n var call = typeof method.call === \"function\" ? method.call(args) : method.call;\n return {call: call, args: args};\n }).then(function (request) {\n return new Promise(function (resolve, reject) {\n web3.provider.send(request, function (err, result) {\n if (!err) {\n resolve(result);\n return;\n }\n reject(err);\n });\n });\n }).catch(function(err) {\n console.error(err);\n });\n };\n });\n};\n\nvar setupProperties = function (obj, properties) {\n properties.forEach(function (property) {\n var proto = {};\n proto.get = function () {\n return new Promise(function(resolve, reject) {\n web3.provider.send({call: property.getter}, function(err, result) {\n if (!err) {\n resolve(result);\n return;\n }\n reject(err);\n });\n });\n };\n if (property.setter) {\n proto.set = function (val) {\n return flattenPromise([val]).then(function (args) {\n return new Promise(function (resolve) {\n web3.provider.send({call: property.setter, args: args}, function (err, result) {\n if (!err) {\n resolve(result);\n return;\n }\n reject(err);\n });\n });\n }).catch(function (err) {\n console.error(err);\n });\n };\n }\n Object.defineProperty(obj, property.name, proto);\n });\n};\n\n// TODO: import from a dependency, don't duplicate.\nvar hexToDec = function (hex) {\n return parseInt(hex, 16).toString();\n};\n\nvar decToHex = function (dec) {\n return parseInt(dec).toString(16);\n};\n\n\nvar web3 = {\n _callbacks: {},\n _events: {},\n providers: {},\n\n toHex: function(str) {\n var hex = \"\";\n for(var i = 0; i < str.length; i++) {\n var n = str.charCodeAt(i).toString(16);\n hex += n.length < 2 ? '0' + n : n;\n }\n\n return hex;\n },\n\n toAscii: function(hex) {\n // Find termination\n var str = \"\";\n var i = 0, l = hex.length;\n if (hex.substring(0, 2) === '0x')\n i = 2;\n for(; i < l; i+=2) {\n var code = hex.charCodeAt(i);\n if(code === 0) {\n break;\n }\n\n str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));\n }\n\n return str;\n },\n\n fromAscii: function(str, pad) {\n pad = pad === undefined ? 32 : pad;\n var hex = this.toHex(str);\n while(hex.length < pad*2)\n hex += \"00\";\n return \"0x\" + hex;\n },\n\n toDecimal: function (val) {\n return hexToDec(val.substring(2));\n },\n\n fromDecimal: function (val) {\n return \"0x\" + decToHex(val);\n },\n\n toEth: function(str) {\n var val = typeof str === \"string\" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;\n var unit = 0;\n var units = [ 'wei', 'Kwei', 'Mwei', 'Gwei', 'szabo', 'finney', 'ether', 'grand', 'Mether', 'Gether', 'Tether', 'Pether', 'Eether', 'Zether', 'Yether', 'Nether', 'Dether', 'Vether', 'Uether' ];\n while (val > 3000 && unit < units.length - 1)\n {\n val /= 1000;\n unit++;\n }\n var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2);\n var replaceFunction = function($0, $1, $2) {\n return $1 + ',' + $2;\n };\n\n while (true) {\n var o = s;\n s = s.replace(/(\\d)(\\d\\d\\d[\\.\\,])/, replaceFunction);\n if (o === s)\n break;\n }\n return s + ' ' + units[unit];\n },\n\n eth: {\n prototype: Object(), // jshint ignore:line\n watch: function (params) {\n return new Filter(params, ethWatch);\n }\n },\n\n db: {\n prototype: Object() // jshint ignore:line\n },\n\n shh: {\n prototype: Object(), // jshint ignore:line\n watch: function (params) {\n return new Filter(params, shhWatch);\n }\n },\n\n on: function(event, id, cb) {\n if(web3._events[event] === undefined) {\n web3._events[event] = {};\n }\n\n web3._events[event][id] = cb;\n return this;\n },\n\n off: function(event, id) {\n if(web3._events[event] !== undefined) {\n delete web3._events[event][id];\n }\n\n return this;\n },\n\n trigger: function(event, id, data) {\n var callbacks = web3._events[event];\n if (!callbacks || !callbacks[id]) {\n return;\n }\n var cb = callbacks[id];\n cb(data);\n }\n};\n\nsetupMethods(web3, web3Methods());\nsetupMethods(web3.eth, ethMethods());\nsetupProperties(web3.eth, ethProperties());\nsetupMethods(web3.db, dbMethods());\nsetupMethods(web3.shh, shhMethods());\n\nvar ethWatch = {\n changed: 'eth_changed'\n};\nsetupMethods(ethWatch, ethWatchMethods());\nvar shhWatch = {\n changed: 'shh_changed'\n};\nsetupMethods(shhWatch, shhWatchMethods());\n\nvar ProviderManager = function() {\n this.queued = [];\n this.polls = [];\n this.ready = false;\n this.provider = undefined;\n this.id = 1;\n\n var self = this;\n var poll = function () {\n if (self.provider && self.provider.poll) {\n self.polls.forEach(function (data) {\n data.data._id = self.id;\n self.id++;\n self.provider.poll(data.data, data.id);\n });\n }\n setTimeout(poll, 12000);\n };\n poll();\n};\n\nProviderManager.prototype.send = function(data, cb) {\n data._id = this.id;\n if (cb) {\n web3._callbacks[data._id] = cb;\n }\n\n data.args = data.args || [];\n this.id++;\n\n if(this.provider !== undefined) {\n this.provider.send(data);\n } else {\n console.warn(\"provider is not set\");\n this.queued.push(data);\n }\n};\n\nProviderManager.prototype.set = function(provider) {\n if(this.provider !== undefined && this.provider.unload !== undefined) {\n this.provider.unload();\n }\n\n this.provider = provider;\n this.ready = true;\n};\n\nProviderManager.prototype.sendQueued = function() {\n for(var i = 0; this.queued.length; i++) {\n // Resend\n this.send(this.queued[i]);\n }\n};\n\nProviderManager.prototype.installed = function() {\n return this.provider !== undefined;\n};\n\nProviderManager.prototype.startPolling = function (data, pollId) {\n if (!this.provider || !this.provider.poll) {\n return;\n }\n this.polls.push({data: data, id: pollId});\n};\n\nProviderManager.prototype.stopPolling = function (pollId) {\n for (var i = this.polls.length; i--;) {\n var poll = this.polls[i];\n if (poll.id === pollId) {\n this.polls.splice(i, 1);\n }\n }\n};\n\nweb3.provider = new ProviderManager();\n\nweb3.setProvider = function(provider) {\n provider.onmessage = messageHandler;\n web3.provider.set(provider);\n web3.provider.sendQueued();\n};\n\nweb3.haveProvider = function() {\n return !!web3.provider.provider;\n};\n\nvar Filter = function(options, impl) {\n this.impl = impl;\n this.callbacks = [];\n\n var self = this;\n this.promise = impl.newFilter(options);\n this.promise.then(function (id) {\n self.id = id;\n web3.on(impl.changed, id, self.trigger.bind(self));\n web3.provider.startPolling({call: impl.changed, args: [id]}, id);\n });\n};\n\nFilter.prototype.arrived = function(callback) {\n this.changed(callback);\n};\n\nFilter.prototype.changed = function(callback) {\n var self = this;\n this.promise.then(function(id) {\n self.callbacks.push(callback);\n });\n};\n\nFilter.prototype.trigger = function(messages) {\n for(var i = 0; i < this.callbacks.length; i++) {\n this.callbacks[i].call(this, messages);\n }\n};\n\nFilter.prototype.uninstall = function() {\n var self = this;\n this.promise.then(function (id) {\n self.impl.uninstallFilter(id);\n web3.provider.stopPolling(id);\n web3.off(impl.changed, id);\n });\n};\n\nFilter.prototype.messages = function() {\n var self = this;\n return this.promise.then(function (id) {\n return self.impl.getMessages(id);\n });\n};\n\nFilter.prototype.logs = function () {\n return this.messages();\n};\n\nfunction messageHandler(data) {\n if(data._event !== undefined) {\n web3.trigger(data._event, data._id, data.data);\n return;\n }\n\n if(data._id) {\n var cb = web3._callbacks[data._id];\n if (cb) {\n cb.call(this, data.error, data.data);\n delete web3._callbacks[data._id];\n }\n }\n}\n\nmodule.exports = web3;\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file websocket.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var WebSocket = require('ws'); // jshint ignore:line\n*/}\n\nvar WebSocketProvider = function(host) {\n // onmessage handlers\n this.handlers = [];\n // queue will be filled with messages if send is invoked before the ws is ready\n this.queued = [];\n this.ready = false;\n\n this.ws = new WebSocket(host);\n\n var self = this;\n this.ws.onmessage = function(event) {\n for(var i = 0; i < self.handlers.length; i++) {\n self.handlers[i].call(self, JSON.parse(event.data), event);\n }\n };\n\n this.ws.onopen = function() {\n self.ready = true;\n\n for(var i = 0; i < self.queued.length; i++) {\n // Resend\n self.send(self.queued[i]);\n }\n };\n};\n\nWebSocketProvider.prototype.send = function(payload) {\n if(this.ready) {\n var data = JSON.stringify(payload);\n\n this.ws.send(data);\n } else {\n this.queued.push(payload);\n }\n};\n\nWebSocketProvider.prototype.onMessage = function(handler) {\n this.handlers.push(handler);\n};\n\nWebSocketProvider.prototype.unload = function() {\n this.ws.close();\n};\nObject.defineProperty(WebSocketProvider.prototype, \"onmessage\", {\n set: function(provider) { this.onMessage(provider); }\n});\n\nmodule.exports = WebSocketProvider;\n", + "var web3 = require('./lib/web3');\nweb3.providers.WebSocketProvider = require('./lib/websocket');\nweb3.providers.HttpRpcProvider = require('./lib/httprpc');\nweb3.providers.QtProvider = require('./lib/qt');\nweb3.providers.AutoProvider = require('./lib/autoprovider');\nweb3.contract = require('./lib/contract');\n\nmodule.exports = web3;\n" + ] +} \ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/dist/ethereum.min.js b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.min.js new file mode 100644 index 0000000000..0ae9610fca --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.min.js @@ -0,0 +1 @@ +require=function t(e,n,r){function o(a,s){if(!n[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;ai;i++)o+=r[i]/8;return o},c=function(){var t=function(t,e){return function(n,r){var o=t;if(0!==n.indexOf(o))return!1;var a=e(n,o);return r="number"==typeof r?r.toString(16):"string"==typeof r?web3.toHex(r):0===r.indexOf("0x")?r.substr(2):(+r).toString(16),i(r,2*a)}},e=function(t,e,n){return function(r,o){return r!==t?!1:i(n?n(o):o,2*e)}},n=function(t){return t?"0x1":"0x0"};return[t("uint",a),t("int",a),t("hash",a),t("string",s),t("real",u),t("ureal",u),e("address",20),e("bool",1,n)]},l=c(),h=function(t,e,n){var r="",a=o(t,e);if(-1!==a){r="0x"+i(a.toString(16),2);for(var s=t[a],u=0;un;n+=2){var o=t.charCodeAt(n);if(0===o)break;e+=String.fromCharCode(parseInt(t.substr(n,2),16))}return e},fromAscii:function(t,e){e=void 0===e?32:e;for(var n=this.toHex(t);n.length<2*e;)n+="00";return"0x"+n},toDecimal:function(t){return p(t.substring(2))},fromDecimal:function(t){return"0x"+d(t)},toEth:function(t){for(var e="string"==typeof t?0===t.indexOf("0x")?parseInt(t.substr(2),16):parseInt(t):t,n=0,r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e>3e3&&n + + + + + + + + +

coinbase balance

+ +
+
+
+
+ + + diff --git a/cmd/mist/assets/ext/ethereum.js/example/contract.html b/cmd/mist/assets/ext/ethereum.js/example/contract.html new file mode 100644 index 0000000000..403d8c9d19 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/example/contract.html @@ -0,0 +1,75 @@ + + + + + + + + + +

contract

+
+
+ +
+ +
+ + + diff --git a/cmd/mist/assets/ext/ethereum.js/example/node-app.js b/cmd/mist/assets/ext/ethereum.js/example/node-app.js new file mode 100644 index 0000000000..f63fa9115f --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/example/node-app.js @@ -0,0 +1,16 @@ +#!/usr/bin/env node + +require('es6-promise').polyfill(); + +var web3 = require("../index.js"); + +web3.setProvider(new web3.providers.HttpRpcProvider('http://localhost:8080')); + +web3.eth.coinbase.then(function(result){ + console.log(result); + return web3.eth.balanceAt(result); +}).then(function(balance){ + console.log(web3.toDecimal(balance)); +}).catch(function(err){ + console.log(err); +}); \ No newline at end of file diff --git a/cmd/mist/assets/ext/ethereum.js/gulpfile.js b/cmd/mist/assets/ext/ethereum.js/gulpfile.js new file mode 100644 index 0000000000..b17e50c39d --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/gulpfile.js @@ -0,0 +1,104 @@ +#!/usr/bin/env node + +'use strict'; + +var path = require('path'); + +var del = require('del'); +var gulp = require('gulp'); +var browserify = require('browserify'); +var jshint = require('gulp-jshint'); +var uglify = require('gulp-uglify'); +var rename = require('gulp-rename'); +var envify = require('envify/custom'); +var unreach = require('unreachable-branch-transform'); +var source = require('vinyl-source-stream'); +var exorcist = require('exorcist'); +var bower = require('bower'); + +var DEST = './dist/'; + +var build = function(src, dst, ugly) { + var result = browserify({ + debug: true, + insert_global_vars: false, + detectGlobals: false, + bundleExternal: false + }) + .require('./' + src + '.js', {expose: 'web3'}) + .add('./' + src + '.js') + .transform('envify', { + NODE_ENV: 'build' + }) + .transform('unreachable-branch-transform'); + + if (ugly) { + result = result.transform('uglifyify', { + mangle: false, + compress: { + dead_code: false, + conditionals: true, + unused: false, + hoist_funs: true, + hoist_vars: true, + negate_iife: false + }, + beautify: true, + warnings: true + }); + } + + return result.bundle() + .pipe(exorcist(path.join( DEST, dst + '.js.map'))) + .pipe(source(dst + '.js')) + .pipe(gulp.dest( DEST )); +}; + +var uglifyFile = function(file) { + return gulp.src( DEST + file + '.js') + .pipe(uglify()) + .pipe(rename(file + '.min.js')) + .pipe(gulp.dest( DEST )); +}; + +gulp.task('bower', function(cb){ + bower.commands.install().on('end', function (installed){ + console.log(installed); + cb(); + }); +}); + +gulp.task('clean', ['lint'], function(cb) { + del([ DEST ], cb); +}); + +gulp.task('lint', function(){ + return gulp.src(['./*.js', './lib/*.js']) + .pipe(jshint()) + .pipe(jshint.reporter('default')); +}); + +gulp.task('build', ['clean'], function () { + return build('index', 'ethereum', true); +}); + +gulp.task('buildDev', ['clean'], function () { + return build('index', 'ethereum', false); +}); + +gulp.task('uglify', ['build'], function(){ + return uglifyFile('ethereum'); +}); + +gulp.task('uglify', ['buildDev'], function(){ + return uglifyFile('ethereum'); +}); + +gulp.task('watch', function() { + gulp.watch(['./lib/*.js'], ['lint', 'prepare', 'build']); +}); + +gulp.task('release', ['bower', 'lint', 'build', 'uglify']); +gulp.task('dev', ['bower', 'lint', 'buildDev', 'uglify']); +gulp.task('default', ['dev']); + diff --git a/cmd/mist/assets/ext/ethereum.js/index.js b/cmd/mist/assets/ext/ethereum.js/index.js new file mode 100644 index 0000000000..99ce66fadb --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/index.js @@ -0,0 +1,8 @@ +var web3 = require('./lib/web3'); +web3.providers.WebSocketProvider = require('./lib/websocket'); +web3.providers.HttpRpcProvider = require('./lib/httprpc'); +web3.providers.QtProvider = require('./lib/qt'); +web3.providers.AutoProvider = require('./lib/autoprovider'); +web3.contract = require('./lib/contract'); + +module.exports = web3; diff --git a/cmd/mist/assets/ext/ethereum.js/lib/abi.js b/cmd/mist/assets/ext/ethereum.js/lib/abi.js new file mode 100644 index 0000000000..1912fff32d --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/abi.js @@ -0,0 +1,267 @@ +/* + This file is part of ethereum.js. + + ethereum.js 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. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file abi.js + * @authors: + * Marek Kotewicz + * Gav Wood + * @date 2014 + */ + +// TODO: is these line is supposed to be here? +if (process.env.NODE_ENV !== 'build') { + var web3 = require('./web3'); // jshint ignore:line +} + +// TODO: make these be actually accurate instead of falling back onto JS's doubles. +var hexToDec = function (hex) { + return parseInt(hex, 16).toString(); +}; + +var decToHex = function (dec) { + return parseInt(dec).toString(16); +}; + +var findIndex = function (array, callback) { + var end = false; + var i = 0; + for (; i < array.length && !end; i++) { + end = callback(array[i]); + } + return end ? i - 1 : -1; +}; + +var findMethodIndex = function (json, methodName) { + return findIndex(json, function (method) { + return method.name === methodName; + }); +}; + +var padLeft = function (string, chars) { + return new Array(chars - string.length + 1).join("0") + string; +}; + +var calcBitPadding = function (type, expected) { + var value = type.slice(expected.length); + if (value === "") { + return 32; + } + return parseInt(value) / 8; +}; + +var calcBytePadding = function (type, expected) { + var value = type.slice(expected.length); + if (value === "") { + return 32; + } + return parseInt(value); +}; + +var calcRealPadding = function (type, expected) { + var value = type.slice(expected.length); + if (value === "") { + return 32; + } + var sizes = value.split('x'); + for (var padding = 0, i = 0; i < sizes; i++) { + padding += (sizes[i] / 8); + } + return padding; +}; + +var setupInputTypes = function () { + + var prefixedType = function (prefix, calcPadding) { + return function (type, value) { + var expected = prefix; + if (type.indexOf(expected) !== 0) { + return false; + } + + var padding = calcPadding(type, expected); + if (typeof value === "number") + value = value.toString(16); + else if (typeof value === "string") + value = web3.toHex(value); + else if (value.indexOf('0x') === 0) + value = value.substr(2); + else + value = (+value).toString(16); + return padLeft(value, padding * 2); + }; + }; + + var namedType = function (name, padding, formatter) { + return function (type, value) { + if (type !== name) { + return false; + } + + return padLeft(formatter ? formatter(value) : value, padding * 2); + }; + }; + + var formatBool = function (value) { + return value ? '0x1' : '0x0'; + }; + + return [ + prefixedType('uint', calcBitPadding), + prefixedType('int', calcBitPadding), + prefixedType('hash', calcBitPadding), + prefixedType('string', calcBytePadding), + prefixedType('real', calcRealPadding), + prefixedType('ureal', calcRealPadding), + namedType('address', 20), + namedType('bool', 1, formatBool), + ]; +}; + +var inputTypes = setupInputTypes(); + +var toAbiInput = function (json, methodName, params) { + var bytes = ""; + var index = findMethodIndex(json, methodName); + + if (index === -1) { + return; + } + + bytes = "0x" + padLeft(index.toString(16), 2); + var method = json[index]; + + for (var i = 0; i < method.inputs.length; i++) { + var found = false; + for (var j = 0; j < inputTypes.length && !found; j++) { + found = inputTypes[j](method.inputs[i].type, params[i]); + } + if (!found) { + console.error('unsupported json type: ' + method.inputs[i].type); + } + bytes += found; + } + return bytes; +}; + +var setupOutputTypes = function () { + + var prefixedType = function (prefix, calcPadding) { + return function (type) { + var expected = prefix; + if (type.indexOf(expected) !== 0) { + return -1; + } + + var padding = calcPadding(type, expected); + return padding * 2; + }; + }; + + var namedType = function (name, padding) { + return function (type) { + return name === type ? padding * 2 : -1; + }; + }; + + var formatInt = function (value) { + return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value); + }; + + var formatHash = function (value) { + return "0x" + value; + }; + + var formatBool = function (value) { + return value === '1' ? true : false; + }; + + var formatString = function (value) { + return web3.toAscii(value); + }; + + return [ + { padding: prefixedType('uint', calcBitPadding), format: formatInt }, + { padding: prefixedType('int', calcBitPadding), format: formatInt }, + { padding: prefixedType('hash', calcBitPadding), format: formatHash }, + { padding: prefixedType('string', calcBytePadding), format: formatString }, + { padding: prefixedType('real', calcRealPadding), format: formatInt }, + { padding: prefixedType('ureal', calcRealPadding), format: formatInt }, + { padding: namedType('address', 20) }, + { padding: namedType('bool', 1), format: formatBool } + ]; +}; + +var outputTypes = setupOutputTypes(); + +var fromAbiOutput = function (json, methodName, output) { + var index = findMethodIndex(json, methodName); + + if (index === -1) { + return; + } + + output = output.slice(2); + + var result = []; + var method = json[index]; + for (var i = 0; i < method.outputs.length; i++) { + var padding = -1; + for (var j = 0; j < outputTypes.length && padding === -1; j++) { + padding = outputTypes[j].padding(method.outputs[i].type); + } + + if (padding === -1) { + // not found output parsing + continue; + } + var res = output.slice(0, padding); + var formatter = outputTypes[j - 1].format; + result.push(formatter ? formatter(res) : ("0x" + res)); + output = output.slice(padding); + } + + return result; +}; + +var inputParser = function (json) { + var parser = {}; + json.forEach(function (method) { + parser[method.name] = function () { + var params = Array.prototype.slice.call(arguments); + return toAbiInput(json, method.name, params); + }; + }); + + return parser; +}; + +var outputParser = function (json) { + var parser = {}; + json.forEach(function (method) { + parser[method.name] = function (output) { + return fromAbiOutput(json, method.name, output); + }; + }); + + return parser; +}; + +if (typeof(module) !== "undefined") { + module.exports = { + inputParser: inputParser, + outputParser: outputParser + }; +} diff --git a/cmd/mist/assets/ext/ethereum.js/lib/autoprovider.js b/cmd/mist/assets/ext/ethereum.js/lib/autoprovider.js new file mode 100644 index 0000000000..3cb83d4a0c --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/autoprovider.js @@ -0,0 +1,103 @@ +/* + This file is part of ethereum.js. + + ethereum.js 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. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file autoprovider.js + * @authors: + * Marek Kotewicz + * Marian Oancea + * @date 2014 + */ + +/* + * @brief if qt object is available, uses QtProvider, + * if not tries to connect over websockets + * if it fails, it uses HttpRpcProvider + */ + +// TODO: is these line is supposed to be here? +if (process.env.NODE_ENV !== 'build') { + var WebSocket = require('ws'); // jshint ignore:line + var web3 = require('./web3'); // jshint ignore:line +} + +var AutoProvider = function (userOptions) { + if (web3.haveProvider()) { + return; + } + + // before we determine what provider we are, we have to cache request + this.sendQueue = []; + this.onmessageQueue = []; + + if (navigator.qt) { + this.provider = new web3.providers.QtProvider(); + return; + } + + userOptions = userOptions || {}; + var options = { + httprpc: userOptions.httprpc || 'http://localhost:8080', + websockets: userOptions.websockets || 'ws://localhost:40404/eth' + }; + + var self = this; + var closeWithSuccess = function (success) { + ws.close(); + if (success) { + self.provider = new web3.providers.WebSocketProvider(options.websockets); + } else { + self.provider = new web3.providers.HttpRpcProvider(options.httprpc); + self.poll = self.provider.poll.bind(self.provider); + } + self.sendQueue.forEach(function (payload) { + self.provider(payload); + }); + self.onmessageQueue.forEach(function (handler) { + self.provider.onmessage = handler; + }); + }; + + var ws = new WebSocket(options.websockets); + + ws.onopen = function() { + closeWithSuccess(true); + }; + + ws.onerror = function() { + closeWithSuccess(false); + }; +}; + +AutoProvider.prototype.send = function (payload) { + if (this.provider) { + this.provider.send(payload); + return; + } + this.sendQueue.push(payload); +}; + +Object.defineProperty(AutoProvider.prototype, 'onmessage', { + set: function (handler) { + if (this.provider) { + this.provider.onmessage = handler; + return; + } + this.onmessageQueue.push(handler); + } +}); + +if (typeof(module) !== "undefined") + module.exports = AutoProvider; diff --git a/cmd/mist/assets/ext/ethereum.js/lib/contract.js b/cmd/mist/assets/ext/ethereum.js/lib/contract.js new file mode 100644 index 0000000000..dc84eb9961 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/contract.js @@ -0,0 +1,66 @@ +/* + This file is part of ethereum.js. + + ethereum.js 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. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file contract.js + * @authors: + * Marek Kotewicz + * @date 2014 + */ + +// TODO: is these line is supposed to be here? +if (process.env.NODE_ENV !== 'build') { + var web3 = require('./web3'); // jshint ignore:line +} + +var abi = require('./abi'); + +var contract = function (address, desc) { + var inputParser = abi.inputParser(desc); + var outputParser = abi.outputParser(desc); + + var contract = {}; + + desc.forEach(function (method) { + contract[method.name] = function () { + var params = Array.prototype.slice.call(arguments); + var parsed = inputParser[method.name].apply(null, params); + + var onSuccess = function (result) { + return outputParser[method.name](result); + }; + + return { + call: function (extra) { + extra = extra || {}; + extra.to = address; + extra.data = parsed; + return web3.eth.call(extra).then(onSuccess); + }, + transact: function (extra) { + extra = extra || {}; + extra.to = address; + extra.data = parsed; + return web3.eth.transact(extra).then(onSuccess); + } + }; + }; + }); + + return contract; +}; + +if (typeof(module) !== "undefined") + module.exports = contract; diff --git a/cmd/mist/assets/ext/ethereum.js/lib/httprpc.js b/cmd/mist/assets/ext/ethereum.js/lib/httprpc.js new file mode 100644 index 0000000000..6823b96b47 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/httprpc.js @@ -0,0 +1,95 @@ +/* + This file is part of ethereum.js. + + ethereum.js 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. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file httprpc.js + * @authors: + * Marek Kotewicz + * Marian Oancea + * @date 2014 + */ + +// TODO: is these line is supposed to be here? +if (process.env.NODE_ENV !== 'build') { + var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line +} + +var HttpRpcProvider = function (host) { + this.handlers = []; + this.host = host; +}; + +function formatJsonRpcObject(object) { + return { + jsonrpc: '2.0', + method: object.call, + params: object.args, + id: object._id + }; +} + +function formatJsonRpcMessage(message) { + var object = JSON.parse(message); + + return { + _id: object.id, + data: object.result, + error: object.error + }; +} + +HttpRpcProvider.prototype.sendRequest = function (payload, cb) { + var data = formatJsonRpcObject(payload); + + var request = new XMLHttpRequest(); + request.open("POST", this.host, true); + request.send(JSON.stringify(data)); + request.onreadystatechange = function () { + if (request.readyState === 4 && cb) { + cb(request); + } + }; +}; + +HttpRpcProvider.prototype.send = function (payload) { + var self = this; + this.sendRequest(payload, function (request) { + self.handlers.forEach(function (handler) { + handler.call(self, formatJsonRpcMessage(request.responseText)); + }); + }); +}; + +HttpRpcProvider.prototype.poll = function (payload, id) { + var self = this; + this.sendRequest(payload, function (request) { + var parsed = JSON.parse(request.responseText); + if (parsed.error || (parsed.result instanceof Array ? parsed.result.length === 0 : !parsed.result)) { + return; + } + self.handlers.forEach(function (handler) { + handler.call(self, {_event: payload.call, _id: id, data: parsed.result}); + }); + }); +}; + +Object.defineProperty(HttpRpcProvider.prototype, "onmessage", { + set: function (handler) { + this.handlers.push(handler); + } +}); + +if (typeof(module) !== "undefined") + module.exports = HttpRpcProvider; diff --git a/cmd/mist/assets/ext/ethereum.js/lib/qt.js b/cmd/mist/assets/ext/ethereum.js/lib/qt.js new file mode 100644 index 0000000000..f51e65da4b --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/qt.js @@ -0,0 +1,46 @@ +/* + This file is part of ethereum.js. + + ethereum.js 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. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file qt.js + * @authors: + * Jeffrey Wilcke + * Marek Kotewicz + * @date 2014 + */ + +var QtProvider = function() { + this.handlers = []; + + var self = this; + navigator.qt.onmessage = function (message) { + self.handlers.forEach(function (handler) { + handler.call(self, JSON.parse(message.data)); + }); + }; +}; + +QtProvider.prototype.send = function(payload) { + navigator.qt.postMessage(JSON.stringify(payload)); +}; + +Object.defineProperty(QtProvider.prototype, "onmessage", { + set: function(handler) { + this.handlers.push(handler); + } +}); + +if (typeof(module) !== "undefined") + module.exports = QtProvider; diff --git a/cmd/mist/assets/ext/ethereum.js/lib/web3.js b/cmd/mist/assets/ext/ethereum.js/lib/web3.js new file mode 100644 index 0000000000..9a85c4d1bd --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/web3.js @@ -0,0 +1,509 @@ +/* + This file is part of ethereum.js. + + ethereum.js 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. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file main.js + * @authors: + * Jeffrey Wilcke + * Marek Kotewicz + * Marian Oancea + * Gav Wood + * @date 2014 + */ + +function flattenPromise (obj) { + if (obj instanceof Promise) { + return Promise.resolve(obj); + } + + if (obj instanceof Array) { + return new Promise(function (resolve) { + var promises = obj.map(function (o) { + return flattenPromise(o); + }); + + return Promise.all(promises).then(function (res) { + for (var i = 0; i < obj.length; i++) { + obj[i] = res[i]; + } + resolve(obj); + }); + }); + } + + if (obj instanceof Object) { + return new Promise(function (resolve) { + var keys = Object.keys(obj); + var promises = keys.map(function (key) { + return flattenPromise(obj[key]); + }); + + return Promise.all(promises).then(function (res) { + for (var i = 0; i < keys.length; i++) { + obj[keys[i]] = res[i]; + } + resolve(obj); + }); + }); + } + + return Promise.resolve(obj); +} + +var web3Methods = function () { + return [ + { name: 'sha3', call: 'web3_sha3' } + ]; +}; + +var ethMethods = function () { + var blockCall = function (args) { + return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber"; + }; + + var transactionCall = function (args) { + return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber'; + }; + + var uncleCall = function (args) { + return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber'; + }; + + var methods = [ + { name: 'balanceAt', call: 'eth_balanceAt' }, + { name: 'stateAt', call: 'eth_stateAt' }, + { name: 'storageAt', call: 'eth_storageAt' }, + { name: 'countAt', call: 'eth_countAt'}, + { name: 'codeAt', call: 'eth_codeAt' }, + { name: 'transact', call: 'eth_transact' }, + { name: 'call', call: 'eth_call' }, + { name: 'block', call: blockCall }, + { name: 'transaction', call: transactionCall }, + { name: 'uncle', call: uncleCall }, + { name: 'compilers', call: 'eth_compilers' }, + { name: 'lll', call: 'eth_lll' }, + { name: 'solidity', call: 'eth_solidity' }, + { name: 'serpent', call: 'eth_serpent' }, + { name: 'logs', call: 'eth_logs' } + ]; + return methods; +}; + +var ethProperties = function () { + return [ + { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' }, + { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' }, + { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' }, + { name: 'gasPrice', getter: 'eth_gasPrice' }, + { name: 'account', getter: 'eth_account' }, + { name: 'accounts', getter: 'eth_accounts' }, + { name: 'peerCount', getter: 'eth_peerCount' }, + { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' }, + { name: 'number', getter: 'eth_number'} + ]; +}; + +var dbMethods = function () { + return [ + { name: 'put', call: 'db_put' }, + { name: 'get', call: 'db_get' }, + { name: 'putString', call: 'db_putString' }, + { name: 'getString', call: 'db_getString' } + ]; +}; + +var shhMethods = function () { + return [ + { name: 'post', call: 'shh_post' }, + { name: 'newIdentity', call: 'shh_newIdentity' }, + { name: 'haveIdentity', call: 'shh_haveIdentity' }, + { name: 'newGroup', call: 'shh_newGroup' }, + { name: 'addToGroup', call: 'shh_addToGroup' } + ]; +}; + +var ethWatchMethods = function () { + var newFilter = function (args) { + return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter'; + }; + + return [ + { name: 'newFilter', call: newFilter }, + { name: 'uninstallFilter', call: 'eth_uninstallFilter' }, + { name: 'getMessages', call: 'eth_filterLogs' } + ]; +}; + +var shhWatchMethods = function () { + return [ + { name: 'newFilter', call: 'shh_newFilter' }, + { name: 'uninstallFilter', call: 'shh_uninstallFilter' }, + { name: 'getMessage', call: 'shh_getMessages' } + ]; +}; + +var setupMethods = function (obj, methods) { + methods.forEach(function (method) { + obj[method.name] = function () { + return flattenPromise(Array.prototype.slice.call(arguments)).then(function (args) { + var call = typeof method.call === "function" ? method.call(args) : method.call; + return {call: call, args: args}; + }).then(function (request) { + return new Promise(function (resolve, reject) { + web3.provider.send(request, function (err, result) { + if (!err) { + resolve(result); + return; + } + reject(err); + }); + }); + }).catch(function(err) { + console.error(err); + }); + }; + }); +}; + +var setupProperties = function (obj, properties) { + properties.forEach(function (property) { + var proto = {}; + proto.get = function () { + return new Promise(function(resolve, reject) { + web3.provider.send({call: property.getter}, function(err, result) { + if (!err) { + resolve(result); + return; + } + reject(err); + }); + }); + }; + if (property.setter) { + proto.set = function (val) { + return flattenPromise([val]).then(function (args) { + return new Promise(function (resolve) { + web3.provider.send({call: property.setter, args: args}, function (err, result) { + if (!err) { + resolve(result); + return; + } + reject(err); + }); + }); + }).catch(function (err) { + console.error(err); + }); + }; + } + Object.defineProperty(obj, property.name, proto); + }); +}; + +// TODO: import from a dependency, don't duplicate. +var hexToDec = function (hex) { + return parseInt(hex, 16).toString(); +}; + +var decToHex = function (dec) { + return parseInt(dec).toString(16); +}; + + +var web3 = { + _callbacks: {}, + _events: {}, + providers: {}, + + toHex: function(str) { + var hex = ""; + for(var i = 0; i < str.length; i++) { + var n = str.charCodeAt(i).toString(16); + hex += n.length < 2 ? '0' + n : n; + } + + return hex; + }, + + toAscii: function(hex) { + // Find termination + var str = ""; + var i = 0, l = hex.length; + if (hex.substring(0, 2) === '0x') + i = 2; + for(; i < l; i+=2) { + var code = hex.charCodeAt(i); + if(code === 0) { + break; + } + + str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); + } + + return str; + }, + + fromAscii: function(str, pad) { + pad = pad === undefined ? 32 : pad; + var hex = this.toHex(str); + while(hex.length < pad*2) + hex += "00"; + return "0x" + hex; + }, + + toDecimal: function (val) { + return hexToDec(val.substring(2)); + }, + + fromDecimal: function (val) { + return "0x" + decToHex(val); + }, + + toEth: function(str) { + var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str; + var unit = 0; + var units = [ 'wei', 'Kwei', 'Mwei', 'Gwei', 'szabo', 'finney', 'ether', 'grand', 'Mether', 'Gether', 'Tether', 'Pether', 'Eether', 'Zether', 'Yether', 'Nether', 'Dether', 'Vether', 'Uether' ]; + while (val > 3000 && unit < units.length - 1) + { + val /= 1000; + unit++; + } + var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2); + var replaceFunction = function($0, $1, $2) { + return $1 + ',' + $2; + }; + + while (true) { + var o = s; + s = s.replace(/(\d)(\d\d\d[\.\,])/, replaceFunction); + if (o === s) + break; + } + return s + ' ' + units[unit]; + }, + + eth: { + prototype: Object(), // jshint ignore:line + watch: function (params) { + return new Filter(params, ethWatch); + } + }, + + db: { + prototype: Object() // jshint ignore:line + }, + + shh: { + prototype: Object(), // jshint ignore:line + watch: function (params) { + return new Filter(params, shhWatch); + } + }, + + on: function(event, id, cb) { + if(web3._events[event] === undefined) { + web3._events[event] = {}; + } + + web3._events[event][id] = cb; + return this; + }, + + off: function(event, id) { + if(web3._events[event] !== undefined) { + delete web3._events[event][id]; + } + + return this; + }, + + trigger: function(event, id, data) { + var callbacks = web3._events[event]; + if (!callbacks || !callbacks[id]) { + return; + } + var cb = callbacks[id]; + cb(data); + } +}; + +setupMethods(web3, web3Methods()); +setupMethods(web3.eth, ethMethods()); +setupProperties(web3.eth, ethProperties()); +setupMethods(web3.db, dbMethods()); +setupMethods(web3.shh, shhMethods()); + +var ethWatch = { + changed: 'eth_changed' +}; +setupMethods(ethWatch, ethWatchMethods()); +var shhWatch = { + changed: 'shh_changed' +}; +setupMethods(shhWatch, shhWatchMethods()); + +var ProviderManager = function() { + this.queued = []; + this.polls = []; + this.ready = false; + this.provider = undefined; + this.id = 1; + + var self = this; + var poll = function () { + if (self.provider && self.provider.poll) { + self.polls.forEach(function (data) { + data.data._id = self.id; + self.id++; + self.provider.poll(data.data, data.id); + }); + } + setTimeout(poll, 12000); + }; + poll(); +}; + +ProviderManager.prototype.send = function(data, cb) { + data._id = this.id; + if (cb) { + web3._callbacks[data._id] = cb; + } + + data.args = data.args || []; + this.id++; + + if(this.provider !== undefined) { + this.provider.send(data); + } else { + console.warn("provider is not set"); + this.queued.push(data); + } +}; + +ProviderManager.prototype.set = function(provider) { + if(this.provider !== undefined && this.provider.unload !== undefined) { + this.provider.unload(); + } + + this.provider = provider; + this.ready = true; +}; + +ProviderManager.prototype.sendQueued = function() { + for(var i = 0; this.queued.length; i++) { + // Resend + this.send(this.queued[i]); + } +}; + +ProviderManager.prototype.installed = function() { + return this.provider !== undefined; +}; + +ProviderManager.prototype.startPolling = function (data, pollId) { + if (!this.provider || !this.provider.poll) { + return; + } + this.polls.push({data: data, id: pollId}); +}; + +ProviderManager.prototype.stopPolling = function (pollId) { + for (var i = this.polls.length; i--;) { + var poll = this.polls[i]; + if (poll.id === pollId) { + this.polls.splice(i, 1); + } + } +}; + +web3.provider = new ProviderManager(); + +web3.setProvider = function(provider) { + provider.onmessage = messageHandler; + web3.provider.set(provider); + web3.provider.sendQueued(); +}; + +web3.haveProvider = function() { + return !!web3.provider.provider; +}; + +var Filter = function(options, impl) { + this.impl = impl; + this.callbacks = []; + + var self = this; + this.promise = impl.newFilter(options); + this.promise.then(function (id) { + self.id = id; + web3.on(impl.changed, id, self.trigger.bind(self)); + web3.provider.startPolling({call: impl.changed, args: [id]}, id); + }); +}; + +Filter.prototype.arrived = function(callback) { + this.changed(callback); +}; + +Filter.prototype.changed = function(callback) { + var self = this; + this.promise.then(function(id) { + self.callbacks.push(callback); + }); +}; + +Filter.prototype.trigger = function(messages) { + for(var i = 0; i < this.callbacks.length; i++) { + this.callbacks[i].call(this, messages); + } +}; + +Filter.prototype.uninstall = function() { + var self = this; + this.promise.then(function (id) { + self.impl.uninstallFilter(id); + web3.provider.stopPolling(id); + web3.off(impl.changed, id); + }); +}; + +Filter.prototype.messages = function() { + var self = this; + return this.promise.then(function (id) { + return self.impl.getMessages(id); + }); +}; + +Filter.prototype.logs = function () { + return this.messages(); +}; + +function messageHandler(data) { + if(data._event !== undefined) { + web3.trigger(data._event, data._id, data.data); + return; + } + + if(data._id) { + var cb = web3._callbacks[data._id]; + if (cb) { + cb.call(this, data.error, data.data); + delete web3._callbacks[data._id]; + } + } +} + +if (typeof(module) !== "undefined") + module.exports = web3; diff --git a/cmd/mist/assets/ext/ethereum.js/lib/websocket.js b/cmd/mist/assets/ext/ethereum.js/lib/websocket.js new file mode 100644 index 0000000000..5b40075e43 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/lib/websocket.js @@ -0,0 +1,78 @@ +/* + This file is part of ethereum.js. + + ethereum.js 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. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file websocket.js + * @authors: + * Jeffrey Wilcke + * Marek Kotewicz + * Marian Oancea + * @date 2014 + */ + +// TODO: is these line is supposed to be here? +if (process.env.NODE_ENV !== 'build') { + var WebSocket = require('ws'); // jshint ignore:line +} + +var WebSocketProvider = function(host) { + // onmessage handlers + this.handlers = []; + // queue will be filled with messages if send is invoked before the ws is ready + this.queued = []; + this.ready = false; + + this.ws = new WebSocket(host); + + var self = this; + this.ws.onmessage = function(event) { + for(var i = 0; i < self.handlers.length; i++) { + self.handlers[i].call(self, JSON.parse(event.data), event); + } + }; + + this.ws.onopen = function() { + self.ready = true; + + for(var i = 0; i < self.queued.length; i++) { + // Resend + self.send(self.queued[i]); + } + }; +}; + +WebSocketProvider.prototype.send = function(payload) { + if(this.ready) { + var data = JSON.stringify(payload); + + this.ws.send(data); + } else { + this.queued.push(payload); + } +}; + +WebSocketProvider.prototype.onMessage = function(handler) { + this.handlers.push(handler); +}; + +WebSocketProvider.prototype.unload = function() { + this.ws.close(); +}; +Object.defineProperty(WebSocketProvider.prototype, "onmessage", { + set: function(provider) { this.onMessage(provider); } +}); + +if (typeof(module) !== "undefined") + module.exports = WebSocketProvider; diff --git a/cmd/mist/assets/ext/ethereum.js/package.json b/cmd/mist/assets/ext/ethereum.js/package.json new file mode 100644 index 0000000000..8f5ba22555 --- /dev/null +++ b/cmd/mist/assets/ext/ethereum.js/package.json @@ -0,0 +1,67 @@ +{ + "name": "ethereum.js", + "namespace": "ethereum", + "version": "0.0.6", + "description": "Ethereum Compatible JavaScript API", + "main": "./index.js", + "directories": { + "lib": "./lib" + }, + "dependencies": { + "es6-promise": "*", + "ws": "*", + "xmlhttprequest": "*" + }, + "devDependencies": { + "bower": ">=1.3.0", + "browserify": ">=6.0", + "del": ">=0.1.1", + "envify": "^3.0.0", + "exorcist": "^0.1.6", + "gulp": ">=3.4.0", + "gulp-jshint": ">=1.5.0", + "gulp-rename": ">=1.2.0", + "gulp-uglify": ">=1.0.0", + "jshint": ">=2.5.0", + "uglifyify": "^2.6.0", + "unreachable-branch-transform": "^0.1.0", + "vinyl-source-stream": "^1.0.0" + }, + "scripts": { + "build": "gulp", + "watch": "gulp watch", + "lint": "gulp lint" + }, + "repository": { + "type": "git", + "url": "https://github.com/ethereum/ethereum.js.git" + }, + "homepage": "https://github.com/ethereum/ethereum.js", + "bugs": { + "url": "https://github.com/ethereum/ethereum.js/issues" + }, + "keywords": [ + "ethereum", + "javascript", + "API" + ], + "author": "ethdev.com", + "authors": [ + { + "name": "Jeffery Wilcke", + "email": "jeff@ethdev.com", + "url": "https://github.com/obscuren" + }, + { + "name": "Marek Kotewicz", + "email": "marek@ethdev.com", + "url": "https://github.com/debris" + }, + { + "name": "Marian Oancea", + "email": "marian@ethdev.com", + "url": "https://github.com/cubedro" + } + ], + "license": "LGPL-3.0" +} diff --git a/cmd/mist/assets/qml/webapp.qml b/cmd/mist/assets/qml/browser.qml similarity index 81% rename from cmd/mist/assets/qml/webapp.qml rename to cmd/mist/assets/qml/browser.qml index bd7399dc9b..f6d2d2d64b 100644 --- a/cmd/mist/assets/qml/webapp.qml +++ b/cmd/mist/assets/qml/browser.qml @@ -66,7 +66,11 @@ Rectangle { onMessages: { // Bit of a cheat to get proper JSON var m = JSON.parse(JSON.parse(JSON.stringify(messages))) - webview.postEvent("messages", [m, id]); + webview.postEvent("messages", id, m); + } + + function onShhMessage(message, id) { + webview.postEvent("shh_changed", id, message) } Item { @@ -105,7 +109,8 @@ Rectangle { leftMargin: 5 rightMargin: 5 } - text: "http://etherian.io" + //text: "http://etherian.io" + text: webview.url; id: uriNav y: parent.height / 2 - this.height / 2 @@ -147,6 +152,12 @@ Rectangle { window.open(request.url.toString()); } + function injectJs(js) { + webview.experimental.navigatorQtObjectEnabled = true; + webview.experimental.evaluateJavaScript(js) + webview.experimental.javascriptEnabled = true; + } + function sendMessage(data) { webview.experimental.postMessage(JSON.stringify(data)) } @@ -155,8 +166,7 @@ Rectangle { experimental.preferences.javascriptEnabled: true experimental.preferences.navigatorQtObjectEnabled: true experimental.preferences.developerExtrasEnabled: true - //experimental.userScripts: ["../ext/qt_messaging_adapter.js", "../ext/q.js", "../ext/big.js", "../ext/string.js", "../ext/html_messaging.js"] - experimental.userScripts: ["../ext/q.js", "../ext/eth.js/main.js", "../ext/eth.js/qt.js", "../ext/setup.js"] + experimental.userScripts: ["../ext/q.js", "../ext/ethereum.js/lib/web3.js", "../ext/ethereum.js/lib/qt.js", "../ext/setup.js"] experimental.onMessageReceived: { console.log("[onMessageReceived]: ", message.data) // TODO move to messaging.js @@ -164,51 +174,51 @@ Rectangle { try { switch(data.call) { - case "compile": + case "eth_compile": postData(data._id, eth.compile(data.args[0])) break - case "coinbase": + case "eth_coinbase": postData(data._id, eth.coinBase()) - case "account": + case "eth_account": postData(data._id, eth.key().address); - case "isListening": + case "eth_istening": postData(data._id, eth.isListening()) break - case "isMining": + case "eth_mining": postData(data._id, eth.isMining()) break - case "peerCount": + case "eth_peerCount": postData(data._id, eth.peerCount()) break - case "countAt": + case "eth_countAt": require(1) postData(data._id, eth.txCountAt(data.args[0])) break - case "codeAt": + case "eth_codeAt": require(1) var code = eth.codeAt(data.args[0]) postData(data._id, code); break - case "blockByNumber": + case "eth_blockByNumber": require(1) var block = eth.blockByNumber(data.args[0]) postData(data._id, block) break - case "blockByHash": + case "eth_blockByHash": require(1) var block = eth.blockByHash(data.args[0]) postData(data._id, block) @@ -219,8 +229,8 @@ Rectangle { postData(data._id, block.transactions[data.args[1]]) break - case "transactionByHash": - case "transactionByNumber": + case "eth_transactionByHash": + case "eth_transactionByNumber": require(2) var block; @@ -234,8 +244,8 @@ Rectangle { postData(data._id, tx) break - case "uncleByHash": - case "uncleByNumber": + case "eth_uncleByHash": + case "eth_uncleByNumber": require(2) var block; @@ -258,7 +268,7 @@ Rectangle { break - case "stateAt": + case "eth_stateAt": require(2); var storage = eth.storageAt(data.args[0], data.args[1]); @@ -266,55 +276,41 @@ Rectangle { break - case "call": + case "eth_call": require(1); var ret = eth.call(data.args) postData(data._id, ret) break - case "balanceAt": + case "eth_balanceAt": require(1); postData(data._id, eth.balanceAt(data.args[0])); break - case "watch": + case "eth_watch": require(2) eth.watch(data.args[0], data.args[1]) - case "disconnect": + case "eth_disconnect": require(1) postData(data._id, null) break; - case "messages": - require(1); - - var messages = JSON.parse(eth.getMessages(data.args[0])) - postData(data._id, messages) - break - - case "mutan": - require(1) - - var code = eth.compileMutan(data.args[0]) - postData(data._id, "0x"+code) - break; - - case "newFilterString": + case "eth_newFilterString": require(1) var id = eth.newFilterString(data.args[0]) postData(data._id, id); break; - case "newFilter": + case "eth_newFilter": require(1) var id = eth.newFilter(data.args[0]) postData(data._id, id); break; - case "getMessages": + case "eth_messages": require(1); var messages = eth.messages(data.args[0]); @@ -323,10 +319,40 @@ Rectangle { break; - case "deleteFilter": + case "eth_deleteFilter": require(1); eth.uninstallFilter(data.args[0]) break; + + + case "shh_newFilter": + require(1); + var id = shh.watch(data.args[0], window); + postData(data._id, id); + break; + + case "shh_newIdentity": + var id = shh.newIdentity() + postData(data._id, id) + + break + + case "shh_post": + require(1); + + var params = data.args[0]; + var fields = ["payload", "to", "from"]; + for(var i = 0; i < fields.length; i++) { + params[fields[i]] = params[fields[i]] || ""; + } + if(typeof params.payload !== "object") { params.payload = [params.payload]; } //params.payload = params.payload.join(""); } + params.topics = params.topics || []; + params.priority = params.priority || 1000; + params.ttl = params.ttl || 100; + + shh.post(params.payload, params.to, params.from, params.topics, params.priority, params.ttl); + + break; } } catch(e) { console.log(data.call + ": " + e) @@ -348,8 +374,8 @@ Rectangle { function postData(seed, data) { webview.experimental.postMessage(JSON.stringify({data: data, _id: seed})) } - function postEvent(event, data) { - webview.experimental.postMessage(JSON.stringify({data: data, _event: event})) + function postEvent(event, id, data) { + webview.experimental.postMessage(JSON.stringify({data: data, _id: id, _event: event})) } function onWatchedCb(data, id) { diff --git a/cmd/mist/assets/qml/main.qml b/cmd/mist/assets/qml/main.qml index 2857570809..e287e384f2 100644 --- a/cmd/mist/assets/qml/main.qml +++ b/cmd/mist/assets/qml/main.qml @@ -45,7 +45,7 @@ ApplicationWindow { // Takes care of loading all default plugins Component.onCompleted: { var wallet = addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "ethereum", active: true}); - var browser = addPlugin("./webapp.qml", {noAdd: true, close: false, section: "ethereum", active: true}); + var browser = addPlugin("./browser.qml", {noAdd: true, close: false, section: "ethereum", active: true}); root.browser = browser; addPlugin("./views/miner.qml", {noAdd: true, close: false, section: "ethereum", active: true}); @@ -59,8 +59,8 @@ ApplicationWindow { mainSplit.setView(wallet.view, wallet.menuItem); - // Call the ready handler - gui.done(); + // Command setup + gui.sendCommand(0) } function addViews(view, path, options) { @@ -512,18 +512,17 @@ ApplicationWindow { var section; switch(options.section) { case "ethereum": - section = menuDefault; - break; + section = menuDefault; + break; case "legacy": - section = menuLegacy; - break; + section = menuLegacy; + break; default: - section = menuApps; - break; + section = menuApps; + break; } var comp = menuItemTemplate.createObject(section) - comp.view = view comp.title = view.title @@ -771,12 +770,9 @@ ApplicationWindow { anchors.fill: parent id: peerTable model: peerModel - TableViewColumn{width: 100; role: "ip" ; title: "IP" } - TableViewColumn{width: 60; role: "port" ; title: "Port" } - TableViewColumn{width: 140; role: "lastResponse"; title: "Last event" } - TableViewColumn{width: 100; role: "latency"; title: "Latency" } + TableViewColumn{width: 200; role: "ip" ; title: "IP" } TableViewColumn{width: 260; role: "version" ; title: "Version" } - TableViewColumn{width: 80; role: "caps" ; title: "Capabilities" } + TableViewColumn{width: 180; role: "caps" ; title: "Capabilities" } } } } @@ -787,8 +783,8 @@ ApplicationWindow { title: "About" minimumWidth: 350 maximumWidth: 350 - maximumHeight: 200 - minimumHeight: 200 + maximumHeight: 280 + minimumHeight: 280 Image { id: aboutIcon @@ -798,7 +794,7 @@ ApplicationWindow { smooth: true source: "../facet.png" x: 10 - y: 10 + y: 30 } Text { @@ -807,7 +803,7 @@ ApplicationWindow { anchors.top: parent.top anchors.topMargin: 30 font.pointSize: 12 - text: "

Mist (0.6.5)

Amalthea


Development

Jeffrey Wilcke
Viktor Trón

Building

Maran Hidskes" + text: "

Mist (0.7.10)


Development

Jeffrey Wilcke
Viktor Trón
Felix Lange
Taylor Gerring
Daniel Nagy

UX

Alex van de Sande
" } } @@ -866,12 +862,15 @@ ApplicationWindow { model: ListModel { id: pastPeers } Component.onCompleted: { + pastPeers.insert(0, {text: "poc-8.ethdev.com:30303"}) + /* var ips = eth.pastPeers() for(var i = 0; i < ips.length; i++) { pastPeers.append({text: ips.get(i)}) } pastPeers.insert(0, {text: "poc-7.ethdev.com:30303"}) + */ } } diff --git a/cmd/mist/assets/qml/views/miner.qml b/cmd/mist/assets/qml/views/miner.qml index e0182649fb..193ce37bea 100644 --- a/cmd/mist/assets/qml/views/miner.qml +++ b/cmd/mist/assets/qml/views/miner.qml @@ -46,6 +46,7 @@ Rectangle { text: "Start" onClicked: { eth.setGasPrice(minGasPrice.text || "10000000000000"); + eth.setExtra(blockExtra.text) if (eth.toggleMining()) { this.text = "Stop"; } else { @@ -55,6 +56,7 @@ Rectangle { } Rectangle { + id: minGasPriceRect anchors.top: parent.top anchors.topMargin: 2 width: 200 @@ -65,6 +67,23 @@ Rectangle { validator: RegExpValidator { regExp: /\d*/ } } } + + Rectangle { + width: 300 + anchors { + left: minGasPriceRect.right + leftMargin: 5 + top: parent.top + topMargin: 2 + } + + TextField { + id: blockExtra + placeholderText: "Extra" + width: parent.width + maximumLength: 1024 + } + } } } diff --git a/cmd/mist/assets/qml/views/wallet.qml b/cmd/mist/assets/qml/views/wallet.qml index 9727ef35c8..b81273a173 100644 --- a/cmd/mist/assets/qml/views/wallet.qml +++ b/cmd/mist/assets/qml/views/wallet.qml @@ -20,7 +20,7 @@ Rectangle { } function setBalance() { - balance.text = "Balance: " + eth.numberToHuman(eth.balanceAt(eth.key().address)) + //balance.text = "Balance: " + eth.numberToHuman(eth.balanceAt(eth.key().address)) if(menuItem) menuItem.secondaryTitle = eth.numberToHuman(eth.balanceAt(eth.key().address)) } diff --git a/cmd/mist/assets/qml/views/whisper.qml b/cmd/mist/assets/qml/views/whisper.qml index b50841ba5f..029376c451 100644 --- a/cmd/mist/assets/qml/views/whisper.qml +++ b/cmd/mist/assets/qml/views/whisper.qml @@ -9,8 +9,7 @@ import Ethereum 1.0 Rectangle { id: root - property var title: "Whisper" - property var iconSource: "../facet.png" + property var title: "Whisper Traffic" property var menuItem objectName: "whisperView" @@ -21,10 +20,22 @@ Rectangle { identity = shh.newIdentity() console.log("New identity:", identity) - var t = shh.watch({topics: ["chat"]}) + var t = shh.watch({}, root) + } + + function onShhMessage(message, i) { + whisperModel.insert(0, {from: message.from, payload: eth.toAscii(message.payload)}) } RowLayout { + id: input + anchors { + left: parent.left + leftMargin: 20 + top: parent.top + topMargin: 20 + } + TextField { id: to placeholderText: "To" @@ -40,8 +51,25 @@ Rectangle { Button { text: "Send" onClicked: { - shh.post(eth.toHex(data.text), "", identity, topics.text.split(","), 500, 50) + shh.post([eth.toHex(data.text)], "", identity, topics.text.split(","), 500, 50) } } } + + TableView { + id: txTableView + anchors { + top: input.bottom + topMargin: 10 + bottom: parent.bottom + left: parent.left + right: parent.right + } + TableViewColumn{ id: fromRole; role: "from" ; title: "From"; width: 300 } + TableViewColumn{ role: "payload" ; title: "Payload" ; width: parent.width - fromRole.width - 2 } + + model: ListModel { + id: whisperModel + } + } } diff --git a/cmd/mist/bindings.go b/cmd/mist/bindings.go index 6d2342c876..f6d1c40da5 100644 --- a/cmd/mist/bindings.go +++ b/cmd/mist/bindings.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 General Public License -// along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package main import ( @@ -26,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/state" ) type plugin struct { @@ -57,7 +61,7 @@ func (gui *Gui) Transact(recipient, value, gas, gasPrice, d string) (string, err data = ethutil.Bytes2Hex(utils.FormatTransactionData(d)) } - return gui.pipe.Transact(gui.privateKey(), recipient, value, gas, gasPrice, data) + return gui.xeth.Transact(gui.privateKey(), recipient, value, gas, gasPrice, data) } func (gui *Gui) SetCustomIdentifier(customIdentifier string) { @@ -72,7 +76,7 @@ func (gui *Gui) GetCustomIdentifier() string { // functions that allow Gui to implement interface guilogger.LogSystem func (gui *Gui) SetLogLevel(level logger.LogLevel) { gui.logLevel = level - gui.stdLog.SetLogLevel(level) + gui.eth.Logger().SetLogLevel(level) gui.config.Save("loglevel", level) } @@ -118,7 +122,7 @@ func (self *Gui) DumpState(hash, path string) { return } - stateDump = block.State().Dump() + stateDump = state.New(block.Root(), self.eth.Db()).Dump() } file, err := os.OpenFile(path[7:], os.O_CREATE|os.O_RDWR, os.ModePerm) diff --git a/cmd/mist/debugger.go b/cmd/mist/debugger.go index a7a286e235..b960e52cf7 100644 --- a/cmd/mist/debugger.go +++ b/cmd/mist/debugger.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 General Public License -// along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package main import ( @@ -151,7 +154,7 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data block := self.lib.eth.ChainManager().CurrentBlock() - env := utils.NewEnv(statedb, block, account.Address(), value) + env := utils.NewEnv(self.lib.eth.ChainManager(), statedb, block, account.Address(), value) self.Logf("callsize %d", len(script)) go func() { @@ -309,9 +312,11 @@ func (d *Debugger) halting(pc int, op vm.OpCode, mem *vm.Memory, stack *vm.Stack d.win.Root().Call("setStack", val.String()) } - stateObject.EachStorage(func(key string, node *ethutil.Value) { - d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", key), fmt.Sprintf("% x", node.Str())}) - }) + it := stateObject.Trie().Iterator() + for it.Next() { + d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", it.Key), fmt.Sprintf("% x", it.Value)}) + + } stackFrameAt := new(big.Int).SetBytes(mem.Get(0, 32)) psize := mem.Len() - int(new(big.Int).SetBytes(mem.Get(0, 32)).Uint64()) diff --git a/cmd/mist/errors.go b/cmd/mist/errors.go index 2069bf26d9..26a172ce95 100644 --- a/cmd/mist/errors.go +++ b/cmd/mist/errors.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 General Public License -// along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package main import ( diff --git a/cmd/mist/ext_app.go b/cmd/mist/ext_app.go index 33c420a7a1..012c94923a 100644 --- a/cmd/mist/ext_app.go +++ b/cmd/mist/ext_app.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 General Public License -// along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package main import ( diff --git a/cmd/mist/flags.go b/cmd/mist/flags.go index 1d77532d90..2f0790b76a 100644 --- a/cmd/mist/flags.go +++ b/cmd/mist/flags.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 General Public License -// along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package main import ( @@ -106,7 +109,7 @@ func Init() { flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file (db)") flag.StringVar(&OutboundPort, "port", "30303", "listening port") flag.BoolVar(&UseUPnP, "upnp", true, "enable UPnP support") - flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers") + flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers") flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on") flag.BoolVar(&StartRpc, "rpc", false, "start rpc server") flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server") diff --git a/cmd/mist/gui.go b/cmd/mist/gui.go index e858d7c61c..fd2ad5a117 100644 --- a/cmd/mist/gui.go +++ b/cmd/mist/gui.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 General Public License -// along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package main import "C" @@ -23,7 +26,9 @@ import ( "bytes" "encoding/json" "fmt" + "io/ioutil" "math/big" + "os" "path" "runtime" "strconv" @@ -43,49 +48,24 @@ import ( "gopkg.in/qml.v1" ) -/* -func LoadExtension(path string) (uintptr, error) { - lib, err := ffi.NewLibrary(path) - if err != nil { - return 0, err - } - - so, err := lib.Fct("sharedObject", ffi.Pointer, nil) - if err != nil { - return 0, err - } - - ptr := so() - - err = lib.Close() - if err != nil { - return 0, err - } - - return ptr.Interface().(uintptr), nil -} -*/ -/* - vec, errr := LoadExtension("/Users/jeffrey/Desktop/build-libqmltest-Desktop_Qt_5_2_1_clang_64bit-Debug/liblibqmltest_debug.dylib") - fmt.Printf("Fetched vec with addr: %#x\n", vec) - if errr != nil { - fmt.Println(errr) - } else { - context.SetVar("vec", (unsafe.Pointer)(vec)) - } -*/ - var guilogger = logger.NewLogger("GUI") +type ServEv byte + +const ( + setup ServEv = iota + update +) + type Gui struct { // The main application window win *qml.Window // QML Engine engine *qml.Engine component *qml.Common - qmlDone bool // The ethereum interface - eth *eth.Ethereum + eth *eth.Ethereum + serviceEvents chan ServEv // The public Ethereum library uiLib *UiLib @@ -96,7 +76,7 @@ type Gui struct { logLevel logger.LogLevel open bool - pipe *xeth.JSXEth + xeth *xeth.JSXEth Session string clientIdentity *p2p.SimpleClientIdentity @@ -104,8 +84,7 @@ type Gui struct { plugins map[string]plugin - miner *miner.Miner - stdLog logger.LogSystem + miner *miner.Miner } // Create GUI, but doesn't start it @@ -115,8 +94,18 @@ func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, clientIden panic(err) } - pipe := xeth.NewJSXEth(ethereum) - gui := &Gui{eth: ethereum, txDb: db, pipe: pipe, logLevel: logger.LogLevel(logLevel), Session: session, open: false, clientIdentity: clientIdentity, config: config, plugins: make(map[string]plugin)} + xeth := xeth.NewJSXEth(ethereum) + gui := &Gui{eth: ethereum, + txDb: db, + xeth: xeth, + logLevel: logger.LogLevel(logLevel), + Session: session, + open: false, + clientIdentity: clientIdentity, + config: config, + plugins: make(map[string]plugin), + serviceEvents: make(chan ServEv, 1), + } data, _ := ethutil.ReadAllFile(path.Join(ethutil.Config.ExecPath, "plugins.json")) json.Unmarshal([]byte(data), &gui.plugins) @@ -128,6 +117,8 @@ func (gui *Gui) Start(assetPath string) { guilogger.Infoln("Starting GUI") + go gui.service() + // Register ethereum functions qml.RegisterTypes("Ethereum", 1, 0, []qml.TypeSpec{{ Init: func(p *xeth.JSBlock, obj qml.Object) { p.Number = 0; p.Hash = "" }, @@ -147,18 +138,7 @@ func (gui *Gui) Start(assetPath string) { context.SetVar("eth", gui.uiLib) context.SetVar("shh", gui.whisper) - // Load the main QML interface - data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) - - var win *qml.Window - var err error - var addlog = false - if len(data) == 0 { - win, err = gui.showKeyImport(context) - } else { - win, err = gui.showWallet(context) - addlog = true - } + win, err := gui.showWallet(context) if err != nil { guilogger.Errorln("asset not found: you can set an alternative asset path on the command line using option 'asset_path'", err) @@ -169,9 +149,7 @@ func (gui *Gui) Start(assetPath string) { win.Show() // only add the gui guilogger after window is shown otherwise slider wont be shown - if addlog { - logger.AddLogSystem(gui) - } + logger.AddLogSystem(gui) win.Wait() // need to silence gui guilogger after window closed otherwise logsystem hangs (but do not save loglevel) @@ -197,18 +175,11 @@ func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) { return nil, err } - gui.win = gui.createWindow(component) - - gui.update() + gui.createWindow(component) return gui.win, nil } -// The done handler will be called by QML when all views have been loaded -func (gui *Gui) Done() { - gui.qmlDone = true -} - func (gui *Gui) ImportKey(filePath string) { } @@ -222,10 +193,8 @@ func (gui *Gui) showKeyImport(context *qml.Context) (*qml.Window, error) { } func (gui *Gui) createWindow(comp qml.Object) *qml.Window { - win := comp.CreateWindow(nil) - - gui.win = win - gui.uiLib.win = win + gui.win = comp.CreateWindow(nil) + gui.uiLib.win = gui.win return gui.win } @@ -253,7 +222,7 @@ func (gui *Gui) setInitialChain(ancientBlocks bool) { sBlk := gui.eth.ChainManager().LastBlockHash() blk := gui.eth.ChainManager().GetBlock(sBlk) for ; blk != nil; blk = gui.eth.ChainManager().GetBlock(sBlk) { - sBlk = blk.PrevHash + sBlk = blk.ParentHash() gui.processBlock(blk, true) } @@ -261,43 +230,40 @@ func (gui *Gui) setInitialChain(ancientBlocks bool) { func (gui *Gui) loadAddressBook() { view := gui.getObjectByName("infoView") - nameReg := gui.pipe.World().Config().Get("NameReg") + nameReg := gui.xeth.World().Config().Get("NameReg") if nameReg != nil { - nameReg.EachStorage(func(name string, value *ethutil.Value) { - if name[0] != 0 { - value.Decode() - - view.Call("addAddress", struct{ Name, Address string }{name, ethutil.Bytes2Hex(value.Bytes())}) + it := nameReg.Trie().Iterator() + for it.Next() { + if it.Key[0] != 0 { + view.Call("addAddress", struct{ Name, Address string }{string(it.Key), ethutil.Bytes2Hex(it.Value)}) } - }) + + } } } func (self *Gui) loadMergedMiningOptions() { view := self.getObjectByName("mergedMiningModel") - nameReg := self.pipe.World().Config().Get("MergeMining") - if nameReg != nil { + mergeMining := self.xeth.World().Config().Get("MergeMining") + if mergeMining != nil { i := 0 - nameReg.EachStorage(func(name string, value *ethutil.Value) { - if name[0] != 0 { - value.Decode() + it := mergeMining.Trie().Iterator() + for it.Next() { + view.Call("addMergedMiningOption", struct { + Checked bool + Name, Address string + Id, ItemId int + }{false, string(it.Key), ethutil.Bytes2Hex(it.Value), 0, i}) - view.Call("addMergedMiningOption", struct { - Checked bool - Name, Address string - Id, ItemId int - }{false, name, ethutil.Bytes2Hex(value.Bytes()), 0, i}) + i++ - i++ - } - }) + } } } func (gui *Gui) insertTransaction(window string, tx *types.Transaction) { - pipe := xeth.New(gui.eth) - nameReg := pipe.World().Config().Get("NameReg") + nameReg := gui.xeth.World().Config().Get("NameReg") addr := gui.address() var inout string @@ -308,7 +274,7 @@ func (gui *Gui) insertTransaction(window string, tx *types.Transaction) { } var ( - ptx = xeth.NewJSTx(tx, pipe.World().State()) + ptx = xeth.NewJSTx(tx) send = nameReg.Storage(tx.From()) rec = nameReg.Storage(tx.To()) s, r string @@ -354,7 +320,7 @@ func (gui *Gui) readPreviousTransactions() { } func (gui *Gui) processBlock(block *types.Block, initial bool) { - name := strings.Trim(gui.pipe.World().Config().Get("NameReg").Storage(block.Coinbase).Str(), "\x00") + name := strings.Trim(gui.xeth.World().Config().Get("NameReg").Storage(block.Coinbase()).Str(), "\x00") b := xeth.NewJSBlock(block) b.Name = name @@ -381,11 +347,48 @@ func (self *Gui) getObjectByName(objectName string) qml.Object { return self.win.Root().ObjectByName(objectName) } -// Simple go routine function that updates the list of peers in the GUI -func (gui *Gui) update() { - // We have to wait for qml to be done loading all the windows. - for !gui.qmlDone { - time.Sleep(300 * time.Millisecond) +func loadJavascriptAssets(gui *Gui) (jsfiles string) { + for _, fn := range []string{"ext/q.js", "ext/eth.js/main.js", "ext/eth.js/qt.js", "ext/setup.js"} { + f, err := os.Open(gui.uiLib.AssetPath(fn)) + if err != nil { + fmt.Println(err) + continue + } + + content, err := ioutil.ReadAll(f) + if err != nil { + fmt.Println(err) + continue + } + jsfiles += string(content) + } + + return +} + +func (gui *Gui) SendCommand(cmd ServEv) { + gui.serviceEvents <- cmd +} + +func (gui *Gui) service() { + for ev := range gui.serviceEvents { + switch ev { + case setup: + go gui.setup() + case update: + go gui.update() + } + } +} + +func (gui *Gui) setup() { + for gui.win == nil { + time.Sleep(time.Millisecond * 200) + } + + for _, plugin := range gui.plugins { + guilogger.Infoln("Loading plugin ", plugin.Name) + gui.win.Root().Call("addPlugin", plugin.Path, "") } go func() { @@ -395,14 +398,21 @@ func (gui *Gui) update() { gui.setPeerInfo() }() - gui.whisper.SetView(gui.win.Root().ObjectByName("whisperView")) + // Inject javascript files each time navigation is requested. + // Unfortunately webview.experimental.userScripts injects _after_ + // the page has loaded which kind of renders it useless... + //jsfiles := loadJavascriptAssets(gui) + gui.getObjectByName("webView").On("navigationRequested", func() { + //gui.getObjectByName("webView").Call("injectJs", jsfiles) + }) - for _, plugin := range gui.plugins { - guilogger.Infoln("Loading plugin ", plugin.Name) + gui.whisper.SetView(gui.getObjectByName("whisperView")) - gui.win.Root().Call("addPlugin", plugin.Path, "") - } + gui.SendCommand(update) +} +// Simple go routine function that updates the list of peers in the GUI +func (gui *Gui) update() { peerUpdateTicker := time.NewTicker(5 * time.Second) generalUpdateTicker := time.NewTicker(500 * time.Millisecond) statsUpdateTicker := time.NewTicker(5 * time.Second) @@ -421,77 +431,75 @@ func (gui *Gui) update() { core.TxPostEvent{}, ) - go func() { - defer events.Unsubscribe() - for { - select { - case ev, isopen := <-events.Chan(): - if !isopen { - return - } - switch ev := ev.(type) { - case core.NewBlockEvent: - gui.processBlock(ev.Block, false) - if bytes.Compare(ev.Block.Coinbase, gui.address()) == 0 { - gui.setWalletValue(gui.eth.ChainManager().State().GetBalance(gui.address()), nil) - } - - case core.TxPreEvent: - tx := ev.Tx - - tstate := gui.eth.ChainManager().TransState() - cstate := gui.eth.ChainManager().State() - - taccount := tstate.GetAccount(gui.address()) - caccount := cstate.GetAccount(gui.address()) - unconfirmedFunds := new(big.Int).Sub(taccount.Balance(), caccount.Balance()) - - gui.setWalletValue(taccount.Balance(), unconfirmedFunds) - gui.insertTransaction("pre", tx) - - case core.TxPostEvent: - tx := ev.Tx - object := state.GetAccount(gui.address()) - - if bytes.Compare(tx.From(), gui.address()) == 0 { - object.SubAmount(tx.Value()) - - gui.txDb.Put(tx.Hash(), tx.RlpEncode()) - } else if bytes.Compare(tx.To(), gui.address()) == 0 { - object.AddAmount(tx.Value()) - - gui.txDb.Put(tx.Hash(), tx.RlpEncode()) - } - - gui.setWalletValue(object.Balance(), nil) - state.UpdateStateObject(object) - } - - case <-peerUpdateTicker.C: - gui.setPeerInfo() - case <-generalUpdateTicker.C: - statusText := "#" + gui.eth.ChainManager().CurrentBlock().Number.String() - lastBlockLabel.Set("text", statusText) - miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.miner.GetPow().GetHashrate(), 10)+"Khash") - - /* - blockLength := gui.eth.BlockPool().BlocksProcessed - chainLength := gui.eth.BlockPool().ChainLength - - var ( - pct float64 = 1.0 / float64(chainLength) * float64(blockLength) - dlWidget = gui.win.Root().ObjectByName("downloadIndicator") - dlLabel = gui.win.Root().ObjectByName("downloadLabel") - ) - dlWidget.Set("value", pct) - dlLabel.Set("text", fmt.Sprintf("%d / %d", blockLength, chainLength)) - */ - - case <-statsUpdateTicker.C: - gui.setStatsPane() + defer events.Unsubscribe() + for { + select { + case ev, isopen := <-events.Chan(): + if !isopen { + return } + switch ev := ev.(type) { + case core.NewBlockEvent: + gui.processBlock(ev.Block, false) + if bytes.Compare(ev.Block.Coinbase(), gui.address()) == 0 { + gui.setWalletValue(gui.eth.ChainManager().State().GetBalance(gui.address()), nil) + } + + case core.TxPreEvent: + tx := ev.Tx + + tstate := gui.eth.ChainManager().TransState() + cstate := gui.eth.ChainManager().State() + + taccount := tstate.GetAccount(gui.address()) + caccount := cstate.GetAccount(gui.address()) + unconfirmedFunds := new(big.Int).Sub(taccount.Balance(), caccount.Balance()) + + gui.setWalletValue(taccount.Balance(), unconfirmedFunds) + gui.insertTransaction("pre", tx) + + case core.TxPostEvent: + tx := ev.Tx + object := state.GetAccount(gui.address()) + + if bytes.Compare(tx.From(), gui.address()) == 0 { + object.SubAmount(tx.Value()) + + gui.txDb.Put(tx.Hash(), tx.RlpEncode()) + } else if bytes.Compare(tx.To(), gui.address()) == 0 { + object.AddAmount(tx.Value()) + + gui.txDb.Put(tx.Hash(), tx.RlpEncode()) + } + + gui.setWalletValue(object.Balance(), nil) + state.UpdateStateObject(object) + } + + case <-peerUpdateTicker.C: + gui.setPeerInfo() + case <-generalUpdateTicker.C: + statusText := "#" + gui.eth.ChainManager().CurrentBlock().Number().String() + lastBlockLabel.Set("text", statusText) + miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.miner.GetPow().GetHashrate(), 10)+"Khash") + + /* + blockLength := gui.eth.BlockPool().BlocksProcessed + chainLength := gui.eth.BlockPool().ChainLength + + var ( + pct float64 = 1.0 / float64(chainLength) * float64(blockLength) + dlWidget = gui.win.Root().ObjectByName("downloadIndicator") + dlLabel = gui.win.Root().ObjectByName("downloadLabel") + ) + dlWidget.Set("value", pct) + dlLabel.Set("text", fmt.Sprintf("%d / %d", blockLength, chainLength)) + */ + + case <-statsUpdateTicker.C: + gui.setStatsPane() } - }() + } } func (gui *Gui) setStatsPane() { @@ -523,7 +531,7 @@ NumGC: %d func (gui *Gui) setPeerInfo() { gui.win.Root().Call("setPeers", fmt.Sprintf("%d / %d", gui.eth.PeerCount(), gui.eth.MaxPeers)) gui.win.Root().Call("resetPeers") - for _, peer := range gui.pipe.Peers() { + for _, peer := range gui.xeth.Peers() { gui.win.Root().Call("addPeer", peer) } } @@ -535,3 +543,35 @@ func (gui *Gui) privateKey() string { func (gui *Gui) address() []byte { return gui.eth.KeyManager().Address() } + +/* +func LoadExtension(path string) (uintptr, error) { + lib, err := ffi.NewLibrary(path) + if err != nil { + return 0, err + } + + so, err := lib.Fct("sharedObject", ffi.Pointer, nil) + if err != nil { + return 0, err + } + + ptr := so() + + err = lib.Close() + if err != nil { + return 0, err + } + + return ptr.Interface().(uintptr), nil +} +*/ +/* + vec, errr := LoadExtension("/Users/jeffrey/Desktop/build-libqmltest-Desktop_Qt_5_2_1_clang_64bit-Debug/liblibqmltest_debug.dylib") + fmt.Printf("Fetched vec with addr: %#x\n", vec) + if errr != nil { + fmt.Println(errr) + } else { + context.SetVar("vec", (unsafe.Pointer)(vec)) + } +*/ diff --git a/cmd/mist/html_container.go b/cmd/mist/html_container.go index b3fc219fad..f2ba6fbe24 100644 --- a/cmd/mist/html_container.go +++ b/cmd/mist/html_container.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 General Public License -// along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package main import ( @@ -139,7 +142,7 @@ func (app *HtmlApplication) Window() *qml.Window { } func (app *HtmlApplication) NewBlock(block *types.Block) { - b := &xeth.JSBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Bytes2Hex(block.Hash())} + b := &xeth.JSBlock{Number: int(block.NumberU64()), Hash: ethutil.Bytes2Hex(block.Hash())} app.webView.Call("onNewBlockCb", b) } diff --git a/cmd/mist/main.go b/cmd/mist/main.go index 3ea6e8e91f..eb0a80addf 100644 --- a/cmd/mist/main.go +++ b/cmd/mist/main.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 General Public License -// along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package main import ( @@ -26,15 +29,17 @@ import ( "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/p2p" "gopkg.in/qml.v1" ) const ( ClientIdentifier = "Mist" - Version = "0.7.9" + Version = "0.8.1" ) var ethereum *eth.Ethereum +var mainlogger = logger.NewLogger("MAIN") func run() error { // precedence: code-internal flag default < config file < environment variables < command line @@ -43,27 +48,25 @@ func run() error { tstart := time.Now() config := utils.InitConfig(VmType, ConfigFile, Datadir, "ETH") - utils.InitDataDir(Datadir) - - stdLog := utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile) - - db := utils.NewDatabase() - err := utils.DBSanityCheck(db) + ethereum, err := eth.New(ð.Config{ + Name: ClientIdentifier, + Version: Version, + KeyStore: KeyStore, + DataDir: Datadir, + LogFile: LogFile, + LogLevel: LogLevel, + Identifier: Identifier, + MaxPeers: MaxPeer, + Port: OutboundPort, + NATType: PMPGateway, + PMPGateway: PMPGateway, + KeyRing: KeyRing, + Dial: true, + }) if err != nil { - ErrorWindow(err) - - os.Exit(1) - } - keyManager := utils.NewKeyManager(KeyStore, Datadir, db) - - // create, import, export keys - utils.KeyTasks(keyManager, KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive) - clientIdentity := utils.NewClientIdentity(ClientIdentifier, Version, Identifier, string(keyManager.PublicKey())) - ethereum := utils.NewEthereum(db, clientIdentity, keyManager, utils.NatType(NatType, PMPGateway), OutboundPort, MaxPeer) - - if ShowGenesis { - utils.ShowGenesis(ethereum) + mainlogger.Fatalln(err) } + utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive) if StartRpc { utils.StartRpc(ethereum, RpcPort) @@ -73,8 +76,7 @@ func run() error { utils.StartWebSockets(ethereum) } - gui := NewWindow(ethereum, config, clientIdentity, KeyRing, LogLevel) - gui.stdLog = stdLog + gui := NewWindow(ethereum, config, ethereum.ClientIdentity().(*p2p.SimpleClientIdentity), KeyRing, LogLevel) utils.RegisterInterrupt(func(os.Signal) { gui.Stop() diff --git a/cmd/mist/qml_container.go b/cmd/mist/qml_container.go index a0a46f9b10..7f5d97bec1 100644 --- a/cmd/mist/qml_container.go +++ b/cmd/mist/qml_container.go @@ -1,19 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 General Public License -// along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package main @@ -66,7 +70,7 @@ func (app *QmlApplication) NewWatcher(quitChan chan bool) { // Events func (app *QmlApplication) NewBlock(block *types.Block) { - pblock := &xeth.JSBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Bytes2Hex(block.Hash())} + pblock := &xeth.JSBlock{Number: int(block.NumberU64()), Hash: ethutil.Bytes2Hex(block.Hash())} app.win.Call("onNewBlockCb", pblock) } diff --git a/cmd/mist/ui_lib.go b/cmd/mist/ui_lib.go index 68f3335631..60c7181c12 100644 --- a/cmd/mist/ui_lib.go +++ b/cmd/mist/ui_lib.go @@ -1,20 +1,23 @@ -// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 General Public License -// along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package main import ( @@ -195,7 +198,9 @@ func (ui *UiLib) Connect(button qml.Object) { } func (ui *UiLib) ConnectToPeer(addr string) { - ui.eth.SuggestPeer(addr) + if err := ui.eth.SuggestPeer(addr); err != nil { + guilogger.Infoln(err) + } } func (ui *UiLib) AssetPath(p string) string { @@ -225,6 +230,87 @@ func (self *UiLib) StartDebugger() { dbWindow.Show() } +func (self *UiLib) Transact(params map[string]interface{}) (string, error) { + object := mapToTxParams(params) + + return self.JSXEth.Transact( + object["from"], + object["to"], + object["value"], + object["gas"], + object["gasPrice"], + object["data"], + ) +} + +func (self *UiLib) Compile(code string) (string, error) { + bcode, err := ethutil.Compile(code, false) + if err != nil { + return err.Error(), err + } + + return ethutil.Bytes2Hex(bcode), err +} + +func (self *UiLib) Call(params map[string]interface{}) (string, error) { + object := mapToTxParams(params) + + return self.JSXEth.Execute( + object["to"], + object["value"], + object["gas"], + object["gasPrice"], + object["data"], + ) +} + +func (self *UiLib) AddLocalTransaction(to, data, gas, gasPrice, value string) int { + return self.miner.AddLocalTx(&miner.LocalTx{ + To: ethutil.Hex2Bytes(to), + Data: ethutil.Hex2Bytes(data), + Gas: gas, + GasPrice: gasPrice, + Value: value, + }) - 1 +} + +func (self *UiLib) RemoveLocalTransaction(id int) { + self.miner.RemoveLocalTx(id) +} + +func (self *UiLib) SetGasPrice(price string) { + self.miner.MinAcceptedGasPrice = ethutil.Big(price) +} + +func (self *UiLib) SetExtra(extra string) { + self.miner.Extra = extra +} + +func (self *UiLib) ToggleMining() bool { + if !self.miner.Mining() { + self.miner.Start() + + return true + } else { + self.miner.Stop() + + return false + } +} + +func (self *UiLib) ToHex(data string) string { + return "0x" + ethutil.Bytes2Hex([]byte(data)) +} + +func (self *UiLib) ToAscii(data string) string { + start := 0 + if len(data) > 1 && data[0:2] == "0x" { + start = 2 + } + return string(ethutil.Hex2Bytes(data[start:])) +} + +/// Ethereum filter methods func (self *UiLib) NewFilter(object map[string]interface{}) (id int) { filter := qt.NewFilterFromMap(object, self.eth) filter.MessageCallback = func(messages state.Messages) { @@ -312,80 +398,3 @@ func mapToTxParams(object map[string]interface{}) map[string]string { return conv } - -func (self *UiLib) Transact(params map[string]interface{}) (string, error) { - object := mapToTxParams(params) - - return self.JSXEth.Transact( - object["from"], - object["to"], - object["value"], - object["gas"], - object["gasPrice"], - object["data"], - ) -} - -func (self *UiLib) Compile(code string) (string, error) { - bcode, err := ethutil.Compile(code, false) - if err != nil { - return err.Error(), err - } - - return ethutil.Bytes2Hex(bcode), err -} - -func (self *UiLib) Call(params map[string]interface{}) (string, error) { - object := mapToTxParams(params) - - return self.JSXEth.Execute( - object["to"], - object["value"], - object["gas"], - object["gasPrice"], - object["data"], - ) -} - -func (self *UiLib) AddLocalTransaction(to, data, gas, gasPrice, value string) int { - return self.miner.AddLocalTx(&miner.LocalTx{ - To: ethutil.Hex2Bytes(to), - Data: ethutil.Hex2Bytes(data), - Gas: gas, - GasPrice: gasPrice, - Value: value, - }) - 1 -} - -func (self *UiLib) RemoveLocalTransaction(id int) { - self.miner.RemoveLocalTx(id) -} - -func (self *UiLib) SetGasPrice(price string) { - self.miner.MinAcceptedGasPrice = ethutil.Big(price) -} - -func (self *UiLib) ToggleMining() bool { - if !self.miner.Mining() { - self.miner.Start() - - return true - } else { - self.miner.Stop() - - return false - } -} - -func (self *UiLib) ToHex(data string) string { - return "0x" + ethutil.Bytes2Hex([]byte(data)) -} - -/* -// XXX Refactor me & MOVE -func (self *Ethereum) InstallFilter(filter *core.Filter) (id int) { - return self.filterManager.InstallFilter(filter) -} -func (self *Ethereum) UninstallFilter(id int) { self.filterManager.UninstallFilter(id) } -func (self *Ethereum) GetFilter(id int) *core.Filter { return self.filterManager.GetFilter(id) } -*/ diff --git a/cmd/peerserver/main.go b/cmd/peerserver/main.go index 0fa7a9b440..341c4dbb9d 100644 --- a/cmd/peerserver/main.go +++ b/cmd/peerserver/main.go @@ -1,10 +1,25 @@ +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ package main import ( "crypto/elliptic" - "fmt" + "flag" "log" - "net" "os" "github.com/ethereum/go-ethereum/crypto" @@ -12,29 +27,32 @@ import ( "github.com/ethereum/go-ethereum/p2p" ) +var ( + natType = flag.String("nat", "", "NAT traversal implementation") + pmpGateway = flag.String("gateway", "", "gateway address for NAT-PMP") + listenAddr = flag.String("addr", ":30301", "listen address") +) + func main() { + flag.Parse() + nat, err := p2p.ParseNAT(*natType, *pmpGateway) + if err != nil { + log.Fatal("invalid nat:", err) + } + logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.InfoLevel)) key, _ := crypto.GenerateKey() marshaled := elliptic.Marshal(crypto.S256(), key.PublicKey.X, key.PublicKey.Y) srv := p2p.Server{ - MaxPeers: 10, - Identity: p2p.NewSimpleClientIdentity("Ethereum(G)", "0.1", "Peer Server Two", string(marshaled)), - ListenAddr: ":30301", - NAT: p2p.UPNP(), + MaxPeers: 100, + Identity: p2p.NewSimpleClientIdentity("Ethereum(G)", "0.1", "Peer Server Two", marshaled), + ListenAddr: *listenAddr, + NAT: nat, + NoDial: true, } if err := srv.Start(); err != nil { - fmt.Println("could not start server:", err) - os.Exit(1) + log.Fatal("could not start server:", err) } - - // add seed peers - seed, err := net.ResolveTCPAddr("tcp", "poc-7.ethdev.com:30300") - if err != nil { - fmt.Println("couldn't resolve:", err) - os.Exit(1) - } - srv.SuggestPeer(seed.IP, seed.Port, nil) - select {} } diff --git a/cmd/rlpdump/main.go b/cmd/rlpdump/main.go new file mode 100644 index 0000000000..8567dcff83 --- /dev/null +++ b/cmd/rlpdump/main.go @@ -0,0 +1,148 @@ +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Felix Lange + */ + +// rlpdump is a pretty-printer for RLP data. +package main + +import ( + "bytes" + "encoding/hex" + "flag" + "fmt" + "io" + "os" + "strings" + + "github.com/ethereum/go-ethereum/rlp" +) + +var ( + hexMode = flag.String("hex", "", "dump given hex data") + noASCII = flag.Bool("noascii", false, "don't print ASCII strings readably") +) + +func init() { + flag.Usage = func() { + fmt.Fprintln(os.Stderr, "Usage:", os.Args[0], "[-noascii] [-hex ] [filename]") + flag.PrintDefaults() + fmt.Fprintln(os.Stderr, ` +Dumps RLP data from the given file in readable form. +If the filename is omitted, data is read from stdin.`) + } +} + +func main() { + flag.Parse() + + var r io.Reader + switch { + case *hexMode != "": + data, err := hex.DecodeString(*hexMode) + if err != nil { + die(err) + } + r = bytes.NewReader(data) + + case flag.NArg() == 0: + r = os.Stdin + + case flag.NArg() == 1: + fd, err := os.Open(flag.Arg(0)) + if err != nil { + die(err) + } + defer fd.Close() + r = fd + + default: + fmt.Fprintln(os.Stderr, "Error: too many arguments") + flag.Usage() + os.Exit(2) + } + + s := rlp.NewStream(r) + for { + if err := dump(s, 0); err != nil { + if err != io.EOF { + die(err) + } + break + } + fmt.Println() + } +} + +func dump(s *rlp.Stream, depth int) error { + kind, size, err := s.Kind() + if err != nil { + return err + } + switch kind { + case rlp.Byte, rlp.String: + str, err := s.Bytes() + if err != nil { + return err + } + if len(str) == 0 || !*noASCII && isASCII(str) { + fmt.Printf("%s%q", ws(depth), str) + } else { + fmt.Printf("%s%x", ws(depth), str) + } + case rlp.List: + s.List() + defer s.ListEnd() + if size == 0 { + fmt.Print(ws(depth) + "[]") + } else { + fmt.Println(ws(depth) + "[") + for i := 0; ; i++ { + if i > 0 { + fmt.Print(",\n") + } + if err := dump(s, depth+1); err == rlp.EOL { + break + } else if err != nil { + return err + } + } + fmt.Print(ws(depth) + "]") + } + } + return nil +} + +func isASCII(b []byte) bool { + for _, c := range b { + if c < 32 || c > 126 { + return false + } + } + return true +} + +func ws(n int) string { + return strings.Repeat(" ", n) +} + +func die(args ...interface{}) { + fmt.Fprintln(os.Stderr, args...) + os.Exit(1) +} diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 3e3ac617af..a57d3266f1 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -1,10 +1,28 @@ +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + * Viktor Tron + */ package utils import ( "fmt" - "io" - "log" - "net" "os" "os/signal" "path" @@ -13,14 +31,15 @@ import ( "runtime" "bitbucket.org/kardianos/osext" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/miner" - "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/xeth" ) @@ -50,15 +69,8 @@ func RunInterruptCallbacks(sig os.Signal) { } } -func AbsolutePath(Datadir string, filename string) string { - if path.IsAbs(filename) { - return filename - } - return path.Join(Datadir, filename) -} - func openLogFile(Datadir string, filename string) *os.File { - path := AbsolutePath(Datadir, filename) + path := ethutil.AbsolutePath(Datadir, filename) file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { panic(fmt.Sprintf("error opening log file '%s': %v", filename, err)) @@ -74,23 +86,13 @@ func confirm(message string) bool { if r == "n" || r == "y" { break } else { - fmt.Printf("Yes or no?", r) + fmt.Printf("Yes or no? (%s)", r) } } return r == "y" } -func DBSanityCheck(db ethutil.Database) error { - d, _ := db.Get([]byte("ProtocolVersion")) - protov := ethutil.NewValue(d).Uint() - if protov != eth.ProtocolVersion && protov != 0 { - return fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, eth.ProtocolVersion, ethutil.Config.ExecPath+"/database") - } - - return nil -} - -func InitDataDir(Datadir string) { +func initDataDir(Datadir string) { _, err := os.Stat(Datadir) if err != nil { if os.IsNotExist(err) { @@ -100,26 +102,8 @@ func InitDataDir(Datadir string) { } } -func InitLogging(Datadir string, LogFile string, LogLevel int, DebugFile string) logger.LogSystem { - var writer io.Writer - if LogFile == "" { - writer = os.Stdout - } else { - writer = openLogFile(Datadir, LogFile) - } - - sys := logger.NewStdLogSystem(writer, log.LstdFlags, logger.LogLevel(LogLevel)) - logger.AddLogSystem(sys) - if DebugFile != "" { - writer = openLogFile(Datadir, DebugFile) - logger.AddLogSystem(logger.NewStdLogSystem(writer, log.LstdFlags, logger.DebugLevel)) - } - - return sys -} - func InitConfig(vmType int, ConfigFile string, Datadir string, EnvPrefix string) *ethutil.ConfigManager { - InitDataDir(Datadir) + initDataDir(Datadir) cfg := ethutil.ReadConfig(ConfigFile, Datadir, EnvPrefix) cfg.VmType = vmType @@ -136,70 +120,19 @@ func exit(err error) { os.Exit(status) } -func NewDatabase() ethutil.Database { - db, err := ethdb.NewLDBDatabase("database") +func StartEthereum(ethereum *eth.Ethereum, UseSeed bool) { + clilogger.Infof("Starting %s", ethereum.ClientIdentity()) + err := ethereum.Start(UseSeed) if err != nil { exit(err) } - return db -} -func NewClientIdentity(clientIdentifier, version, customIdentifier string, pubkey string) *p2p.SimpleClientIdentity { - return p2p.NewSimpleClientIdentity(clientIdentifier, version, customIdentifier, pubkey) -} - -func NatType(natType string, gateway string) (nat p2p.NAT) { - switch natType { - case "UPNP": - nat = p2p.UPNP() - case "PMP": - ip := net.ParseIP(gateway) - if ip == nil { - clilogger.Fatalf("cannot resolve PMP gateway IP %s", gateway) - } - nat = p2p.PMP(ip) - case "": - default: - clilogger.Fatalf("unrecognised NAT type '%s'", natType) - } - return -} - -func NewEthereum(db ethutil.Database, clientIdentity p2p.ClientIdentity, keyManager *crypto.KeyManager, nat p2p.NAT, OutboundPort string, MaxPeer int) *eth.Ethereum { - ethereum, err := eth.New(db, clientIdentity, keyManager, nat, OutboundPort, MaxPeer) - if err != nil { - clilogger.Fatalln("eth start err:", err) - } - return ethereum -} - -func StartEthereum(ethereum *eth.Ethereum, UseSeed bool) { - clilogger.Infof("Starting %s", ethereum.ClientIdentity()) - ethereum.Start(UseSeed) RegisterInterrupt(func(sig os.Signal) { ethereum.Stop() logger.Flush() }) } -func ShowGenesis(ethereum *eth.Ethereum) { - clilogger.Infoln(ethereum.ChainManager().Genesis()) - exit(nil) -} - -func NewKeyManager(KeyStore string, Datadir string, db ethutil.Database) *crypto.KeyManager { - var keyManager *crypto.KeyManager - switch { - case KeyStore == "db": - keyManager = crypto.NewDBKeyManager(db) - case KeyStore == "file": - keyManager = crypto.NewFileKeyManager(Datadir) - default: - exit(fmt.Errorf("unknown keystore type: %s", KeyStore)) - } - return keyManager -} - func DefaultAssetPath() string { var assetPath string // If the current working directory is the go-ethereum dir @@ -325,9 +258,10 @@ func BlockDo(ethereum *eth.Ethereum, hash []byte) error { return fmt.Errorf("unknown block %x", hash) } - parent := ethereum.ChainManager().GetBlock(block.PrevHash) + parent := ethereum.ChainManager().GetBlock(block.ParentHash()) - _, err := ethereum.BlockManager().TransitionState(parent.State(), parent, block) + statedb := state.New(parent.Root(), ethereum.Db()) + _, err := ethereum.BlockProcessor().TransitionState(statedb, parent, block) if err != nil { return err } @@ -335,3 +269,25 @@ func BlockDo(ethereum *eth.Ethereum, hash []byte) error { return nil } + +func ImportChain(ethereum *eth.Ethereum, fn string) error { + clilogger.Infof("importing chain '%s'\n", fn) + fh, err := os.OpenFile(fn, os.O_RDONLY, os.ModePerm) + if err != nil { + return err + } + defer fh.Close() + + var chain types.Blocks + if err := rlp.Decode(fh, &chain); err != nil { + return err + } + + ethereum.ChainManager().Reset() + if err := ethereum.ChainManager().InsertChain(chain); err != nil { + return err + } + clilogger.Infof("imported %d blocks\n", len(chain)) + + return nil +} diff --git a/cmd/utils/vm_env.go b/cmd/utils/vm_env.go index 461a797c2d..5eaf63b651 100644 --- a/cmd/utils/vm_env.go +++ b/cmd/utils/vm_env.go @@ -1,3 +1,23 @@ +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package utils import ( @@ -10,6 +30,7 @@ import ( ) type VMEnv struct { + chain *core.ChainManager state *state.StateDB block *types.Block @@ -20,8 +41,9 @@ type VMEnv struct { Gas *big.Int } -func NewEnv(state *state.StateDB, block *types.Block, transactor []byte, value *big.Int) *VMEnv { +func NewEnv(chain *core.ChainManager, state *state.StateDB, block *types.Block, transactor []byte, value *big.Int) *VMEnv { return &VMEnv{ + chain: chain, state: state, block: block, transactor: transactor, @@ -30,17 +52,23 @@ func NewEnv(state *state.StateDB, block *types.Block, transactor []byte, value * } func (self *VMEnv) Origin() []byte { return self.transactor } -func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number } -func (self *VMEnv) PrevHash() []byte { return self.block.PrevHash } -func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase } -func (self *VMEnv) Time() int64 { return self.block.Time } -func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty } -func (self *VMEnv) BlockHash() []byte { return self.block.Hash() } +func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() } +func (self *VMEnv) PrevHash() []byte { return self.block.ParentHash() } +func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() } +func (self *VMEnv) Time() int64 { return self.block.Time() } +func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() } +func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() } func (self *VMEnv) Value() *big.Int { return self.value } func (self *VMEnv) State() *state.StateDB { return self.state } -func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit } func (self *VMEnv) Depth() int { return self.depth } func (self *VMEnv) SetDepth(i int) { self.depth = i } +func (self *VMEnv) GetHash(n uint64) []byte { + if block := self.chain.GetBlockByNumber(n); block != nil { + return block.Hash() + } + + return nil +} func (self *VMEnv) AddLog(log state.Log) { self.state.AddLog(log) } @@ -52,19 +80,19 @@ func (self *VMEnv) vm(addr, data []byte, gas, price, value *big.Int) *core.Execu return core.NewExecution(self, addr, data, gas, price, value) } -func (self *VMEnv) Call(caller vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { +func (self *VMEnv) Call(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { exe := self.vm(addr, data, gas, price, value) ret, err := exe.Call(addr, caller) self.Gas = exe.Gas return ret, err } -func (self *VMEnv) CallCode(caller vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { +func (self *VMEnv) CallCode(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { exe := self.vm(caller.Address(), data, gas, price, value) return exe.Call(addr, caller) } -func (self *VMEnv) Create(caller vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ClosureRef) { +func (self *VMEnv) Create(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { exe := self.vm(addr, data, gas, price, value) return exe.Create(caller) } diff --git a/cmd/utils/websockets.go b/cmd/utils/websockets.go index 29f9b8aebf..003e1bc227 100644 --- a/cmd/utils/websockets.go +++ b/cmd/utils/websockets.go @@ -1,12 +1,35 @@ +/* + 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 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 General Public License + along with go-ethereum. If not, see . +*/ +/** + * @authors + * Jeffrey Wilcke + */ package utils import ( "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/websocket" "github.com/ethereum/go-ethereum/xeth" ) +var wslogger = logger.NewLogger("WS") + func args(v ...interface{}) []interface{} { return v } @@ -30,73 +53,73 @@ func (self *WebSocketServer) Serv() { data := ethutil.NewValue(msg.Args) bcode, err := ethutil.Compile(data.Get(0).Str(), false) if err != nil { - c.Write(args(nil, err.Error()), msg.Seed) + c.Write(args(nil, err.Error()), msg.Id) } code := ethutil.Bytes2Hex(bcode) - c.Write(args(code, nil), msg.Seed) - case "getBlockByNumber": + c.Write(args(code, nil), msg.Id) + case "eth_blockByNumber": args := msg.Arguments() block := pipe.BlockByNumber(int32(args.Get(0).Uint())) - c.Write(block, msg.Seed) + c.Write(block, msg.Id) - case "getKey": - c.Write(pipe.Key().PrivateKey, msg.Seed) - case "transact": + case "eth_blockByHash": + args := msg.Arguments() + + c.Write(pipe.BlockByHash(args.Get(0).Str()), msg.Id) + + case "eth_transact": if mp, ok := msg.Args[0].(map[string]interface{}); ok { object := mapToTxParams(mp) c.Write( - args(pipe.Transact(object["from"], object["to"], object["value"], object["gas"], object["gasPrice"], object["data"])), - msg.Seed, + args(pipe.Transact(pipe.Key().PrivateKey, object["to"], object["value"], object["gas"], object["gasPrice"], object["data"])), + msg.Id, ) } - case "getCoinBase": - c.Write(pipe.CoinBase(), msg.Seed) + case "eth_gasPrice": + c.Write("10000000000000", msg.Id) + case "eth_coinbase": + c.Write(pipe.CoinBase(), msg.Id) - case "getIsListening": - c.Write(pipe.IsListening(), msg.Seed) + case "eth_listening": + c.Write(pipe.IsListening(), msg.Id) - case "getIsMining": - c.Write(pipe.IsMining(), msg.Seed) + case "eth_mining": + c.Write(pipe.IsMining(), msg.Id) - case "getPeerCoint": - c.Write(pipe.PeerCount(), msg.Seed) + case "eth_peerCount": + c.Write(pipe.PeerCount(), msg.Id) - case "getCountAt": + case "eth_countAt": args := msg.Arguments() - c.Write(pipe.TxCountAt(args.Get(0).Str()), msg.Seed) + c.Write(pipe.TxCountAt(args.Get(0).Str()), msg.Id) - case "getCodeAt": + case "eth_codeAt": args := msg.Arguments() - c.Write(len(pipe.CodeAt(args.Get(0).Str())), msg.Seed) + c.Write(len(pipe.CodeAt(args.Get(0).Str())), msg.Id) - case "getBlockByHash": + case "eth_storageAt": args := msg.Arguments() - c.Write(pipe.BlockByHash(args.Get(0).Str()), msg.Seed) + c.Write(pipe.StorageAt(args.Get(0).Str(), args.Get(1).Str()), msg.Id) - case "getStorageAt": + case "eth_balanceAt": args := msg.Arguments() - c.Write(pipe.StorageAt(args.Get(0).Str(), args.Get(1).Str()), msg.Seed) + c.Write(pipe.BalanceAt(args.Get(0).Str()), msg.Id) - case "getBalanceAt": + case "eth_secretToAddress": args := msg.Arguments() - c.Write(pipe.BalanceAt(args.Get(0).Str()), msg.Seed) + c.Write(pipe.SecretToAddress(args.Get(0).Str()), msg.Id) - case "getSecretToAddress": - args := msg.Arguments() - - c.Write(pipe.SecretToAddress(args.Get(0).Str()), msg.Seed) - - case "newFilter": - case "newFilterString": - case "messages": + case "eth_newFilter": + case "eth_newFilterString": + case "eth_messages": // TODO } @@ -106,6 +129,8 @@ func (self *WebSocketServer) Serv() { } func StartWebSockets(eth *eth.Ethereum) { + wslogger.Infoln("Starting WebSockets") + sock := NewWebSocketServer(eth) go sock.Serv() } diff --git a/core/block_manager.go b/core/block_processor.go similarity index 61% rename from core/block_manager.go rename to core/block_processor.go index 85b4891a5e..3ccf2d03c9 100644 --- a/core/block_manager.go +++ b/core/block_processor.go @@ -6,7 +6,6 @@ import ( "fmt" "math/big" "sync" - "time" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" @@ -17,24 +16,13 @@ import ( "github.com/ethereum/go-ethereum/pow" "github.com/ethereum/go-ethereum/pow/ezp" "github.com/ethereum/go-ethereum/state" + "gopkg.in/fatih/set.v0" ) var statelogger = logger.NewLogger("BLOCK") -type Peer interface { - Inbound() bool - LastSend() time.Time - LastPong() int64 - Host() []byte - Port() uint16 - Version() string - PingTime() string - Connected() *int32 - Caps() *ethutil.Value -} - type EthManager interface { - BlockManager() *BlockManager + BlockProcessor() *BlockProcessor ChainManager() *ChainManager TxPool() *TxPool PeerCount() int @@ -47,7 +35,8 @@ type EthManager interface { EventMux() *event.TypeMux } -type BlockManager struct { +type BlockProcessor struct { + db ethutil.Database // Mutex for locking the block processor. Blocks can only be handled one at a time mutex sync.Mutex // Canonical block chain @@ -69,8 +58,9 @@ type BlockManager struct { eventMux *event.TypeMux } -func NewBlockManager(txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockManager { - sm := &BlockManager{ +func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor { + sm := &BlockProcessor{ + db: db, mem: make(map[string]*big.Int), Pow: ezp.New(), bc: chainManager, @@ -81,11 +71,11 @@ func NewBlockManager(txpool *TxPool, chainManager *ChainManager, eventMux *event return sm } -func (sm *BlockManager) TransitionState(statedb *state.StateDB, parent, block *types.Block) (receipts types.Receipts, err error) { - coinbase := statedb.GetOrNewStateObject(block.Coinbase) - coinbase.SetGasPool(block.CalcGasLimit(parent)) +func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block) (receipts types.Receipts, err error) { + coinbase := statedb.GetOrNewStateObject(block.Header().Coinbase) + coinbase.SetGasPool(CalcGasLimit(parent, block)) - // Process the transactions on to current block + // Process the transactions on to parent state receipts, _, _, _, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), false) if err != nil { return nil, err @@ -94,7 +84,7 @@ func (sm *BlockManager) TransitionState(statedb *state.StateDB, parent, block *t return receipts, nil } -func (self *BlockManager) ApplyTransactions(coinbase *state.StateObject, state *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, types.Transactions, types.Transactions, types.Transactions, error) { +func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, types.Transactions, types.Transactions, types.Transactions, error) { var ( receipts types.Receipts handled, unhandled types.Transactions @@ -112,7 +102,7 @@ done: txGas := new(big.Int).Set(tx.Gas()) cb := state.GetStateObject(coinbase.Address()) - st := NewStateTransition(cb, tx, state, block) + st := NewStateTransition(NewEnv(state, self.bc, tx, block), tx, cb) _, err = st.TransitionState() if err != nil { switch { @@ -127,7 +117,6 @@ done: statelogger.Infoln(err) erroneous = append(erroneous, tx) err = nil - continue } } @@ -141,6 +130,7 @@ done: receipt := types.NewReceipt(state.Root(), cumulative) receipt.SetLogs(state.Logs()) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + chainlogger.Debugln(receipt) // Notify all subscribers if !transientProcess { @@ -156,38 +146,34 @@ done: } block.Reward = cumulativeSum - block.GasUsed = totalUsedGas + block.Header().GasUsed = totalUsedGas return receipts, handled, unhandled, erroneous, err } -func (sm *BlockManager) Process(block *types.Block) (td *big.Int, msgs state.Messages, err error) { +func (sm *BlockProcessor) Process(block *types.Block) (td *big.Int, msgs state.Messages, err error) { // Processing a blocks may never happen simultaneously sm.mutex.Lock() defer sm.mutex.Unlock() - if sm.bc.HasBlock(block.Hash()) { - return nil, nil, &KnownBlockError{block.Number, block.Hash()} + header := block.Header() + if sm.bc.HasBlock(header.Hash()) { + return nil, nil, &KnownBlockError{header.Number, header.Hash()} } - if !sm.bc.HasBlock(block.PrevHash) { - return nil, nil, ParentError(block.PrevHash) + if !sm.bc.HasBlock(header.ParentHash) { + return nil, nil, ParentError(header.ParentHash) } - parent := sm.bc.GetBlock(block.PrevHash) + parent := sm.bc.GetBlock(header.ParentHash) return sm.ProcessWithParent(block, parent) } -func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.Int, messages state.Messages, err error) { +func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big.Int, messages state.Messages, err error) { sm.lastAttemptedBlock = block - state := parent.State().Copy() - - // Defer the Undo on the Trie. If the block processing happened - // we don't want to undo but since undo only happens on dirty - // nodes this won't happen because Commit would have been called - // before that. - defer state.Reset() + state := state.New(parent.Root(), sm.db) + //state := state.New(parent.Trie().Copy()) // Block validation if err = sm.ValidateBlock(block, parent); err != nil { @@ -199,21 +185,24 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I return } + header := block.Header() + rbloom := types.CreateBloom(receipts) - if bytes.Compare(rbloom, block.LogsBloom) != 0 { + if bytes.Compare(rbloom, header.Bloom) != 0 { err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom) return } txSha := types.DeriveSha(block.Transactions()) - if bytes.Compare(txSha, block.TxSha) != 0 { - err = fmt.Errorf("validating transaction root. received=%x got=%x", block.TxSha, txSha) + if bytes.Compare(txSha, header.TxHash) != 0 { + err = fmt.Errorf("validating transaction root. received=%x got=%x", header.TxHash, txSha) return } receiptSha := types.DeriveSha(receipts) - if bytes.Compare(receiptSha, block.ReceiptSha) != 0 { - err = fmt.Errorf("validating receipt root. received=%x got=%x", block.ReceiptSha, receiptSha) + if bytes.Compare(receiptSha, header.ReceiptHash) != 0 { + fmt.Println("receipts", receipts) + err = fmt.Errorf("validating receipt root. received=%x got=%x", header.ReceiptHash, receiptSha) return } @@ -223,8 +212,8 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I state.Update(ethutil.Big0) - if !block.State().Cmp(state) { - err = fmt.Errorf("invalid merkle root. received=%x got=%x", block.Root(), state.Root()) + if !bytes.Equal(header.Root, state.Root()) { + err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root()) return } @@ -233,10 +222,12 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I // Sync the current block's state to the database and cancelling out the deferred Undo state.Sync() + state.Manifest().SetHash(block.Hash()) + messages := state.Manifest().Messages state.Manifest().Reset() - chainlogger.Infof("Processed block #%d (%x...)\n", block.Number, block.Hash()[0:4]) + chainlogger.Infof("processed block #%d (%x...)\n", header.Number, block.Hash()[0:4]) sm.txpool.RemoveSet(block.Transactions()) @@ -246,16 +237,16 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I } } -func (sm *BlockManager) CalculateTD(block *types.Block) (*big.Int, bool) { +func (sm *BlockProcessor) CalculateTD(block *types.Block) (*big.Int, bool) { uncleDiff := new(big.Int) - for _, uncle := range block.Uncles { + for _, uncle := range block.Uncles() { uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty) } // TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty td := new(big.Int) td = td.Add(sm.bc.Td(), uncleDiff) - td = td.Add(td, block.Difficulty) + td = td.Add(td, block.Header().Difficulty) // The new TD will only be accepted if the new difficulty is // is greater than the previous. @@ -269,15 +260,20 @@ func (sm *BlockManager) CalculateTD(block *types.Block) (*big.Int, bool) { // Validates the current block. Returns an error if the block was invalid, // an uncle or anything that isn't on the current block chain. // Validation validates easy over difficult (dagger takes longer time = difficult) -func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error { - expd := CalcDifficulty(block, parent) - if expd.Cmp(block.Difficulty) < 0 { - return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd) +func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error { + if len(block.Header().Extra) > 1024 { + return fmt.Errorf("Block extra data too long (%d)", len(block.Header().Extra)) } - diff := block.Time - parent.Time + expd := CalcDifficulty(block, parent) + if expd.Cmp(block.Header().Difficulty) < 0 { + fmt.Println("parent\n", parent) + return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd) + } + + diff := block.Header().Time - parent.Header().Time if diff < 0 { - return ValidationError("Block timestamp less then prev block %v (%v - %v)", diff, block.Time, sm.bc.CurrentBlock().Time) + return ValidationError("Block timestamp less then prev block %v (%v - %v)", diff, block.Header().Time, sm.bc.CurrentBlock().Header().Time) } /* XXX @@ -289,37 +285,47 @@ func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error { // Verify the nonce of the block. Return an error if it's not valid if !sm.Pow.Verify(block /*block.HashNoNonce(), block.Difficulty, block.Nonce*/) { - return ValidationError("Block's nonce is invalid (= %v)", ethutil.Bytes2Hex(block.Nonce)) + return ValidationError("Block's nonce is invalid (= %v)", ethutil.Bytes2Hex(block.Header().Nonce)) } return nil } -func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent *types.Block) error { +func (sm *BlockProcessor) AccumelateRewards(statedb *state.StateDB, block, parent *types.Block) error { reward := new(big.Int).Set(BlockReward) - knownUncles := ethutil.Set(parent.Uncles) - nonces := ethutil.NewSet(block.Nonce) - for _, uncle := range block.Uncles { - if nonces.Include(uncle.Nonce) { + ancestors := set.New() + for _, ancestor := range sm.bc.GetAncestors(block, 6) { + ancestors.Add(string(ancestor.Hash())) + } + + uncles := set.New() + uncles.Add(string(block.Hash())) + for _, uncle := range block.Uncles() { + if uncles.Has(string(uncle.Hash())) { // Error not unique return UncleError("Uncle not unique") } + uncles.Add(string(uncle.Hash())) - uncleParent := sm.bc.GetBlock(uncle.PrevHash) - if uncleParent == nil { - return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.PrevHash[0:4])) + if !ancestors.Has(uncle.ParentHash) { + return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4])) } - if uncleParent.Number.Cmp(new(big.Int).Sub(parent.Number, big.NewInt(6))) < 0 { - return UncleError("Uncle too old") - } + /* + uncleParent := sm.bc.GetBlock(uncle.ParentHash) + if uncleParent == nil { + return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4])) + } - if knownUncles.Include(uncle.Hash()) { - return UncleError("Uncle in chain") - } + if uncleParent.Number().Cmp(new(big.Int).Sub(parent.Number(), big.NewInt(6))) < 0 { + return UncleError("Uncle too old") + } - nonces.Insert(uncle.Nonce) + if knownUncles.Has(string(uncle.Hash())) { + return UncleError("Uncle in chain") + } + */ r := new(big.Int) r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16)) @@ -331,31 +337,32 @@ func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent } // Get the account associated with the coinbase - account := statedb.GetAccount(block.Coinbase) + account := statedb.GetAccount(block.Header().Coinbase) // Reward amount of ether to the coinbase address account.AddAmount(reward) statedb.Manifest().AddMessage(&state.Message{ - To: block.Coinbase, - Input: nil, - Origin: nil, - Block: block.Hash(), Timestamp: block.Time, Coinbase: block.Coinbase, Number: block.Number, + To: block.Header().Coinbase, + Input: nil, + Origin: nil, + Timestamp: int64(block.Header().Time), Coinbase: block.Header().Coinbase, Number: block.Header().Number, Value: new(big.Int).Add(reward, block.Reward), }) return nil } -func (sm *BlockManager) GetMessages(block *types.Block) (messages []*state.Message, err error) { - if !sm.bc.HasBlock(block.PrevHash) { - return nil, ParentError(block.PrevHash) +func (sm *BlockProcessor) GetMessages(block *types.Block) (messages []*state.Message, err error) { + if !sm.bc.HasBlock(block.Header().ParentHash) { + return nil, ParentError(block.Header().ParentHash) } sm.lastAttemptedBlock = block var ( - parent = sm.bc.GetBlock(block.PrevHash) - state = parent.State().Copy() + parent = sm.bc.GetBlock(block.Header().ParentHash) + //state = state.New(parent.Trie().Copy()) + state = state.New(parent.Root(), sm.db) ) defer state.Reset() diff --git a/core/chain_manager.go b/core/chain_manager.go index e6268c01e0..90b5692ac1 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -1,6 +1,7 @@ package core import ( + "bytes" "fmt" "math/big" "sync" @@ -9,44 +10,52 @@ import ( "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/state" ) var chainlogger = logger.NewLogger("CHAIN") -func AddTestNetFunds(block *types.Block) { - for _, addr := range []string{ - "51ba59315b3a95761d0863b05ccc7a7f54703d99", - "e4157b34ea9615cfbde6b4fda419828124b70c78", - "b9c015918bdaba24b4ff057a92a3873d6eb201be", - "6c386a4b26f73c802f34673f7248bb118f97424a", - "cd2a3d9f938e13cd947ec05abc7fe734df8dd826", - "2ef47100e0787b915105fd5e3f4ff6752079d5cb", - "e6716f9544a56c530d868e4bfbacb172315bdead", - "1a26338f0d905e295fccb71fa9ea849ffa12aaf4", - } { - codedAddr := ethutil.Hex2Bytes(addr) - account := block.State().GetAccount(codedAddr) - account.SetBalance(ethutil.Big("1606938044258990275541962092341162602522202993782792835301376")) //ethutil.BigPow(2, 200) - block.State().UpdateStateObject(account) - } +type StateQuery interface { + GetAccount(addr []byte) *state.StateObject } func CalcDifficulty(block, parent *types.Block) *big.Int { diff := new(big.Int) - adjust := new(big.Int).Rsh(parent.Difficulty, 10) - if block.Time >= parent.Time+5 { - diff.Sub(parent.Difficulty, adjust) + bh, ph := block.Header(), parent.Header() + adjust := new(big.Int).Rsh(ph.Difficulty, 10) + if bh.Time >= ph.Time+13 { + diff.Sub(ph.Difficulty, adjust) } else { - diff.Add(parent.Difficulty, adjust) + diff.Add(ph.Difficulty, adjust) } return diff } +func CalcGasLimit(parent, block *types.Block) *big.Int { + if block.Number().Cmp(big.NewInt(0)) == 0 { + return ethutil.BigPow(10, 6) + } + + // ((1024-1) * parent.gasLimit + (gasUsed * 6 / 5)) / 1024 + + previous := new(big.Int).Mul(big.NewInt(1024-1), parent.GasLimit()) + current := new(big.Rat).Mul(new(big.Rat).SetInt(parent.GasUsed()), big.NewRat(6, 5)) + curInt := new(big.Int).Div(current.Num(), current.Denom()) + + result := new(big.Int).Add(previous, curInt) + result.Div(result, big.NewInt(1024)) + + min := big.NewInt(125000) + + return ethutil.BigMax(min, result) +} + type ChainManager struct { //eth EthManager + db ethutil.Database processor types.BlockProcessor eventMux *event.TypeMux genesisBlock *types.Block @@ -88,13 +97,9 @@ func (self *ChainManager) CurrentBlock() *types.Block { return self.currentBlock } -func NewChainManager(mux *event.TypeMux) *ChainManager { - bc := &ChainManager{} - bc.genesisBlock = types.NewBlockFromBytes(ethutil.Encode(Genesis)) - bc.eventMux = mux - +func NewChainManager(db ethutil.Database, mux *event.TypeMux) *ChainManager { + bc := &ChainManager{db: db, genesisBlock: GenesisBlock(db), eventMux: mux} bc.setLastBlock() - bc.transState = bc.State().Copy() return bc @@ -112,7 +117,7 @@ func (self *ChainManager) SetProcessor(proc types.BlockProcessor) { } func (self *ChainManager) State() *state.StateDB { - return self.CurrentBlock().State() + return state.New(self.CurrentBlock().Root(), self.db) } func (self *ChainManager) TransState() *state.StateDB { @@ -120,23 +125,21 @@ func (self *ChainManager) TransState() *state.StateDB { } func (bc *ChainManager) setLastBlock() { - data, _ := ethutil.Config.Db.Get([]byte("LastBlock")) + data, _ := bc.db.Get([]byte("LastBlock")) if len(data) != 0 { - // Prep genesis - AddTestNetFunds(bc.genesisBlock) - - block := types.NewBlockFromBytes(data) - bc.currentBlock = block + var block types.Block + rlp.Decode(bytes.NewReader(data), &block) + bc.currentBlock = &block bc.lastBlockHash = block.Hash() - bc.lastBlockNumber = block.Number.Uint64() + bc.lastBlockNumber = block.Header().Number.Uint64() // Set the last know difficulty (might be 0x0 as initial value, Genesis) - bc.td = ethutil.BigD(ethutil.Config.Db.LastKnownTD()) + bc.td = ethutil.BigD(bc.db.LastKnownTD()) } else { bc.Reset() } - chainlogger.Infof("Last block (#%d) %x\n", bc.lastBlockNumber, bc.currentBlock.Hash()) + chainlogger.Infof("Last block (#%d) %x TD=%v\n", bc.lastBlockNumber, bc.currentBlock.Hash(), bc.td) } // Block creation & chain handling @@ -144,27 +147,28 @@ func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block { bc.mu.RLock() defer bc.mu.RUnlock() - var root interface{} - hash := ZeroHash256 + var root []byte + parentHash := ZeroHash256 if bc.CurrentBlock != nil { - root = bc.currentBlock.Root() - hash = bc.lastBlockHash + root = bc.currentBlock.Header().Root + parentHash = bc.lastBlockHash } - block := types.CreateBlock( - root, - hash, + block := types.NewBlock( + parentHash, coinbase, + root, ethutil.BigPow(2, 32), nil, "") parent := bc.currentBlock if parent != nil { - block.Difficulty = CalcDifficulty(block, parent) - block.Number = new(big.Int).Add(bc.currentBlock.Number, ethutil.Big1) - block.GasLimit = block.CalcGasLimit(bc.currentBlock) + header := block.Header() + header.Difficulty = CalcDifficulty(block, parent) + header.Number = new(big.Int).Add(parent.Header().Number, ethutil.Big1) + header.GasLimit = CalcGasLimit(parent, block) } @@ -175,37 +179,35 @@ func (bc *ChainManager) Reset() { bc.mu.Lock() defer bc.mu.Unlock() - AddTestNetFunds(bc.genesisBlock) + for block := bc.currentBlock; block != nil; block = bc.GetBlock(block.Header().ParentHash) { + bc.db.Delete(block.Hash()) + } - bc.genesisBlock.Trie().Sync() // Prepare the genesis block bc.write(bc.genesisBlock) bc.insert(bc.genesisBlock) bc.currentBlock = bc.genesisBlock bc.setTotalDifficulty(ethutil.Big("0")) - - // Set the last know difficulty (might be 0x0 as initial value, Genesis) - bc.td = ethutil.BigD(ethutil.Config.Db.LastKnownTD()) } func (self *ChainManager) Export() []byte { self.mu.RLock() defer self.mu.RUnlock() - chainlogger.Infof("exporting %v blocks...\n", self.currentBlock.Number) + chainlogger.Infof("exporting %v blocks...\n", self.currentBlock.Header().Number) - blocks := make([]*types.Block, int(self.currentBlock.Number.Int64())+1) - for block := self.currentBlock; block != nil; block = self.GetBlock(block.PrevHash) { - blocks[block.Number.Int64()] = block + blocks := make([]*types.Block, int(self.currentBlock.NumberU64())+1) + for block := self.currentBlock; block != nil; block = self.GetBlock(block.Header().ParentHash) { + blocks[block.NumberU64()] = block } return ethutil.Encode(blocks) } func (bc *ChainManager) insert(block *types.Block) { - encodedBlock := block.RlpEncode() - ethutil.Config.Db.Put([]byte("LastBlock"), encodedBlock) + encodedBlock := ethutil.Encode(block) + bc.db.Put([]byte("LastBlock"), encodedBlock) bc.currentBlock = block bc.lastBlockHash = block.Hash() } @@ -213,8 +215,8 @@ func (bc *ChainManager) insert(block *types.Block) { func (bc *ChainManager) write(block *types.Block) { bc.writeBlockInfo(block) - encodedBlock := block.RlpEncode() - ethutil.Config.Db.Put(block.Hash(), encodedBlock) + encodedBlock := ethutil.Encode(block.RlpDataForStorage()) + bc.db.Put(block.Hash(), encodedBlock) } // Accessors @@ -224,7 +226,7 @@ func (bc *ChainManager) Genesis() *types.Block { // Block fetching methods func (bc *ChainManager) HasBlock(hash []byte) bool { - data, _ := ethutil.Config.Db.Get(hash) + data, _ := bc.db.Get(hash) return len(data) != 0 } @@ -236,85 +238,98 @@ func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain // XXX Could be optimised by using a different database which only holds hashes (i.e., linked list) for i := uint64(0); i < max; i++ { + block = self.GetBlock(block.Header().ParentHash) chain = append(chain, block.Hash()) - - if block.Number.Cmp(ethutil.Big0) <= 0 { + if block.Header().Number.Cmp(ethutil.Big0) <= 0 { break } - - block = self.GetBlock(block.PrevHash) } return } func (self *ChainManager) GetBlock(hash []byte) *types.Block { - data, _ := ethutil.Config.Db.Get(hash) + data, _ := self.db.Get(hash) if len(data) == 0 { return nil } + var block types.Block + if err := rlp.Decode(bytes.NewReader(data), &block); err != nil { + fmt.Println(err) + return nil + } - return types.NewBlockFromBytes(data) + return &block +} + +func (self *ChainManager) GetUnclesInChain(block *types.Block, length int) (uncles []*types.Header) { + for i := 0; block != nil && i < length; i++ { + uncles = append(uncles, block.Uncles()...) + block = self.GetBlock(block.ParentHash()) + } + + return +} + +func (self *ChainManager) GetAncestors(block *types.Block, length int) (blocks []*types.Block) { + for i := 0; i < length; i++ { + block = self.GetBlock(block.ParentHash()) + if block == nil { + break + } + + blocks = append(blocks, block) + } + + return } func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block { self.mu.RLock() defer self.mu.RUnlock() - block := self.currentBlock - for ; block != nil; block = self.GetBlock(block.PrevHash) { - if block.Number.Uint64() == num { - break - } - } + var block *types.Block - if block != nil && block.Number.Uint64() == 0 && num != 0 { - return nil + if num <= self.currentBlock.Number().Uint64() { + block = self.currentBlock + for ; block != nil; block = self.GetBlock(block.Header().ParentHash) { + if block.Header().Number.Uint64() == num { + break + } + } } return block } func (bc *ChainManager) setTotalDifficulty(td *big.Int) { - ethutil.Config.Db.Put([]byte("LTD"), td.Bytes()) + bc.db.Put([]byte("LTD"), td.Bytes()) bc.td = td } func (self *ChainManager) CalcTotalDiff(block *types.Block) (*big.Int, error) { - parent := self.GetBlock(block.PrevHash) + parent := self.GetBlock(block.Header().ParentHash) if parent == nil { - return nil, fmt.Errorf("Unable to calculate total diff without known parent %x", block.PrevHash) + return nil, fmt.Errorf("Unable to calculate total diff without known parent %x", block.Header().ParentHash) } - parentTd := parent.BlockInfo().TD + parentTd := parent.Td uncleDiff := new(big.Int) - for _, uncle := range block.Uncles { + for _, uncle := range block.Uncles() { uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty) } td := new(big.Int) td = td.Add(parentTd, uncleDiff) - td = td.Add(td, block.Difficulty) + td = td.Add(td, block.Header().Difficulty) return td, nil } -func (bc *ChainManager) BlockInfo(block *types.Block) types.BlockInfo { - bi := types.BlockInfo{} - data, _ := ethutil.Config.Db.Get(append(block.Hash(), []byte("Info")...)) - bi.RlpDecode(data) - - return bi -} - // Unexported method for writing extra non-essential block info to the db func (bc *ChainManager) writeBlockInfo(block *types.Block) { bc.lastBlockNumber++ - bi := types.BlockInfo{Number: bc.lastBlockNumber, Hash: block.Hash(), Parent: block.PrevHash, TD: bc.td} - - // For now we use the block hash with the words "info" appended as key - ethutil.Config.Db.Put(append(block.Hash(), []byte("Info")...), bi.RlpEncode()) } func (bc *ChainManager) Stop() { @@ -331,24 +346,26 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { continue } - chainlogger.Infof("block #%v process failed (%x)\n", block.Number, block.Hash()[:4]) + h := block.Header() + chainlogger.Infof("block #%v process failed (%x)\n", h.Number, h.Hash()[:4]) chainlogger.Infoln(block) chainlogger.Infoln(err) return err } + block.Td = td self.mu.Lock() { - self.write(block) + cblock := self.currentBlock if td.Cmp(self.td) > 0 { - if block.Number.Cmp(new(big.Int).Add(self.currentBlock.Number, ethutil.Big1)) < 0 { - chainlogger.Infof("Split detected. New head #%v (%x), was #%v (%x)\n", block.Number, block.Hash()[:4], self.currentBlock.Number, self.currentBlock.Hash()[:4]) + if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, ethutil.Big1)) < 0 { + chainlogger.Infof("Split detected. New head #%v (%x), was #%v (%x)\n", block.Header().Number, block.Hash()[:4], cblock.Header().Number, cblock.Hash()[:4]) } self.setTotalDifficulty(td) self.insert(block) - self.transState = self.currentBlock.State().Copy() + self.transState = state.New(cblock.Root(), self.db) //state.New(cblock.Trie().Copy()) } } @@ -360,3 +377,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { return nil } + +// Satisfy state query interface +func (self *ChainManager) GetAccount(addr []byte) *state.StateObject { + return self.State().GetAccount(addr) +} diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go index 52be8b0eab..725352dafa 100644 --- a/core/chain_manager_test.go +++ b/core/chain_manager_test.go @@ -1,49 +1,39 @@ package core import ( + "bytes" "fmt" + "os" "path" "runtime" + "strconv" "testing" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" - //logpkg "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/rlp" ) -//var Logger logpkg.LogSystem -//var Log = logpkg.NewLogger("TEST") - func init() { runtime.GOMAXPROCS(runtime.NumCPU()) - //Logger = logpkg.NewStdLogSystem(os.Stdout, log.LstdFlags, logpkg.InfoLevel) - //logpkg.AddLogSystem(Logger) - ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH") - - db, err := ethdb.NewMemDatabase() - if err != nil { - panic("Could not create mem-db, failing") - } - ethutil.Config.Db = db } -func loadChain(fn string, t *testing.T) types.Blocks { - c1, err := ethutil.ReadAllFile(path.Join("..", "_data", fn)) +func loadChain(fn string, t *testing.T) (types.Blocks, error) { + fh, err := os.OpenFile(path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "_data", fn), os.O_RDONLY, os.ModePerm) if err != nil { - fmt.Println(err) - t.FailNow() + return nil, err } - value := ethutil.NewValueFromBytes([]byte(c1)) - blocks := make(types.Blocks, value.Len()) - it := value.NewIterator() - for it.Next() { - blocks[it.Idx()] = types.NewBlockFromRlpValue(it.Value()) + defer fh.Close() + + var chain types.Blocks + if err := rlp.Decode(fh, &chain); err != nil { + return nil, err } - return blocks + return chain, nil } func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *testing.T) { @@ -56,12 +46,24 @@ func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t * } func TestChainInsertions(t *testing.T) { - chain1 := loadChain("chain1", t) - chain2 := loadChain("chain2", t) + db, _ := ethdb.NewMemDatabase() + + chain1, err := loadChain("valid1", t) + if err != nil { + fmt.Println(err) + t.FailNow() + } + + chain2, err := loadChain("valid2", t) + if err != nil { + fmt.Println(err) + t.FailNow() + } + var eventMux event.TypeMux - chainMan := NewChainManager(&eventMux) - txPool := NewTxPool(chainMan, nil, &eventMux) - blockMan := NewBlockManager(txPool, chainMan, &eventMux) + chainMan := NewChainManager(db, &eventMux) + txPool := NewTxPool(&eventMux) + blockMan := NewBlockProcessor(db, txPool, chainMan, &eventMux) chainMan.SetProcessor(blockMan) const max = 2 @@ -73,5 +75,56 @@ func TestChainInsertions(t *testing.T) { for i := 0; i < max; i++ { <-done } - fmt.Println(chainMan.CurrentBlock()) + + if bytes.Equal(chain2[len(chain2)-1].Hash(), chainMan.CurrentBlock().Hash()) { + t.Error("chain2 is canonical and shouldn't be") + } + + if !bytes.Equal(chain1[len(chain1)-1].Hash(), chainMan.CurrentBlock().Hash()) { + t.Error("chain1 isn't canonical and should be") + } +} + +func TestChainMultipleInsertions(t *testing.T) { + db, _ := ethdb.NewMemDatabase() + + const max = 4 + chains := make([]types.Blocks, max) + var longest int + for i := 0; i < max; i++ { + var err error + name := "valid" + strconv.Itoa(i+1) + chains[i], err = loadChain(name, t) + if len(chains[i]) >= len(chains[longest]) { + longest = i + } + fmt.Println("loaded", name, "with a length of", len(chains[i])) + if err != nil { + fmt.Println(err) + t.FailNow() + } + } + var eventMux event.TypeMux + chainMan := NewChainManager(db, &eventMux) + txPool := NewTxPool(&eventMux) + blockMan := NewBlockProcessor(db, txPool, chainMan, &eventMux) + chainMan.SetProcessor(blockMan) + done := make(chan bool, max) + for i, chain := range chains { + // XXX the go routine would otherwise reference the same (chain[3]) variable and fail + i := i + chain := chain + go func() { + insertChain(done, chainMan, chain, t) + fmt.Println(i, "done") + }() + } + + for i := 0; i < max; i++ { + <-done + } + + if !bytes.Equal(chains[longest][len(chains[longest])-1].Hash(), chainMan.CurrentBlock().Hash()) { + t.Error("Invalid canonical chain") + } } diff --git a/core/execution.go b/core/execution.go index cd98746c41..43f4b58fb0 100644 --- a/core/execution.go +++ b/core/execution.go @@ -3,42 +3,41 @@ package core import ( "fmt" "math/big" + "time" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/vm" ) type Execution struct { - vm vm.VirtualMachine + env vm.Environment address, input []byte Gas, price, value *big.Int - object *state.StateObject SkipTransfer bool } func NewExecution(env vm.Environment, address, input []byte, gas, gasPrice, value *big.Int) *Execution { - evm := vm.New(env, vm.DebugVmTy) - - return &Execution{vm: evm, address: address, input: input, Gas: gas, price: gasPrice, value: value} + return &Execution{env: env, address: address, input: input, Gas: gas, price: gasPrice, value: value} } func (self *Execution) Addr() []byte { return self.address } -func (self *Execution) Call(codeAddr []byte, caller vm.ClosureRef) ([]byte, error) { +func (self *Execution) Call(codeAddr []byte, caller vm.ContextRef) ([]byte, error) { // Retrieve the executing code - code := self.vm.Env().State().GetCode(codeAddr) + code := self.env.State().GetCode(codeAddr) return self.exec(code, codeAddr, caller) } -func (self *Execution) exec(code, contextAddr []byte, caller vm.ClosureRef) (ret []byte, err error) { - env := self.vm.Env() - chainlogger.Debugf("pre state %x\n", env.State().Root()) +func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret []byte, err error) { + env := self.env + evm := vm.New(env, vm.DebugVmTy) + + if env.Depth() == vm.MaxCallDepth { + caller.ReturnGas(self.Gas, self.price) - if self.vm.Env().Depth() == vm.MaxCallDepth { - // Consume all gas (by not returning it) and return a depth error return nil, vm.DepthError{} } @@ -55,22 +54,19 @@ func (self *Execution) exec(code, contextAddr []byte, caller vm.ClosureRef) (ret } snapshot := env.State().Copy() - defer func() { - if /*vm.IsDepthErr(err) ||*/ vm.IsOOGErr(err) { - env.State().Set(snapshot) - } - chainlogger.Debugf("post state %x\n", env.State().Root()) - }() - - self.object = to - ret, err = self.vm.Run(to, caller, code, self.value, self.Gas, self.price, self.input) + start := time.Now() + ret, err = evm.Run(to, caller, code, self.value, self.Gas, self.price, self.input) + if err != nil { + env.State().Set(snapshot) + } + chainlogger.Debugf("vm took %v\n", time.Since(start)) return } -func (self *Execution) Create(caller vm.ClosureRef) (ret []byte, err error, account *state.StateObject) { +func (self *Execution) Create(caller vm.ContextRef) (ret []byte, err error, account *state.StateObject) { ret, err = self.exec(self.input, nil, caller) - account = self.vm.Env().State().GetStateObject(self.address) + account = self.env.State().GetStateObject(self.address) return } diff --git a/core/filter.go b/core/filter.go index fb992782df..29be8841c9 100644 --- a/core/filter.go +++ b/core/filter.go @@ -76,13 +76,14 @@ func (self *Filter) SetSkip(skip int) { // Run filters messages with the current parameters set func (self *Filter) Find() []*state.Message { + earliestBlock := self.eth.ChainManager().CurrentBlock() var earliestBlockNo uint64 = uint64(self.earliest) if self.earliest == -1 { - earliestBlockNo = self.eth.ChainManager().CurrentBlock().Number.Uint64() + earliestBlockNo = earliestBlock.NumberU64() } var latestBlockNo uint64 = uint64(self.latest) if self.latest == -1 { - latestBlockNo = self.eth.ChainManager().CurrentBlock().Number.Uint64() + latestBlockNo = earliestBlock.NumberU64() } var ( @@ -93,7 +94,7 @@ func (self *Filter) Find() []*state.Message { for i := 0; !quit && block != nil; i++ { // Quit on latest switch { - case block.Number.Uint64() == earliestBlockNo, block.Number.Uint64() == 0: + case block.NumberU64() == earliestBlockNo, block.NumberU64() == 0: quit = true case self.max <= len(messages): break @@ -103,7 +104,7 @@ func (self *Filter) Find() []*state.Message { // current parameters if self.bloomFilter(block) { // Get the messages of the block - msgs, err := self.eth.BlockManager().GetMessages(block) + msgs, err := self.eth.BlockProcessor().GetMessages(block) if err != nil { chainlogger.Warnln("err: filter get messages ", err) @@ -113,7 +114,7 @@ func (self *Filter) Find() []*state.Message { messages = append(messages, self.FilterMessages(msgs)...) } - block = self.eth.ChainManager().GetBlock(block.PrevHash) + block = self.eth.ChainManager().GetBlock(block.ParentHash()) } skip := int(math.Min(float64(len(messages)), float64(self.skip))) @@ -176,7 +177,7 @@ func (self *Filter) bloomFilter(block *types.Block) bool { var fromIncluded, toIncluded bool if len(self.from) > 0 { for _, from := range self.from { - if types.BloomLookup(block.LogsBloom, from) || bytes.Equal(block.Coinbase, from) { + if types.BloomLookup(block.Bloom(), from) || bytes.Equal(block.Coinbase(), from) { fromIncluded = true break } @@ -187,7 +188,7 @@ func (self *Filter) bloomFilter(block *types.Block) bool { if len(self.to) > 0 { for _, to := range self.to { - if types.BloomLookup(block.LogsBloom, ethutil.U256(new(big.Int).Add(ethutil.Big1, ethutil.BigD(to))).Bytes()) || bytes.Equal(block.Coinbase, to) { + if types.BloomLookup(block.Bloom(), ethutil.U256(new(big.Int).Add(ethutil.Big1, ethutil.BigD(to))).Bytes()) || bytes.Equal(block.Coinbase(), to) { toIncluded = true break } diff --git a/core/genesis.go b/core/genesis.go index 707154759a..d9edaace23 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -3,8 +3,10 @@ package core import ( "math/big" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/state" ) /* @@ -17,36 +19,37 @@ var ZeroHash512 = make([]byte, 64) var EmptyShaList = crypto.Sha3(ethutil.Encode([]interface{}{})) var EmptyListRoot = crypto.Sha3(ethutil.Encode("")) -var GenesisHeader = []interface{}{ - // Previous hash (none) - ZeroHash256, - // Empty uncles - EmptyShaList, - // Coinbase - ZeroHash160, - // Root state - EmptyShaList, - // tx root - EmptyListRoot, - // receipt root - EmptyListRoot, - // bloom - ZeroHash512, - // Difficulty - //ethutil.BigPow(2, 22), - big.NewInt(131072), - // Number - ethutil.Big0, - // Block upper gas bound - big.NewInt(1000000), - // Block gas used - ethutil.Big0, - // Time - ethutil.Big0, - // Extra - nil, - // Nonce - crypto.Sha3(big.NewInt(42).Bytes()), -} +func GenesisBlock(db ethutil.Database) *types.Block { + genesis := types.NewBlock(ZeroHash256, ZeroHash160, nil, big.NewInt(131072), crypto.Sha3(big.NewInt(42).Bytes()), "") + genesis.Header().Number = ethutil.Big0 + genesis.Header().GasLimit = big.NewInt(1000000) + genesis.Header().GasUsed = ethutil.Big0 + genesis.Header().Time = 0 + genesis.Td = ethutil.Big0 -var Genesis = []interface{}{GenesisHeader, []interface{}{}, []interface{}{}} + genesis.SetUncles([]*types.Header{}) + genesis.SetTransactions(types.Transactions{}) + genesis.SetReceipts(types.Receipts{}) + + statedb := state.New(genesis.Root(), db) + //statedb := state.New(genesis.Trie()) + for _, addr := range []string{ + "51ba59315b3a95761d0863b05ccc7a7f54703d99", + "e4157b34ea9615cfbde6b4fda419828124b70c78", + "b9c015918bdaba24b4ff057a92a3873d6eb201be", + "6c386a4b26f73c802f34673f7248bb118f97424a", + "cd2a3d9f938e13cd947ec05abc7fe734df8dd826", + "2ef47100e0787b915105fd5e3f4ff6752079d5cb", + "e6716f9544a56c530d868e4bfbacb172315bdead", + "1a26338f0d905e295fccb71fa9ea849ffa12aaf4", + } { + codedAddr := ethutil.Hex2Bytes(addr) + account := statedb.GetAccount(codedAddr) + account.SetBalance(ethutil.Big("1606938044258990275541962092341162602522202993782792835301376")) //ethutil.BigPow(2, 200) + statedb.UpdateStateObject(account) + } + statedb.Sync() + genesis.Header().Root = statedb.Root() + + return genesis +} diff --git a/core/helper_test.go b/core/helper_test.go index b340144fdd..7b41b86f15 100644 --- a/core/helper_test.go +++ b/core/helper_test.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/wire" + "github.com/ethereum/go-ethereum/p2p" ) // Implement our EthTest Manager @@ -54,11 +54,11 @@ func (tm *TestManager) TxPool() *TxPool { func (tm *TestManager) EventMux() *event.TypeMux { return tm.eventMux } -func (tm *TestManager) Broadcast(msgType wire.MsgType, data []interface{}) { +func (tm *TestManager) Broadcast(msgType p2p.Msg, data []interface{}) { fmt.Println("Broadcast not implemented") } -func (tm *TestManager) ClientIdentity() wire.ClientIdentity { +func (tm *TestManager) ClientIdentity() p2p.ClientIdentity { return nil } func (tm *TestManager) KeyManager() *crypto.KeyManager { @@ -77,7 +77,6 @@ func NewTestManager() *TestManager { fmt.Println("Could not create mem-db, failing") return nil } - ethutil.Config.Db = db testManager := &TestManager{} testManager.eventMux = new(event.TypeMux) diff --git a/core/simple_pow.go b/core/simple_pow.go deleted file mode 100644 index 9a8bc9592b..0000000000 --- a/core/simple_pow.go +++ /dev/null @@ -1 +0,0 @@ -package core diff --git a/core/state_transition.go b/core/state_transition.go index 9e81ddf284..b22c5bf217 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -4,7 +4,6 @@ import ( "fmt" "math/big" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/state" @@ -28,18 +27,17 @@ import ( * 6) Derive new state root */ type StateTransition struct { - coinbase, receiver []byte - msg Message - gas, gasPrice *big.Int - initialGas *big.Int - value *big.Int - data []byte - state *state.StateDB - block *types.Block + coinbase []byte + msg Message + gas, gasPrice *big.Int + initialGas *big.Int + value *big.Int + data []byte + state *state.StateDB cb, rec, sen *state.StateObject - Env vm.Environment + env vm.Environment } type Message interface { @@ -69,16 +67,19 @@ func MessageGasValue(msg Message) *big.Int { return new(big.Int).Mul(msg.Gas(), msg.GasPrice()) } -func NewStateTransition(coinbase *state.StateObject, msg Message, state *state.StateDB, block *types.Block) *StateTransition { - return &StateTransition{coinbase.Address(), msg.To(), msg, new(big.Int), new(big.Int).Set(msg.GasPrice()), new(big.Int), msg.Value(), msg.Data(), state, block, coinbase, nil, nil, nil} -} - -func (self *StateTransition) VmEnv() vm.Environment { - if self.Env == nil { - self.Env = NewEnv(self.state, self.msg, self.block) +func NewStateTransition(env vm.Environment, msg Message, coinbase *state.StateObject) *StateTransition { + return &StateTransition{ + coinbase: coinbase.Address(), + env: env, + msg: msg, + gas: new(big.Int), + gasPrice: new(big.Int).Set(msg.GasPrice()), + initialGas: new(big.Int), + value: msg.Value(), + data: msg.Data(), + state: env.State(), + cb: coinbase, } - - return self.Env } func (self *StateTransition) Coinbase() *state.StateObject { @@ -112,7 +113,7 @@ func (self *StateTransition) BuyGas() error { sender := self.From() if sender.Balance().Cmp(MessageGasValue(self.msg)) < 0 { - return fmt.Errorf("Insufficient funds to pre-pay gas. Req %v, has %v", MessageGasValue(self.msg), sender.Balance()) + return fmt.Errorf("insufficient ETH for gas (%x). Req %v, has %v", sender.Address()[:4], MessageGasValue(self.msg), sender.Balance()) } coinbase := self.Coinbase() @@ -183,18 +184,25 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) { return } - vmenv := self.VmEnv() - var ref vm.ClosureRef + vmenv := self.env + var ref vm.ContextRef if MessageCreatesContract(msg) { - self.rec = MakeContract(msg, self.state) - - ret, err, ref = vmenv.Create(sender, self.rec.Address(), self.msg.Data(), self.gas, self.gasPrice, self.value) - ref.SetCode(ret) + contract := MakeContract(msg, self.state) + ret, err, ref = vmenv.Create(sender, contract.Address(), self.msg.Data(), self.gas, self.gasPrice, self.value) + if err == nil { + dataGas := big.NewInt(int64(len(ret))) + dataGas.Mul(dataGas, vm.GasCreateByte) + if err = self.UseGas(dataGas); err == nil { + //self.state.SetCode(ref.Address(), ret) + ref.SetCode(ret) + } + } } else { ret, err = vmenv.Call(self.From(), self.To().Address(), self.msg.Data(), self.gas, self.gasPrice, self.value) } + if err != nil { - statelogger.Debugln(err) + self.UseGas(self.gas) } return @@ -211,20 +219,19 @@ func MakeContract(msg Message, state *state.StateDB) *state.StateObject { } func (self *StateTransition) RefundGas() { - coinbaseSub := new(big.Int).Set(self.gas) - uhalf := new(big.Int).Div(self.GasUsed(), ethutil.Big2) - for addr, ref := range self.state.Refunds() { - refund := ethutil.BigMin(uhalf, ref) - coinbaseSub.Add(self.gas, refund) - self.state.AddBalance([]byte(addr), refund.Mul(refund, self.msg.GasPrice())) - } - coinbase, sender := self.Coinbase(), self.From() - coinbase.RefundGas(coinbaseSub, self.msg.GasPrice()) - // Return remaining gas remaining := new(big.Int).Mul(self.gas, self.msg.GasPrice()) sender.AddAmount(remaining) + + uhalf := new(big.Int).Div(self.GasUsed(), ethutil.Big2) + for addr, ref := range self.state.Refunds() { + refund := ethutil.BigMin(uhalf, ref) + self.gas.Add(self.gas, refund) + self.state.AddBalance([]byte(addr), refund.Mul(refund, self.msg.GasPrice())) + } + + coinbase.RefundGas(self.gas, self.msg.GasPrice()) } func (self *StateTransition) GasUsed() *big.Int { diff --git a/core/transaction_pool.go b/core/transaction_pool.go index 1149d4cfb8..d3aec90502 100644 --- a/core/transaction_pool.go +++ b/core/transaction_pool.go @@ -1,16 +1,12 @@ package core import ( - "bytes" - "container/list" "fmt" - "math/big" - "sync" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" - "github.com/ethereum/go-ethereum/state" ) var txplogger = logger.NewLogger("TXP") @@ -26,101 +22,59 @@ const ( minGasPrice = 1000000 ) -var MinGasPrice = big.NewInt(10000000000000) - -func EachTx(pool *list.List, it func(*types.Transaction, *list.Element) bool) { - for e := pool.Front(); e != nil; e = e.Next() { - if it(e.Value.(*types.Transaction), e) { - break - } - } -} - -func FindTx(pool *list.List, finder func(*types.Transaction, *list.Element) bool) *types.Transaction { - for e := pool.Front(); e != nil; e = e.Next() { - if tx, ok := e.Value.(*types.Transaction); ok { - if finder(tx, e) { - return tx - } - } - } - - return nil -} - type TxProcessor interface { ProcessTransaction(tx *types.Transaction) } // The tx pool a thread safe transaction pool handler. In order to // guarantee a non blocking pool we use a queue channel which can be -// independently read without needing access to the actual pool. If the -// pool is being drained or synced for whatever reason the transactions -// will simple queue up and handled when the mutex is freed. +// independently read without needing access to the actual pool. type TxPool struct { - // The mutex for accessing the Tx pool. - mutex sync.Mutex // Queueing channel for reading and writing incoming // transactions to queueChan chan *types.Transaction // Quiting channel quit chan bool // The actual pool - pool *list.List + //pool *list.List + txs map[string]*types.Transaction SecondaryProcessor TxProcessor subscribers []chan TxMsg - chainManager *ChainManager - eventMux *event.TypeMux + eventMux *event.TypeMux } -func NewTxPool(chainManager *ChainManager, eventMux *event.TypeMux) *TxPool { +func NewTxPool(eventMux *event.TypeMux) *TxPool { return &TxPool{ - pool: list.New(), - queueChan: make(chan *types.Transaction, txPoolQueueSize), - quit: make(chan bool), - chainManager: chainManager, - eventMux: eventMux, + txs: make(map[string]*types.Transaction), + queueChan: make(chan *types.Transaction, txPoolQueueSize), + quit: make(chan bool), + eventMux: eventMux, } } -// Blocking function. Don't use directly. Use QueueTransaction instead -func (pool *TxPool) addTransaction(tx *types.Transaction) { - pool.mutex.Lock() - defer pool.mutex.Unlock() - - pool.pool.PushBack(tx) - - // Broadcast the transaction to the rest of the peers - pool.eventMux.Post(TxPreEvent{tx}) -} - func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error { - // Get the last block so we can retrieve the sender and receiver from - // the merkle trie - block := pool.chainManager.CurrentBlock - // Something has gone horribly wrong if this happens - if block == nil { - return fmt.Errorf("No last block on the block chain") - } - if len(tx.To()) != 0 && len(tx.To()) != 20 { return fmt.Errorf("Invalid recipient. len = %d", len(tx.To())) } v, _, _ := tx.Curve() if v > 28 || v < 27 { - return fmt.Errorf("tx.v != (28 || 27)") + return fmt.Errorf("tx.v != (28 || 27) => %v", v) } + /* XXX this kind of validation needs to happen elsewhere in the gui when sending txs. + Other clients should do their own validation. Value transfer could throw error + but doesn't necessarily invalidate the tx. Gas can still be payed for and miner + can still be rewarded for their inclusion and processing. // Get the sender senderAddr := tx.From() if senderAddr == nil { return fmt.Errorf("invalid sender") } - sender := pool.chainManager.State().GetAccount(senderAddr) + sender := pool.stateQuery.GetAccount(senderAddr) totAmount := new(big.Int).Set(tx.Value()) // Make sure there's enough in the sender's account. Having insufficient @@ -128,21 +82,18 @@ func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error { if sender.Balance().Cmp(totAmount) < 0 { return fmt.Errorf("Insufficient amount in sender's (%x) account", tx.From()) } - - // Increment the nonce making each tx valid only once to prevent replay - // attacks + */ return nil } -func (self *TxPool) Add(tx *types.Transaction) error { - hash := tx.Hash() - foundTx := FindTx(self.pool, func(tx *types.Transaction, e *list.Element) bool { - return bytes.Compare(tx.Hash(), hash) == 0 - }) +func (self *TxPool) addTx(tx *types.Transaction) { + self.txs[string(tx.Hash())] = tx +} - if foundTx != nil { - return fmt.Errorf("Known transaction (%x)", hash[0:4]) +func (self *TxPool) Add(tx *types.Transaction) error { + if self.txs[string(tx.Hash())] != nil { + return fmt.Errorf("Known transaction (%x)", tx.Hash()[0:4]) } err := self.ValidateTransaction(tx) @@ -150,9 +101,16 @@ func (self *TxPool) Add(tx *types.Transaction) error { return err } - self.addTransaction(tx) + self.addTx(tx) - txplogger.Debugf("(t) %x => %x (%v) %x\n", tx.From()[:4], tx.To()[:4], tx.Value, tx.Hash()) + var to string + if len(tx.To()) > 0 { + to = ethutil.Bytes2Hex(tx.To()[:4]) + } else { + to = "[NEW_CONTRACT]" + } + + txplogger.Debugf("(t) %x => %s (%v) %x\n", tx.From()[:4], to, tx.Value, tx.Hash()) // Notify the subscribers go self.eventMux.Post(TxPreEvent{tx}) @@ -161,7 +119,7 @@ func (self *TxPool) Add(tx *types.Transaction) error { } func (self *TxPool) Size() int { - return self.pool.Len() + return len(self.txs) } func (self *TxPool) AddTransactions(txs []*types.Transaction) { @@ -174,64 +132,45 @@ func (self *TxPool) AddTransactions(txs []*types.Transaction) { } } -func (pool *TxPool) GetTransactions() []*types.Transaction { - pool.mutex.Lock() - defer pool.mutex.Unlock() - - txList := make([]*types.Transaction, pool.pool.Len()) +func (self *TxPool) GetTransactions() (txs types.Transactions) { + txs = make(types.Transactions, self.Size()) i := 0 - for e := pool.pool.Front(); e != nil; e = e.Next() { - tx := e.Value.(*types.Transaction) - - txList[i] = tx - + for _, tx := range self.txs { + txs[i] = tx i++ } - return txList + return } -func (pool *TxPool) RemoveInvalid(state *state.StateDB) { - pool.mutex.Lock() - defer pool.mutex.Unlock() - - for e := pool.pool.Front(); e != nil; e = e.Next() { - tx := e.Value.(*types.Transaction) - sender := state.GetAccount(tx.From()) +func (pool *TxPool) RemoveInvalid(query StateQuery) { + var removedTxs types.Transactions + for _, tx := range pool.txs { + sender := query.GetAccount(tx.From()) err := pool.ValidateTransaction(tx) + fmt.Println(err, sender.Nonce, tx.Nonce()) if err != nil || sender.Nonce >= tx.Nonce() { - pool.pool.Remove(e) + removedTxs = append(removedTxs, tx) } } + + pool.RemoveSet(removedTxs) } func (self *TxPool) RemoveSet(txs types.Transactions) { - self.mutex.Lock() - defer self.mutex.Unlock() - for _, tx := range txs { - EachTx(self.pool, func(t *types.Transaction, element *list.Element) bool { - if t == tx { - self.pool.Remove(element) - return true // To stop the loop - } - return false - }) + delete(self.txs, string(tx.Hash())) } } func (pool *TxPool) Flush() []*types.Transaction { txList := pool.GetTransactions() - - // Recreate a new list all together - // XXX Is this the fastest way? - pool.pool = list.New() + pool.txs = make(map[string]*types.Transaction) return txList } func (pool *TxPool) Start() { - //go pool.queueHandler() } func (pool *TxPool) Stop() { diff --git a/core/transaction_pool_test.go b/core/transaction_pool_test.go new file mode 100644 index 0000000000..7f192fc4dd --- /dev/null +++ b/core/transaction_pool_test.go @@ -0,0 +1,87 @@ +package core + +import ( + "crypto/ecdsa" + "testing" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/state" +) + +// State query interface +type stateQuery struct{ db ethutil.Database } + +func SQ() stateQuery { + db, _ := ethdb.NewMemDatabase() + return stateQuery{db: db} +} + +func (self stateQuery) GetAccount(addr []byte) *state.StateObject { + return state.NewStateObject(addr, self.db) +} + +func transaction() *types.Transaction { + return types.NewTransactionMessage(make([]byte, 20), ethutil.Big0, ethutil.Big0, ethutil.Big0, nil) +} + +func setup() (*TxPool, *ecdsa.PrivateKey) { + var m event.TypeMux + key, _ := crypto.GenerateKey() + return NewTxPool(&m), key +} + +func TestTxAdding(t *testing.T) { + pool, key := setup() + tx1 := transaction() + tx1.SignECDSA(key) + err := pool.Add(tx1) + if err != nil { + t.Error(err) + } + + err = pool.Add(tx1) + if err == nil { + t.Error("added tx twice") + } +} + +func TestAddInvalidTx(t *testing.T) { + pool, _ := setup() + tx1 := transaction() + err := pool.Add(tx1) + if err == nil { + t.Error("expected error") + } +} + +func TestRemoveSet(t *testing.T) { + pool, _ := setup() + tx1 := transaction() + pool.addTx(tx1) + pool.RemoveSet(types.Transactions{tx1}) + if pool.Size() > 0 { + t.Error("expected pool size to be 0") + } +} + +func TestRemoveInvalid(t *testing.T) { + pool, key := setup() + tx1 := transaction() + pool.addTx(tx1) + pool.RemoveInvalid(SQ()) + if pool.Size() > 0 { + t.Error("expected pool size to be 0") + } + + tx1.SetNonce(1) + tx1.SignECDSA(key) + pool.addTx(tx1) + pool.RemoveInvalid(SQ()) + if pool.Size() != 1 { + t.Error("expected pool size to be 1, is", pool.Size()) + } +} diff --git a/core/types/block.go b/core/types/block.go index 2d889f35f4..be57e86a65 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -9,41 +9,233 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" - "github.com/ethereum/go-ethereum/state" - "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/rlp" ) -type BlockInfo struct { - Number uint64 - Hash []byte - Parent []byte - TD *big.Int +type Header struct { + // Hash to the previous block + ParentHash ethutil.Bytes + // Uncles of this block + UncleHash []byte + // The coin base address + Coinbase []byte + // Block Trie state + Root []byte + // Tx sha + TxHash []byte + // Receipt sha + ReceiptHash []byte + // Bloom + Bloom []byte + // Difficulty for the current block + Difficulty *big.Int + // The block number + Number *big.Int + // Gas limit + GasLimit *big.Int + // Gas used + GasUsed *big.Int + // Creation time + Time uint64 + // Extra data + Extra string + // Block Nonce for verification + Nonce ethutil.Bytes } -func (bi *BlockInfo) RlpDecode(data []byte) { - decoder := ethutil.NewValueFromBytes(data) +func (self *Header) rlpData(withNonce bool) []interface{} { + fields := []interface{}{self.ParentHash, self.UncleHash, self.Coinbase, self.Root, self.TxHash, self.ReceiptHash, self.Bloom, self.Difficulty, self.Number, self.GasLimit, self.GasUsed, self.Time, self.Extra} + if withNonce { + fields = append(fields, self.Nonce) + } - bi.Number = decoder.Get(0).Uint() - bi.Hash = decoder.Get(1).Bytes() - bi.Parent = decoder.Get(2).Bytes() - bi.TD = decoder.Get(3).BigInt() + return fields } -func (bi *BlockInfo) RlpEncode() []byte { - return ethutil.Encode([]interface{}{bi.Number, bi.Hash, bi.Parent, bi.TD}) +func (self *Header) RlpData() interface{} { + return self.rlpData(true) +} + +func (self *Header) Hash() []byte { + return crypto.Sha3(ethutil.Encode(self.rlpData(true))) +} + +func (self *Header) HashNoNonce() []byte { + return crypto.Sha3(ethutil.Encode(self.rlpData(false))) +} + +type Block struct { + // Preset Hash for mock + HeaderHash []byte + ParentHeaderHash []byte + header *Header + uncles []*Header + transactions Transactions + Td *big.Int + + receipts Receipts + Reward *big.Int +} + +func NewBlock(parentHash []byte, coinbase []byte, root []byte, difficulty *big.Int, nonce []byte, extra string) *Block { + header := &Header{ + Root: root, + ParentHash: parentHash, + Coinbase: coinbase, + Difficulty: difficulty, + Nonce: nonce, + Time: uint64(time.Now().Unix()), + Extra: extra, + GasUsed: new(big.Int), + GasLimit: new(big.Int), + } + + block := &Block{header: header, Reward: new(big.Int)} + + return block +} + +func NewBlockWithHeader(header *Header) *Block { + return &Block{header: header} +} + +func (self *Block) DecodeRLP(s *rlp.Stream) error { + var extblock struct { + Header *Header + Txs []*Transaction + Uncles []*Header + TD *big.Int // optional + } + if err := s.Decode(&extblock); err != nil { + return err + } + self.header = extblock.Header + self.uncles = extblock.Uncles + self.transactions = extblock.Txs + self.Td = extblock.TD + return nil +} + +func (self *Block) Header() *Header { + return self.header +} + +func (self *Block) Uncles() []*Header { + return self.uncles +} + +func (self *Block) SetUncles(uncleHeaders []*Header) { + self.uncles = uncleHeaders + self.header.UncleHash = crypto.Sha3(ethutil.Encode(uncleHeaders)) +} + +func (self *Block) Transactions() Transactions { + return self.transactions +} + +func (self *Block) Transaction(hash []byte) *Transaction { + for _, transaction := range self.transactions { + if bytes.Equal(hash, transaction.Hash()) { + return transaction + } + } + return nil +} + +func (self *Block) SetTransactions(transactions Transactions) { + self.transactions = transactions + self.header.TxHash = DeriveSha(transactions) +} + +func (self *Block) Receipts() Receipts { + return self.receipts +} + +func (self *Block) SetReceipts(receipts Receipts) { + self.receipts = receipts + self.header.ReceiptHash = DeriveSha(receipts) + self.header.Bloom = CreateBloom(receipts) +} + +func (self *Block) RlpData() interface{} { + return []interface{}{self.header, self.transactions, self.uncles} +} + +func (self *Block) RlpDataForStorage() interface{} { + return []interface{}{self.header, self.transactions, self.uncles, self.Td /* TODO receipts */} +} + +// Header accessors (add as you need them) +func (self *Block) Number() *big.Int { return self.header.Number } +func (self *Block) NumberU64() uint64 { return self.header.Number.Uint64() } +func (self *Block) Bloom() []byte { return self.header.Bloom } +func (self *Block) Coinbase() []byte { return self.header.Coinbase } +func (self *Block) Time() int64 { return int64(self.header.Time) } +func (self *Block) GasLimit() *big.Int { return self.header.GasLimit } +func (self *Block) GasUsed() *big.Int { return self.header.GasUsed } + +//func (self *Block) Trie() *ptrie.Trie { return ptrie.New(self.header.Root, ethutil.Config.Db) } +//func (self *Block) State() *state.StateDB { return state.New(self.Trie()) } +func (self *Block) Root() []byte { return self.header.Root } +func (self *Block) SetRoot(root []byte) { self.header.Root = root } +func (self *Block) Size() ethutil.StorageSize { return ethutil.StorageSize(len(ethutil.Encode(self))) } + +// Implement pow.Block +func (self *Block) Difficulty() *big.Int { return self.header.Difficulty } +func (self *Block) N() []byte { return self.header.Nonce } +func (self *Block) HashNoNonce() []byte { return self.header.HashNoNonce() } + +func (self *Block) Hash() []byte { + if self.HeaderHash != nil { + return self.HeaderHash + } else { + return self.header.Hash() + } +} + +func (self *Block) ParentHash() []byte { + if self.ParentHeaderHash != nil { + return self.ParentHeaderHash + } else { + return self.header.ParentHash + } +} + +func (self *Block) String() string { + return fmt.Sprintf(`BLOCK(%x): Size: %v TD: %v { +Header: +[ +%v +] +Transactions: +%v +Uncles: +%v +} +`, self.header.Hash(), self.Size(), self.Td, self.header, self.transactions, self.uncles) +} + +func (self *Header) String() string { + return fmt.Sprintf(` + ParentHash: %x + UncleHash: %x + Coinbase: %x + Root: %x + TxSha %x + ReceiptSha: %x + Bloom: %x + Difficulty: %v + Number: %v + GasLimit: %v + GasUsed: %v + Time: %v + Extra: %v + Nonce: %x +`, self.ParentHash, self.UncleHash, self.Coinbase, self.Root, self.TxHash, self.ReceiptHash, self.Bloom, self.Difficulty, self.Number, self.GasLimit, self.GasUsed, self.Time, self.Extra, self.Nonce) } type Blocks []*Block -func (self Blocks) AsSet() ethutil.UniqueSet { - set := make(ethutil.UniqueSet) - for _, block := range self { - set.Insert(block.Hash()) - } - - return set -} - type BlockBy func(b1, b2 *Block) bool func (self BlockBy) Sort(blocks Blocks) { @@ -65,352 +257,4 @@ func (self blockSorter) Swap(i, j int) { } func (self blockSorter) Less(i, j int) bool { return self.by(self.blocks[i], self.blocks[j]) } -func Number(b1, b2 *Block) bool { return b1.Number.Cmp(b2.Number) < 0 } - -type Block struct { - // Hash to the previous block - PrevHash ethutil.Bytes - // Uncles of this block - Uncles Blocks - UncleSha []byte - // The coin base address - Coinbase []byte - // Block Trie state - //state *ethutil.Trie - state *state.StateDB - // Difficulty for the current block - Difficulty *big.Int - // Creation time - Time int64 - // The block number - Number *big.Int - // Gas limit - GasLimit *big.Int - // Gas used - GasUsed *big.Int - // Extra data - Extra string - // Block Nonce for verification - Nonce ethutil.Bytes - // List of transactions and/or contracts - transactions Transactions - receipts Receipts - TxSha, ReceiptSha []byte - LogsBloom []byte - - Reward *big.Int -} - -func NewBlockFromBytes(raw []byte) *Block { - block := &Block{} - block.RlpDecode(raw) - - return block -} - -// New block takes a raw encoded string -func NewBlockFromRlpValue(rlpValue *ethutil.Value) *Block { - block := &Block{} - block.RlpValueDecode(rlpValue) - - return block -} - -func CreateBlock(root interface{}, - prevHash []byte, - base []byte, - Difficulty *big.Int, - Nonce []byte, - extra string) *Block { - - block := &Block{ - PrevHash: prevHash, - Coinbase: base, - Difficulty: Difficulty, - Nonce: Nonce, - Time: time.Now().Unix(), - Extra: extra, - UncleSha: nil, - GasUsed: new(big.Int), - GasLimit: new(big.Int), - } - block.SetUncles([]*Block{}) - - block.state = state.New(trie.New(ethutil.Config.Db, root)) - - return block -} - -// Returns a hash of the block -func (block *Block) Hash() ethutil.Bytes { - return crypto.Sha3(ethutil.NewValue(block.header()).Encode()) - //return crypto.Sha3(block.Value().Encode()) -} - -func (block *Block) HashNoNonce() []byte { - return crypto.Sha3(ethutil.Encode(block.miningHeader())) -} - -func (block *Block) State() *state.StateDB { - return block.state -} - -func (block *Block) Transactions() Transactions { - return block.transactions -} - -func (block *Block) CalcGasLimit(parent *Block) *big.Int { - if block.Number.Cmp(big.NewInt(0)) == 0 { - return ethutil.BigPow(10, 6) - } - - // ((1024-1) * parent.gasLimit + (gasUsed * 6 / 5)) / 1024 - - previous := new(big.Int).Mul(big.NewInt(1024-1), parent.GasLimit) - current := new(big.Rat).Mul(new(big.Rat).SetInt(parent.GasUsed), big.NewRat(6, 5)) - curInt := new(big.Int).Div(current.Num(), current.Denom()) - - result := new(big.Int).Add(previous, curInt) - result.Div(result, big.NewInt(1024)) - - min := big.NewInt(125000) - - return ethutil.BigMax(min, result) -} - -func (block *Block) BlockInfo() BlockInfo { - bi := BlockInfo{} - data, _ := ethutil.Config.Db.Get(append(block.Hash(), []byte("Info")...)) - bi.RlpDecode(data) - - return bi -} - -func (self *Block) GetTransaction(hash []byte) *Transaction { - for _, tx := range self.transactions { - if bytes.Compare(tx.Hash(), hash) == 0 { - return tx - } - } - - return nil -} - -// Sync the block's state and contract respectively -func (block *Block) Sync() { - block.state.Sync() -} - -func (block *Block) Undo() { - // Sync the block state itself - block.state.Reset() -} - -/////// Block Encoding -func (block *Block) rlpReceipts() interface{} { - // Marshal the transactions of this block - encR := make([]interface{}, len(block.receipts)) - for i, r := range block.receipts { - // Cast it to a string (safe) - encR[i] = r.RlpData() - } - - return encR -} - -func (block *Block) rlpUncles() interface{} { - // Marshal the transactions of this block - uncles := make([]interface{}, len(block.Uncles)) - for i, uncle := range block.Uncles { - // Cast it to a string (safe) - uncles[i] = uncle.header() - } - - return uncles -} - -func (block *Block) SetUncles(uncles []*Block) { - block.Uncles = uncles - block.UncleSha = crypto.Sha3(ethutil.Encode(block.rlpUncles())) -} - -func (self *Block) SetReceipts(receipts Receipts) { - self.receipts = receipts - self.ReceiptSha = DeriveSha(receipts) - self.LogsBloom = CreateBloom(receipts) -} - -func (self *Block) SetTransactions(txs Transactions) { - self.transactions = txs - self.TxSha = DeriveSha(txs) -} - -func (block *Block) Value() *ethutil.Value { - return ethutil.NewValue([]interface{}{block.header(), block.transactions, block.rlpUncles()}) -} - -func (block *Block) RlpEncode() []byte { - // Encode a slice interface which contains the header and the list of - // transactions. - return block.Value().Encode() -} - -func (block *Block) RlpDecode(data []byte) { - rlpValue := ethutil.NewValueFromBytes(data) - block.RlpValueDecode(rlpValue) -} - -func (block *Block) RlpValueDecode(decoder *ethutil.Value) { - block.setHeader(decoder.Get(0)) - - // Tx list might be empty if this is an uncle. Uncles only have their - // header set. - if decoder.Get(1).IsNil() == false { // Yes explicitness - //receipts := decoder.Get(1) - //block.receipts = make([]*Receipt, receipts.Len()) - txs := decoder.Get(1) - block.transactions = make(Transactions, txs.Len()) - for i := 0; i < txs.Len(); i++ { - block.transactions[i] = NewTransactionFromValue(txs.Get(i)) - //receipt := NewRecieptFromValue(receipts.Get(i)) - //block.transactions[i] = receipt.Tx - //block.receipts[i] = receipt - } - - } - - if decoder.Get(2).IsNil() == false { // Yes explicitness - uncles := decoder.Get(2) - block.Uncles = make([]*Block, uncles.Len()) - for i := 0; i < uncles.Len(); i++ { - block.Uncles[i] = NewUncleBlockFromValue(uncles.Get(i)) - } - } - -} - -func (self *Block) setHeader(header *ethutil.Value) { - self.PrevHash = header.Get(0).Bytes() - self.UncleSha = header.Get(1).Bytes() - self.Coinbase = header.Get(2).Bytes() - self.state = state.New(trie.New(ethutil.Config.Db, header.Get(3).Val)) - self.TxSha = header.Get(4).Bytes() - self.ReceiptSha = header.Get(5).Bytes() - self.LogsBloom = header.Get(6).Bytes() - self.Difficulty = header.Get(7).BigInt() - self.Number = header.Get(8).BigInt() - self.GasLimit = header.Get(9).BigInt() - self.GasUsed = header.Get(10).BigInt() - self.Time = int64(header.Get(11).BigInt().Uint64()) - self.Extra = header.Get(12).Str() - self.Nonce = header.Get(13).Bytes() -} - -func NewUncleBlockFromValue(header *ethutil.Value) *Block { - block := &Block{} - block.setHeader(header) - - return block -} - -func (block *Block) Trie() *trie.Trie { - return block.state.Trie -} - -func (block *Block) Root() interface{} { - return block.state.Root() -} - -func (block *Block) Diff() *big.Int { - return block.Difficulty -} - -func (self *Block) Receipts() []*Receipt { - return self.receipts -} - -func (block *Block) miningHeader() []interface{} { - return []interface{}{ - // Sha of the previous block - block.PrevHash, - // Sha of uncles - block.UncleSha, - // Coinbase address - block.Coinbase, - // root state - block.Root(), - // tx root - block.TxSha, - // Sha of tx - block.ReceiptSha, - // Bloom - block.LogsBloom, - // Current block Difficulty - block.Difficulty, - // The block number - block.Number, - // Block upper gas bound - block.GasLimit, - // Block gas used - block.GasUsed, - // Time the block was found? - block.Time, - // Extra data - block.Extra, - } -} - -func (block *Block) header() []interface{} { - return append(block.miningHeader(), block.Nonce) -} - -func (block *Block) String() string { - return fmt.Sprintf(` - BLOCK(%x): Size: %v - PrevHash: %x - UncleSha: %x - Coinbase: %x - Root: %x - TxSha %x - ReceiptSha: %x - Bloom: %x - Difficulty: %v - Number: %v - MaxLimit: %v - GasUsed: %v - Time: %v - Extra: %v - Nonce: %x - NumTx: %v -`, - block.Hash(), - block.Size(), - block.PrevHash, - block.UncleSha, - block.Coinbase, - block.Root(), - block.TxSha, - block.ReceiptSha, - block.LogsBloom, - block.Difficulty, - block.Number, - block.GasLimit, - block.GasUsed, - block.Time, - block.Extra, - block.Nonce, - len(block.transactions), - ) -} - -func (self *Block) Size() ethutil.StorageSize { - return ethutil.StorageSize(len(self.RlpEncode())) -} - -// Implement RlpEncodable -func (self *Block) RlpData() interface{} { - return []interface{}{self.header(), self.transactions, self.rlpUncles()} -} - -// Implement pow.Block -func (self *Block) N() []byte { return self.Nonce } +func Number(b1, b2 *Block) bool { return b1.Header().Number.Cmp(b2.Header().Number) < 0 } diff --git a/types/ethereum.go b/core/types/block_test.go similarity index 100% rename from types/ethereum.go rename to core/types/block_test.go diff --git a/core/types/derive_sha.go b/core/types/derive_sha.go index 1897ff198f..b2c4422103 100644 --- a/core/types/derive_sha.go +++ b/core/types/derive_sha.go @@ -1,6 +1,7 @@ package types import ( + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/trie" ) @@ -11,10 +12,11 @@ type DerivableList interface { } func DeriveSha(list DerivableList) []byte { - trie := trie.New(ethutil.Config.Db, "") + db, _ := ethdb.NewMemDatabase() + trie := trie.New(nil, db) for i := 0; i < list.Len(); i++ { - trie.Update(string(ethutil.NewValue(i).Encode()), string(list.GetRlp(i))) + trie.Update(ethutil.Encode(i), list.GetRlp(i)) } - return trie.GetRoot() + return trie.Root() } diff --git a/core/types/transaction.go b/core/types/transaction.go index 95a256a763..83d76648fd 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -1,11 +1,14 @@ package types import ( + "bytes" + "crypto/ecdsa" "fmt" "math/big" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/rlp" "github.com/obscuren/secp256k1-go" ) @@ -14,22 +17,22 @@ func IsContractAddr(addr []byte) bool { } type Transaction struct { - nonce uint64 - recipient []byte - value *big.Int - gas *big.Int - gasPrice *big.Int - data []byte - v byte - r, s []byte + AccountNonce uint64 + Price *big.Int + GasLimit *big.Int + Recipient []byte + Amount *big.Int + Payload []byte + V uint64 + R, S []byte } -func NewContractCreationTx(value, gas, gasPrice *big.Int, script []byte) *Transaction { - return &Transaction{recipient: nil, value: value, gas: gas, gasPrice: gasPrice, data: script} +func NewContractCreationTx(Amount, gasAmount, price *big.Int, data []byte) *Transaction { + return NewTransactionMessage(nil, Amount, gasAmount, price, data) } -func NewTransactionMessage(to []byte, value, gas, gasPrice *big.Int, data []byte) *Transaction { - return &Transaction{recipient: to, value: value, gasPrice: gasPrice, gas: gas, data: data} +func NewTransactionMessage(to []byte, Amount, gasAmount, price *big.Int, data []byte) *Transaction { + return &Transaction{Recipient: to, Amount: Amount, Price: price, GasLimit: gasAmount, Payload: data} } func NewTransactionFromBytes(data []byte) *Transaction { @@ -39,7 +42,7 @@ func NewTransactionFromBytes(data []byte) *Transaction { return tx } -func NewTransactionFromValue(val *ethutil.Value) *Transaction { +func NewTransactionFromAmount(val *ethutil.Value) *Transaction { tx := &Transaction{} tx.RlpValueDecode(val) @@ -47,33 +50,33 @@ func NewTransactionFromValue(val *ethutil.Value) *Transaction { } func (tx *Transaction) Hash() []byte { - data := []interface{}{tx.Nonce, tx.gasPrice, tx.gas, tx.recipient, tx.Value, tx.Data} + data := []interface{}{tx.AccountNonce, tx.Price, tx.GasLimit, tx.Recipient, tx.Amount, tx.Payload} - return crypto.Sha3(ethutil.NewValue(data).Encode()) + return crypto.Sha3(ethutil.Encode(data)) } func (self *Transaction) Data() []byte { - return self.data + return self.Payload } func (self *Transaction) Gas() *big.Int { - return self.gas + return self.GasLimit } func (self *Transaction) GasPrice() *big.Int { - return self.gasPrice + return self.Price } func (self *Transaction) Value() *big.Int { - return self.value + return self.Amount } func (self *Transaction) Nonce() uint64 { - return self.nonce + return self.AccountNonce } -func (self *Transaction) SetNonce(nonce uint64) { - self.nonce = nonce +func (self *Transaction) SetNonce(AccountNonce uint64) { + self.AccountNonce = AccountNonce } func (self *Transaction) From() []byte { @@ -81,13 +84,13 @@ func (self *Transaction) From() []byte { } func (self *Transaction) To() []byte { - return self.recipient + return self.Recipient } func (tx *Transaction) Curve() (v byte, r []byte, s []byte) { - v = tx.v - r = ethutil.LeftPadBytes(tx.r, 32) - s = ethutil.LeftPadBytes(tx.s, 32) + v = byte(tx.V) + r = ethutil.LeftPadBytes(tx.R, 32) + s = ethutil.LeftPadBytes(tx.S, 32) return } @@ -108,8 +111,8 @@ func (tx *Transaction) PublicKey() []byte { sig := append(r, s...) sig = append(sig, v-27) - pubkey := crypto.Ecrecover(append(hash, sig...)) - //pubkey, _ := secp256k1.RecoverPubkey(hash, sig) + //pubkey := crypto.Ecrecover(append(hash, sig...)) + pubkey, _ := secp256k1.RecoverPubkey(hash, sig) return pubkey } @@ -130,44 +133,41 @@ func (tx *Transaction) Sign(privk []byte) error { sig := tx.Signature(privk) - tx.r = sig[:32] - tx.s = sig[32:64] - tx.v = sig[64] + 27 + tx.R = sig[:32] + tx.S = sig[32:64] + tx.V = uint64(sig[64] + 27) return nil } -func (tx *Transaction) RlpData() interface{} { - data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.recipient, tx.Value, tx.Data} - - // TODO Remove prefixing zero's - - return append(data, tx.v, new(big.Int).SetBytes(tx.r).Bytes(), new(big.Int).SetBytes(tx.s).Bytes()) +func (tx *Transaction) SignECDSA(key *ecdsa.PrivateKey) error { + return tx.Sign(crypto.FromECDSA(key)) } -func (tx *Transaction) RlpValue() *ethutil.Value { - return ethutil.NewValue(tx.RlpData()) +func (tx *Transaction) RlpData() interface{} { + data := []interface{}{tx.AccountNonce, tx.Price, tx.GasLimit, tx.Recipient, tx.Amount, tx.Payload} + + return append(data, tx.V, new(big.Int).SetBytes(tx.R).Bytes(), new(big.Int).SetBytes(tx.S).Bytes()) } func (tx *Transaction) RlpEncode() []byte { - return tx.RlpValue().Encode() + return ethutil.Encode(tx) } func (tx *Transaction) RlpDecode(data []byte) { - tx.RlpValueDecode(ethutil.NewValueFromBytes(data)) + rlp.Decode(bytes.NewReader(data), tx) } func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) { - tx.nonce = decoder.Get(0).Uint() - tx.gasPrice = decoder.Get(1).BigInt() - tx.gas = decoder.Get(2).BigInt() - tx.recipient = decoder.Get(3).Bytes() - tx.value = decoder.Get(4).BigInt() - tx.data = decoder.Get(5).Bytes() - tx.v = byte(decoder.Get(6).Uint()) - - tx.r = decoder.Get(7).Bytes() - tx.s = decoder.Get(8).Bytes() + tx.AccountNonce = decoder.Get(0).Uint() + tx.Price = decoder.Get(1).BigInt() + tx.GasLimit = decoder.Get(2).BigInt() + tx.Recipient = decoder.Get(3).Bytes() + tx.Amount = decoder.Get(4).BigInt() + tx.Payload = decoder.Get(5).Bytes() + tx.V = decoder.Get(6).Uint() + tx.R = decoder.Get(7).Bytes() + tx.S = decoder.Get(8).Bytes() } func (tx *Transaction) String() string { @@ -178,25 +178,28 @@ func (tx *Transaction) String() string { To: %x Nonce: %v GasPrice: %v - Gas: %v + GasLimit %v Value: %v Data: 0x%x V: 0x%x R: 0x%x S: 0x%x - `, + Hex: %x +`, tx.Hash(), - len(tx.recipient) == 0, + len(tx.Recipient) == 0, tx.From(), - tx.recipient, - tx.nonce, - tx.gasPrice, - tx.gas, - tx.Value, - tx.Data, - tx.v, - tx.r, - tx.s) + tx.To(), + tx.AccountNonce, + tx.Price, + tx.GasLimit, + tx.Amount, + tx.Payload, + tx.V, + tx.R, + tx.S, + ethutil.Encode(tx), + ) } // Transaction slice type for basic sorting @@ -219,5 +222,5 @@ func (s Transactions) GetRlp(i int) []byte { return ethutil.Rlp(s[i]) } type TxByNonce struct{ Transactions } func (s TxByNonce) Less(i, j int) bool { - return s.Transactions[i].nonce < s.Transactions[j].nonce + return s.Transactions[i].AccountNonce < s.Transactions[j].AccountNonce } diff --git a/core/vm_env.go b/core/vm_env.go index ad63ecf9c6..624a633334 100644 --- a/core/vm_env.go +++ b/core/vm_env.go @@ -13,10 +13,12 @@ type VMEnv struct { block *types.Block msg Message depth int + chain *ChainManager } -func NewEnv(state *state.StateDB, msg Message, block *types.Block) *VMEnv { +func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, block *types.Block) *VMEnv { return &VMEnv{ + chain: chain, state: state, block: block, msg: msg, @@ -24,17 +26,22 @@ func NewEnv(state *state.StateDB, msg Message, block *types.Block) *VMEnv { } func (self *VMEnv) Origin() []byte { return self.msg.From() } -func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number } -func (self *VMEnv) PrevHash() []byte { return self.block.PrevHash } -func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase } -func (self *VMEnv) Time() int64 { return self.block.Time } -func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty } -func (self *VMEnv) BlockHash() []byte { return self.block.Hash() } +func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() } +func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() } +func (self *VMEnv) Time() int64 { return self.block.Time() } +func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() } +func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() } func (self *VMEnv) Value() *big.Int { return self.msg.Value() } func (self *VMEnv) State() *state.StateDB { return self.state } -func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit } func (self *VMEnv) Depth() int { return self.depth } func (self *VMEnv) SetDepth(i int) { self.depth = i } +func (self *VMEnv) GetHash(n uint64) []byte { + if block := self.chain.GetBlockByNumber(n); block != nil { + return block.Hash() + } + + return nil +} func (self *VMEnv) AddLog(log state.Log) { self.state.AddLog(log) } @@ -46,16 +53,16 @@ func (self *VMEnv) vm(addr, data []byte, gas, price, value *big.Int) *Execution return NewExecution(self, addr, data, gas, price, value) } -func (self *VMEnv) Call(me vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { +func (self *VMEnv) Call(me vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { exe := self.vm(addr, data, gas, price, value) return exe.Call(addr, me) } -func (self *VMEnv) CallCode(me vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { +func (self *VMEnv) CallCode(me vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { exe := self.vm(me.Address(), data, gas, price, value) return exe.Call(addr, me) } -func (self *VMEnv) Create(me vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ClosureRef) { +func (self *VMEnv) Create(me vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { exe := self.vm(addr, data, gas, price, value) return exe.Create(me) } diff --git a/eth/backend.go b/eth/backend.go index 0aad6a5141..ad04863092 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -1,11 +1,13 @@ package eth import ( + "fmt" "net" "sync" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" ethlogger "github.com/ethereum/go-ethereum/logger" @@ -16,9 +18,30 @@ import ( ) const ( - seedNodeAddress = "poc-7.ethdev.com:30300" + seedNodeAddress = "poc-8.ethdev.com:30303" ) +type Config struct { + Name string + Version string + Identifier string + KeyStore string + DataDir string + LogFile string + LogLevel int + KeyRing string + + MaxPeers int + Port string + NATType string + PMPGateway string + + Shh bool + Dial bool + + KeyManager *crypto.KeyManager +} + var logger = ethlogger.NewLogger("SERV") type Ethereum struct { @@ -32,13 +55,13 @@ type Ethereum struct { //*** SERVICES *** // State manager for processing new blocks and managing the over all states - blockManager *core.BlockManager - txPool *core.TxPool - chainManager *core.ChainManager - blockPool *BlockPool - whisper *whisper.Whisper + blockProcessor *core.BlockProcessor + txPool *core.TxPool + chainManager *core.ChainManager + blockPool *BlockPool + whisper *whisper.Whisper - server *p2p.Server + net *p2p.Server eventMux *event.TypeMux txSub event.Subscription blockSub event.Subscription @@ -47,6 +70,7 @@ type Ethereum struct { keyManager *crypto.KeyManager clientIdentity p2p.ClientIdentity + logger ethlogger.LogSystem synclock sync.Mutex syncGroup sync.WaitGroup @@ -54,47 +78,82 @@ type Ethereum struct { Mining bool } -func New(db ethutil.Database, identity p2p.ClientIdentity, keyManager *crypto.KeyManager, nat p2p.NAT, port string, maxPeers int) (*Ethereum, error) { +func New(config *Config) (*Ethereum, error) { + // Boostrap database + logger := ethlogger.New(config.DataDir, config.LogFile, config.LogLevel) + db, err := ethdb.NewLDBDatabase("blockchain") + if err != nil { + return nil, err + } + + // Perform database sanity checks + d, _ := db.Get([]byte("ProtocolVersion")) + protov := ethutil.NewValue(d).Uint() + if protov != ProtocolVersion && protov != 0 { + return nil, fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, ProtocolVersion, ethutil.Config.ExecPath+"/database") + } + + // Create new keymanager + var keyManager *crypto.KeyManager + switch config.KeyStore { + case "db": + keyManager = crypto.NewDBKeyManager(db) + case "file": + keyManager = crypto.NewFileKeyManager(config.DataDir) + default: + return nil, fmt.Errorf("unknown keystore type: %s", config.KeyStore) + } + // Initialise the keyring + keyManager.Init(config.KeyRing, 0, false) + + // Create a new client id for this instance. This will help identifying the node on the network + clientId := p2p.NewSimpleClientIdentity(config.Name, config.Version, config.Identifier, keyManager.PublicKey()) saveProtocolVersion(db) - ethutil.Config.Db = db + //ethutil.Config.Db = db eth := &Ethereum{ shutdownChan: make(chan bool), quit: make(chan bool), db: db, keyManager: keyManager, - clientIdentity: identity, + clientIdentity: clientId, blacklist: p2p.NewBlacklist(), eventMux: &event.TypeMux{}, + logger: logger, } - eth.chainManager = core.NewChainManager(eth.EventMux()) - eth.txPool = core.NewTxPool(eth.chainManager, eth.EventMux()) - eth.blockManager = core.NewBlockManager(eth.txPool, eth.chainManager, eth.EventMux()) - eth.chainManager.SetProcessor(eth.blockManager) + eth.chainManager = core.NewChainManager(db, eth.EventMux()) + eth.txPool = core.NewTxPool(eth.EventMux()) + eth.blockProcessor = core.NewBlockProcessor(db, eth.txPool, eth.chainManager, eth.EventMux()) + eth.chainManager.SetProcessor(eth.blockProcessor) eth.whisper = whisper.New() hasBlock := eth.chainManager.HasBlock insertChain := eth.chainManager.InsertChain eth.blockPool = NewBlockPool(hasBlock, insertChain, ezp.Verify) - // Start services - eth.txPool.Start() - ethProto := EthProtocol(eth.txPool, eth.chainManager, eth.blockPool) protocols := []p2p.Protocol{ethProto, eth.whisper.Protocol()} - server := &p2p.Server{ - Identity: identity, - MaxPeers: maxPeers, - Protocols: protocols, - ListenAddr: ":" + port, - Blacklist: eth.blacklist, - NAT: nat, + nat, err := p2p.ParseNAT(config.NATType, config.PMPGateway) + if err != nil { + return nil, err + } + fmt.Println(nat) + + eth.net = &p2p.Server{ + Identity: clientId, + MaxPeers: config.MaxPeers, + Protocols: protocols, + Blacklist: eth.blacklist, + NAT: p2p.UPNP(), + NoDial: !config.Dial, } - eth.server = server + if len(config.Port) > 0 { + eth.net.ListenAddr = ":" + config.Port + } return eth, nil } @@ -103,6 +162,10 @@ func (s *Ethereum) KeyManager() *crypto.KeyManager { return s.keyManager } +func (s *Ethereum) Logger() ethlogger.LogSystem { + return s.logger +} + func (s *Ethereum) ClientIdentity() p2p.ClientIdentity { return s.clientIdentity } @@ -111,8 +174,8 @@ func (s *Ethereum) ChainManager() *core.ChainManager { return s.chainManager } -func (s *Ethereum) BlockManager() *core.BlockManager { - return s.blockManager +func (s *Ethereum) BlockProcessor() *core.BlockProcessor { + return s.blockProcessor } func (s *Ethereum) TxPool() *core.TxPool { @@ -144,25 +207,31 @@ func (s *Ethereum) IsListening() bool { } func (s *Ethereum) PeerCount() int { - return s.server.PeerCount() + return s.net.PeerCount() } func (s *Ethereum) Peers() []*p2p.Peer { - return s.server.Peers() + return s.net.Peers() } func (s *Ethereum) MaxPeers() int { - return s.server.MaxPeers + return s.net.MaxPeers } // Start the ethereum func (s *Ethereum) Start(seed bool) error { - err := s.server.Start() + err := s.net.Start() if err != nil { return err } + + // Start services + s.txPool.Start() s.blockPool.Start() - s.whisper.Start() + + if s.whisper != nil { + s.whisper.Start() + } // broadcast transactions s.txSub = s.eventMux.Subscribe(core.TxPreEvent{}) @@ -191,7 +260,7 @@ func (self *Ethereum) SuggestPeer(addr string) error { return err } - self.server.SuggestPeer(netaddr.IP, netaddr.Port, nil) + self.net.SuggestPeer(netaddr.IP, netaddr.Port, nil) return nil } @@ -210,7 +279,9 @@ func (s *Ethereum) Stop() { s.txPool.Stop() s.eventMux.Stop() s.blockPool.Stop() - s.whisper.Stop() + if s.whisper != nil { + s.whisper.Stop() + } logger.Infoln("Server stopped") close(s.shutdownChan) @@ -227,15 +298,17 @@ func (self *Ethereum) txBroadcastLoop() { // automatically stops if unsubscribe for obj := range self.txSub.Chan() { event := obj.(core.TxPreEvent) - self.server.Broadcast("eth", TxMsg, []interface{}{event.Tx.RlpData()}) + self.net.Broadcast("eth", TxMsg, event.Tx.RlpData()) } } func (self *Ethereum) blockBroadcastLoop() { // automatically stops if unsubscribe - for obj := range self.txSub.Chan() { - event := obj.(core.NewMinedBlockEvent) - self.server.Broadcast("eth", NewBlockMsg, event.Block.Value().Val) + for obj := range self.blockSub.Chan() { + switch ev := obj.(type) { + case core.NewMinedBlockEvent: + self.net.Broadcast("eth", NewBlockMsg, ev.Block.RlpData(), ev.Block.Td) + } } } diff --git a/eth/block_pool.go b/eth/block_pool.go index 7cfbc63f86..b624d064a5 100644 --- a/eth/block_pool.go +++ b/eth/block_pool.go @@ -1,6 +1,8 @@ package eth import ( + "bytes" + "fmt" "math" "math/big" "math/rand" @@ -19,37 +21,45 @@ var poolLogger = ethlogger.NewLogger("Blockpool") const ( blockHashesBatchSize = 256 blockBatchSize = 64 - blocksRequestInterval = 10 // seconds + blocksRequestInterval = 500 // ms blocksRequestRepetition = 1 - blockHashesRequestInterval = 10 // seconds - blocksRequestMaxIdleRounds = 10 - cacheTimeout = 3 // minutes - blockTimeout = 5 // minutes + blockHashesRequestInterval = 500 // ms + blocksRequestMaxIdleRounds = 100 + blockHashesTimeout = 60 // seconds + blocksTimeout = 120 // seconds ) type poolNode struct { - lock sync.RWMutex - hash []byte - block *types.Block - child *poolNode - parent *poolNode - section *section - knownParent bool - peer string - source string - complete bool + lock sync.RWMutex + hash []byte + td *big.Int + block *types.Block + parent *poolNode + peer string + blockBy string +} + +type poolEntry struct { + node *poolNode + section *section + index int } type BlockPool struct { - lock sync.RWMutex - pool map[string]*poolNode + lock sync.RWMutex + chainLock sync.RWMutex + + pool map[string]*poolEntry peersLock sync.RWMutex peers map[string]*peerInfo peer *peerInfo quit chan bool + purgeC chan bool + flushC chan bool wg sync.WaitGroup + procWg sync.WaitGroup running bool // the minimal interface with blockchain @@ -61,17 +71,37 @@ type BlockPool struct { type peerInfo struct { lock sync.RWMutex - td *big.Int - currentBlock []byte - id string + td *big.Int + currentBlockHash []byte + currentBlock *types.Block + currentBlockC chan *types.Block + parentHash []byte + headSection *section + headSectionC chan *section + id string requestBlockHashes func([]byte) error requestBlocks func([][]byte) error peerError func(int, string, ...interface{}) sections map[string]*section - roots []*poolNode - quitC chan bool + + quitC chan bool +} + +// structure to store long range links on chain to skip along +type section struct { + lock sync.RWMutex + parent *section + child *section + top *poolNode + bottom *poolNode + nodes []*poolNode + controlC chan *peerInfo + suicideC chan bool + blockChainC chan bool + forkC chan chan bool + offC chan bool } func NewBlockPool(hasBlock func(hash []byte) bool, insertChain func(types.Blocks) error, verifyPoW func(pow.Block) bool, @@ -92,7 +122,9 @@ func (self *BlockPool) Start() { } self.running = true self.quit = make(chan bool) - self.pool = make(map[string]*poolNode) + self.flushC = make(chan bool) + self.pool = make(map[string]*poolEntry) + self.lock.Unlock() self.peersLock.Lock() @@ -110,69 +142,257 @@ func (self *BlockPool) Stop() { return } self.running = false + self.lock.Unlock() - poolLogger.Infoln("Stopping") + poolLogger.Infoln("Stopping...") close(self.quit) - self.lock.Lock() + //self.wg.Wait() + self.peersLock.Lock() self.peers = nil - self.pool = nil self.peer = nil - self.wg.Wait() - self.lock.Unlock() self.peersLock.Unlock() + + self.lock.Lock() + self.pool = nil + self.lock.Unlock() + + poolLogger.Infoln("Stopped") +} + +func (self *BlockPool) Purge() { + self.lock.Lock() + if !self.running { + self.lock.Unlock() + return + } + self.lock.Unlock() + + poolLogger.Infoln("Purging...") + + close(self.purgeC) + self.wg.Wait() + + self.purgeC = make(chan bool) + poolLogger.Infoln("Stopped") } +func (self *BlockPool) Wait(t time.Duration) { + self.lock.Lock() + if !self.running { + self.lock.Unlock() + return + } + self.lock.Unlock() + + poolLogger.Infoln("Waiting for processes to complete...") + close(self.flushC) + w := make(chan bool) + go func() { + self.procWg.Wait() + close(w) + }() + + select { + case <-w: + poolLogger.Infoln("Processes complete") + case <-time.After(t): + poolLogger.Warnf("Timeout") + } + self.flushC = make(chan bool) +} + // AddPeer is called by the eth protocol instance running on the peer after // the status message has been received with total difficulty and current block hash // AddPeer can only be used once, RemovePeer needs to be called when the peer disconnects -func (self *BlockPool) AddPeer(td *big.Int, currentBlock []byte, peerId string, requestBlockHashes func([]byte) error, requestBlocks func([][]byte) error, peerError func(int, string, ...interface{})) bool { +func (self *BlockPool) AddPeer(td *big.Int, currentBlockHash []byte, peerId string, requestBlockHashes func([]byte) error, requestBlocks func([][]byte) error, peerError func(int, string, ...interface{})) (best bool) { + self.peersLock.Lock() defer self.peersLock.Unlock() - if self.peers[peerId] != nil { - panic("peer already added") + peer, ok := self.peers[peerId] + if ok { + if bytes.Compare(peer.currentBlockHash, currentBlockHash) != 0 { + poolLogger.Debugf("Update peer %v with td %v and current block %s", peerId, td, name(currentBlockHash)) + peer.lock.Lock() + peer.td = td + peer.currentBlockHash = currentBlockHash + peer.currentBlock = nil + peer.parentHash = nil + peer.headSection = nil + peer.lock.Unlock() + } + } else { + peer = &peerInfo{ + td: td, + currentBlockHash: currentBlockHash, + id: peerId, //peer.Identity().Pubkey() + requestBlockHashes: requestBlockHashes, + requestBlocks: requestBlocks, + peerError: peerError, + sections: make(map[string]*section), + currentBlockC: make(chan *types.Block), + headSectionC: make(chan *section), + } + self.peers[peerId] = peer + poolLogger.Debugf("add new peer %v with td %v and current block %x", peerId, td, currentBlockHash[:4]) } - peer := &peerInfo{ - td: td, - currentBlock: currentBlock, - id: peerId, //peer.Identity().Pubkey() - requestBlockHashes: requestBlockHashes, - requestBlocks: requestBlocks, - peerError: peerError, + // check peer current head + if self.hasBlock(currentBlockHash) { + // peer not ahead + return false } - self.peers[peerId] = peer - poolLogger.Debugf("add new peer %v with td %v", peerId, td) - currentTD := ethutil.Big0 - if self.peer != nil { - currentTD = self.peer.td + + if self.peer == peer { + // new block update + // peer is already active best peer, request hashes + poolLogger.Debugf("[%s] already the best peer. Request new head section info from %s", peerId, name(currentBlockHash)) + peer.headSectionC <- nil + best = true + } else { + currentTD := ethutil.Big0 + if self.peer != nil { + currentTD = self.peer.td + } + if td.Cmp(currentTD) > 0 { + poolLogger.Debugf("peer %v promoted best peer", peerId) + self.switchPeer(self.peer, peer) + self.peer = peer + best = true + } } - if td.Cmp(currentTD) > 0 { - self.peer.stop(peer) - peer.start(self.peer) - poolLogger.Debugf("peer %v promoted to best peer", peerId) - self.peer = peer - return true - } - return false + return +} + +func (self *BlockPool) requestHeadSection(peer *peerInfo) { + self.wg.Add(1) + self.procWg.Add(1) + poolLogger.Debugf("[%s] head section at [%s] requesting info", peer.id, name(peer.currentBlockHash)) + + go func() { + var idle bool + peer.lock.RLock() + quitC := peer.quitC + currentBlockHash := peer.currentBlockHash + peer.lock.RUnlock() + blockHashesRequestTimer := time.NewTimer(0) + blocksRequestTimer := time.NewTimer(0) + suicide := time.NewTimer(blockHashesTimeout * time.Second) + blockHashesRequestTimer.Stop() + defer blockHashesRequestTimer.Stop() + defer blocksRequestTimer.Stop() + + entry := self.get(currentBlockHash) + if entry != nil { + entry.node.lock.RLock() + currentBlock := entry.node.block + entry.node.lock.RUnlock() + if currentBlock != nil { + peer.lock.Lock() + peer.currentBlock = currentBlock + peer.parentHash = currentBlock.ParentHash() + poolLogger.Debugf("[%s] head block [%s] found", peer.id, name(currentBlockHash)) + peer.lock.Unlock() + blockHashesRequestTimer.Reset(0) + blocksRequestTimer.Stop() + } + } + + LOOP: + for { + + select { + case <-self.quit: + break LOOP + + case <-quitC: + poolLogger.Debugf("[%s] head section at [%s] incomplete - quit request loop", peer.id, name(currentBlockHash)) + break LOOP + + case headSection := <-peer.headSectionC: + peer.lock.Lock() + peer.headSection = headSection + if headSection == nil { + oldBlockHash := currentBlockHash + currentBlockHash = peer.currentBlockHash + poolLogger.Debugf("[%s] head section changed [%s] -> [%s]", peer.id, name(oldBlockHash), name(currentBlockHash)) + if idle { + idle = false + suicide.Reset(blockHashesTimeout * time.Second) + self.procWg.Add(1) + } + blocksRequestTimer.Reset(blocksRequestInterval * time.Millisecond) + } else { + poolLogger.DebugDetailf("[%s] head section at [%s] created", peer.id, name(currentBlockHash)) + if !idle { + idle = true + suicide.Stop() + self.procWg.Done() + } + } + peer.lock.Unlock() + blockHashesRequestTimer.Stop() + + case <-blockHashesRequestTimer.C: + poolLogger.DebugDetailf("[%s] head section at [%s] not found, requesting block hashes", peer.id, name(currentBlockHash)) + peer.requestBlockHashes(currentBlockHash) + blockHashesRequestTimer.Reset(blockHashesRequestInterval * time.Millisecond) + + case currentBlock := <-peer.currentBlockC: + peer.lock.Lock() + peer.currentBlock = currentBlock + peer.parentHash = currentBlock.ParentHash() + poolLogger.DebugDetailf("[%s] head block [%s] found", peer.id, name(currentBlockHash)) + peer.lock.Unlock() + if self.hasBlock(currentBlock.ParentHash()) { + if err := self.insertChain(types.Blocks([]*types.Block{currentBlock})); err != nil { + peer.peerError(ErrInvalidBlock, "%v", err) + } + if !idle { + idle = true + suicide.Stop() + self.procWg.Done() + } + } else { + blockHashesRequestTimer.Reset(0) + } + blocksRequestTimer.Stop() + + case <-blocksRequestTimer.C: + peer.lock.RLock() + poolLogger.DebugDetailf("[%s] head block [%s] not found, requesting", peer.id, name(currentBlockHash)) + peer.requestBlocks([][]byte{peer.currentBlockHash}) + peer.lock.RUnlock() + blocksRequestTimer.Reset(blocksRequestInterval * time.Millisecond) + + case <-suicide.C: + peer.peerError(ErrInsufficientChainInfo, "peer failed to provide block hashes or head block for block hash %x", currentBlockHash) + break LOOP + } + } + self.wg.Done() + if !idle { + self.procWg.Done() + } + }() } // RemovePeer is called by the eth protocol when the peer disconnects func (self *BlockPool) RemovePeer(peerId string) { self.peersLock.Lock() defer self.peersLock.Unlock() - peer := self.peers[peerId] - if peer == nil { + peer, ok := self.peers[peerId] + if !ok { return } - self.peers[peerId] = nil - poolLogger.Debugf("remove peer %v", peerId[0:4]) + delete(self.peers, peerId) + poolLogger.Debugf("remove peer %v", peerId) // if current best peer is removed, need find a better one - if self.peer != nil && peerId == self.peer.id { + if self.peer == peer { var newPeer *peerInfo max := ethutil.Big0 // peer with the highest self-acclaimed TD is chosen @@ -182,13 +402,13 @@ func (self *BlockPool) RemovePeer(peerId string) { newPeer = info } } - self.peer.stop(peer) - peer.start(self.peer) if newPeer != nil { - poolLogger.Debugf("peer %v with td %v promoted to best peer", newPeer.id[0:4], newPeer.td) + poolLogger.Debugf("peer %v with td %v promoted to best peer", newPeer.id, newPeer.td) } else { - poolLogger.Warnln("no peers left") + poolLogger.Warnln("no peers") } + self.peer = newPeer + self.switchPeer(peer, newPeer) } } @@ -200,97 +420,180 @@ func (self *BlockPool) RemovePeer(peerId string) { // this function needs to run asynchronously for one peer since the message is discarded??? func (self *BlockPool) AddBlockHashes(next func() ([]byte, bool), peerId string) { - // check if this peer is the best + // register with peer manager loop + peer, best := self.getPeer(peerId) if !best { return } // peer is still the best - var child *poolNode - var depth int + var size, n int + var hash []byte + var ok, headSection bool + var sec, child, parent *section + var entry *poolEntry + var nodes []*poolNode + bestPeer := peer - // iterate using next (rlp stream lazy decoder) feeding hashesC - self.wg.Add(1) - go func() { - for { - select { - case <-self.quit: - return - case <-peer.quitC: - // if the peer is demoted, no more hashes taken - break - default: - hash, ok := next() - if !ok { - // message consumed chain skeleton built - break - } - // check if known block connecting the downloaded chain to our blockchain - if self.hasBlock(hash) { - poolLogger.Infof("known block (%x...)\n", hash[0:4]) - if child != nil { - child.Lock() - // mark child as absolute pool root with parent known to blockchain - child.knownParent = true - child.Unlock() - } - break - } - // - var parent *poolNode - // look up node in pool - parent = self.get(hash) - if parent != nil { - // reached a known chain in the pool - // request blocks on the newly added part of the chain - if child != nil { - self.link(parent, child) + hash, ok = next() + peer.lock.Lock() + if bytes.Compare(peer.parentHash, hash) == 0 { + if self.hasBlock(peer.currentBlockHash) { + return + } + poolLogger.Debugf("adding hashes at chain head for best peer %s starting from [%s]", peerId, name(peer.currentBlockHash)) + headSection = true - // activate the current chain - self.activateChain(parent, peer, true) - poolLogger.Debugf("potential chain of %v blocks added, reached blockpool, activate chain", depth) - break - } - // if this is the first hash, we expect to find it - parent.RLock() - grandParent := parent.parent - parent.RUnlock() - if grandParent != nil { - // activate the current chain - self.activateChain(parent, peer, true) - poolLogger.Debugf("block hash found, activate chain") - break - } - // the first node is the root of a chain in the pool, rejoice and continue - } - // if node does not exist, create it and index in the pool - section := §ion{} - if child == nil { - section.top = parent - } - parent = &poolNode{ - hash: hash, - child: child, - section: section, - peer: peerId, - } - self.set(hash, parent) - poolLogger.Debugf("create potential block for %x...", hash[0:4]) - - depth++ - child = parent + if entry := self.get(peer.currentBlockHash); entry == nil { + node := &poolNode{ + hash: peer.currentBlockHash, + block: peer.currentBlock, + peer: peerId, + blockBy: peerId, } + if size == 0 { + sec = newSection() + } + nodes = append(nodes, node) + size++ + n++ + } else { + child = entry.section } - if child != nil { - poolLogger.Debugf("chain of %v hashes added", depth) - // start a processSection on the last node, but switch off asking - // hashes and blocks until next peer confirms this chain - section := self.processSection(child) - peer.addSection(child.hash, section) - section.start() + } else { + poolLogger.Debugf("adding hashes for best peer %s starting from [%s]", peerId, name(hash)) + } + quitC := peer.quitC + peer.lock.Unlock() + +LOOP: + // iterate using next (rlp stream lazy decoder) feeding hashesC + for ; ok; hash, ok = next() { + n++ + select { + case <-self.quit: + return + case <-quitC: + // if the peer is demoted, no more hashes taken + bestPeer = nil + break LOOP + default: } - }() + if self.hasBlock(hash) { + // check if known block connecting the downloaded chain to our blockchain + poolLogger.DebugDetailf("[%s] known block", name(hash)) + // mark child as absolute pool root with parent known to blockchain + if sec != nil { + self.connectToBlockChain(sec) + } else { + if child != nil { + self.connectToBlockChain(child) + } + } + break LOOP + } + // look up node in pool + entry = self.get(hash) + if entry != nil { + // reached a known chain in the pool + if entry.node == entry.section.bottom && n == 1 { + // the first block hash received is an orphan in the pool, so rejoice and continue + poolLogger.DebugDetailf("[%s] connecting child section", sectionName(entry.section)) + child = entry.section + continue LOOP + } + poolLogger.DebugDetailf("[%s] reached blockpool chain", name(hash)) + parent = entry.section + break LOOP + } + // if node for block hash does not exist, create it and index in the pool + node := &poolNode{ + hash: hash, + peer: peerId, + } + if size == 0 { + sec = newSection() + } + nodes = append(nodes, node) + size++ + } //for + + self.chainLock.Lock() + + poolLogger.DebugDetailf("added %v hashes sent by %s", n, peerId) + + if parent != nil && entry != nil && entry.node != parent.top { + poolLogger.DebugDetailf("[%s] split section at fork", sectionName(parent)) + parent.controlC <- nil + waiter := make(chan bool) + parent.forkC <- waiter + chain := parent.nodes + parent.nodes = chain[entry.index:] + parent.top = parent.nodes[0] + orphan := newSection() + self.link(orphan, parent.child) + self.processSection(orphan, chain[0:entry.index]) + orphan.controlC <- nil + close(waiter) + } + + if size > 0 { + self.processSection(sec, nodes) + poolLogger.DebugDetailf("[%s]->[%s](%v)->[%s] new chain section", sectionName(parent), sectionName(sec), size, sectionName(child)) + self.link(parent, sec) + self.link(sec, child) + } else { + poolLogger.DebugDetailf("[%s]->[%s] connecting known sections", sectionName(parent), sectionName(child)) + self.link(parent, child) + } + + self.chainLock.Unlock() + + if parent != nil && bestPeer != nil { + self.activateChain(parent, peer) + poolLogger.Debugf("[%s] activate parent section [%s]", name(parent.top.hash), sectionName(parent)) + } + + if sec != nil { + peer.addSection(sec.top.hash, sec) + // request next section here once, only repeat if bottom block arrives, + // otherwise no way to check if it arrived + peer.requestBlockHashes(sec.bottom.hash) + sec.controlC <- bestPeer + poolLogger.Debugf("[%s] activate new section", sectionName(sec)) + } + + if headSection { + var headSec *section + switch { + case sec != nil: + headSec = sec + case child != nil: + headSec = child + default: + headSec = parent + } + peer.headSectionC <- headSec + } +} + +func name(hash []byte) (name string) { + if hash == nil { + name = "" + } else { + name = fmt.Sprintf("%x", hash[:4]) + } + return +} + +func sectionName(section *section) (name string) { + if section == nil { + name = "" + } else { + name = fmt.Sprintf("%x-%x", section.bottom.hash[:4], section.top.hash[:4]) + } + return } // AddBlock is the entry point for the eth protocol when blockmsg is received upon requests @@ -299,67 +602,125 @@ func (self *BlockPool) AddBlockHashes(next func() ([]byte, bool), peerId string) // only the first PoW-valid block for a hash is considered legit func (self *BlockPool) AddBlock(block *types.Block, peerId string) { hash := block.Hash() - node := self.get(hash) - node.RLock() - b := node.block - node.RUnlock() - if b != nil { + self.peersLock.Lock() + peer := self.peer + self.peersLock.Unlock() + + entry := self.get(hash) + if bytes.Compare(hash, peer.currentBlockHash) == 0 { + poolLogger.Debugf("add head block [%s] for peer %s", name(hash), peerId) + peer.currentBlockC <- block + } else { + if entry == nil { + poolLogger.Warnf("unrequested block [%s] by peer %s", name(hash), peerId) + self.peerError(peerId, ErrUnrequestedBlock, "%x", hash) + } + } + if entry == nil { return } - if node == nil && !self.hasBlock(hash) { - self.peerError(peerId, ErrUnrequestedBlock, "%x", hash) + + node := entry.node + node.lock.Lock() + defer node.lock.Unlock() + + // check if block already present + if node.block != nil { + poolLogger.DebugDetailf("block [%s] already sent by %s", name(hash), node.blockBy) return } - // validate block for PoW - if !self.verifyPoW(block) { - self.peerError(peerId, ErrInvalidPoW, "%x", hash) + + if self.hasBlock(hash) { + poolLogger.DebugDetailf("block [%s] already known", name(hash)) + } else { + + // validate block for PoW + if !self.verifyPoW(block) { + poolLogger.Warnf("invalid pow on block [%s] by peer %s", name(hash), peerId) + self.peerError(peerId, ErrInvalidPoW, "%x", hash) + return + } } - node.Lock() + poolLogger.Debugf("added block [%s] sent by peer %s", name(hash), peerId) node.block = block - node.source = peerId - node.Unlock() + node.blockBy = peerId + } -// iterates down a known poolchain and activates fetching processes -// on each chain section for the peer -// stops if the peer is demoted -// registers last section root as root for the peer (in case peer is promoted a second time, to remember) -func (self *BlockPool) activateChain(node *poolNode, peer *peerInfo, on bool) { - self.wg.Add(1) - go func() { - for { - node.sectionRLock() - bottom := node.section.bottom - if bottom == nil { // the chain section is being created or killed - break - } - // register this section with the peer - if peer != nil { - peer.addSection(bottom.hash, bottom.section) - if on { - bottom.section.start() - } else { - bottom.section.start() - } - } - if bottom.parent == nil { - node = bottom - break - } - // if peer demoted stop activation - select { - case <-peer.quitC: - break - default: - } +func (self *BlockPool) connectToBlockChain(section *section) { + select { + case <-section.offC: + self.addSectionToBlockChain(section) + case <-section.blockChainC: + default: + close(section.blockChainC) + } +} - node = bottom.parent - bottom.sectionRUnlock() +func (self *BlockPool) addSectionToBlockChain(section *section) (rest int, err error) { + + var blocks types.Blocks + var node *poolNode + var keys []string + rest = len(section.nodes) + for rest > 0 { + rest-- + node = section.nodes[rest] + node.lock.RLock() + block := node.block + node.lock.RUnlock() + if block == nil { + break } - // remember root for this peer - peer.addRoot(node) - self.wg.Done() - }() + keys = append(keys, string(node.hash)) + blocks = append(blocks, block) + } + + self.lock.Lock() + for _, key := range keys { + delete(self.pool, key) + } + self.lock.Unlock() + + poolLogger.Infof("insert %v blocks into blockchain", len(blocks)) + err = self.insertChain(blocks) + if err != nil { + // TODO: not clear which peer we need to address + // peerError should dispatch to peer if still connected and disconnect + self.peerError(node.blockBy, ErrInvalidBlock, "%v", err) + poolLogger.Warnf("invalid block %x", node.hash) + poolLogger.Warnf("penalise peers %v (hash), %v (block)", node.peer, node.blockBy) + // penalise peer in node.blockBy + // self.disconnect() + } + return +} + +func (self *BlockPool) activateChain(section *section, peer *peerInfo) { + poolLogger.DebugDetailf("[%s] activate known chain for peer %s", sectionName(section), peer.id) + i := 0 +LOOP: + for section != nil { + // register this section with the peer and quit if registered + poolLogger.DebugDetailf("[%s] register section with peer %s", sectionName(section), peer.id) + if peer.addSection(section.top.hash, section) == section { + return + } + poolLogger.DebugDetailf("[%s] activate section process", sectionName(section)) + select { + case section.controlC <- peer: + case <-section.offC: + } + i++ + section = self.getParent(section) + select { + case <-peer.quitC: + break LOOP + case <-self.quit: + break LOOP + default: + } + } } // main worker thread on each section in the poolchain @@ -370,261 +731,341 @@ func (self *BlockPool) activateChain(node *poolNode, peer *peerInfo, on bool) { // - when turned off (if peer disconnects and new peer connects with alternative chain), no blockrequests are made but absolute expiry timer is ticking // - when turned back on it recursively calls itself on the root of the next chain section // - when exits, signals to -func (self *BlockPool) processSection(node *poolNode) *section { - // absolute time after which sub-chain is killed if not complete (some blocks are missing) - suicideTimer := time.After(blockTimeout * time.Minute) - var blocksRequestTimer, blockHashesRequestTimer <-chan time.Time - var nodeC, missingC, processC chan *poolNode - controlC := make(chan bool) - resetC := make(chan bool) - var hashes [][]byte - var i, total, missing, lastMissing, depth int - var blockHashesRequests, blocksRequests int - var idle int - var init, alarm, done, same, running, once bool - orignode := node - hash := node.hash +func (self *BlockPool) processSection(sec *section, nodes []*poolNode) { - node.sectionLock() - defer node.sectionUnlock() - section := §ion{controlC: controlC, resetC: resetC} - node.section = section + for i, node := range nodes { + entry := &poolEntry{node: node, section: sec, index: i} + self.set(node.hash, entry) + } + sec.bottom = nodes[len(nodes)-1] + sec.top = nodes[0] + sec.nodes = nodes + poolLogger.DebugDetailf("[%s] setup section process", sectionName(sec)) + + self.wg.Add(1) go func() { - self.wg.Add(1) - for { - node.sectionRLock() - controlC = node.section.controlC - node.sectionRUnlock() - if init { - // missing blocks read from nodeC - // initialized section - if depth == 0 { - break + // absolute time after which sub-chain is killed if not complete (some blocks are missing) + suicideTimer := time.After(blocksTimeout * time.Second) + + var peer, newPeer *peerInfo + + var blocksRequestTimer, blockHashesRequestTimer <-chan time.Time + var blocksRequestTime, blockHashesRequestTime bool + var blocksRequests, blockHashesRequests int + var blocksRequestsComplete, blockHashesRequestsComplete bool + + // node channels for the section + var missingC, processC, offC chan *poolNode + // container for missing block hashes + var hashes [][]byte + + var i, missing, lastMissing, depth int + var idle int + var init, done, same, ready bool + var insertChain bool + var quitC chan bool + + var blockChainC = sec.blockChainC + + var parentHash []byte + + LOOP: + for { + + if insertChain { + insertChain = false + rest, err := self.addSectionToBlockChain(sec) + if err != nil { + close(sec.suicideC) + continue LOOP } - // enable select case to read missing block when ready - processC = missingC - missingC = make(chan *poolNode, lastMissing) - nodeC = nil - // only do once - init = false - } else { - if !once { - missingC = nil - processC = nil - i = 0 - total = 0 - lastMissing = 0 + if rest == 0 { + blocksRequestsComplete = true + child := self.getChild(sec) + if child != nil { + self.connectToBlockChain(child) + } } } - // went through all blocks in section - if i != 0 && i == lastMissing { - if len(hashes) > 0 { - // send block requests to peers - self.requestBlocks(blocksRequests, hashes) - } - blocksRequests++ - poolLogger.Debugf("[%x] block request attempt %v: missing %v/%v/%v", hash[0:4], blocksRequests, missing, total, depth) - if missing == lastMissing { - // idle round - if same { - // more than once - idle++ - // too many idle rounds - if idle > blocksRequestMaxIdleRounds { - poolLogger.Debugf("[%x] block requests had %v idle rounds (%v total attempts): missing %v/%v/%v\ngiving up...", hash[0:4], idle, blocksRequests, missing, total, depth) - self.killChain(node, nil) - break - } - } else { - idle = 0 - } - same = true + if blockHashesRequestsComplete && blocksRequestsComplete { + // not waiting for hashes any more + poolLogger.Debugf("[%s] section complete %v blocks retrieved (%v attempts), hash requests complete on root (%v attempts)", sectionName(sec), depth, blocksRequests, blockHashesRequests) + break LOOP + } // otherwise suicide if no hashes coming + + if done { + // went through all blocks in section + if missing == 0 { + // no missing blocks + poolLogger.DebugDetailf("[%s] got all blocks. process complete (%v total blocksRequests): missing %v/%v/%v", sectionName(sec), blocksRequests, missing, lastMissing, depth) + blocksRequestsComplete = true + blocksRequestTimer = nil + blocksRequestTime = false } else { - if missing == 0 { - // no missing nodes - poolLogger.Debugf("block request process complete on section %x... (%v total blocksRequests): missing %v/%v/%v", hash[0:4], blockHashesRequests, blocksRequests, missing, total, depth) - node.Lock() - orignode.complete = true - node.Unlock() - blocksRequestTimer = nil - if blockHashesRequestTimer == nil { - // not waiting for hashes any more - poolLogger.Debugf("hash request on root %x... successful (%v total attempts)\nquitting...", hash[0:4], blockHashesRequests) - break - } // otherwise suicide if no hashes coming + poolLogger.DebugDetailf("[%s] section checked: missing %v/%v/%v", sectionName(sec), missing, lastMissing, depth) + // some missing blocks + blocksRequests++ + if len(hashes) > 0 { + // send block requests to peers + self.requestBlocks(blocksRequests, hashes) + hashes = nil + } + if missing == lastMissing { + // idle round + if same { + // more than once + idle++ + // too many idle rounds + if idle >= blocksRequestMaxIdleRounds { + poolLogger.DebugDetailf("[%s] block requests had %v idle rounds (%v total attempts): missing %v/%v/%v\ngiving up...", sectionName(sec), idle, blocksRequests, missing, lastMissing, depth) + close(sec.suicideC) + } + } else { + idle = 0 + } + same = true + } else { + same = false } - same = false } lastMissing = missing - i = 0 - missing = 0 - // ready for next round - done = true - } - if done && alarm { - poolLogger.Debugf("start checking if new blocks arrived (attempt %v): missing %v/%v/%v", blocksRequests, missing, total, depth) - blocksRequestTimer = time.After(blocksRequestInterval * time.Second) - alarm = false + ready = true done = false - // processC supposed to be empty and never closed so just swap, no need to allocate - tempC := processC - processC = missingC - missingC = tempC + // save a new processC (blocks still missing) + offC = missingC + missingC = processC + // put processC offline + processC = nil } - select { - case <-self.quit: - break - case <-suicideTimer: - self.killChain(node, nil) - poolLogger.Warnf("[%x] timeout. (%v total attempts): missing %v/%v/%v", hash[0:4], blocksRequests, missing, total, depth) - break - case <-blocksRequestTimer: - alarm = true - case <-blockHashesRequestTimer: - orignode.RLock() - parent := orignode.parent - orignode.RUnlock() - if parent != nil { + // + + if ready && blocksRequestTime && !blocksRequestsComplete { + poolLogger.DebugDetailf("[%s] check if new blocks arrived (attempt %v): missing %v/%v/%v", sectionName(sec), blocksRequests, missing, lastMissing, depth) + blocksRequestTimer = time.After(blocksRequestInterval * time.Millisecond) + blocksRequestTime = false + processC = offC + } + + if blockHashesRequestTime { + var parentSection = self.getParent(sec) + if parentSection == nil { + if parent := self.get(parentHash); parent != nil { + parentSection = parent.section + self.chainLock.Lock() + self.link(parentSection, sec) + self.chainLock.Unlock() + } else { + if self.hasBlock(parentHash) { + insertChain = true + blockHashesRequestTime = false + blockHashesRequestTimer = nil + blockHashesRequestsComplete = true + continue LOOP + } + } + } + if parentSection != nil { // if not root of chain, switch off - poolLogger.Debugf("[%x] parent found, hash requests deactivated (after %v total attempts)\n", hash[0:4], blockHashesRequests) + poolLogger.DebugDetailf("[%s] parent found, hash requests deactivated (after %v total attempts)\n", sectionName(sec), blockHashesRequests) blockHashesRequestTimer = nil + blockHashesRequestsComplete = true } else { blockHashesRequests++ - poolLogger.Debugf("[%x] hash request on root (%v total attempts)\n", hash[0:4], blockHashesRequests) - self.requestBlockHashes(parent.hash) - blockHashesRequestTimer = time.After(blockHashesRequestInterval * time.Second) + poolLogger.Debugf("[%s] hash request on root (%v total attempts)\n", sectionName(sec), blockHashesRequests) + peer.requestBlockHashes(sec.bottom.hash) + blockHashesRequestTimer = time.After(blockHashesRequestInterval * time.Millisecond) } - case r, ok := <-controlC: - if !ok { - break - } - if running && !r { - poolLogger.Debugf("process on section %x... (%v total attempts): missing %v/%v/%v", hash[0:4], blocksRequests, missing, total, depth) + blockHashesRequestTime = false + } - alarm = false + select { + case <-self.quit: + break LOOP + + case <-quitC: + // peer quit or demoted, put section in idle mode + quitC = nil + go func() { + sec.controlC <- nil + }() + + case <-self.purgeC: + suicideTimer = time.After(0) + + case <-suicideTimer: + close(sec.suicideC) + poolLogger.Debugf("[%s] timeout. (%v total attempts): missing %v/%v/%v", sectionName(sec), blocksRequests, missing, lastMissing, depth) + + case <-sec.suicideC: + poolLogger.Debugf("[%s] suicide", sectionName(sec)) + + // first delink from child and parent under chainlock + self.chainLock.Lock() + self.link(nil, sec) + self.link(sec, nil) + self.chainLock.Unlock() + // delete node entries from pool index under pool lock + self.lock.Lock() + for _, node := range sec.nodes { + delete(self.pool, string(node.hash)) + } + self.lock.Unlock() + + break LOOP + + case <-blocksRequestTimer: + poolLogger.DebugDetailf("[%s] block request time", sectionName(sec)) + blocksRequestTime = true + + case <-blockHashesRequestTimer: + poolLogger.DebugDetailf("[%s] hash request time", sectionName(sec)) + blockHashesRequestTime = true + + case newPeer = <-sec.controlC: + + // active -> idle + if peer != nil && newPeer == nil { + self.procWg.Done() + if init { + poolLogger.Debugf("[%s] idle mode (%v total attempts): missing %v/%v/%v", sectionName(sec), blocksRequests, missing, lastMissing, depth) + } + blocksRequestTime = false blocksRequestTimer = nil + blockHashesRequestTime = false blockHashesRequestTimer = nil - processC = nil + if processC != nil { + offC = processC + processC = nil + } } - if !running && r { - poolLogger.Debugf("[%x] on", hash[0:4]) - orignode.RLock() - parent := orignode.parent - complete := orignode.complete - knownParent := orignode.knownParent - orignode.RUnlock() - if !complete { - poolLogger.Debugf("[%x] activate block requests", hash[0:4]) - blocksRequestTimer = time.After(0) + // idle -> active + if peer == nil && newPeer != nil { + self.procWg.Add(1) + + poolLogger.Debugf("[%s] active mode", sectionName(sec)) + if !blocksRequestsComplete { + blocksRequestTime = true } - if parent == nil && !knownParent { - // if no parent but not connected to blockchain - poolLogger.Debugf("[%x] activate block hashes requests", hash[0:4]) - blockHashesRequestTimer = time.After(0) - } else { - blockHashesRequestTimer = nil + if !blockHashesRequestsComplete && parentHash != nil { + blockHashesRequestTime = true } - alarm = true - processC = missingC - if !once { + if !init { + processC = make(chan *poolNode, blockHashesBatchSize) + missingC = make(chan *poolNode, blockHashesBatchSize) + i = 0 + missing = 0 + self.wg.Add(1) + self.procWg.Add(1) + depth = len(sec.nodes) + lastMissing = depth // if not run at least once fully, launch iterator - processC = make(chan *poolNode) - missingC = make(chan *poolNode) - self.foldUp(orignode, processC) - once = true + go func() { + var node *poolNode + IT: + for _, node = range sec.nodes { + select { + case processC <- node: + case <-self.quit: + break IT + } + } + close(processC) + self.wg.Done() + self.procWg.Done() + }() + } else { + poolLogger.Debugf("[%s] restore earlier state", sectionName(sec)) + processC = offC } } - total = lastMissing - case <-resetC: - once = false + // reset quitC to current best peer + if newPeer != nil { + quitC = newPeer.quitC + } + peer = newPeer + + case waiter := <-sec.forkC: + // this case just blocks the process until section is split at the fork + <-waiter init = false done = false + ready = false + case node, ok := <-processC: - if !ok { + if !ok && !init { // channel closed, first iteration finished init = true - once = true - continue + done = true + processC = make(chan *poolNode, missing) + poolLogger.DebugDetailf("[%s] section initalised: missing %v/%v/%v", sectionName(sec), missing, lastMissing, depth) + continue LOOP + } + if ready { + i = 0 + missing = 0 + ready = false } i++ // if node has no block - node.RLock() + node.lock.RLock() block := node.block - nhash := node.hash - knownParent := node.knownParent - node.RUnlock() - if !init { - depth++ - } + node.lock.RUnlock() if block == nil { missing++ - if !init { - total++ - } - hashes = append(hashes, nhash) + hashes = append(hashes, node.hash) if len(hashes) == blockBatchSize { + poolLogger.Debugf("[%s] request %v missing blocks", sectionName(sec), len(hashes)) self.requestBlocks(blocksRequests, hashes) hashes = nil } missingC <- node } else { - // block is found - if knownParent { - // connected to the blockchain, insert the longest chain of blocks - var blocks types.Blocks - child := node - parent := node - node.sectionRLock() - for child != nil && child.block != nil { - parent = child - blocks = append(blocks, parent.block) - child = parent.child + if i == lastMissing { + if blockChainC == nil { + insertChain = true + } else { + if parentHash == nil { + parentHash = block.ParentHash() + poolLogger.Debugf("[%s] found root block [%s]", sectionName(sec), name(parentHash)) + blockHashesRequestTime = true + } } - node.sectionRUnlock() - poolLogger.Debugf("[%x] insert %v blocks into blockchain", hash[0:4], len(blocks)) - if err := self.insertChain(blocks); err != nil { - // TODO: not clear which peer we need to address - // peerError should dispatch to peer if still connected and disconnect - self.peerError(node.source, ErrInvalidBlock, "%v", err) - poolLogger.Debugf("invalid block %v", node.hash) - poolLogger.Debugf("penalise peers %v (hash), %v (block)", node.peer, node.source) - // penalise peer in node.source - self.killChain(node, nil) - // self.disconnect() - break - } - // if suceeded mark the next one (no block yet) as connected to blockchain - if child != nil { - child.Lock() - child.knownParent = true - child.Unlock() - } - // reset starting node to first node with missing block - orignode = child - // pop the inserted ancestors off the channel - for i := 1; i < len(blocks); i++ { - <-processC - } - // delink inserted chain section - self.killChain(node, parent) } } - } - } - poolLogger.Debugf("[%x] quit after\n%v block hashes requests\n%v block requests: missing %v/%v/%v", hash[0:4], blockHashesRequests, blocksRequests, missing, total, depth) + if i == lastMissing && init { + done = true + } + + case <-blockChainC: + // closed blockChain channel indicates that the blockpool is reached + // connected to the blockchain, insert the longest chain of blocks + poolLogger.Debugf("[%s] reached blockchain", sectionName(sec)) + blockChainC = nil + // switch off hash requests in case they were on + blockHashesRequestTime = false + blockHashesRequestTimer = nil + blockHashesRequestsComplete = true + // section root has block + if len(sec.nodes) > 0 && sec.nodes[len(sec.nodes)-1].block != nil { + insertChain = true + } + continue LOOP + + } // select + } // for + + close(sec.offC) self.wg.Done() - node.sectionLock() - node.section.controlC = nil - node.sectionUnlock() - // this signals that controller not available + if peer != nil { + self.procWg.Done() + } }() - return section - + return } func (self *BlockPool) peerError(peerId string, code int, format string, params ...interface{}) { @@ -636,39 +1077,39 @@ func (self *BlockPool) peerError(peerId string, code int, format string, params } } -func (self *BlockPool) requestBlockHashes(hash []byte) { - self.peersLock.Lock() - defer self.peersLock.Unlock() - if self.peer != nil { - self.peer.requestBlockHashes(hash) - } -} - func (self *BlockPool) requestBlocks(attempts int, hashes [][]byte) { - // distribute block request among known peers - self.peersLock.Lock() - defer self.peersLock.Unlock() - peerCount := len(self.peers) - // on first attempt use the best peer - if attempts == 0 { - self.peer.requestBlocks(hashes) - return - } - repetitions := int(math.Min(float64(peerCount), float64(blocksRequestRepetition))) - poolLogger.Debugf("request %v missing blocks from %v/%v peers", len(hashes), repetitions, peerCount) - i := 0 - indexes := rand.Perm(peerCount)[0:(repetitions - 1)] - sort.Ints(indexes) - for _, peer := range self.peers { - if i == indexes[0] { - peer.requestBlocks(hashes) - indexes = indexes[1:] - if len(indexes) == 0 { - break - } + self.wg.Add(1) + self.procWg.Add(1) + go func() { + // distribute block request among known peers + self.peersLock.Lock() + defer self.peersLock.Unlock() + peerCount := len(self.peers) + // on first attempt use the best peer + if attempts == 0 { + poolLogger.Debugf("request %v missing blocks from best peer %s", len(hashes), self.peer.id) + self.peer.requestBlocks(hashes) + return } - i++ - } + repetitions := int(math.Min(float64(peerCount), float64(blocksRequestRepetition))) + i := 0 + indexes := rand.Perm(peerCount)[0:repetitions] + sort.Ints(indexes) + poolLogger.Debugf("request %v missing blocks from %v/%v peers: chosen %v", len(hashes), repetitions, peerCount, indexes) + for _, peer := range self.peers { + if i == indexes[0] { + poolLogger.Debugf("request %v missing blocks from peer %s", len(hashes), peer.id) + peer.requestBlocks(hashes) + indexes = indexes[1:] + if len(indexes) == 0 { + break + } + } + i++ + } + self.wg.Done() + self.procWg.Done() + }() } func (self *BlockPool) getPeer(peerId string) (*peerInfo, bool) { @@ -679,337 +1120,120 @@ func (self *BlockPool) getPeer(peerId string) (*peerInfo, bool) { } info, ok := self.peers[peerId] if !ok { - panic("unknown peer") + return nil, false } return info, false } -func (self *peerInfo) addSection(hash []byte, section *section) { +func (self *peerInfo) addSection(hash []byte, section *section) (found *section) { self.lock.Lock() defer self.lock.Unlock() - self.sections[string(hash)] = section + key := string(hash) + found = self.sections[key] + poolLogger.DebugDetailf("[%s] section process stored for %s", sectionName(section), self.id) + self.sections[key] = section + return } -func (self *peerInfo) addRoot(node *poolNode) { - self.lock.Lock() - defer self.lock.Unlock() - self.roots = append(self.roots, node) -} - -// (re)starts processes registered for this peer (self) -func (self *peerInfo) start(peer *peerInfo) { - self.lock.Lock() - defer self.lock.Unlock() - self.quitC = make(chan bool) - for _, root := range self.roots { - root.sectionRLock() - if root.section.bottom != nil { - if root.parent == nil { - self.requestBlockHashes(root.hash) - } - } - root.sectionRUnlock() - } - self.roots = nil - self.controlSections(peer, true) -} - -// (re)starts process without requests, only suicide timer -func (self *peerInfo) stop(peer *peerInfo) { - self.lock.RLock() - defer self.lock.RUnlock() - close(self.quitC) - self.controlSections(peer, false) -} - -func (self *peerInfo) controlSections(peer *peerInfo, on bool) { - if peer != nil { - peer.lock.RLock() - defer peer.lock.RUnlock() - } - for hash, section := range peer.sections { - if section.done() { - delete(self.sections, hash) - } - _, exists := peer.sections[hash] - if on || peer == nil || exists { - if on { - // self is best peer - section.start() - } else { - // (re)starts process without requests, only suicide timer - section.stop() - } - } - } -} - -// called when parent is found in pool -// parent and child are guaranteed to be on different sections -func (self *BlockPool) link(parent, child *poolNode) { - var top bool - parent.sectionLock() - if child != nil { - child.sectionLock() - } - if parent == parent.section.top && parent.section.top != nil { - top = true - } - var bottom bool - - if child == child.section.bottom { - bottom = true - } - if parent.child != child { - orphan := parent.child - if orphan != nil { - // got a fork in the chain - if top { - orphan.lock.Lock() - // make old child orphan - orphan.parent = nil - orphan.lock.Unlock() - } else { // we are under section lock - // make old child orphan - orphan.parent = nil - // reset section objects above the fork - nchild := orphan.child - node := orphan - section := §ion{bottom: orphan} - for node.section == nchild.section { - node = nchild - node.section = section - nchild = node.child +func (self *BlockPool) switchPeer(oldPeer, newPeer *peerInfo) { + if newPeer != nil { + newPeer.quitC = make(chan bool) + poolLogger.DebugDetailf("[%s] activate section processes", newPeer.id) + var addSections []*section + for hash, section := range newPeer.sections { + // split sections get reorganised here + if string(section.top.hash) != hash { + addSections = append(addSections, section) + if entry := self.get([]byte(hash)); entry != nil { + addSections = append(addSections, entry.section) } - section.top = node - // set up a suicide - self.processSection(orphan).stop() } + } + for _, section := range addSections { + newPeer.sections[string(section.top.hash)] = section + } + for hash, section := range newPeer.sections { + // this will block if section process is waiting for peer lock + select { + case <-section.offC: + poolLogger.DebugDetailf("[%s][%x] section process complete - remove", newPeer.id, hash[:4]) + delete(newPeer.sections, hash) + case section.controlC <- newPeer: + poolLogger.DebugDetailf("[%s][%x] activates section [%s]", newPeer.id, hash[:4], sectionName(section)) + } + } + newPeer.lock.Lock() + headSection := newPeer.headSection + currentBlockHash := newPeer.currentBlockHash + newPeer.lock.Unlock() + if headSection == nil { + poolLogger.DebugDetailf("[%s] head section for [%s] not created, requesting info", newPeer.id, name(currentBlockHash)) + self.requestHeadSection(newPeer) } else { - // child is on top of a chain need to close section - child.section.bottom = child - } - // adopt new child - parent.child = child - if !top { - parent.section.top = parent - // restart section process so that shorter section is scanned for blocks - parent.section.reset() + if entry := self.get(currentBlockHash); entry != nil { + headSection = entry.section + } + poolLogger.DebugDetailf("[%s] activate chain at head section [%s] for current head [%s]", newPeer.id, sectionName(headSection), name(currentBlockHash)) + self.activateChain(headSection, newPeer) } } + if oldPeer != nil { + poolLogger.DebugDetailf("[%s] quit section processes", oldPeer.id) + close(oldPeer.quitC) + } +} +func (self *BlockPool) getParent(sec *section) *section { + self.chainLock.RLock() + defer self.chainLock.RUnlock() + return sec.parent +} + +func (self *BlockPool) getChild(sec *section) *section { + self.chainLock.RLock() + defer self.chainLock.RUnlock() + return sec.child +} + +func newSection() (sec *section) { + sec = §ion{ + controlC: make(chan *peerInfo), + suicideC: make(chan bool), + blockChainC: make(chan bool), + offC: make(chan bool), + forkC: make(chan chan bool), + } + return +} + +// link should only be called under chainLock +func (self *BlockPool) link(parent *section, child *section) { + if parent != nil { + exChild := parent.child + parent.child = child + if exChild != nil && exChild != child { + poolLogger.Debugf("[%s] chain fork [%s] -> [%s]", sectionName(parent), sectionName(exChild), sectionName(child)) + exChild.parent = nil + } + } if child != nil { - if child.parent != parent { - stepParent := child.parent - if stepParent != nil { - if bottom { - stepParent.Lock() - stepParent.child = nil - stepParent.Unlock() - } else { - // we are on the same section - // if it is a aberrant reverse fork, - stepParent.child = nil - node := stepParent - nparent := stepParent.child - section := §ion{top: stepParent} - for node.section == nparent.section { - node = nparent - node.section = section - node = node.parent - } - } - } else { - // linking to a root node, ie. parent is under the root of a chain - parent.section.top = parent - } + exParent := child.parent + if exParent != nil && exParent != parent { + poolLogger.Debugf("[%s] chain reverse fork [%s] -> [%s]", sectionName(child), sectionName(exParent), sectionName(parent)) + exParent.child = nil } child.parent = parent - child.section.bottom = child - } - // this needed if someone lied about the parent before - child.knownParent = false - - parent.sectionUnlock() - if child != nil { - child.sectionUnlock() } } -// this immediately kills the chain from node to end (inclusive) section by section -func (self *BlockPool) killChain(node *poolNode, end *poolNode) { - poolLogger.Debugf("kill chain section with root node %v", node) - - node.sectionLock() - node.section.abort() - self.set(node.hash, nil) - child := node.child - top := node.section.top - i := 1 - self.wg.Add(1) - go func() { - var quit bool - for node != top && node != end && child != nil { - node = child - select { - case <-self.quit: - quit = true - break - default: - } - self.set(node.hash, nil) - child = node.child - } - poolLogger.Debugf("killed chain section of %v blocks with root node %v", i, node) - if !quit { - if node == top { - if node != end && child != nil && end != nil { - // - self.killChain(child, end) - } - } else { - if child != nil { - // delink rest of this section if ended midsection - child.section.bottom = child - child.parent = nil - } - } - } - node.section.bottom = nil - node.sectionUnlock() - self.wg.Done() - }() -} - -// structure to store long range links on chain to skip along -type section struct { - lock sync.RWMutex - bottom *poolNode - top *poolNode - controlC chan bool - resetC chan bool -} - -func (self *section) start() { +func (self *BlockPool) get(hash []byte) (node *poolEntry) { self.lock.RLock() defer self.lock.RUnlock() - if self.controlC != nil { - self.controlC <- true - } -} - -func (self *section) stop() { - self.lock.RLock() - defer self.lock.RUnlock() - if self.controlC != nil { - self.controlC <- false - } -} - -func (self *section) reset() { - self.lock.RLock() - defer self.lock.RUnlock() - if self.controlC != nil { - self.resetC <- true - self.controlC <- false - } -} - -func (self *section) abort() { - self.lock.Lock() - defer self.lock.Unlock() - if self.controlC != nil { - close(self.controlC) - self.controlC = nil - } -} - -func (self *section) done() bool { - self.lock.Lock() - defer self.lock.Unlock() - if self.controlC != nil { - return true - } - return false -} - -func (self *BlockPool) get(hash []byte) (node *poolNode) { - self.lock.Lock() - defer self.lock.Unlock() return self.pool[string(hash)] } -func (self *BlockPool) set(hash []byte, node *poolNode) { +func (self *BlockPool) set(hash []byte, node *poolEntry) { self.lock.Lock() defer self.lock.Unlock() self.pool[string(hash)] = node } - -// first time for block request, this iteration retrieves nodes of the chain -// from node up to top (all the way if nil) via child links -// copies the controller -// and feeds nodeC channel -// this is performed under section readlock to prevent top from going away -// when -func (self *BlockPool) foldUp(node *poolNode, nodeC chan *poolNode) { - self.wg.Add(1) - go func() { - node.sectionRLock() - defer node.sectionRUnlock() - for node != nil { - select { - case <-self.quit: - break - case nodeC <- node: - if node == node.section.top { - break - } - node = node.child - } - } - close(nodeC) - self.wg.Done() - }() -} - -func (self *poolNode) Lock() { - self.sectionLock() - self.lock.Lock() -} - -func (self *poolNode) Unlock() { - self.lock.Unlock() - self.sectionUnlock() -} - -func (self *poolNode) RLock() { - self.lock.RLock() -} - -func (self *poolNode) RUnlock() { - self.lock.RUnlock() -} - -func (self *poolNode) sectionLock() { - self.lock.RLock() - defer self.lock.RUnlock() - self.section.lock.Lock() -} - -func (self *poolNode) sectionUnlock() { - self.lock.RLock() - defer self.lock.RUnlock() - self.section.lock.Unlock() -} - -func (self *poolNode) sectionRLock() { - self.lock.RLock() - defer self.lock.RUnlock() - self.section.lock.RLock() -} - -func (self *poolNode) sectionRUnlock() { - self.lock.RLock() - defer self.lock.RUnlock() - self.section.lock.RUnlock() -} diff --git a/eth/block_pool_test.go b/eth/block_pool_test.go index 315cc748db..94c3b43d29 100644 --- a/eth/block_pool_test.go +++ b/eth/block_pool_test.go @@ -1,115 +1,65 @@ package eth import ( - "bytes" "fmt" "log" + "math/big" "os" "sync" "testing" + "time" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" ethlogger "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/pow" ) -var sys = ethlogger.NewStdLogSystem(os.Stdout, log.LstdFlags, ethlogger.LogLevel(ethlogger.DebugDetailLevel)) +const waitTimeout = 60 // seconds -type testChainManager struct { - knownBlock func(hash []byte) bool - addBlock func(*types.Block) error - checkPoW func(*types.Block) bool -} +var logsys = ethlogger.NewStdLogSystem(os.Stdout, log.LstdFlags, ethlogger.LogLevel(ethlogger.DebugDetailLevel)) -func (self *testChainManager) KnownBlock(hash []byte) bool { - if self.knownBlock != nil { - return self.knownBlock(hash) +var ini = false + +func logInit() { + if !ini { + ethlogger.AddLogSystem(logsys) + ini = true } - return false } -func (self *testChainManager) AddBlock(block *types.Block) error { - if self.addBlock != nil { - return self.addBlock(block) - } - return nil -} - -func (self *testChainManager) CheckPoW(block *types.Block) bool { - if self.checkPoW != nil { - return self.checkPoW(block) - } - return false -} - -func knownBlock(hashes ...[]byte) (f func([]byte) bool) { - f = func(block []byte) bool { - for _, hash := range hashes { - if bytes.Compare(block, hash) == 0 { - return true - } - } +// test helpers +func arrayEq(a, b []int) bool { + if len(a) != len(b) { return false } - return -} - -func addBlock(hashes ...[]byte) (f func(*types.Block) error) { - f = func(block *types.Block) error { - for _, hash := range hashes { - if bytes.Compare(block.Hash(), hash) == 0 { - return fmt.Errorf("invalid by test") - } + for i := range a { + if a[i] != b[i] { + return false } - return nil - } - return -} - -func checkPoW(hashes ...[]byte) (f func(*types.Block) bool) { - f = func(block *types.Block) bool { - for _, hash := range hashes { - if bytes.Compare(block.Hash(), hash) == 0 { - return false - } - } - return true - } - return -} - -func newTestChainManager(knownBlocks [][]byte, invalidBlocks [][]byte, invalidPoW [][]byte) *testChainManager { - return &testChainManager{ - knownBlock: knownBlock(knownBlocks...), - addBlock: addBlock(invalidBlocks...), - checkPoW: checkPoW(invalidPoW...), } + return true } type intToHash map[int][]byte type hashToInt map[string]int +// hashPool is a test helper, that allows random hashes to be referred to by integers type testHashPool struct { intToHash hashToInt + lock sync.Mutex } func newHash(i int) []byte { return crypto.Sha3([]byte(string(i))) } -func newTestBlockPool(knownBlockIndexes []int, invalidBlockIndexes []int, invalidPoWIndexes []int) (hashPool *testHashPool, blockPool *BlockPool) { - hashPool = &testHashPool{make(intToHash), make(hashToInt)} - knownBlocks := hashPool.indexesToHashes(knownBlockIndexes) - invalidBlocks := hashPool.indexesToHashes(invalidBlockIndexes) - invalidPoW := hashPool.indexesToHashes(invalidPoWIndexes) - blockPool = NewBlockPool(newTestChainManager(knownBlocks, invalidBlocks, invalidPoW)) - return -} - func (self *testHashPool) indexesToHashes(indexes []int) (hashes [][]byte) { + self.lock.Lock() + defer self.lock.Unlock() for _, i := range indexes { hash, found := self.intToHash[i] if !found { @@ -123,6 +73,8 @@ func (self *testHashPool) indexesToHashes(indexes []int) (hashes [][]byte) { } func (self *testHashPool) hashesToIndexes(hashes [][]byte) (indexes []int) { + self.lock.Lock() + defer self.lock.Unlock() for _, hash := range hashes { i, found := self.hashToInt[string(hash)] if !found { @@ -133,66 +85,898 @@ func (self *testHashPool) hashesToIndexes(hashes [][]byte) (indexes []int) { return } -type protocolChecker struct { +// test blockChain is an integer trie +type blockChain map[int][]int + +// blockPoolTester provides the interface between tests and a blockPool +// +// refBlockChain is used to guide which blocks will be accepted as valid +// blockChain gives the current state of the blockchain and +// accumulates inserts so that we can check the resulting chain +type blockPoolTester struct { + hashPool *testHashPool + lock sync.RWMutex + refBlockChain blockChain + blockChain blockChain + blockPool *BlockPool + t *testing.T +} + +func newTestBlockPool(t *testing.T) (hashPool *testHashPool, blockPool *BlockPool, b *blockPoolTester) { + hashPool = &testHashPool{intToHash: make(intToHash), hashToInt: make(hashToInt)} + b = &blockPoolTester{ + t: t, + hashPool: hashPool, + blockChain: make(blockChain), + refBlockChain: make(blockChain), + } + b.blockPool = NewBlockPool(b.hasBlock, b.insertChain, b.verifyPoW) + blockPool = b.blockPool + return +} + +func (self *blockPoolTester) Errorf(format string, params ...interface{}) { + fmt.Printf(format+"\n", params...) + self.t.Errorf(format, params...) +} + +// blockPoolTester implements the 3 callbacks needed by the blockPool: +// hasBlock, insetChain, verifyPoW +func (self *blockPoolTester) hasBlock(block []byte) (ok bool) { + self.lock.RLock() + defer self.lock.RUnlock() + indexes := self.hashPool.hashesToIndexes([][]byte{block}) + i := indexes[0] + _, ok = self.blockChain[i] + fmt.Printf("has block %v (%x...): %v\n", i, block[0:4], ok) + return +} + +func (self *blockPoolTester) insertChain(blocks types.Blocks) error { + self.lock.RLock() + defer self.lock.RUnlock() + var parent, child int + var children, refChildren []int + var ok bool + for _, block := range blocks { + child = self.hashPool.hashesToIndexes([][]byte{block.Hash()})[0] + _, ok = self.blockChain[child] + if ok { + fmt.Printf("block %v already in blockchain\n", child) + continue // already in chain + } + parent = self.hashPool.hashesToIndexes([][]byte{block.ParentHeaderHash})[0] + children, ok = self.blockChain[parent] + if !ok { + return fmt.Errorf("parent %v not in blockchain ", parent) + } + ok = false + var found bool + refChildren, found = self.refBlockChain[parent] + if found { + for _, c := range refChildren { + if c == child { + ok = true + } + } + if !ok { + return fmt.Errorf("invalid block %v", child) + } + } else { + ok = true + } + if ok { + // accept any blocks if parent not in refBlockChain + fmt.Errorf("blockchain insert %v -> %v\n", parent, child) + self.blockChain[parent] = append(children, child) + self.blockChain[child] = nil + } + } + return nil +} + +func (self *blockPoolTester) verifyPoW(pblock pow.Block) bool { + return true +} + +// test helper that compares the resulting blockChain to the desired blockChain +func (self *blockPoolTester) checkBlockChain(blockChain map[int][]int) { + for k, v := range self.blockChain { + fmt.Printf("got: %v -> %v\n", k, v) + } + for k, v := range blockChain { + fmt.Printf("expected: %v -> %v\n", k, v) + } + if len(blockChain) != len(self.blockChain) { + self.Errorf("blockchain incorrect (zlength differ)") + } + for k, v := range blockChain { + vv, ok := self.blockChain[k] + if !ok || !arrayEq(v, vv) { + self.Errorf("blockchain incorrect on %v -> %v (!= %v)", k, vv, v) + } + } +} + +// + +// peerTester provides the peer callbacks for the blockPool +// it registers actual callbacks so that result can be compared to desired behaviour +// provides helper functions to mock the protocol calls to the blockPool +type peerTester struct { blockHashesRequests []int blocksRequests [][]int - invalidBlocks []error + blocksRequestsMap map[int]bool + peerErrors []int + blockPool *BlockPool hashPool *testHashPool - lock sync.Mutex + lock sync.RWMutex + id string + td int + currentBlock int + t *testing.T } +// peerTester constructor takes hashPool and blockPool from the blockPoolTester +func (self *blockPoolTester) newPeer(id string, td int, cb int) *peerTester { + return &peerTester{ + id: id, + td: td, + currentBlock: cb, + hashPool: self.hashPool, + blockPool: self.blockPool, + t: self.t, + blocksRequestsMap: make(map[int]bool), + } +} + +func (self *peerTester) Errorf(format string, params ...interface{}) { + fmt.Printf(format+"\n", params...) + self.t.Errorf(format, params...) +} + +// helper to compare actual and expected block requests +func (self *peerTester) checkBlocksRequests(blocksRequests ...[]int) { + if len(blocksRequests) > len(self.blocksRequests) { + self.Errorf("blocks requests incorrect (length differ)\ngot %v\nexpected %v", self.blocksRequests, blocksRequests) + } else { + for i, rr := range blocksRequests { + r := self.blocksRequests[i] + if !arrayEq(r, rr) { + self.Errorf("blocks requests incorrect\ngot %v\nexpected %v", self.blocksRequests, blocksRequests) + } + } + } +} + +// helper to compare actual and expected block hash requests +func (self *peerTester) checkBlockHashesRequests(blocksHashesRequests ...int) { + rr := blocksHashesRequests + self.lock.RLock() + r := self.blockHashesRequests + self.lock.RUnlock() + if len(r) != len(rr) { + self.Errorf("block hashes requests incorrect (length differ)\ngot %v\nexpected %v", r, rr) + } else { + if !arrayEq(r, rr) { + self.Errorf("block hashes requests incorrect\ngot %v\nexpected %v", r, rr) + } + } +} + +// waiter function used by peer.AddBlocks +// blocking until requests appear +// since block requests are sent to any random peers +// block request map is shared between peers +// times out after a period +func (self *peerTester) waitBlocksRequests(blocksRequest ...int) { + timeout := time.After(waitTimeout * time.Second) + rr := blocksRequest + for { + self.lock.RLock() + r := self.blocksRequestsMap + fmt.Printf("[%s] blocks request check %v (%v)\n", self.id, rr, r) + i := 0 + for i = 0; i < len(rr); i++ { + _, ok := r[rr[i]] + if !ok { + break + } + } + self.lock.RUnlock() + + if i == len(rr) { + return + } + time.Sleep(100 * time.Millisecond) + select { + case <-timeout: + default: + } + } +} + +// waiter function used by peer.AddBlockHashes +// blocking until requests appear +// times out after a period +func (self *peerTester) waitBlockHashesRequests(blocksHashesRequest int) { + timeout := time.After(waitTimeout * time.Second) + rr := blocksHashesRequest + for i := 0; ; { + self.lock.RLock() + r := self.blockHashesRequests + self.lock.RUnlock() + fmt.Printf("[%s] block hash request check %v (%v)\n", self.id, rr, r) + for ; i < len(r); i++ { + if rr == r[i] { + return + } + } + time.Sleep(100 * time.Millisecond) + select { + case <-timeout: + default: + } + } +} + +// mocks a simple blockchain 0 (genesis) ... n (head) +func (self *blockPoolTester) initRefBlockChain(n int) { + for i := 0; i < n; i++ { + self.refBlockChain[i] = []int{i + 1} + } +} + +// peerTester functions that mimic protocol calls to the blockpool +// registers the peer with the blockPool +func (self *peerTester) AddPeer() bool { + hash := self.hashPool.indexesToHashes([]int{self.currentBlock})[0] + return self.blockPool.AddPeer(big.NewInt(int64(self.td)), hash, self.id, self.requestBlockHashes, self.requestBlocks, self.peerError) +} + +// peer sends blockhashes if and when gets a request +func (self *peerTester) AddBlockHashes(indexes ...int) { + fmt.Printf("ready to add block hashes %v\n", indexes) + + self.waitBlockHashesRequests(indexes[0]) + fmt.Printf("adding block hashes %v\n", indexes) + hashes := self.hashPool.indexesToHashes(indexes) + i := 1 + next := func() (hash []byte, ok bool) { + if i < len(hashes) { + hash = hashes[i] + ok = true + i++ + } + return + } + self.blockPool.AddBlockHashes(next, self.id) +} + +// peer sends blocks if and when there is a request +// (in the shared request store, not necessarily to a person) +func (self *peerTester) AddBlocks(indexes ...int) { + hashes := self.hashPool.indexesToHashes(indexes) + fmt.Printf("ready to add blocks %v\n", indexes[1:]) + self.waitBlocksRequests(indexes[1:]...) + fmt.Printf("adding blocks %v \n", indexes[1:]) + for i := 1; i < len(hashes); i++ { + fmt.Printf("adding block %v %x\n", indexes[i], hashes[i][:4]) + self.blockPool.AddBlock(&types.Block{HeaderHash: ethutil.Bytes(hashes[i]), ParentHeaderHash: ethutil.Bytes(hashes[i-1])}, self.id) + } +} + +// peer callbacks // -1 is special: not found (a hash never seen) -func (self *protocolChecker) requestBlockHashesCallBack() (requestBlockHashesCallBack func([]byte) error) { - requestBlockHashesCallBack = func(hash []byte) error { - indexes := self.hashPool.hashesToIndexes([][]byte{hash}) - self.lock.Lock() - defer self.lock.Unlock() - self.blockHashesRequests = append(self.blockHashesRequests, indexes[0]) - return nil - } - return +// records block hashes requests by the blockPool +func (self *peerTester) requestBlockHashes(hash []byte) error { + indexes := self.hashPool.hashesToIndexes([][]byte{hash}) + fmt.Printf("[%s] blocks hash request %v %x\n", self.id, indexes[0], hash[:4]) + self.lock.Lock() + defer self.lock.Unlock() + self.blockHashesRequests = append(self.blockHashesRequests, indexes[0]) + return nil } -func (self *protocolChecker) requestBlocksCallBack() (requestBlocksCallBack func([][]byte) error) { - requestBlocksCallBack = func(hashes [][]byte) error { - indexes := self.hashPool.hashesToIndexes(hashes) - self.lock.Lock() - defer self.lock.Unlock() - self.blocksRequests = append(self.blocksRequests, indexes) - return nil +// records block requests by the blockPool +func (self *peerTester) requestBlocks(hashes [][]byte) error { + indexes := self.hashPool.hashesToIndexes(hashes) + fmt.Printf("blocks request %v %x...\n", indexes, hashes[0][:4]) + self.lock.Lock() + defer self.lock.Unlock() + self.blocksRequests = append(self.blocksRequests, indexes) + for _, i := range indexes { + self.blocksRequestsMap[i] = true } - return + return nil } -func (self *protocolChecker) invalidBlockCallBack() (invalidBlockCallBack func(error)) { - invalidBlockCallBack = func(err error) { - self.invalidBlocks = append(self.invalidBlocks, err) - } - return +// records the error codes of all the peerErrors found the blockPool +func (self *peerTester) peerError(code int, format string, params ...interface{}) { + self.peerErrors = append(self.peerErrors, code) } +// the actual tests func TestAddPeer(t *testing.T) { - ethlogger.AddLogSystem(sys) - knownBlockIndexes := []int{0, 1} - invalidBlockIndexes := []int{2, 3} - invalidPoWIndexes := []int{4, 5} - hashPool, blockPool := newTestBlockPool(knownBlockIndexes, invalidBlockIndexes, invalidPoWIndexes) - // TODO: - // hashPool, blockPool, blockChainChecker = newTestBlockPool(knownBlockIndexes, invalidBlockIndexes, invalidPoWIndexes) - peer0 := &protocolChecker{ - // blockHashesRequests: make([]int), - // blocksRequests: make([][]int), - // invalidBlocks: make([]error), - hashPool: hashPool, - } - best := blockPool.AddPeer(ethutil.Big1, newHash(100), "0", - peer0.requestBlockHashesCallBack(), - peer0.requestBlocksCallBack(), - peer0.invalidBlockCallBack(), - ) + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + peer0 := blockPoolTester.newPeer("peer0", 1, 0) + peer1 := blockPoolTester.newPeer("peer1", 2, 1) + peer2 := blockPoolTester.newPeer("peer2", 3, 2) + var peer *peerInfo + + blockPool.Start() + + // pool + best := peer0.AddPeer() if !best { - t.Errorf("peer not accepted as best") + t.Errorf("peer0 (TD=1) not accepted as best") } + if blockPool.peer.id != "peer0" { + t.Errorf("peer0 (TD=1) not set as best") + } + // peer0.checkBlockHashesRequests(0) + + best = peer2.AddPeer() + if !best { + t.Errorf("peer2 (TD=3) not accepted as best") + } + if blockPool.peer.id != "peer2" { + t.Errorf("peer2 (TD=3) not set as best") + } + peer2.waitBlocksRequests(2) + + best = peer1.AddPeer() + if best { + t.Errorf("peer1 (TD=2) accepted as best") + } + if blockPool.peer.id != "peer2" { + t.Errorf("peer2 (TD=3) not set any more as best") + } + if blockPool.peer.td.Cmp(big.NewInt(int64(3))) != 0 { + t.Errorf("peer1 TD not set") + } + + peer2.td = 4 + peer2.currentBlock = 3 + best = peer2.AddPeer() + if !best { + t.Errorf("peer2 (TD=4) not accepted as best") + } + if blockPool.peer.id != "peer2" { + t.Errorf("peer2 (TD=4) not set as best") + } + if blockPool.peer.td.Cmp(big.NewInt(int64(4))) != 0 { + t.Errorf("peer2 TD not updated") + } + peer2.waitBlocksRequests(3) + + peer1.td = 3 + peer1.currentBlock = 2 + best = peer1.AddPeer() + if best { + t.Errorf("peer1 (TD=3) should not be set as best") + } + if blockPool.peer.id == "peer1" { + t.Errorf("peer1 (TD=3) should not be set as best") + } + peer, best = blockPool.getPeer("peer1") + if peer.td.Cmp(big.NewInt(int64(3))) != 0 { + t.Errorf("peer1 TD should be updated") + } + + blockPool.RemovePeer("peer2") + peer, best = blockPool.getPeer("peer2") + if peer != nil { + t.Errorf("peer2 not removed") + } + + if blockPool.peer.id != "peer1" { + t.Errorf("existing peer1 (TD=3) should be set as best peer") + } + peer1.waitBlocksRequests(2) + + blockPool.RemovePeer("peer1") + peer, best = blockPool.getPeer("peer1") + if peer != nil { + t.Errorf("peer1 not removed") + } + + if blockPool.peer.id != "peer0" { + t.Errorf("existing peer0 (TD=1) should be set as best peer") + } + peer0.waitBlocksRequests(0) + + blockPool.RemovePeer("peer0") + peer, best = blockPool.getPeer("peer0") + if peer != nil { + t.Errorf("peer1 not removed") + } + + // adding back earlier peer ok + peer0.currentBlock = 3 + best = peer0.AddPeer() + if !best { + t.Errorf("peer0 (TD=1) should be set as best") + } + + if blockPool.peer.id != "peer0" { + t.Errorf("peer0 (TD=1) should be set as best") + } + peer0.waitBlocksRequests(3) + blockPool.Stop() } + +func TestPeerWithKnownBlock(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.refBlockChain[0] = nil + blockPoolTester.blockChain[0] = nil + blockPool.Start() + + peer0 := blockPoolTester.newPeer("0", 1, 0) + peer0.AddPeer() + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + // no request on known block + peer0.checkBlockHashesRequests() +} + +func TestPeerWithKnownParentBlock(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.initRefBlockChain(1) + blockPoolTester.blockChain[0] = nil + blockPool.Start() + + peer0 := blockPoolTester.newPeer("0", 1, 1) + peer0.AddPeer() + peer0.AddBlocks(0, 1) + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + peer0.checkBlocksRequests([]int{1}) + peer0.checkBlockHashesRequests() + blockPoolTester.refBlockChain[1] = []int{} + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) +} + +func TestSimpleChain(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.blockChain[0] = nil + blockPoolTester.initRefBlockChain(2) + + blockPool.Start() + + peer1 := blockPoolTester.newPeer("peer1", 1, 2) + peer1.AddPeer() + peer1.AddBlocks(1, 2) + go peer1.AddBlockHashes(2, 1, 0) + peer1.AddBlocks(0, 1) + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + blockPoolTester.refBlockChain[2] = []int{} + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) +} + +func TestChainConnectingWithParentHash(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.blockChain[0] = nil + blockPoolTester.initRefBlockChain(3) + + blockPool.Start() + + peer1 := blockPoolTester.newPeer("peer1", 1, 3) + peer1.AddPeer() + go peer1.AddBlocks(2, 3) + go peer1.AddBlockHashes(3, 2, 1) + peer1.AddBlocks(0, 1, 2) + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + blockPoolTester.refBlockChain[3] = []int{} + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) +} + +func TestInvalidBlock(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.blockChain[0] = nil + blockPoolTester.initRefBlockChain(2) + blockPoolTester.refBlockChain[2] = []int{} + + blockPool.Start() + + peer1 := blockPoolTester.newPeer("peer1", 1, 3) + peer1.AddPeer() + go peer1.AddBlocks(2, 3) + go peer1.AddBlockHashes(3, 2, 1, 0) + peer1.AddBlocks(0, 1, 2) + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + blockPoolTester.refBlockChain[2] = []int{} + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) + if len(peer1.peerErrors) == 1 { + if peer1.peerErrors[0] != ErrInvalidBlock { + t.Errorf("wrong error, got %v, expected %v", peer1.peerErrors[0], ErrInvalidBlock) + } + } else { + t.Errorf("expected invalid block error, got nothing %v", peer1.peerErrors) + } +} + +func TestVerifyPoW(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.blockChain[0] = nil + blockPoolTester.initRefBlockChain(3) + first := false + blockPoolTester.blockPool.verifyPoW = func(b pow.Block) bool { + bb, _ := b.(*types.Block) + indexes := blockPoolTester.hashPool.hashesToIndexes([][]byte{bb.Hash()}) + if indexes[0] == 2 && !first { + first = true + return false + } else { + return true + } + + } + + blockPool.Start() + + peer1 := blockPoolTester.newPeer("peer1", 1, 3) + peer1.AddPeer() + go peer1.AddBlocks(2, 3) + go peer1.AddBlockHashes(3, 2, 1, 0) + peer1.AddBlocks(0, 1, 2) + + // blockPool.Wait(waitTimeout * time.Second) + time.Sleep(1 * time.Second) + blockPool.Stop() + blockPoolTester.refBlockChain[1] = []int{} + delete(blockPoolTester.refBlockChain, 2) + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) + if len(peer1.peerErrors) == 1 { + if peer1.peerErrors[0] != ErrInvalidPoW { + t.Errorf("wrong error, got %v, expected %v", peer1.peerErrors[0], ErrInvalidPoW) + } + } else { + t.Errorf("expected invalid pow error, got nothing") + } +} + +func TestMultiSectionChain(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.blockChain[0] = nil + blockPoolTester.initRefBlockChain(5) + + blockPool.Start() + + peer1 := blockPoolTester.newPeer("peer1", 1, 5) + + peer1.AddPeer() + go peer1.AddBlocks(4, 5) + go peer1.AddBlockHashes(5, 4, 3) + go peer1.AddBlocks(2, 3, 4) + go peer1.AddBlockHashes(3, 2, 1, 0) + peer1.AddBlocks(0, 1, 2) + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + blockPoolTester.refBlockChain[5] = []int{} + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) +} + +func TestNewBlocksOnPartialChain(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.blockChain[0] = nil + blockPoolTester.initRefBlockChain(7) + blockPool.Start() + + peer1 := blockPoolTester.newPeer("peer1", 1, 5) + + peer1.AddPeer() + go peer1.AddBlocks(4, 5) // partially complete section + go peer1.AddBlockHashes(5, 4, 3) + peer1.AddBlocks(3, 4) // partially complete section + // peer1 found new blocks + peer1.td = 2 + peer1.currentBlock = 7 + peer1.AddPeer() + go peer1.AddBlocks(6, 7) + go peer1.AddBlockHashes(7, 6, 5) + go peer1.AddBlocks(2, 3) + go peer1.AddBlocks(5, 6) + go peer1.AddBlockHashes(3, 2, 1, 0) // tests that hash request from known chain root is remembered + peer1.AddBlocks(0, 1, 2) + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + blockPoolTester.refBlockChain[7] = []int{} + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) +} + +func TestPeerSwitchUp(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.blockChain[0] = nil + blockPoolTester.initRefBlockChain(7) + + blockPool.Start() + + peer1 := blockPoolTester.newPeer("peer1", 1, 6) + peer2 := blockPoolTester.newPeer("peer2", 2, 7) + peer2.blocksRequestsMap = peer1.blocksRequestsMap + + peer1.AddPeer() + go peer1.AddBlocks(5, 6) + go peer1.AddBlockHashes(6, 5, 4, 3) // + peer1.AddBlocks(2, 3) // section partially complete, block 3 will be preserved after peer demoted + peer2.AddPeer() // peer2 is promoted as best peer, peer1 is demoted + go peer2.AddBlocks(6, 7) + go peer2.AddBlockHashes(7, 6) // + go peer2.AddBlocks(4, 5) // tests that block request for earlier section is remembered + go peer1.AddBlocks(3, 4) // tests that connecting section by demoted peer is remembered and blocks are accepted from demoted peer + go peer2.AddBlockHashes(3, 2, 1, 0) // tests that known chain section is activated, hash requests from 3 is remembered + peer2.AddBlocks(0, 1, 2) // final blocks linking to blockchain sent + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + blockPoolTester.refBlockChain[7] = []int{} + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) +} + +func TestPeerSwitchDown(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.blockChain[0] = nil + blockPoolTester.initRefBlockChain(6) + blockPool.Start() + + peer1 := blockPoolTester.newPeer("peer1", 1, 4) + peer2 := blockPoolTester.newPeer("peer2", 2, 6) + peer2.blocksRequestsMap = peer1.blocksRequestsMap + + peer2.AddPeer() + peer2.AddBlocks(5, 6) // partially complete, section will be preserved + go peer2.AddBlockHashes(6, 5, 4) // + peer2.AddBlocks(4, 5) // + blockPool.RemovePeer("peer2") // peer2 disconnects + peer1.AddPeer() // inferior peer1 is promoted as best peer + go peer1.AddBlockHashes(4, 3, 2, 1, 0) // + go peer1.AddBlocks(3, 4) // tests that section set by demoted peer is remembered and blocks are accepted , this connects the chain sections together + peer1.AddBlocks(0, 1, 2, 3) + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + blockPoolTester.refBlockChain[6] = []int{} + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) +} + +func TestPeerCompleteSectionSwitchDown(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.blockChain[0] = nil + blockPoolTester.initRefBlockChain(6) + blockPool.Start() + + peer1 := blockPoolTester.newPeer("peer1", 1, 4) + peer2 := blockPoolTester.newPeer("peer2", 2, 6) + peer2.blocksRequestsMap = peer1.blocksRequestsMap + + peer2.AddPeer() + peer2.AddBlocks(5, 6) // partially complete, section will be preserved + go peer2.AddBlockHashes(6, 5, 4) // + peer2.AddBlocks(3, 4, 5) // complete section + blockPool.RemovePeer("peer2") // peer2 disconnects + peer1.AddPeer() // inferior peer1 is promoted as best peer + peer1.AddBlockHashes(4, 3, 2, 1, 0) // tests that hash request are directly connecting if the head block exists + peer1.AddBlocks(0, 1, 2, 3) + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + blockPoolTester.refBlockChain[6] = []int{} + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) +} + +func TestPeerSwitchBack(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.blockChain[0] = nil + blockPoolTester.initRefBlockChain(8) + + blockPool.Start() + + peer1 := blockPoolTester.newPeer("peer1", 2, 11) + peer2 := blockPoolTester.newPeer("peer2", 1, 8) + peer2.blocksRequestsMap = peer1.blocksRequestsMap + + peer2.AddPeer() + go peer2.AddBlocks(7, 8) + go peer2.AddBlockHashes(8, 7, 6) + go peer2.AddBlockHashes(6, 5, 4) + peer2.AddBlocks(4, 5) // section partially complete + peer1.AddPeer() // peer1 is promoted as best peer + go peer1.AddBlocks(10, 11) // + peer1.AddBlockHashes(11, 10) // only gives useless results + blockPool.RemovePeer("peer1") // peer1 disconnects + go peer2.AddBlockHashes(4, 3, 2, 1, 0) // tests that asking for hashes from 4 is remembered + go peer2.AddBlocks(3, 4, 5, 6, 7, 8) // tests that section 4, 5, 6 and 7, 8 are remembered for missing blocks + peer2.AddBlocks(0, 1, 2, 3) + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + blockPoolTester.refBlockChain[8] = []int{} + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) +} + +func TestForkSimple(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.blockChain[0] = nil + blockPoolTester.initRefBlockChain(9) + blockPoolTester.refBlockChain[3] = []int{4, 7} + delete(blockPoolTester.refBlockChain, 6) + + blockPool.Start() + + peer1 := blockPoolTester.newPeer("peer1", 1, 9) + peer2 := blockPoolTester.newPeer("peer2", 2, 6) + peer2.blocksRequestsMap = peer1.blocksRequestsMap + + peer1.AddPeer() + go peer1.AddBlocks(8, 9) + go peer1.AddBlockHashes(9, 8, 7, 3, 2) + peer1.AddBlocks(1, 2, 3, 7, 8) + peer2.AddPeer() // peer2 is promoted as best peer + go peer2.AddBlocks(5, 6) // + go peer2.AddBlockHashes(6, 5, 4, 3, 2) // fork on 3 -> 4 (earlier child: 7) + go peer2.AddBlocks(1, 2, 3, 4, 5) + go peer2.AddBlockHashes(2, 1, 0) + peer2.AddBlocks(0, 1, 2) + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + blockPoolTester.refBlockChain[6] = []int{} + blockPoolTester.refBlockChain[3] = []int{4} + delete(blockPoolTester.refBlockChain, 7) + delete(blockPoolTester.refBlockChain, 8) + delete(blockPoolTester.refBlockChain, 9) + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) + +} + +func TestForkSwitchBackByNewBlocks(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.blockChain[0] = nil + blockPoolTester.initRefBlockChain(11) + blockPoolTester.refBlockChain[3] = []int{4, 7} + delete(blockPoolTester.refBlockChain, 6) + + blockPool.Start() + + peer1 := blockPoolTester.newPeer("peer1", 1, 9) + peer2 := blockPoolTester.newPeer("peer2", 2, 6) + peer2.blocksRequestsMap = peer1.blocksRequestsMap + + peer1.AddPeer() + peer1.AddBlocks(8, 9) // + go peer1.AddBlockHashes(9, 8, 7, 3, 2) // + peer1.AddBlocks(7, 8) // partial section + peer2.AddPeer() // + peer2.AddBlocks(5, 6) // + go peer2.AddBlockHashes(6, 5, 4, 3, 2) // peer2 forks on block 3 + peer2.AddBlocks(1, 2, 3, 4, 5) // + + // peer1 finds new blocks + peer1.td = 3 + peer1.currentBlock = 11 + peer1.AddPeer() + go peer1.AddBlocks(10, 11) + go peer1.AddBlockHashes(11, 10, 9) + peer1.AddBlocks(9, 10) + go peer1.AddBlocks(3, 7) // tests that block requests on earlier fork are remembered + go peer1.AddBlockHashes(2, 1, 0) // tests that hash request from root of connecting chain section (added by demoted peer) is remembered + peer1.AddBlocks(0, 1) + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + blockPoolTester.refBlockChain[11] = []int{} + blockPoolTester.refBlockChain[3] = []int{7} + delete(blockPoolTester.refBlockChain, 6) + delete(blockPoolTester.refBlockChain, 5) + delete(blockPoolTester.refBlockChain, 4) + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) + +} + +func TestForkSwitchBackByPeerSwitchBack(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.blockChain[0] = nil + blockPoolTester.initRefBlockChain(9) + blockPoolTester.refBlockChain[3] = []int{4, 7} + delete(blockPoolTester.refBlockChain, 6) + + blockPool.Start() + + peer1 := blockPoolTester.newPeer("peer1", 1, 9) + peer2 := blockPoolTester.newPeer("peer2", 2, 6) + peer2.blocksRequestsMap = peer1.blocksRequestsMap + + peer1.AddPeer() + go peer1.AddBlocks(8, 9) + go peer1.AddBlockHashes(9, 8, 7, 3, 2) + peer1.AddBlocks(7, 8) + peer2.AddPeer() + go peer2.AddBlocks(5, 6) // + go peer2.AddBlockHashes(6, 5, 4, 3, 2) // peer2 forks on block 3 + peer2.AddBlocks(2, 3, 4, 5) // + blockPool.RemovePeer("peer2") // peer2 disconnects, peer1 is promoted again as best peer + go peer1.AddBlocks(3, 7) // tests that block requests on earlier fork are remembered and orphan section relinks to existing parent block + go peer1.AddBlocks(1, 2) // + go peer1.AddBlockHashes(2, 1, 0) // + peer1.AddBlocks(0, 1) + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + blockPoolTester.refBlockChain[9] = []int{} + blockPoolTester.refBlockChain[3] = []int{7} + delete(blockPoolTester.refBlockChain, 6) + delete(blockPoolTester.refBlockChain, 5) + delete(blockPoolTester.refBlockChain, 4) + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) + +} + +func TestForkCompleteSectionSwitchBackByPeerSwitchBack(t *testing.T) { + logInit() + _, blockPool, blockPoolTester := newTestBlockPool(t) + blockPoolTester.blockChain[0] = nil + blockPoolTester.initRefBlockChain(9) + blockPoolTester.refBlockChain[3] = []int{4, 7} + delete(blockPoolTester.refBlockChain, 6) + + blockPool.Start() + + peer1 := blockPoolTester.newPeer("peer1", 1, 9) + peer2 := blockPoolTester.newPeer("peer2", 2, 6) + peer2.blocksRequestsMap = peer1.blocksRequestsMap + + peer1.AddPeer() + go peer1.AddBlocks(8, 9) + go peer1.AddBlockHashes(9, 8, 7) + peer1.AddBlocks(3, 7, 8) // make sure this section is complete + time.Sleep(1 * time.Second) + go peer1.AddBlockHashes(7, 3, 2) // block 3/7 is section boundary + peer1.AddBlocks(2, 3) // partially complete sections block 2 missing + peer2.AddPeer() // + go peer2.AddBlocks(5, 6) // + go peer2.AddBlockHashes(6, 5, 4, 3, 2) // peer2 forks on block 3 + peer2.AddBlocks(2, 3, 4, 5) // block 2 still missing. + blockPool.RemovePeer("peer2") // peer2 disconnects, peer1 is promoted again as best peer + // peer1.AddBlockHashes(7, 3) // tests that hash request from fork root is remembered even though section process completed + go peer1.AddBlockHashes(2, 1, 0) // + peer1.AddBlocks(0, 1, 2) + + blockPool.Wait(waitTimeout * time.Second) + blockPool.Stop() + blockPoolTester.refBlockChain[9] = []int{} + blockPoolTester.refBlockChain[3] = []int{7} + delete(blockPoolTester.refBlockChain, 6) + delete(blockPoolTester.refBlockChain, 5) + delete(blockPoolTester.refBlockChain, 4) + blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) + +} diff --git a/eth/error.go b/eth/error.go index d1daad5750..9c4a684818 100644 --- a/eth/error.go +++ b/eth/error.go @@ -16,6 +16,7 @@ const ( ErrInvalidBlock ErrInvalidPoW ErrUnrequestedBlock + ErrInsufficientChainInfo ) var errorToString = map[int]string{ @@ -30,6 +31,7 @@ var errorToString = map[int]string{ ErrInvalidBlock: "Invalid block", ErrInvalidPoW: "Invalid PoW", ErrUnrequestedBlock: "Unrequested block", + ErrInsufficientChainInfo: "Insufficient chain info", } type protocolError struct { @@ -52,18 +54,17 @@ func ProtocolError(code int, format string, params ...interface{}) (err *protoco } func (self protocolError) Error() (message string) { - message = self.message - if message == "" { - message, ok := errorToString[self.Code] + if len(message) == 0 { + var ok bool + self.message, ok = errorToString[self.Code] if !ok { panic("invalid error code") } if self.format != "" { - message += ": " + fmt.Sprintf(self.format, self.params...) + self.message += ": " + fmt.Sprintf(self.format, self.params...) } - self.message = message } - return + return self.message } func (self *protocolError) Fatal() bool { diff --git a/eth/protocol.go b/eth/protocol.go index 3b6f95d440..24a0f0a8e8 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -3,7 +3,7 @@ package eth import ( "bytes" "fmt" - "math" + "io" "math/big" "github.com/ethereum/go-ethereum/core/types" @@ -13,7 +13,7 @@ import ( ) const ( - ProtocolVersion = 49 + ProtocolVersion = 51 NetworkId = 0 ProtocolLength = uint64(8) ProtocolMaxMsgSize = 10 * 1024 * 1024 @@ -67,6 +67,8 @@ type newBlockMsgData struct { TD *big.Int } +const maxHashes = 255 + type getBlockHashesMsgData struct { Hash []byte Amount uint64 @@ -95,14 +97,13 @@ func runEthProtocol(txPool txPool, chainManager chainManager, blockPool blockPoo blockPool: blockPool, rw: rw, peer: peer, - id: (string)(peer.Identity().Pubkey()), + id: fmt.Sprintf("%x", peer.Identity().Pubkey()[:8]), } err = self.handleStatus() if err == nil { for { err = self.handle() if err != nil { - fmt.Println(err) self.blockPool.RemovePeer(self.id) break } @@ -117,112 +118,118 @@ func (self *ethProtocol) handle() error { return err } if msg.Size > ProtocolMaxMsgSize { - return ProtocolError(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) + return self.protoError(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) } // make sure that the payload has been fully consumed defer msg.Discard() switch msg.Code { - + case GetTxMsg: // ignore case StatusMsg: - return ProtocolError(ErrExtraStatusMsg, "") + return self.protoError(ErrExtraStatusMsg, "") case TxMsg: // TODO: rework using lazy RLP stream var txs []*types.Transaction if err := msg.Decode(&txs); err != nil { - return ProtocolError(ErrDecode, "%v", err) + return self.protoError(ErrDecode, "msg %v: %v", msg, err) } self.txPool.AddTransactions(txs) case GetBlockHashesMsg: var request getBlockHashesMsgData if err := msg.Decode(&request); err != nil { - return ProtocolError(ErrDecode, "%v", err) + return self.protoError(ErrDecode, "->msg %v: %v", msg, err) + } + + //request.Amount = uint64(math.Min(float64(maxHashes), float64(request.Amount))) + if request.Amount > maxHashes { + request.Amount = maxHashes } hashes := self.chainManager.GetBlockHashesFromHash(request.Hash, request.Amount) - return self.rw.EncodeMsg(BlockHashesMsg, ethutil.ByteSliceToInterface(hashes)...) + return p2p.EncodeMsg(self.rw, BlockHashesMsg, ethutil.ByteSliceToInterface(hashes)...) case BlockHashesMsg: // TODO: redo using lazy decode , this way very inefficient on known chains - msgStream := rlp.NewListStream(msg.Payload, uint64(msg.Size)) + msgStream := rlp.NewStream(msg.Payload) var err error + var i int + iter := func() (hash []byte, ok bool) { hash, err = msgStream.Bytes() if err == nil { + i++ ok = true + } else { + if err != io.EOF { + self.protoError(ErrDecode, "msg %v: after %v hashes : %v", msg, i, err) + } } return } + self.blockPool.AddBlockHashes(iter, self.id) - if err != nil && err != rlp.EOL { - return ProtocolError(ErrDecode, "%v", err) - } case GetBlocksMsg: - var blockHashes [][]byte - if err := msg.Decode(&blockHashes); err != nil { - return ProtocolError(ErrDecode, "%v", err) - } - max := int(math.Min(float64(len(blockHashes)), blockHashesBatchSize)) + msgStream := rlp.NewStream(msg.Payload) var blocks []interface{} - for i, hash := range blockHashes { - if i >= max { - break + var i int + for { + i++ + var hash []byte + if err := msgStream.Decode(&hash); err != nil { + if err == io.EOF { + break + } else { + return self.protoError(ErrDecode, "msg %v: %v", msg, err) + } } block := self.chainManager.GetBlock(hash) if block != nil { - blocks = append(blocks, block.Value().Raw()) + blocks = append(blocks, block) + } + if i == blockHashesBatchSize { + break } } - return self.rw.EncodeMsg(BlocksMsg, blocks...) + return p2p.EncodeMsg(self.rw, BlocksMsg, blocks...) case BlocksMsg: - msgStream := rlp.NewListStream(msg.Payload, uint64(msg.Size)) + msgStream := rlp.NewStream(msg.Payload) for { - var block *types.Block + var block types.Block if err := msgStream.Decode(&block); err != nil { - if err == rlp.EOL { + if err == io.EOF { break } else { - return ProtocolError(ErrDecode, "%v", err) + return self.protoError(ErrDecode, "msg %v: %v", msg, err) } } - self.blockPool.AddBlock(block, self.id) + self.blockPool.AddBlock(&block, self.id) } case NewBlockMsg: var request newBlockMsgData if err := msg.Decode(&request); err != nil { - return ProtocolError(ErrDecode, "%v", err) + return self.protoError(ErrDecode, "msg %v: %v", msg, err) } hash := request.Block.Hash() // to simplify backend interface adding a new block // uses AddPeer followed by AddHashes, AddBlock only if peer is the best peer // (or selected as new best peer) if self.blockPool.AddPeer(request.TD, hash, self.id, self.requestBlockHashes, self.requestBlocks, self.protoErrorDisconnect) { - called := true - iter := func() (hash []byte, ok bool) { - if called { - called = false - return hash, true - } else { - return - } - } - self.blockPool.AddBlockHashes(iter, self.id) self.blockPool.AddBlock(request.Block, self.id) } default: - return ProtocolError(ErrInvalidMsgCode, "%v", msg.Code) + return self.protoError(ErrInvalidMsgCode, "%v", msg.Code) } return nil } type statusMsgData struct { - ProtocolVersion uint - NetworkId uint + ProtocolVersion uint32 + NetworkId uint32 TD *big.Int CurrentBlock []byte GenesisBlock []byte @@ -253,56 +260,56 @@ func (self *ethProtocol) handleStatus() error { } if msg.Code != StatusMsg { - return ProtocolError(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg) + return self.protoError(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg) } if msg.Size > ProtocolMaxMsgSize { - return ProtocolError(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) + return self.protoError(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) } var status statusMsgData if err := msg.Decode(&status); err != nil { - return ProtocolError(ErrDecode, "%v", err) + return self.protoError(ErrDecode, "msg %v: %v", msg, err) } _, _, genesisBlock := self.chainManager.Status() if bytes.Compare(status.GenesisBlock, genesisBlock) != 0 { - return ProtocolError(ErrGenesisBlockMismatch, "%x (!= %x)", status.GenesisBlock, genesisBlock) + return self.protoError(ErrGenesisBlockMismatch, "%x (!= %x)", status.GenesisBlock, genesisBlock) } if status.NetworkId != NetworkId { - return ProtocolError(ErrNetworkIdMismatch, "%d (!= %d)", status.NetworkId, NetworkId) + return self.protoError(ErrNetworkIdMismatch, "%d (!= %d)", status.NetworkId, NetworkId) } if ProtocolVersion != status.ProtocolVersion { - return ProtocolError(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, ProtocolVersion) + return self.protoError(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, ProtocolVersion) } self.peer.Infof("Peer is [eth] capable (%d/%d). TD=%v H=%x\n", status.ProtocolVersion, status.NetworkId, status.TD, status.CurrentBlock[:4]) - //self.blockPool.AddPeer(status.TD, status.CurrentBlock, self.id, self.requestBlockHashes, self.requestBlocks, self.protoErrorDisconnect) - self.peer.Infoln("AddPeer(IGNORED)") + self.blockPool.AddPeer(status.TD, status.CurrentBlock, self.id, self.requestBlockHashes, self.requestBlocks, self.protoErrorDisconnect) return nil } func (self *ethProtocol) requestBlockHashes(from []byte) error { self.peer.Debugf("fetching hashes (%d) %x...\n", blockHashesBatchSize, from[0:4]) - return self.rw.EncodeMsg(GetBlockHashesMsg, from, blockHashesBatchSize) + return p2p.EncodeMsg(self.rw, GetBlockHashesMsg, interface{}(from), uint64(blockHashesBatchSize)) } func (self *ethProtocol) requestBlocks(hashes [][]byte) error { self.peer.Debugf("fetching %v blocks", len(hashes)) - return self.rw.EncodeMsg(GetBlocksMsg, ethutil.ByteSliceToInterface(hashes)) + return p2p.EncodeMsg(self.rw, GetBlocksMsg, ethutil.ByteSliceToInterface(hashes)...) } func (self *ethProtocol) protoError(code int, format string, params ...interface{}) (err *protocolError) { err = ProtocolError(code, format, params...) if err.Fatal() { - self.peer.Errorln(err) + self.peer.Errorln("err %v", err) + // disconnect } else { - self.peer.Debugln(err) + self.peer.Debugf("fyi %v", err) } return } @@ -310,10 +317,10 @@ func (self *ethProtocol) protoError(code int, format string, params ...interface func (self *ethProtocol) protoErrorDisconnect(code int, format string, params ...interface{}) { err := ProtocolError(code, format, params...) if err.Fatal() { - self.peer.Errorln(err) + self.peer.Errorln("err %v", err) // disconnect } else { - self.peer.Debugln(err) + self.peer.Debugf("fyi %v", err) } } diff --git a/eth/protocol_test.go b/eth/protocol_test.go index 322aec7b70..224b59abd3 100644 --- a/eth/protocol_test.go +++ b/eth/protocol_test.go @@ -1,37 +1,46 @@ package eth import ( + "bytes" "io" + "log" "math/big" + "os" "testing" + "time" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethutil" + ethlogger "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/p2p" ) +var sys = ethlogger.NewStdLogSystem(os.Stdout, log.LstdFlags, ethlogger.LogLevel(ethlogger.DebugDetailLevel)) + type testMsgReadWriter struct { in chan p2p.Msg - out chan p2p.Msg + out []p2p.Msg } func (self *testMsgReadWriter) In(msg p2p.Msg) { self.in <- msg } -func (self *testMsgReadWriter) Out(msg p2p.Msg) { - self.in <- msg +func (self *testMsgReadWriter) Out() (msg p2p.Msg, ok bool) { + if len(self.out) > 0 { + msg = self.out[0] + self.out = self.out[1:] + ok = true + } + return } func (self *testMsgReadWriter) WriteMsg(msg p2p.Msg) error { - self.out <- msg + self.out = append(self.out, msg) return nil } -func (self *testMsgReadWriter) EncodeMsg(code uint64, data ...interface{}) error { - return self.WriteMsg(p2p.NewMsg(code, data)) -} - func (self *testMsgReadWriter) ReadMsg() (p2p.Msg, error) { msg, ok := <-self.in if !ok { @@ -40,145 +49,83 @@ func (self *testMsgReadWriter) ReadMsg() (p2p.Msg, error) { return msg, nil } -func errorCheck(t *testing.T, expCode int, err error) { - perr, ok := err.(*protocolError) - if ok && perr != nil { - if code := perr.Code; code != expCode { - ok = false - } - } - if !ok { - t.Errorf("expected error code %v, got %v", ErrNoStatusMsg, err) - } -} - -type TestBackend struct { +type testTxPool struct { getTransactions func() []*types.Transaction addTransactions func(txs []*types.Transaction) - getBlockHashes func(hash []byte, amount uint32) (hashes [][]byte) - addBlockHashes func(next func() ([]byte, bool), peerId string) - getBlock func(hash []byte) *types.Block - addBlock func(block *types.Block, peerId string) (err error) - addPeer func(td *big.Int, currentBlock []byte, peerId string, requestHashes func([]byte) error, requestBlocks func([][]byte) error, invalidBlock func(error)) (best bool) - removePeer func(peerId string) - status func() (td *big.Int, currentBlock []byte, genesisBlock []byte) } -func (self *TestBackend) GetTransactions() (txs []*types.Transaction) { - if self.getTransactions != nil { - txs = self.getTransactions() - } - return +type testChainManager struct { + getBlockHashes func(hash []byte, amount uint64) (hashes [][]byte) + getBlock func(hash []byte) *types.Block + status func() (td *big.Int, currentBlock []byte, genesisBlock []byte) } -func (self *TestBackend) AddTransactions(txs []*types.Transaction) { +type testBlockPool struct { + addBlockHashes func(next func() ([]byte, bool), peerId string) + addBlock func(block *types.Block, peerId string) (err error) + addPeer func(td *big.Int, currentBlock []byte, peerId string, requestHashes func([]byte) error, requestBlocks func([][]byte) error, peerError func(int, string, ...interface{})) (best bool) + removePeer func(peerId string) +} + +// func (self *testTxPool) GetTransactions() (txs []*types.Transaction) { +// if self.getTransactions != nil { +// txs = self.getTransactions() +// } +// return +// } + +func (self *testTxPool) AddTransactions(txs []*types.Transaction) { if self.addTransactions != nil { self.addTransactions(txs) } } -func (self *TestBackend) GetBlockHashes(hash []byte, amount uint32) (hashes [][]byte) { +func (self *testChainManager) GetBlockHashesFromHash(hash []byte, amount uint64) (hashes [][]byte) { if self.getBlockHashes != nil { hashes = self.getBlockHashes(hash, amount) } return } -<<<<<<< HEAD -<<<<<<< HEAD -func (self *TestBackend) AddBlockHashes(next func() ([]byte, bool), peerId string) { - if self.addBlockHashes != nil { - self.addBlockHashes(next, peerId) - } -} - -======= -func (self *TestBackend) AddHash(hash []byte, peer *p2p.Peer) (more bool) { - if self.addHash != nil { - more = self.addHash(hash, peer) -======= -func (self *TestBackend) AddBlockHashes(next func() ([]byte, bool), peerId string) { - if self.addBlockHashes != nil { - self.addBlockHashes(next, peerId) ->>>>>>> eth protocol changes - } -} -<<<<<<< HEAD ->>>>>>> initial commit for eth-p2p integration -======= - ->>>>>>> eth protocol changes -func (self *TestBackend) GetBlock(hash []byte) (block *types.Block) { - if self.getBlock != nil { - block = self.getBlock(hash) - } - return -} - -<<<<<<< HEAD -<<<<<<< HEAD -func (self *TestBackend) AddBlock(block *types.Block, peerId string) (err error) { - if self.addBlock != nil { - err = self.addBlock(block, peerId) -======= -func (self *TestBackend) AddBlock(td *big.Int, block *types.Block, peer *p2p.Peer) (fetchHashes bool, err error) { - if self.addBlock != nil { - fetchHashes, err = self.addBlock(td, block, peer) ->>>>>>> initial commit for eth-p2p integration -======= -func (self *TestBackend) AddBlock(block *types.Block, peerId string) (err error) { - if self.addBlock != nil { - err = self.addBlock(block, peerId) ->>>>>>> eth protocol changes - } - return -} - -<<<<<<< HEAD -<<<<<<< HEAD -func (self *TestBackend) AddPeer(td *big.Int, currentBlock []byte, peerId string, requestBlockHashes func([]byte) error, requestBlocks func([][]byte) error, invalidBlock func(error)) (best bool) { - if self.addPeer != nil { - best = self.addPeer(td, currentBlock, peerId, requestBlockHashes, requestBlocks, invalidBlock) -======= -func (self *TestBackend) AddPeer(td *big.Int, currentBlock []byte, peer *p2p.Peer) (fetchHashes bool) { - if self.addPeer != nil { - fetchHashes = self.addPeer(td, currentBlock, peer) ->>>>>>> initial commit for eth-p2p integration -======= -func (self *TestBackend) AddPeer(td *big.Int, currentBlock []byte, peerId string, requestBlockHashes func([]byte) error, requestBlocks func([][]byte) error, invalidBlock func(error)) (best bool) { - if self.addPeer != nil { - best = self.addPeer(td, currentBlock, peerId, requestBlockHashes, requestBlocks, invalidBlock) ->>>>>>> eth protocol changes - } - return -} - -<<<<<<< HEAD -<<<<<<< HEAD -======= ->>>>>>> eth protocol changes -func (self *TestBackend) RemovePeer(peerId string) { - if self.removePeer != nil { - self.removePeer(peerId) - } -} - -<<<<<<< HEAD -======= ->>>>>>> initial commit for eth-p2p integration -======= ->>>>>>> eth protocol changes -func (self *TestBackend) Status() (td *big.Int, currentBlock []byte, genesisBlock []byte) { +func (self *testChainManager) Status() (td *big.Int, currentBlock []byte, genesisBlock []byte) { if self.status != nil { td, currentBlock, genesisBlock = self.status() } return } -<<<<<<< HEAD -<<<<<<< HEAD -======= ->>>>>>> eth protocol changes +func (self *testChainManager) GetBlock(hash []byte) (block *types.Block) { + if self.getBlock != nil { + block = self.getBlock(hash) + } + return +} + +func (self *testBlockPool) AddBlockHashes(next func() ([]byte, bool), peerId string) { + if self.addBlockHashes != nil { + self.addBlockHashes(next, peerId) + } +} + +func (self *testBlockPool) AddBlock(block *types.Block, peerId string) { + if self.addBlock != nil { + self.addBlock(block, peerId) + } +} + +func (self *testBlockPool) AddPeer(td *big.Int, currentBlock []byte, peerId string, requestBlockHashes func([]byte) error, requestBlocks func([][]byte) error, peerError func(int, string, ...interface{})) (best bool) { + if self.addPeer != nil { + best = self.addPeer(td, currentBlock, peerId, requestBlockHashes, requestBlocks, peerError) + } + return +} + +func (self *testBlockPool) RemovePeer(peerId string) { + if self.removePeer != nil { + self.removePeer(peerId) + } +} + // TODO: refactor this into p2p/client_identity type peerId struct { pubkey []byte @@ -201,32 +148,119 @@ func testPeer() *p2p.Peer { return p2p.NewPeer(&peerId{}, []p2p.Cap{}) } -func TestErrNoStatusMsg(t *testing.T) { -<<<<<<< HEAD -======= -func TestEth(t *testing.T) { ->>>>>>> initial commit for eth-p2p integration -======= ->>>>>>> eth protocol changes - quit := make(chan bool) - rw := &testMsgReadWriter{make(chan p2p.Msg, 10), make(chan p2p.Msg, 10)} - testBackend := &TestBackend{} - var err error - go func() { -<<<<<<< HEAD -<<<<<<< HEAD - err = runEthProtocol(testBackend, testPeer(), rw) -======= - err = runEthProtocol(testBackend, nil, rw) ->>>>>>> initial commit for eth-p2p integration -======= - err = runEthProtocol(testBackend, testPeer(), rw) ->>>>>>> eth protocol changes - close(quit) - }() - statusMsg := p2p.NewMsg(4) - rw.In(statusMsg) - <-quit - errorCheck(t, ErrNoStatusMsg, err) - // read(t, remote, []byte("hello, world"), nil) +type ethProtocolTester struct { + quit chan error + rw *testMsgReadWriter // p2p.MsgReadWriter + txPool *testTxPool // txPool + chainManager *testChainManager // chainManager + blockPool *testBlockPool // blockPool + t *testing.T +} + +func newEth(t *testing.T) *ethProtocolTester { + return ðProtocolTester{ + quit: make(chan error), + rw: &testMsgReadWriter{in: make(chan p2p.Msg, 10)}, + txPool: &testTxPool{}, + chainManager: &testChainManager{}, + blockPool: &testBlockPool{}, + t: t, + } +} + +func (self *ethProtocolTester) reset() { + self.rw = &testMsgReadWriter{in: make(chan p2p.Msg, 10)} + self.quit = make(chan error) +} + +func (self *ethProtocolTester) checkError(expCode int, delay time.Duration) (err error) { + var timer = time.After(delay) + select { + case err = <-self.quit: + case <-timer: + self.t.Errorf("no error after %v, expected %v", delay, expCode) + return + } + perr, ok := err.(*protocolError) + if ok && perr != nil { + if code := perr.Code; code != expCode { + self.t.Errorf("expected protocol error (code %v), got %v (%v)", expCode, code, err) + } + } else { + self.t.Errorf("expected protocol error (code %v), got %v", expCode, err) + } + return +} + +func (self *ethProtocolTester) In(msg p2p.Msg) { + self.rw.In(msg) +} + +func (self *ethProtocolTester) Out() (p2p.Msg, bool) { + return self.rw.Out() +} + +func (self *ethProtocolTester) checkMsg(i int, code uint64, val interface{}) (msg p2p.Msg) { + if i >= len(self.rw.out) { + self.t.Errorf("expected at least %v msgs, got %v", i, len(self.rw.out)) + return + } + msg = self.rw.out[i] + if msg.Code != code { + self.t.Errorf("expected msg code %v, got %v", code, msg.Code) + } + if val != nil { + if err := msg.Decode(val); err != nil { + self.t.Errorf("rlp encoding error: %v", err) + } + } + return +} + +func (self *ethProtocolTester) run() { + err := runEthProtocol(self.txPool, self.chainManager, self.blockPool, testPeer(), self.rw) + self.quit <- err +} + +func TestStatusMsgErrors(t *testing.T) { + logInit() + eth := newEth(t) + td := ethutil.Big1 + currentBlock := []byte{1} + genesis := []byte{2} + eth.chainManager.status = func() (*big.Int, []byte, []byte) { return td, currentBlock, genesis } + go eth.run() + statusMsg := p2p.NewMsg(4) + eth.In(statusMsg) + delay := 1 * time.Second + eth.checkError(ErrNoStatusMsg, delay) + var status statusMsgData + eth.checkMsg(0, StatusMsg, &status) // first outgoing msg should be StatusMsg + if status.TD.Cmp(td) != 0 || + status.ProtocolVersion != ProtocolVersion || + status.NetworkId != NetworkId || + status.TD.Cmp(td) != 0 || + bytes.Compare(status.CurrentBlock, currentBlock) != 0 || + bytes.Compare(status.GenesisBlock, genesis) != 0 { + t.Errorf("incorrect outgoing status") + } + + eth.reset() + go eth.run() + statusMsg = p2p.NewMsg(0, uint32(48), uint32(0), td, currentBlock, genesis) + eth.In(statusMsg) + eth.checkError(ErrProtocolVersionMismatch, delay) + + eth.reset() + go eth.run() + statusMsg = p2p.NewMsg(0, uint32(49), uint32(1), td, currentBlock, genesis) + eth.In(statusMsg) + eth.checkError(ErrNetworkIdMismatch, delay) + + eth.reset() + go eth.run() + statusMsg = p2p.NewMsg(0, uint32(49), uint32(0), td, currentBlock, []byte{3}) + eth.In(statusMsg) + eth.checkError(ErrGenesisBlockMismatch, delay) + } diff --git a/eth/test/README.md b/eth/test/README.md new file mode 100644 index 0000000000..65728efa5b --- /dev/null +++ b/eth/test/README.md @@ -0,0 +1,27 @@ += Integration tests for eth protocol and blockpool + +This is a simple suite of tests to fire up a local test node with peers to test blockchain synchronisation and download. +The scripts call ethereum (assumed to be compiled in go-ethereum root). + +To run a test: + + . run.sh 00 02 + +Without arguments, all tests are run. + +Peers are launched with preloaded imported chains. In order to prevent them from synchronizing with each other they are set with `-dial=false` and `-maxpeer 1` options. They log into `/tmp/eth.test/nodes/XX` where XX is the last two digits of their port. + +Chains to import can be bootstrapped by letting nodes mine for some time. This is done with + + . bootstrap.sh + +Only the relative timing and forks matter so they should work if the bootstrap script is rerun. +The reference blockchain of tests are soft links to these import chains and check at the end of a test run. + +Connecting to peers and exporting blockchain is scripted with JS files executed by the JSRE, see `tests/XX.sh`. + +Each test is set with a timeout. This may vary on different computers so adjust sensibly. +If you kill a test before it completes, do not forget to kill all the background processes, since they will impact the result. Use: + + killall ethereum + diff --git a/eth/test/bootstrap.sh b/eth/test/bootstrap.sh new file mode 100644 index 0000000000..3da038be8b --- /dev/null +++ b/eth/test/bootstrap.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# bootstrap chains - used to regenerate tests/chains/*.chain + +mkdir -p chains +bash ./mine.sh 00 10 +bash ./mine.sh 01 5 00 +bash ./mine.sh 02 10 00 +bash ./mine.sh 03 5 02 +bash ./mine.sh 04 10 02 \ No newline at end of file diff --git a/eth/test/chains/00.chain b/eth/test/chains/00.chain new file mode 100755 index 0000000000..ad3c05b24a Binary files /dev/null and b/eth/test/chains/00.chain differ diff --git a/eth/test/chains/01.chain b/eth/test/chains/01.chain new file mode 100755 index 0000000000..56c9aef65f Binary files /dev/null and b/eth/test/chains/01.chain differ diff --git a/eth/test/chains/02.chain b/eth/test/chains/02.chain new file mode 100755 index 0000000000..440c92d658 Binary files /dev/null and b/eth/test/chains/02.chain differ diff --git a/eth/test/chains/03.chain b/eth/test/chains/03.chain new file mode 100755 index 0000000000..1cc7570ab4 Binary files /dev/null and b/eth/test/chains/03.chain differ diff --git a/eth/test/chains/04.chain b/eth/test/chains/04.chain new file mode 100755 index 0000000000..d4e5b1aa81 Binary files /dev/null and b/eth/test/chains/04.chain differ diff --git a/eth/test/mine.sh b/eth/test/mine.sh new file mode 100644 index 0000000000..0d95db1e43 --- /dev/null +++ b/eth/test/mine.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# bash ./mine.sh node_id timeout(sec) [basechain] +ETH=../../ethereum +MINE="$ETH -datadir tmp/nodes/$1 -seed=false -port '' -shh=false -id test$1" +rm -rf tmp/nodes/$1 +echo "Creating chain $1..." +if [[ "" != "$3" ]]; then + CHAIN="chains/$3.chain" + CHAINARG="-chain $CHAIN" + $MINE -mine $CHAINARG -loglevel 3 | grep 'importing' +fi +$MINE -mine -loglevel 0 & +PID=$! +sleep $2 +kill $PID +$MINE -loglevel 3 <(echo "eth.export(\"chains/$1.chain\")") > /tmp/eth.test/mine.tmp & +PID=$! +sleep 1 +kill $PID +cat /tmp/eth.test/mine.tmp | grep 'exporting' diff --git a/eth/test/run.sh b/eth/test/run.sh new file mode 100644 index 0000000000..5229af0353 --- /dev/null +++ b/eth/test/run.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# bash run.sh (testid0 testid1 ...) +# runs tests tests/testid0.sh tests/testid1.sh ... +# without arguments, it runs all tests + +. tests/common.sh + +TESTS= + +if [ "$#" -eq 0 ]; then + for NAME in tests/??.sh; do + i=`basename $NAME .sh` + TESTS="$TESTS $i" + done +else + TESTS=$@ +fi + +ETH=../../ethereum +DIR="/tmp/eth.test/nodes" +TIMEOUT=10 + +mkdir -p $DIR/js + +echo "running tests $TESTS" +for NAME in $TESTS; do + PIDS= + CHAIN="tests/$NAME.chain" + JSFILE="$DIR/js/$NAME.js" + CHAIN_TEST="$DIR/$NAME/chain" + + echo "RUN: test $NAME" + cat tests/common.js > $JSFILE + . tests/$NAME.sh + sleep $TIMEOUT + echo "timeout after $TIMEOUT seconds: killing $PIDS" + kill $PIDS + if [ -r "$CHAIN" ]; then + if diff $CHAIN $CHAIN_TEST >/dev/null ; then + echo "chain ok: $CHAIN=$CHAIN_TEST" + else + echo "FAIL: chains differ: expected $CHAIN ; got $CHAIN_TEST" + continue + fi + fi + ERRORS=$DIR/errors + if [ -r "$ERRORS" ]; then + echo "FAIL: " + cat $ERRORS + else + echo PASS + fi +done \ No newline at end of file diff --git a/eth/test/tests/00.chain b/eth/test/tests/00.chain new file mode 120000 index 0000000000..9655cb3df7 --- /dev/null +++ b/eth/test/tests/00.chain @@ -0,0 +1 @@ +../chains/01.chain \ No newline at end of file diff --git a/eth/test/tests/00.sh b/eth/test/tests/00.sh new file mode 100644 index 0000000000..9c5077164b --- /dev/null +++ b/eth/test/tests/00.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +TIMEOUT=4 + +cat >> $JSFILE <> $JSFILE <> $JSFILE <> $JSFILE <> $JSFILE <> $JSFILE < 1 && path[:2] == "~/" { usr, _ := user.Current() dir := usr.HomeDir @@ -58,3 +59,10 @@ func WriteFile(filePath string, content []byte) error { return nil } + +func AbsolutePath(Datadir string, filename string) string { + if path.IsAbs(filename) { + return filename + } + return path.Join(Datadir, filename) +} diff --git a/ethutil/rlp.go b/ethutil/rlp.go index 1bc1a58a71..0cb0d611ce 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -137,7 +137,7 @@ func Encode(object interface{}) []byte { case byte: buff.Write(Encode(big.NewInt(int64(t)))) case *big.Int: - // Not sure how this is possible while we check for + // Not sure how this is possible while we check for nil if t == nil { buff.WriteByte(0xc0) } else { diff --git a/gocoverage.sh b/gocoverage.sh index 35038108b9..24c8e92801 100755 --- a/gocoverage.sh +++ b/gocoverage.sh @@ -13,7 +13,10 @@ for dir in $(find . -maxdepth 10 -not -path './.git*' -not -path '*/_*' -type d) do if ls $dir/*.go &> /dev/null; then # echo $dir - go test -covermode=count -coverprofile=$dir/profile.tmp $dir + if [[ $dir != "./tests/vm" ]] + then + go test -covermode=count -coverprofile=$dir/profile.tmp $dir + fi if [ -f $dir/profile.tmp ] then cat $dir/profile.tmp | tail -n +2 >> profile.cov @@ -26,4 +29,4 @@ go tool cover -func profile.cov # To submit the test coverage result to coveralls.io, # use goveralls (https://github.com/mattn/goveralls) -# goveralls -coverprofile=profile.cov -service=travis-ci +goveralls -coverprofile=profile.cov -service=travis-ci -repotoken $COVERALLS_TOKEN diff --git a/install_deps.sh b/install_deps.sh deleted file mode 100755 index 73a3133244..0000000000 --- a/install_deps.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -set -e - -TEST_DEPS=$(go list -f '{{.Imports}} {{.TestImports}} {{.XTestImports}}' github.com/ethereum/go-ethereum/... | sed -e 's/\[//g' | sed -e 's/\]//g' | sed -e 's/C //g') -if [ "$TEST_DEPS" ]; then - go get -race $TEST_DEPS -fi diff --git a/javascript/javascript_runtime.go b/javascript/javascript_runtime.go index af1405049f..adc9022b74 100644 --- a/javascript/javascript_runtime.go +++ b/javascript/javascript_runtime.go @@ -129,10 +129,9 @@ func (self *JSRE) initStdFuncs() { */ func (self *JSRE) dump(call otto.FunctionCall) otto.Value { - var state *state.StateDB + var block *types.Block if len(call.ArgumentList) > 0 { - var block *types.Block if call.Argument(0).IsNumber() { num, _ := call.Argument(0).ToInteger() block = self.ethereum.ChainManager().GetBlockByNumber(uint64(num)) @@ -149,12 +148,12 @@ func (self *JSRE) dump(call otto.FunctionCall) otto.Value { return otto.UndefinedValue() } - state = block.State() } else { - state = self.ethereum.ChainManager().State() + block = self.ethereum.ChainManager().CurrentBlock() } - v, _ := self.Vm.ToValue(state.Dump()) + statedb := state.New(block.Root(), self.ethereum.Db()) + v, _ := self.Vm.ToValue(statedb.Dump()) return v } diff --git a/javascript/types.go b/javascript/types.go index cf5a6677bc..61a57033b2 100644 --- a/javascript/types.go +++ b/javascript/types.go @@ -18,11 +18,11 @@ type JSStateObject struct { func (self *JSStateObject) EachStorage(call otto.FunctionCall) otto.Value { cb := call.Argument(0) - self.JSObject.EachStorage(func(key string, value *ethutil.Value) { - value.Decode() - cb.Call(self.eth.toVal(self), self.eth.toVal(key), self.eth.toVal(ethutil.Bytes2Hex(value.Bytes()))) - }) + it := self.JSObject.Trie().Iterator() + for it.Next() { + cb.Call(self.eth.toVal(self), self.eth.toVal(ethutil.Bytes2Hex(it.Key)), self.eth.toVal(ethutil.Bytes2Hex(it.Value))) + } return otto.UndefinedValue() } @@ -72,15 +72,21 @@ type JSEthereum struct { ethereum *eth.Ethereum } -func (self *JSEthereum) GetBlock(hash string) otto.Value { - return self.toVal(&JSBlock{self.JSXEth.BlockByHash(hash), self}) +func (self *JSEthereum) Block(v interface{}) otto.Value { + if number, ok := v.(int64); ok { + return self.toVal(&JSBlock{self.JSXEth.BlockByNumber(int32(number)), self}) + } else if hash, ok := v.(string); ok { + return self.toVal(&JSBlock{self.JSXEth.BlockByHash(hash), self}) + } + + return otto.UndefinedValue() } -func (self *JSEthereum) GetPeers() otto.Value { +func (self *JSEthereum) Peers() otto.Value { return self.toVal(self.JSXEth.Peers()) } -func (self *JSEthereum) GetKey() otto.Value { +func (self *JSEthereum) Key() otto.Value { return self.toVal(self.JSXEth.Key()) } @@ -88,10 +94,6 @@ func (self *JSEthereum) GetStateObject(addr string) otto.Value { return self.toVal(&JSStateObject{xeth.NewJSObject(self.JSXEth.World().SafeGet(ethutil.Hex2Bytes(addr))), self}) } -func (self *JSEthereum) Peers() otto.Value { - return self.toVal(self.JSXEth.Peers()) -} - func (self *JSEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) otto.Value { r, err := self.JSXEth.Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr) if err != nil { @@ -103,18 +105,6 @@ func (self *JSEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, return self.toVal(r) } -func (self *JSEthereum) Create(key, valueStr, gasStr, gasPriceStr, scriptStr string) otto.Value { - r, err := self.JSXEth.Transact(key, "", valueStr, gasStr, gasPriceStr, scriptStr) - - if err != nil { - fmt.Println(err) - - return otto.UndefinedValue() - } - - return self.toVal(r) -} - func (self *JSEthereum) toVal(v interface{}) otto.Value { result, err := self.vm.ToValue(v) diff --git a/logger/log.go b/logger/log.go new file mode 100644 index 0000000000..53065f870b --- /dev/null +++ b/logger/log.go @@ -0,0 +1,33 @@ +package logger + +import ( + "fmt" + "io" + "log" + "os" + + "github.com/ethereum/go-ethereum/ethutil" +) + +func openLogFile(datadir string, filename string) *os.File { + path := ethutil.AbsolutePath(datadir, filename) + file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + panic(fmt.Sprintf("error opening log file '%s': %v", filename, err)) + } + return file +} + +func New(datadir string, logFile string, logLevel int) LogSystem { + var writer io.Writer + if logFile == "" { + writer = os.Stdout + } else { + writer = openLogFile(datadir, logFile) + } + + sys := NewStdLogSystem(writer, log.LstdFlags, LogLevel(logLevel)) + AddLogSystem(sys) + + return sys +} diff --git a/miner/miner.go b/miner/miner.go index d909c228b7..52dd5687d1 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -31,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/pow" "github.com/ethereum/go-ethereum/pow/ezp" + "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" @@ -56,7 +57,7 @@ type Miner struct { eth *eth.Ethereum events event.Subscription - uncles types.Blocks + uncles []*types.Header localTxs map[int]*LocalTx localTxId int @@ -69,6 +70,7 @@ type Miner struct { mining bool MinAcceptedGasPrice *big.Int + Extra string } func New(coinbase []byte, eth *eth.Ethereum) *Miner { @@ -174,25 +176,27 @@ func (self *Miner) reset() { func (self *Miner) mine() { var ( - blockManager = self.eth.BlockManager() - chainMan = self.eth.ChainManager() - block = chainMan.NewBlock(self.Coinbase) + blockProcessor = self.eth.BlockProcessor() + chainMan = self.eth.ChainManager() + block = chainMan.NewBlock(self.Coinbase) + state = state.New(block.Root(), self.eth.Db()) ) + block.Header().Extra = self.Extra // Apply uncles if len(self.uncles) > 0 { block.SetUncles(self.uncles) } - parent := chainMan.GetBlock(block.PrevHash) - coinbase := block.State().GetOrNewStateObject(block.Coinbase) - coinbase.SetGasPool(block.CalcGasLimit(parent)) + parent := chainMan.GetBlock(block.ParentHash()) + coinbase := state.GetOrNewStateObject(block.Coinbase()) + coinbase.SetGasPool(core.CalcGasLimit(parent, block)) transactions := self.finiliseTxs() // Accumulate all valid transactions and apply them to the new state // Error may be ignored. It's not important during mining - receipts, txs, _, erroneous, err := blockManager.ApplyTransactions(coinbase, block.State(), block, transactions, true) + receipts, txs, _, erroneous, err := blockProcessor.ApplyTransactions(coinbase, state, block, transactions, true) if err != nil { minerlogger.Debugln(err) } @@ -202,16 +206,17 @@ func (self *Miner) mine() { block.SetReceipts(receipts) // Accumulate the rewards included for this block - blockManager.AccumelateRewards(block.State(), block, parent) + blockProcessor.AccumelateRewards(state, block, parent) - block.State().Update(ethutil.Big0) + state.Update(ethutil.Big0) + block.SetRoot(state.Root()) minerlogger.Infof("Mining on block. Includes %v transactions", len(transactions)) // Find a valid nonce nonce := self.pow.Search(block, self.powQuitCh) if nonce != nil { - block.Nonce = nonce + block.Header().Nonce = nonce err := chainMan.InsertChain(types.Blocks{block}) if err != nil { minerlogger.Infoln(err) diff --git a/p2p/client_identity.go b/p2p/client_identity.go index bc865b63b0..f15fd01bfc 100644 --- a/p2p/client_identity.go +++ b/p2p/client_identity.go @@ -17,10 +17,10 @@ type SimpleClientIdentity struct { customIdentifier string os string implementation string - pubkey string + pubkey []byte } -func NewSimpleClientIdentity(clientIdentifier string, version string, customIdentifier string, pubkey string) *SimpleClientIdentity { +func NewSimpleClientIdentity(clientIdentifier string, version string, customIdentifier string, pubkey []byte) *SimpleClientIdentity { clientIdentity := &SimpleClientIdentity{ clientIdentifier: clientIdentifier, version: version, diff --git a/p2p/client_identity_test.go b/p2p/client_identity_test.go index 40b0e6f5e1..7248a7b1a7 100644 --- a/p2p/client_identity_test.go +++ b/p2p/client_identity_test.go @@ -7,7 +7,7 @@ import ( ) func TestClientIdentity(t *testing.T) { - clientIdentity := NewSimpleClientIdentity("Ethereum(G)", "0.5.16", "test", "pubkey") + clientIdentity := NewSimpleClientIdentity("Ethereum(G)", "0.5.16", "test", []byte("pubkey")) clientString := clientIdentity.String() expected := fmt.Sprintf("Ethereum(G)/v0.5.16/test/%s/%s", runtime.GOOS, runtime.Version()) if clientString != expected { diff --git a/p2p/message.go b/p2p/message.go index f5418ff473..daf2bf05c1 100644 --- a/p2p/message.go +++ b/p2p/message.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/binary" "errors" + "fmt" "io" "io/ioutil" "math/big" @@ -49,7 +50,14 @@ func encodePayload(params ...interface{}) []byte { // For the decoding rules, please see package rlp. func (msg Msg) Decode(val interface{}) error { s := rlp.NewListStream(msg.Payload, uint64(msg.Size)) - return s.Decode(val) + if err := s.Decode(val); err != nil { + return newPeerError(errInvalidMsg, "(code %#x) (size %d) %v", msg.Code, msg.Size, err) + } + return nil +} + +func (msg Msg) String() string { + return fmt.Sprintf("msg #%v (%v bytes)", msg.Code, msg.Size) } // Discard reads any remaining payload data into a black hole. @@ -63,14 +71,11 @@ type MsgReader interface { } type MsgWriter interface { - // WriteMsg sends an existing message. - // The Payload reader of the message is consumed. + // WriteMsg sends a message. It will block until the message's + // Payload has been consumed by the other end. + // // Note that messages can be sent only once. WriteMsg(Msg) error - - // EncodeMsg writes an RLP-encoded message with the given - // code and data elements. - EncodeMsg(code uint64, data ...interface{}) error } // MsgReadWriter provides reading and writing of encoded messages. @@ -79,6 +84,12 @@ type MsgReadWriter interface { MsgWriter } +// EncodeMsg writes an RLP-encoded message with the given code and +// data elements. +func EncodeMsg(w MsgWriter, code uint64, data ...interface{}) error { + return w.WriteMsg(NewMsg(code, data...)) +} + var magicToken = []byte{34, 64, 8, 145} func writeMsg(w io.Writer, msg Msg) error { @@ -201,11 +212,6 @@ func (p *MsgPipeRW) WriteMsg(msg Msg) error { return ErrPipeClosed } -// EncodeMsg is a convenient shorthand for sending an RLP-encoded message. -func (p *MsgPipeRW) EncodeMsg(code uint64, data ...interface{}) error { - return p.WriteMsg(NewMsg(code, data...)) -} - // ReadMsg returns a message sent on the other end of the pipe. func (p *MsgPipeRW) ReadMsg() (Msg, error) { if atomic.LoadInt32(p.closed) == 0 { diff --git a/p2p/message_test.go b/p2p/message_test.go index 066d2516d4..5cde9abf5b 100644 --- a/p2p/message_test.go +++ b/p2p/message_test.go @@ -75,8 +75,8 @@ func TestDecodeRealMsg(t *testing.T) { func ExampleMsgPipe() { rw1, rw2 := MsgPipe() go func() { - rw1.EncodeMsg(8, []byte{0, 0}) - rw1.EncodeMsg(5, []byte{1, 1}) + EncodeMsg(rw1, 8, []byte{0, 0}) + EncodeMsg(rw1, 5, []byte{1, 1}) rw1.Close() }() @@ -100,7 +100,7 @@ loop: rw1, rw2 := MsgPipe() done := make(chan struct{}) go func() { - if err := rw1.EncodeMsg(1); err == nil { + if err := EncodeMsg(rw1, 1); err == nil { t.Error("EncodeMsg returned nil error") } else if err != ErrPipeClosed { t.Error("EncodeMsg returned wrong error: got %v, want %v", err, ErrPipeClosed) diff --git a/p2p/nat.go b/p2p/nat.go new file mode 100644 index 0000000000..9b771c3e8c --- /dev/null +++ b/p2p/nat.go @@ -0,0 +1,23 @@ +package p2p + +import ( + "fmt" + "net" +) + +func ParseNAT(natType string, gateway string) (nat NAT, err error) { + switch natType { + case "UPNP": + nat = UPNP() + case "PMP": + ip := net.ParseIP(gateway) + if ip == nil { + return nil, fmt.Errorf("cannot resolve PMP gateway IP %s", gateway) + } + nat = PMP(ip) + case "": + default: + return nil, fmt.Errorf("unrecognised NAT type '%s'", natType) + } + return +} diff --git a/p2p/peer.go b/p2p/peer.go index 86c4d7ab54..2380a3285b 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -45,8 +45,8 @@ func (d peerAddr) String() string { return fmt.Sprintf("%v:%d", d.IP, d.Port) } -func (d peerAddr) RlpData() interface{} { - return []interface{}{d.IP, d.Port, d.Pubkey} +func (d *peerAddr) RlpData() interface{} { + return []interface{}{string(d.IP), d.Port, d.Pubkey} } // Peer represents a remote peer. @@ -426,7 +426,7 @@ func (rw *proto) WriteMsg(msg Msg) error { } func (rw *proto) EncodeMsg(code uint64, data ...interface{}) error { - return rw.WriteMsg(NewMsg(code, data)) + return rw.WriteMsg(NewMsg(code, data...)) } func (rw *proto) ReadMsg() (Msg, error) { diff --git a/p2p/peer_test.go b/p2p/peer_test.go index f7759786ef..4ee88f112b 100644 --- a/p2p/peer_test.go +++ b/p2p/peer_test.go @@ -30,9 +30,8 @@ var discard = Protocol{ func testPeer(protos []Protocol) (net.Conn, *Peer, <-chan error) { conn1, conn2 := net.Pipe() - id := NewSimpleClientIdentity("test", "0", "0", "public key") peer := newPeer(conn1, protos, nil) - peer.ourID = id + peer.ourID = &peerId{} peer.pubkeyHook = func(*peerAddr) error { return nil } errc := make(chan error, 1) go func() { @@ -127,10 +126,10 @@ func TestPeerProtoEncodeMsg(t *testing.T) { Name: "a", Length: 2, Run: func(peer *Peer, rw MsgReadWriter) error { - if err := rw.EncodeMsg(2); err == nil { + if err := EncodeMsg(rw, 2); err == nil { t.Error("expected error for out-of-range msg code, got nil") } - if err := rw.EncodeMsg(1); err != nil { + if err := EncodeMsg(rw, 1, "foo", "bar"); err != nil { t.Errorf("write error: %v", err) } return nil @@ -148,6 +147,13 @@ func TestPeerProtoEncodeMsg(t *testing.T) { if msg.Code != 17 { t.Errorf("incorrect message code: got %d, expected %d", msg.Code, 17) } + var data []string + if err := msg.Decode(&data); err != nil { + t.Errorf("payload decode error: %v", err) + } + if !reflect.DeepEqual(data, []string{"foo", "bar"}) { + t.Errorf("payload RLP mismatch, got %#v, want %#v", data, []string{"foo", "bar"}) + } } func TestPeerWrite(t *testing.T) { @@ -226,8 +232,8 @@ func TestPeerActivity(t *testing.T) { } func TestNewPeer(t *testing.T) { - id := NewSimpleClientIdentity("clientid", "version", "customid", "pubkey") caps := []Cap{{"foo", 2}, {"bar", 3}} + id := &peerId{} p := NewPeer(id, caps) if !reflect.DeepEqual(p.Caps(), caps) { t.Errorf("Caps mismatch: got %v, expected %v", p.Caps(), caps) diff --git a/p2p/protocol.go b/p2p/protocol.go index 3f52205f59..1d121a8855 100644 --- a/p2p/protocol.go +++ b/p2p/protocol.go @@ -3,8 +3,6 @@ package p2p import ( "bytes" "time" - - "github.com/ethereum/go-ethereum/ethutil" ) // Protocol represents a P2P subprotocol implementation. @@ -89,20 +87,25 @@ type baseProtocol struct { func runBaseProtocol(peer *Peer, rw MsgReadWriter) error { bp := &baseProtocol{rw, peer} - if err := bp.doHandshake(rw); err != nil { + errc := make(chan error, 1) + go func() { errc <- rw.WriteMsg(bp.handshakeMsg()) }() + if err := bp.readHandshake(); err != nil { + return err + } + // handle write error + if err := <-errc; err != nil { return err } // run main loop - quit := make(chan error, 1) go func() { for { if err := bp.handle(rw); err != nil { - quit <- err + errc <- err break } } }() - return bp.loop(quit) + return bp.loop(errc) } var pingTimeout = 2 * time.Second @@ -116,14 +119,14 @@ func (bp *baseProtocol) loop(quit <-chan error) error { getPeersTick := time.NewTicker(10 * time.Second) defer getPeersTick.Stop() - err := bp.rw.EncodeMsg(getPeersMsg) + err := EncodeMsg(bp.rw, getPeersMsg) for err == nil { select { case err = <-quit: return err case <-getPeersTick.C: - err = bp.rw.EncodeMsg(getPeersMsg) + err = EncodeMsg(bp.rw, getPeersMsg) case event := <-activity.Chan(): ping.Reset(pingTimeout) lastActive = event.(time.Time) @@ -131,7 +134,7 @@ func (bp *baseProtocol) loop(quit <-chan error) error { if lastActive.Add(pingTimeout * 2).Before(t) { err = newPeerError(errPingTimeout, "") } else if lastActive.Add(pingTimeout).Before(t) { - err = bp.rw.EncodeMsg(pingMsg) + err = EncodeMsg(bp.rw, pingMsg) } } } @@ -161,7 +164,7 @@ func (bp *baseProtocol) handle(rw MsgReadWriter) error { return discRequestedError(reason[0]) case pingMsg: - return bp.rw.EncodeMsg(pongMsg) + return EncodeMsg(bp.rw, pongMsg) case pongMsg: @@ -174,7 +177,7 @@ func (bp *baseProtocol) handle(rw MsgReadWriter) error { // // TODO: add event mechanism to notify baseProtocol for new peers if len(peers) > 0 { - return bp.rw.EncodeMsg(peersMsg, peers) + return EncodeMsg(bp.rw, peersMsg, peers...) } case peersMsg: @@ -193,14 +196,9 @@ func (bp *baseProtocol) handle(rw MsgReadWriter) error { return nil } -func (bp *baseProtocol) doHandshake(rw MsgReadWriter) error { - // send our handshake - if err := rw.WriteMsg(bp.handshakeMsg()); err != nil { - return err - } - +func (bp *baseProtocol) readHandshake() error { // read and handle remote handshake - msg, err := rw.ReadMsg() + msg, err := bp.rw.ReadMsg() if err != nil { return err } @@ -210,12 +208,10 @@ func (bp *baseProtocol) doHandshake(rw MsgReadWriter) error { if msg.Size > baseProtocolMaxMsgSize { return newPeerError(errMisc, "message too big") } - var hs handshake if err := msg.Decode(&hs); err != nil { return err } - // validate handshake info if hs.Version != baseProtocolVersion { return newPeerError(errP2PVersionMismatch, "Require protocol %d, received %d\n", @@ -238,9 +234,7 @@ func (bp *baseProtocol) doHandshake(rw MsgReadWriter) error { if err := bp.peer.pubkeyHook(pa); err != nil { return newPeerError(errPubkeyForbidden, "%v", err) } - // TODO: remove Caps with empty name - var addr *peerAddr if hs.ListenPort != 0 { addr = newPeerAddr(bp.peer.conn.RemoteAddr(), hs.NodeID) @@ -271,9 +265,9 @@ func (bp *baseProtocol) handshakeMsg() Msg { ) } -func (bp *baseProtocol) peerList() []ethutil.RlpEncodable { +func (bp *baseProtocol) peerList() []interface{} { peers := bp.peer.otherPeers() - ds := make([]ethutil.RlpEncodable, 0, len(peers)) + ds := make([]interface{}, 0, len(peers)) for _, p := range peers { p.infolock.Lock() addr := p.listenAddr diff --git a/p2p/protocol_test.go b/p2p/protocol_test.go index 65f26fb12d..b1d10ac536 100644 --- a/p2p/protocol_test.go +++ b/p2p/protocol_test.go @@ -2,12 +2,111 @@ package p2p import ( "fmt" + "net" + "reflect" + "sync" "testing" + + "github.com/ethereum/go-ethereum/crypto" ) +type peerId struct { + pubkey []byte +} + +func (self *peerId) String() string { + return fmt.Sprintf("test peer %x", self.Pubkey()[:4]) +} + +func (self *peerId) Pubkey() (pubkey []byte) { + pubkey = self.pubkey + if len(pubkey) == 0 { + pubkey = crypto.GenerateNewKeyPair().PublicKey + self.pubkey = pubkey + } + return +} + +func newTestPeer() (peer *Peer) { + peer = NewPeer(&peerId{}, []Cap{}) + peer.pubkeyHook = func(*peerAddr) error { return nil } + peer.ourID = &peerId{} + peer.listenAddr = &peerAddr{} + peer.otherPeers = func() []*Peer { return nil } + return +} + +func TestBaseProtocolPeers(t *testing.T) { + peerList := []*peerAddr{ + {IP: net.ParseIP("1.2.3.4"), Port: 2222, Pubkey: []byte{}}, + {IP: net.ParseIP("5.6.7.8"), Port: 3333, Pubkey: []byte{}}, + } + listenAddr := &peerAddr{IP: net.ParseIP("1.3.5.7"), Port: 1111, Pubkey: []byte{}} + rw1, rw2 := MsgPipe() + defer rw1.Close() + wg := new(sync.WaitGroup) + + // run matcher, close pipe when addresses have arrived + numPeers := len(peerList) + 1 + addrChan := make(chan *peerAddr) + wg.Add(1) + go func() { + i := 0 + for got := range addrChan { + var want *peerAddr + switch { + case i < len(peerList): + want = peerList[i] + case i == len(peerList): + want = listenAddr // listenAddr should be the last thing sent + } + t.Logf("got peer %d/%d: %v", i+1, numPeers, got) + if !reflect.DeepEqual(want, got) { + t.Errorf("mismatch: got %+v, want %+v", got, want) + } + i++ + if i == numPeers { + break + } + } + if i != numPeers { + t.Errorf("wrong number of peers received: got %d, want %d", i, numPeers) + } + rw1.Close() + wg.Done() + }() + + // run first peer (in background) + peer1 := newTestPeer() + peer1.ourListenAddr = listenAddr + peer1.otherPeers = func() []*Peer { + pl := make([]*Peer, len(peerList)) + for i, addr := range peerList { + pl[i] = &Peer{listenAddr: addr} + } + return pl + } + wg.Add(1) + go func() { + runBaseProtocol(peer1, rw1) + wg.Done() + }() + + // run second peer + peer2 := newTestPeer() + peer2.newPeerAddr = addrChan // feed peer suggestions into matcher + if err := runBaseProtocol(peer2, rw2); err != ErrPipeClosed { + t.Errorf("peer2 terminated with unexpected error: %v", err) + } + + // terminate matcher + close(addrChan) + wg.Wait() +} + func TestBaseProtocolDisconnect(t *testing.T) { - peer := NewPeer(NewSimpleClientIdentity("p1", "", "", "foo"), nil) - peer.ourID = NewSimpleClientIdentity("p2", "", "", "bar") + peer := NewPeer(&peerId{}, nil) + peer.ourID = &peerId{} peer.pubkeyHook = func(*peerAddr) error { return nil } rw1, rw2 := MsgPipe() @@ -16,7 +115,7 @@ func TestBaseProtocolDisconnect(t *testing.T) { if err := expectMsg(rw2, handshakeMsg); err != nil { t.Error(err) } - err := rw2.EncodeMsg(handshakeMsg, + err := EncodeMsg(rw2, handshakeMsg, baseProtocolVersion, "", []interface{}{}, @@ -29,9 +128,10 @@ func TestBaseProtocolDisconnect(t *testing.T) { if err := expectMsg(rw2, getPeersMsg); err != nil { t.Error(err) } - if err := rw2.EncodeMsg(discMsg, DiscQuitting); err != nil { + if err := EncodeMsg(rw2, discMsg, DiscQuitting); err != nil { t.Error(err) } + close(done) }() diff --git a/p2p/server.go b/p2p/server.go index 3267812343..cfff442f71 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -113,9 +113,11 @@ func (srv *Server) PeerCount() int { // SuggestPeer injects an address into the outbound address pool. func (srv *Server) SuggestPeer(ip net.IP, port int, nodeID []byte) { + addr := &peerAddr{ip, uint64(port), nodeID} select { - case srv.peerConnect <- &peerAddr{ip, uint64(port), nodeID}: + case srv.peerConnect <- addr: default: // don't block + srvlog.Warnf("peer suggestion %v ignored", addr) } } @@ -258,6 +260,7 @@ func (srv *Server) listenLoop() { for { select { case slot := <-srv.peerSlots: + srvlog.Debugf("grabbed slot %v for listening", slot) conn, err := srv.listener.Accept() if err != nil { srv.peerSlots <- slot @@ -330,6 +333,7 @@ func (srv *Server) dialLoop() { case desc := <-suggest: // candidate peer found, will dial out asyncronously // if connection fails slot will be released + srvlog.Infof("dial %v (%v)", desc, *slot) go srv.dialPeer(desc, *slot) // we can watch if more peers needed in the next loop slots = srv.peerSlots diff --git a/p2p/server_test.go b/p2p/server_test.go index 5c0d08d398..ceb89e3f7f 100644 --- a/p2p/server_test.go +++ b/p2p/server_test.go @@ -11,7 +11,7 @@ import ( func startTestServer(t *testing.T, pf peerFunc) *Server { server := &Server{ - Identity: NewSimpleClientIdentity("clientIdentifier", "version", "customIdentifier", "pubkey"), + Identity: &peerId{}, MaxPeers: 10, ListenAddr: "127.0.0.1:0", newPeerFunc: pf, diff --git a/pow/ar/block.go b/pow/ar/block.go deleted file mode 100644 index 2124b53b4b..0000000000 --- a/pow/ar/block.go +++ /dev/null @@ -1,12 +0,0 @@ -package ar - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/trie" -) - -type Block interface { - Trie() *trie.Trie - Diff() *big.Int -} diff --git a/pow/ar/ops.go b/pow/ar/ops.go deleted file mode 100644 index 3a099be087..0000000000 --- a/pow/ar/ops.go +++ /dev/null @@ -1,54 +0,0 @@ -package ar - -import "math/big" - -const lenops int64 = 9 - -type OpsFunc func(a, b *big.Int) *big.Int - -var ops [lenops]OpsFunc - -func init() { - ops[0] = Add - ops[1] = Mul - ops[2] = Mod - ops[3] = Xor - ops[4] = And - ops[5] = Or - ops[6] = Sub1 - ops[7] = XorSub - ops[8] = Rsh -} - -func Add(x, y *big.Int) *big.Int { - return new(big.Int).Add(x, y) -} -func Mul(x, y *big.Int) *big.Int { - return new(big.Int).Mul(x, y) -} -func Mod(x, y *big.Int) *big.Int { - return new(big.Int).Mod(x, y) -} -func Xor(x, y *big.Int) *big.Int { - return new(big.Int).Xor(x, y) -} -func And(x, y *big.Int) *big.Int { - return new(big.Int).And(x, y) -} -func Or(x, y *big.Int) *big.Int { - return new(big.Int).Or(x, y) -} -func Sub1(x, y *big.Int) *big.Int { - a := big.NewInt(-1) - a.Sub(a, x) - - return a -} -func XorSub(x, y *big.Int) *big.Int { - t := Sub1(x, nil) - - return t.Xor(t, y) -} -func Rsh(x, y *big.Int) *big.Int { - return new(big.Int).Rsh(x, uint(y.Uint64()%64)) -} diff --git a/pow/ar/pow.go b/pow/ar/pow.go deleted file mode 100644 index 8991a674ba..0000000000 --- a/pow/ar/pow.go +++ /dev/null @@ -1,122 +0,0 @@ -package ar - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/ethutil" -) - -type Entry struct { - op OpsFunc - i, j *big.Int -} - -type Tape struct { - tape []Entry - block Block -} - -func NewTape(block Block) *Tape { - return &Tape{nil, block} -} - -func (self *Tape) gen(w, h int64, gen NumberGenerator) { - self.tape = nil - - for v := int64(0); v < h; v++ { - op := ops[gen.rand64(lenops).Int64()] - r := gen.rand64(100).Uint64() - - var j *big.Int - if r < 20 && v > 20 { - j = self.tape[len(self.tape)-1].i - } else { - j = gen.rand64(w) - } - - i := gen.rand64(w) - self.tape = append(self.tape, Entry{op, i, j}) - } -} - -func (self *Tape) runTape(w, h int64, gen NumberGenerator) *big.Int { - var mem []*big.Int - for i := int64(0); i < w; i++ { - mem = append(mem, gen.rand(ethutil.BigPow(2, 64))) - } - - set := func(i, j int) Entry { - entry := self.tape[i*100+j] - mem[entry.i.Uint64()] = entry.op(entry.i, entry.j) - - return entry - } - - dir := true - for i := 0; i < int(h)/100; i++ { - var entry Entry - if dir { - for j := 0; j < 100; j++ { - entry = set(i, j) - } - } else { - for j := 99; i >= 0; j-- { - entry = set(i, j) - } - } - - t := mem[entry.i.Uint64()] - if big.NewInt(2).Cmp(new(big.Int).Mod(t, big.NewInt(37))) < 0 { - dir = !dir - } - } - - return Sha3(mem) -} - -func (self *Tape) Verify(header, nonce []byte) bool { - n := ethutil.BigD(nonce) - - var w int64 = 10000 - var h int64 = 150000 - gen := Rnd(Sha3([]interface{}{header, new(big.Int).Div(n, big.NewInt(1000))})) - self.gen(w, h, gen) - - gen = Rnd(Sha3([]interface{}{header, new(big.Int).Mod(n, big.NewInt(1000))})) - hash := self.runTape(w, h, gen) - - it := self.block.Trie().Iterator() - next := it.Next(string(new(big.Int).Mod(hash, ethutil.BigPow(2, 160)).Bytes())) - - req := ethutil.BigPow(2, 256) - req.Div(req, self.block.Diff()) - return Sha3([]interface{}{hash, next}).Cmp(req) < 0 -} - -func (self *Tape) Run(header []byte) []byte { - nonce := big.NewInt(0) - var w int64 = 10000 - var h int64 = 150000 - - req := ethutil.BigPow(2, 256) - req.Div(req, self.block.Diff()) - - for { - if new(big.Int).Mod(nonce, b(1000)).Cmp(b(0)) == 0 { - gen := Rnd(Sha3([]interface{}{header, new(big.Int).Div(nonce, big.NewInt(1000))})) - self.gen(w, h, gen) - } - - gen := Rnd(Sha3([]interface{}{header, new(big.Int).Mod(nonce, big.NewInt(1000))})) - hash := self.runTape(w, h, gen) - - it := self.block.Trie().Iterator() - next := it.Next(string(new(big.Int).Mod(hash, ethutil.BigPow(2, 160)).Bytes())) - - if Sha3([]interface{}{hash, next}).Cmp(req) < 0 { - return nonce.Bytes() - } else { - nonce.Add(nonce, ethutil.Big1) - } - } -} diff --git a/pow/ar/pow_test.go b/pow/ar/pow_test.go deleted file mode 100644 index b1ebf92818..0000000000 --- a/pow/ar/pow_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package ar - -import ( - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/trie" -) - -type TestBlock struct { - trie *trie.Trie -} - -func NewTestBlock() *TestBlock { - db, _ := ethdb.NewMemDatabase() - return &TestBlock{ - trie: trie.New(db, ""), - } -} - -func (self *TestBlock) Diff() *big.Int { - return b(10) -} - -func (self *TestBlock) Trie() *trie.Trie { - return self.trie -} - -func (self *TestBlock) Hash() []byte { - a := make([]byte, 32) - a[0] = 10 - a[1] = 2 - return a -} - -func TestPow(t *testing.T) { - entry := make([]byte, 32) - entry[0] = 255 - - block := NewTestBlock() - - pow := NewTape(block) - nonce := pow.Run(block.Hash()) - fmt.Println("Found nonce", nonce) -} diff --git a/pow/ar/rnd.go b/pow/ar/rnd.go deleted file mode 100644 index c62f4e0622..0000000000 --- a/pow/ar/rnd.go +++ /dev/null @@ -1,66 +0,0 @@ -package ar - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethutil" -) - -var b = big.NewInt - -type Node interface { - Big() *big.Int -} - -type ByteNode []byte - -func (self ByteNode) Big() *big.Int { - return ethutil.BigD(ethutil.Encode([]byte(self))) -} - -func Sha3(v interface{}) *big.Int { - if b, ok := v.(*big.Int); ok { - return ethutil.BigD(crypto.Sha3(b.Bytes())) - } else if b, ok := v.([]interface{}); ok { - return ethutil.BigD(crypto.Sha3(ethutil.Encode(b))) - } else if s, ok := v.([]*big.Int); ok { - v := make([]interface{}, len(s)) - for i, b := range s { - v[i] = b - } - - return ethutil.BigD(crypto.Sha3(ethutil.Encode(v))) - } - - return nil -} - -type NumberGenerator interface { - rand(r *big.Int) *big.Int - rand64(r int64) *big.Int -} - -type rnd struct { - seed *big.Int -} - -func Rnd(s *big.Int) rnd { - return rnd{s} -} - -func (self rnd) rand(r *big.Int) *big.Int { - o := b(0).Mod(self.seed, r) - - self.seed.Div(self.seed, r) - - if self.seed.Cmp(ethutil.BigPow(2, 64)) < 0 { - self.seed = Sha3(self.seed) - } - - return o -} - -func (self rnd) rand64(r int64) *big.Int { - return self.rand(b(r)) -} diff --git a/pow/block.go b/pow/block.go index 4759e19fb3..62df2b5ff5 100644 --- a/pow/block.go +++ b/pow/block.go @@ -3,7 +3,7 @@ package pow import "math/big" type Block interface { - Diff() *big.Int + Difficulty() *big.Int HashNoNonce() []byte N() []byte } diff --git a/core/dagger.go b/pow/dagger/dagger.go similarity index 99% rename from core/dagger.go rename to pow/dagger/dagger.go index 3039d89959..9ac0004433 100644 --- a/core/dagger.go +++ b/pow/dagger/dagger.go @@ -1,4 +1,4 @@ -package core +package dagger import ( "hash" diff --git a/core/dagger_test.go b/pow/dagger/dagger_test.go similarity index 96% rename from core/dagger_test.go rename to pow/dagger/dagger_test.go index e80064e6bf..f3a71d1eb4 100644 --- a/core/dagger_test.go +++ b/pow/dagger/dagger_test.go @@ -1,4 +1,4 @@ -package core +package dagger import ( "math/big" diff --git a/pow/ezp/pow.go b/pow/ezp/pow.go index f669f8aa4a..8c164798ac 100644 --- a/pow/ezp/pow.go +++ b/pow/ezp/pow.go @@ -21,7 +21,7 @@ type EasyPow struct { } func New() *EasyPow { - return &EasyPow{turbo: true} + return &EasyPow{turbo: false} } func (pow *EasyPow) GetHashrate() int64 { @@ -35,7 +35,7 @@ func (pow *EasyPow) Turbo(on bool) { func (pow *EasyPow) Search(block pow.Block, stop <-chan struct{}) []byte { r := rand.New(rand.NewSource(time.Now().UnixNano())) hash := block.HashNoNonce() - diff := block.Diff() + diff := block.Difficulty() i := int64(0) start := time.Now().UnixNano() t := time.Now() @@ -89,5 +89,5 @@ func verify(hash []byte, diff *big.Int, nonce []byte) bool { } func Verify(block pow.Block) bool { - return verify(block.HashNoNonce(), block.Diff(), block.N()) + return verify(block.HashNoNonce(), block.Difficulty(), block.N()) } diff --git a/profile.cov b/profile.cov deleted file mode 100644 index e92cd379f3..0000000000 --- a/profile.cov +++ /dev/null @@ -1,3038 +0,0 @@ -mode: count -github.com/ethereum/go-ethereum/chain/state_transition.go:40.134,42.2 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:44.60,45.20 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:49.2,50.16 2 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:45.20,47.3 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:52.58,53.21 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:57.2,59.17 2 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:53.21,55.3 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:61.60,62.49 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:66.2,66.21 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:70.2,71.17 2 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:62.49,64.3 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:66.21,68.3 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:74.60,75.30 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:78.2,80.12 2 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:75.30,77.3 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:83.54,85.2 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:87.45,91.50 3 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:95.2,97.16 3 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:101.2,104.12 3 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:91.50,93.3 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:97.16,99.3 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:107.42,114.2 4 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:116.53,123.30 2 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:128.2,128.37 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:132.2,132.12 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:123.30,125.3 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:128.37,130.3 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:135.60,139.39 2 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:143.2,155.45 4 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:160.2,162.46 3 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:166.2,166.42 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:170.2,172.26 2 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:198.2,207.41 2 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:264.2,264.8 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:139.39,141.3 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:155.45,157.3 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:162.46,164.3 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:166.42,168.3 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:172.26,181.22 5 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:186.3,186.33 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:181.22,183.4 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:187.4,196.3 4 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:207.41,214.20 3 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:220.3,221.20 2 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:214.20,218.4 2 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:222.4,223.29 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:223.29,225.21 2 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:231.4,231.20 1 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:225.21,229.5 2 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:267.122,281.2 5 0 -github.com/ethereum/go-ethereum/chain/state_transition.go:284.81,291.2 4 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:34.79,35.48 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:35.48,36.42 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:36.42,37.9 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:42.102,43.48 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:51.2,51.12 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:43.48,44.49 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:44.49,45.21 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:45.21,47.5 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:80.45,87.2 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:90.59,98.2 4 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:100.70,105.18 2 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:109.2,109.55 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:113.2,113.38 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:119.2,124.41 3 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:128.2,128.21 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:137.2,137.12 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:105.18,107.3 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:109.55,111.3 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:113.38,115.3 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:124.41,126.3 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:128.21,129.51 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:129.51,131.4 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:140.36,142.6 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:142.6,143.10 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:144.3,146.83 2 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:150.4,150.22 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:155.4,156.18 2 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:170.3,171.13 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:146.83,148.5 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:150.22,151.10 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:156.18,158.5 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:158.6,169.5 5 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:176.61,178.2 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:180.64,186.53 5 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:194.2,194.15 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:186.53,192.3 3 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:197.55,201.53 3 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:201.53,205.45 4 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:205.45,207.4 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:211.55,215.25 3 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:215.25,216.76 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:216.76,217.15 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:221.4,221.16 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:217.15,220.5 2 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:226.50,234.2 3 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:236.29,238.2 1 0 -github.com/ethereum/go-ethereum/chain/transaction_pool.go:240.28,246.2 3 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:78.57,89.2 4 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:91.35,93.2 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:95.34,97.2 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:99.53,101.2 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:103.51,105.2 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:107.52,109.2 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:111.55,115.2 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:117.54,119.2 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:121.232,131.25 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:178.2,180.53 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:131.25,140.17 6 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:159.3,173.62 10 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:140.17,142.11 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:143.4,145.13 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:146.4,149.15 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:150.4,154.13 4 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:173.62,175.4 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:183.99,188.34 3 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:192.2,192.37 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:195.2,197.44 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:188.34,190.3 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:192.37,194.3 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:200.121,211.61 4 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:215.2,216.16 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:220.2,221.44 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:226.2,227.54 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:233.2,233.55 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:238.2,238.66 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:244.2,245.49 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:250.2,252.31 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:258.2,258.41 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:211.61,213.3 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:216.16,218.3 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:221.44,224.3 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:227.54,230.3 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:233.55,236.3 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:238.66,241.3 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:245.49,248.3 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:252.31,255.3 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:258.41,272.3 7 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:272.4,274.3 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:277.120,283.16 4 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:287.2,287.22 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:283.16,285.3 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:290.74,292.37 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:297.2,303.26 4 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:310.2,310.19 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:292.37,294.3 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:303.26,308.3 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:316.73,318.36 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:322.2,323.14 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:335.2,335.72 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:339.2,339.12 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:318.36,320.3 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:323.14,325.3 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:335.72,337.3 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:342.97,347.37 4 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:378.2,382.12 3 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:347.37,348.34 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:353.3,354.25 2 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:358.3,358.81 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:362.3,362.40 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:366.3,374.68 6 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:348.34,351.4 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:354.25,356.4 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:358.81,360.4 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:362.40,364.4 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:385.96,386.37 1 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:390.2,403.39 6 0 -github.com/ethereum/go-ethereum/chain/block_manager.go:386.37,388.3 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:34.40,36.2 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:38.62,40.2 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:45.54,47.2 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:49.50,51.2 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:53.44,55.2 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:57.42,59.2 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:61.42,63.2 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:65.40,67.2 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:69.37,71.2 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:73.39,75.2 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:78.45,80.25 2 0 -github.com/ethereum/go-ethereum/chain/filter.go:83.2,84.23 2 0 -github.com/ethereum/go-ethereum/chain/filter.go:88.2,93.41 2 0 -github.com/ethereum/go-ethereum/chain/filter.go:119.2,121.24 2 0 -github.com/ethereum/go-ethereum/chain/filter.go:80.25,82.3 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:84.23,86.3 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:93.41,95.10 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:104.3,104.30 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:116.3,116.59 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:96.3,97.15 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:98.3,99.9 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:104.30,107.18 2 0 -github.com/ethereum/go-ethereum/chain/filter.go:113.4,113.61 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:107.18,110.10 2 0 -github.com/ethereum/go-ethereum/chain/filter.go:124.58,125.33 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:131.2,131.8 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:125.33,126.34 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:126.34,128.4 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:134.76,138.31 2 0 -github.com/ethereum/go-ethereum/chain/filter.go:172.2,172.17 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:138.31,139.57 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:143.3,143.63 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:147.3,148.29 2 0 -github.com/ethereum/go-ethereum/chain/filter.go:152.3,152.46 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:165.3,165.13 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:169.3,169.39 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:139.57,140.12 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:143.63,144.12 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:148.29,150.4 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:152.46,153.95 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:157.4,157.110 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:161.4,162.9 2 0 -github.com/ethereum/go-ethereum/chain/filter.go:153.95,154.13 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:157.110,158.13 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:165.13,166.12 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:175.58,177.24 2 0 -github.com/ethereum/go-ethereum/chain/filter.go:188.2,188.22 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:199.2,199.35 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:177.24,178.34 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:178.34,179.48 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:179.48,181.10 2 0 -github.com/ethereum/go-ethereum/chain/filter.go:184.4,186.3 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:188.22,189.30 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:189.30,190.114 1 0 -github.com/ethereum/go-ethereum/chain/filter.go:190.114,192.10 2 0 -github.com/ethereum/go-ethereum/chain/filter.go:195.4,197.3 1 0 -github.com/ethereum/go-ethereum/chain/error.go:14.38,16.2 1 0 -github.com/ethereum/go-ethereum/chain/error.go:18.37,20.2 1 0 -github.com/ethereum/go-ethereum/chain/error.go:22.34,26.2 2 0 -github.com/ethereum/go-ethereum/chain/error.go:32.37,34.2 1 0 -github.com/ethereum/go-ethereum/chain/error.go:36.35,38.2 1 0 -github.com/ethereum/go-ethereum/chain/error.go:40.33,44.2 2 0 -github.com/ethereum/go-ethereum/chain/error.go:51.42,53.2 1 0 -github.com/ethereum/go-ethereum/chain/error.go:55.70,57.2 1 0 -github.com/ethereum/go-ethereum/chain/error.go:59.38,63.2 2 0 -github.com/ethereum/go-ethereum/chain/error.go:70.36,74.2 2 0 -github.com/ethereum/go-ethereum/chain/error.go:75.40,77.2 1 0 -github.com/ethereum/go-ethereum/chain/error.go:78.51,80.2 1 0 -github.com/ethereum/go-ethereum/chain/error.go:87.37,89.2 1 0 -github.com/ethereum/go-ethereum/chain/error.go:91.43,93.2 1 0 -github.com/ethereum/go-ethereum/chain/error.go:95.33,99.2 2 0 -github.com/ethereum/go-ethereum/chain/error.go:105.35,107.2 1 0 -github.com/ethereum/go-ethereum/chain/error.go:108.41,110.2 1 0 -github.com/ethereum/go-ethereum/chain/error.go:112.36,116.2 2 0 -github.com/ethereum/go-ethereum/chain/error.go:122.37,124.2 1 0 -github.com/ethereum/go-ethereum/chain/error.go:125.30,128.2 2 0 -github.com/ethereum/go-ethereum/chain/vm_env.go:17.83,23.2 1 0 -github.com/ethereum/go-ethereum/chain/vm_env.go:25.43,25.70 1 0 -github.com/ethereum/go-ethereum/chain/vm_env.go:26.43,26.71 1 0 -github.com/ethereum/go-ethereum/chain/vm_env.go:27.43,27.73 1 0 -github.com/ethereum/go-ethereum/chain/vm_env.go:28.43,28.73 1 0 -github.com/ethereum/go-ethereum/chain/vm_env.go:29.43,29.69 1 0 -github.com/ethereum/go-ethereum/chain/vm_env.go:30.43,30.75 1 0 -github.com/ethereum/go-ethereum/chain/vm_env.go:31.43,31.71 1 0 -github.com/ethereum/go-ethereum/chain/vm_env.go:32.43,32.67 1 0 -github.com/ethereum/go-ethereum/chain/vm_env.go:33.43,33.64 1 0 -github.com/ethereum/go-ethereum/chain/vm_env.go:34.43,34.73 1 0 -github.com/ethereum/go-ethereum/chain/vm_env.go:35.43,37.2 1 0 -github.com/ethereum/go-ethereum/chain/vm_env.go:38.73,40.2 1 0 -github.com/ethereum/go-ethereum/chain/asm.go:11.48,13.6 2 0 -github.com/ethereum/go-ethereum/chain/asm.go:49.2,49.12 1 0 -github.com/ethereum/go-ethereum/chain/asm.go:13.6,14.50 1 0 -github.com/ethereum/go-ethereum/chain/asm.go:19.3,25.13 4 0 -github.com/ethereum/go-ethereum/chain/asm.go:46.3,46.27 1 0 -github.com/ethereum/go-ethereum/chain/asm.go:14.50,16.4 1 0 -github.com/ethereum/go-ethereum/chain/asm.go:26.3,33.39 3 0 -github.com/ethereum/go-ethereum/chain/asm.go:37.4,38.22 2 0 -github.com/ethereum/go-ethereum/chain/asm.go:41.4,43.31 2 0 -github.com/ethereum/go-ethereum/chain/asm.go:33.39,35.5 1 0 -github.com/ethereum/go-ethereum/chain/asm.go:38.22,40.5 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:17.42,27.4 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:27.4,32.3 4 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:35.58,39.33 3 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:45.2,45.13 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:39.33,41.3 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:41.4,43.3 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:63.38,71.2 4 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:73.67,75.2 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:77.40,79.20 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:94.2,94.88 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:79.20,90.3 6 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:90.4,92.3 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:98.64,102.28 3 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:107.2,118.19 4 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:125.2,125.14 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:102.28,105.3 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:118.19,123.3 3 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:128.33,140.2 6 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:143.49,154.2 6 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:157.48,159.2 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:162.52,165.2 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:167.92,169.18 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:174.2,174.35 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:185.2,185.8 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:169.18,171.3 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:174.35,178.42 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:182.3,182.40 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:178.42,179.9 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:188.62,190.20 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:203.2,203.38 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:190.20,191.31 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:200.3,200.13 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:191.31,193.63 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:193.63,194.63 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:194.63,196.6 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:206.69,208.60 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:214.2,214.60 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:218.2,218.14 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:208.60,209.35 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:209.35,210.9 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:214.60,216.3 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:221.57,224.2 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:226.79,228.19 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:232.2,235.37 3 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:239.2,243.16 4 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:228.19,230.3 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:235.37,237.3 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:246.71,252.2 4 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:255.60,261.2 3 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:263.32,264.28 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:264.28,266.3 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:269.72,271.2 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:274.99,275.49 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:284.2,285.26 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:275.49,282.3 4 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:285.26,288.3 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:291.81,293.15 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:295.2,295.49 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:321.2,321.26 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:326.2,328.8 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:293.15,293.42 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:295.49,302.20 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:307.3,309.17 3 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:317.3,318.24 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:302.20,305.4 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:309.17,316.4 5 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:321.26,324.3 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:341.48,344.31 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:348.2,348.14 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:344.31,346.3 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:351.44,353.48 2 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:357.2,357.28 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:353.48,355.3 1 0 -github.com/ethereum/go-ethereum/chain/chain_manager.go:365.48,368.2 2 0 -github.com/ethereum/go-ethereum/chain/dagger.go:31.41,33.2 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:35.36,37.2 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:39.77,47.6 7 0 -github.com/ethereum/go-ethereum/chain/dagger.go:76.2,76.12 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:47.6,48.10 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:71.3,71.17 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:49.3,52.14 3 0 -github.com/ethereum/go-ethereum/chain/dagger.go:53.3,56.41 2 0 -github.com/ethereum/go-ethereum/chain/dagger.go:65.4,66.35 2 0 -github.com/ethereum/go-ethereum/chain/dagger.go:56.41,63.5 5 0 -github.com/ethereum/go-ethereum/chain/dagger.go:66.35,68.5 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:71.17,73.4 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:79.75,92.2 8 0 -github.com/ethereum/go-ethereum/chain/dagger.go:94.44,95.2 0 0 -github.com/ethereum/go-ethereum/chain/dagger.go:104.59,107.28 2 0 -github.com/ethereum/go-ethereum/chain/dagger.go:125.2,125.14 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:107.28,112.23 4 0 -github.com/ethereum/go-ethereum/chain/dagger.go:120.3,120.12 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:112.23,117.4 2 0 -github.com/ethereum/go-ethereum/chain/dagger.go:120.12,121.9 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:128.57,141.40 8 0 -github.com/ethereum/go-ethereum/chain/dagger.go:146.2,146.40 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:153.2,153.24 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:141.40,145.3 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:146.40,148.29 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:148.29,150.4 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:156.60,163.2 4 0 -github.com/ethereum/go-ethereum/chain/dagger.go:165.52,173.2 5 0 -github.com/ethereum/go-ethereum/chain/dagger.go:175.54,176.12 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:180.2,181.12 2 0 -github.com/ethereum/go-ethereum/chain/dagger.go:187.2,193.39 6 0 -github.com/ethereum/go-ethereum/chain/dagger.go:206.2,208.12 2 0 -github.com/ethereum/go-ethereum/chain/dagger.go:176.12,178.3 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:181.12,183.3 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:183.4,185.3 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:193.39,204.3 9 0 -github.com/ethereum/go-ethereum/chain/dagger.go:211.32,214.2 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:216.46,224.25 6 0 -github.com/ethereum/go-ethereum/chain/dagger.go:240.2,240.31 1 0 -github.com/ethereum/go-ethereum/chain/dagger.go:224.25,238.3 10 0 -github.com/ethereum/go-ethereum/chain/types/block.go:23.45,30.2 5 0 -github.com/ethereum/go-ethereum/chain/types/block.go:32.41,34.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:38.46,40.29 2 0 -github.com/ethereum/go-ethereum/chain/types/block.go:44.2,44.12 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:40.29,42.3 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:49.41,55.2 2 0 -github.com/ethereum/go-ethereum/chain/types/block.go:62.35,62.62 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:63.40,65.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:66.45,66.95 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:68.33,68.72 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:104.43,109.2 3 0 -github.com/ethereum/go-ethereum/chain/types/block.go:112.59,117.2 3 0 -github.com/ethereum/go-ethereum/chain/types/block.go:124.23,143.2 4 0 -github.com/ethereum/go-ethereum/chain/types/block.go:146.42,149.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:151.42,153.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:155.42,157.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:159.49,161.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:163.58,164.42 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:170.2,179.36 7 0 -github.com/ethereum/go-ethereum/chain/types/block.go:164.42,166.3 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:182.43,188.2 4 0 -github.com/ethereum/go-ethereum/chain/types/block.go:190.61,191.39 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:197.2,197.12 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:191.39,192.42 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:192.42,194.4 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:201.28,203.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:205.28,208.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:211.47,214.35 2 0 -github.com/ethereum/go-ethereum/chain/types/block.go:219.2,219.13 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:214.35,217.3 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:222.45,225.37 2 0 -github.com/ethereum/go-ethereum/chain/types/block.go:230.2,230.15 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:225.37,228.3 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:233.48,236.2 2 0 -github.com/ethereum/go-ethereum/chain/types/block.go:238.51,242.2 3 0 -github.com/ethereum/go-ethereum/chain/types/block.go:244.54,247.2 2 0 -github.com/ethereum/go-ethereum/chain/types/block.go:249.44,251.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:253.40,257.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:259.44,262.2 2 0 -github.com/ethereum/go-ethereum/chain/types/block.go:264.60,269.37 2 0 -github.com/ethereum/go-ethereum/chain/types/block.go:283.2,283.37 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:269.37,274.34 3 0 -github.com/ethereum/go-ethereum/chain/types/block.go:274.34,279.4 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:283.37,286.37 3 0 -github.com/ethereum/go-ethereum/chain/types/block.go:286.37,288.4 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:293.53,309.2 15 0 -github.com/ethereum/go-ethereum/chain/types/block.go:311.59,316.2 3 0 -github.com/ethereum/go-ethereum/chain/types/block.go:318.39,320.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:322.40,324.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:326.37,328.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:330.42,332.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:334.50,365.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:367.44,369.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:371.37,410.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:412.47,414.2 1 0 -github.com/ethereum/go-ethereum/chain/types/block.go:417.42,419.2 1 0 -github.com/ethereum/go-ethereum/chain/types/bloom9.go:11.44,13.35 2 0 -github.com/ethereum/go-ethereum/chain/types/bloom9.go:17.2,17.46 1 0 -github.com/ethereum/go-ethereum/chain/types/bloom9.go:13.35,15.3 1 0 -github.com/ethereum/go-ethereum/chain/types/bloom9.go:20.42,22.27 2 0 -github.com/ethereum/go-ethereum/chain/types/bloom9.go:37.2,37.12 1 0 -github.com/ethereum/go-ethereum/chain/types/bloom9.go:22.27,24.36 2 0 -github.com/ethereum/go-ethereum/chain/types/bloom9.go:28.3,28.26 1 0 -github.com/ethereum/go-ethereum/chain/types/bloom9.go:24.36,26.4 1 0 -github.com/ethereum/go-ethereum/chain/types/bloom9.go:28.26,30.4 1 0 -github.com/ethereum/go-ethereum/chain/types/bloom9.go:40.32,42.35 2 0 -github.com/ethereum/go-ethereum/chain/types/bloom9.go:48.2,48.10 1 0 -github.com/ethereum/go-ethereum/chain/types/bloom9.go:42.35,46.3 3 0 -github.com/ethereum/go-ethereum/chain/types/bloom9.go:51.42,56.2 3 0 -github.com/ethereum/go-ethereum/chain/types/derive_sha.go:13.43,15.34 2 0 -github.com/ethereum/go-ethereum/chain/types/derive_sha.go:19.2,19.23 1 0 -github.com/ethereum/go-ethereum/chain/types/derive_sha.go:15.34,17.3 1 0 -github.com/ethereum/go-ethereum/chain/types/receipt.go:19.67,21.2 1 0 -github.com/ethereum/go-ethereum/chain/types/receipt.go:23.55,28.2 3 0 -github.com/ethereum/go-ethereum/chain/types/receipt.go:30.47,32.2 1 0 -github.com/ethereum/go-ethereum/chain/types/receipt.go:34.61,40.16 5 0 -github.com/ethereum/go-ethereum/chain/types/receipt.go:40.16,42.3 1 0 -github.com/ethereum/go-ethereum/chain/types/receipt.go:45.44,47.2 1 0 -github.com/ethereum/go-ethereum/chain/types/receipt.go:49.41,51.2 1 0 -github.com/ethereum/go-ethereum/chain/types/receipt.go:53.47,54.57 1 0 -github.com/ethereum/go-ethereum/chain/types/receipt.go:58.2,58.13 1 0 -github.com/ethereum/go-ethereum/chain/types/receipt.go:54.57,56.3 1 0 -github.com/ethereum/go-ethereum/chain/types/receipt.go:61.38,63.2 1 0 -github.com/ethereum/go-ethereum/chain/types/receipt.go:67.43,67.63 1 0 -github.com/ethereum/go-ethereum/chain/types/receipt.go:68.43,68.74 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:15.39,18.2 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:34.87,36.2 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:38.96,40.2 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:42.56,47.2 3 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:49.63,54.2 3 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:56.46,58.2 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:60.48,63.2 2 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:65.38,69.2 2 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:71.47,73.2 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:76.42,78.2 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:80.67,88.2 2 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:90.53,96.2 3 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:98.43,112.2 7 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:114.40,119.40 2 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:123.2,123.37 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:119.40,121.3 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:126.49,135.2 5 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:137.46,143.2 2 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:145.50,147.2 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:149.43,151.2 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:153.47,155.2 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:157.63,169.34 10 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:169.34,171.3 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:174.40,201.2 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:206.48,209.26 2 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:214.2,214.12 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:209.26,212.3 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:216.44,216.61 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:217.44,217.71 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:218.44,218.72 1 0 -github.com/ethereum/go-ethereum/chain/types/transaction.go:222.40,224.2 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:20.45,23.32 2 4 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:45.2,45.25 1 4 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:23.32,24.22 1 4 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:24.22,25.22 1 4 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:25.22,26.21 1 4 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:36.5,36.8 1 4 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:27.5,28.22 1 1 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:29.5,30.26 1 1 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:31.5,32.26 1 1 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:33.5,34.46 1 1 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:37.6,39.5 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:40.5,42.4 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:48.52,49.9 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:50.2,51.38 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:52.2,54.32 2 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:60.3,60.39 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:61.2,62.64 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:67.3,67.14 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:68.2,69.20 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:54.32,55.19 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:58.4,58.7 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:55.19,56.10 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:62.64,64.4 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:64.5,64.79 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:64.79,66.4 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:73.34,77.19 3 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:83.2,83.20 1 0 -github.com/ethereum/go-ethereum/compression/rle/read_write.go:77.19,81.3 3 0 -github.com/ethereum/go-ethereum/crypto/crypto.go:13.31,18.2 3 1 -github.com/ethereum/go-ethereum/crypto/crypto.go:21.51,23.2 1 0 -github.com/ethereum/go-ethereum/crypto/crypto.go:25.33,29.2 2 1 -github.com/ethereum/go-ethereum/crypto/crypto.go:31.36,36.2 3 1 -github.com/ethereum/go-ethereum/crypto/crypto.go:38.36,47.2 3 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:18.55,20.2 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:22.52,24.2 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:26.41,28.2 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:30.41,32.2 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:34.42,36.2 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:38.41,40.2 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:42.39,44.2 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:46.67,48.16 2 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:51.2,52.12 2 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:48.16,50.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:55.61,57.12 2 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:64.2,64.21 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:57.12,60.17 3 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:60.17,62.4 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:67.45,69.2 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:71.80,72.29 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:75.2,79.16 5 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:82.2,85.12 4 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:72.29,74.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:79.16,81.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:88.50,89.31 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:92.2,93.12 2 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:89.31,91.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:96.73,98.12 2 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:105.2,105.20 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:108.2,108.42 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:98.12,101.17 3 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:101.17,103.4 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:105.20,107.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:111.96,113.16 2 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:116.2,116.42 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:113.16,115.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:119.87,121.16 2 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:124.2,124.42 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:121.16,123.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_manager.go:127.47,130.2 2 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:24.51,26.2 1 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:28.67,31.2 2 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:33.61,35.16 2 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:38.2,40.16 3 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:44.2,44.24 1 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:47.2,47.21 1 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:35.16,37.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:40.16,42.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:44.24,46.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:54.69,61.38 7 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:68.2,69.19 2 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:73.2,76.16 4 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:80.2,82.16 3 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:86.2,88.16 3 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:92.2,94.16 3 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:98.2,98.12 1 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:61.38,66.3 4 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:69.19,71.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:76.16,78.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:82.16,84.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:88.16,90.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:94.16,96.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:101.63,103.19 2 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:106.2,109.16 3 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:112.2,112.36 1 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:103.19,105.3 1 0 -github.com/ethereum/go-ethereum/crypto/key_store.go:109.16,111.3 1 0 -github.com/ethereum/go-ethereum/crypto/keypair.go:19.36,23.2 3 0 -github.com/ethereum/go-ethereum/crypto/keypair.go:25.57,27.16 2 0 -github.com/ethereum/go-ethereum/crypto/keypair.go:31.2,31.61 1 0 -github.com/ethereum/go-ethereum/crypto/keypair.go:27.16,29.3 1 0 -github.com/ethereum/go-ethereum/crypto/keypair.go:34.36,35.22 1 0 -github.com/ethereum/go-ethereum/crypto/keypair.go:38.2,38.18 1 0 -github.com/ethereum/go-ethereum/crypto/keypair.go:35.22,37.3 1 0 -github.com/ethereum/go-ethereum/crypto/keypair.go:41.37,42.22 1 0 -github.com/ethereum/go-ethereum/crypto/keypair.go:45.2,45.19 1 0 -github.com/ethereum/go-ethereum/crypto/keypair.go:42.22,44.3 1 0 -github.com/ethereum/go-ethereum/crypto/keypair.go:48.64,50.2 1 0 -github.com/ethereum/go-ethereum/crypto/keypair.go:52.38,54.2 1 0 -github.com/ethereum/go-ethereum/crypto/keypair.go:56.45,58.2 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:15.28,17.2 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:19.48,21.2 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:23.46,24.21 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:28.2,28.12 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:24.21,26.3 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:31.32,33.2 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:35.29,37.2 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:39.42,40.33 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:40.33,42.3 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:45.44,47.27 2 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:50.2,50.16 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:47.27,49.3 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:53.59,57.16 4 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:60.2,61.16 2 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:64.2,64.21 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:57.16,59.3 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:61.16,63.3 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:67.61,70.45 3 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:84.2,84.39 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:70.45,73.23 3 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:79.3,79.23 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:73.23,75.4 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:75.5,75.29 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:75.29,77.4 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:79.23,81.4 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:87.61,89.27 2 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:96.2,96.21 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:89.27,91.17 2 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:94.3,94.30 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:91.17,93.4 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:99.57,102.16 3 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:106.2,107.16 2 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:110.2,110.21 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:102.16,105.3 2 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:107.16,109.3 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:113.38,115.2 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:117.45,119.32 2 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:122.2,122.10 1 0 -github.com/ethereum/go-ethereum/crypto/keyring.go:119.32,121.3 1 0 -github.com/ethereum/go-ethereum/crypto/mnemonic.go:9.50,10.26 1 24 -github.com/ethereum/go-ethereum/crypto/mnemonic.go:15.2,15.11 1 0 -github.com/ethereum/go-ethereum/crypto/mnemonic.go:10.26,11.17 1 18817 -github.com/ethereum/go-ethereum/crypto/mnemonic.go:11.17,13.4 1 24 -github.com/ethereum/go-ethereum/crypto/mnemonic.go:18.46,22.56 3 1 -github.com/ethereum/go-ethereum/crypto/mnemonic.go:30.2,30.12 1 1 -github.com/ethereum/go-ethereum/crypto/mnemonic.go:22.56,29.3 6 8 -github.com/ethereum/go-ethereum/crypto/mnemonic.go:33.46,37.39 3 1 -github.com/ethereum/go-ethereum/crypto/mnemonic.go:59.2,59.12 1 1 -github.com/ethereum/go-ethereum/crypto/mnemonic.go:37.39,50.12 9 8 -github.com/ethereum/go-ethereum/crypto/mnemonic.go:53.3,53.12 1 8 -github.com/ethereum/go-ethereum/crypto/mnemonic.go:56.3,57.32 2 8 -github.com/ethereum/go-ethereum/crypto/mnemonic.go:50.12,52.4 1 4 -github.com/ethereum/go-ethereum/crypto/mnemonic.go:53.12,55.4 1 2 -github.com/ethereum/go-ethereum/ethdb/memory_database.go:16.45,20.2 2 0 -github.com/ethereum/go-ethereum/ethdb/memory_database.go:22.54,24.2 1 0 -github.com/ethereum/go-ethereum/ethdb/memory_database.go:26.56,28.2 1 0 -github.com/ethereum/go-ethereum/ethdb/memory_database.go:38.49,42.2 2 0 -github.com/ethereum/go-ethereum/ethdb/memory_database.go:44.32,45.30 1 0 -github.com/ethereum/go-ethereum/ethdb/memory_database.go:45.30,49.3 3 0 -github.com/ethereum/go-ethereum/ethdb/memory_database.go:52.32,53.2 0 0 -github.com/ethereum/go-ethereum/ethdb/memory_database.go:55.45,58.35 2 0 -github.com/ethereum/go-ethereum/ethdb/memory_database.go:62.2,62.13 1 0 -github.com/ethereum/go-ethereum/ethdb/memory_database.go:58.35,60.3 1 0 -github.com/ethereum/go-ethereum/ethdb/database.go:18.56,23.16 3 0 -github.com/ethereum/go-ethereum/ethdb/database.go:27.2,29.22 2 0 -github.com/ethereum/go-ethereum/ethdb/database.go:23.16,25.3 1 0 -github.com/ethereum/go-ethereum/ethdb/database.go:32.56,33.15 1 0 -github.com/ethereum/go-ethereum/ethdb/database.go:37.2,38.16 2 0 -github.com/ethereum/go-ethereum/ethdb/database.go:33.15,35.3 1 0 -github.com/ethereum/go-ethereum/ethdb/database.go:38.16,40.3 1 0 -github.com/ethereum/go-ethereum/ethdb/database.go:43.58,45.16 2 0 -github.com/ethereum/go-ethereum/ethdb/database.go:49.2,49.15 1 0 -github.com/ethereum/go-ethereum/ethdb/database.go:53.2,53.17 1 0 -github.com/ethereum/go-ethereum/ethdb/database.go:45.16,47.3 1 0 -github.com/ethereum/go-ethereum/ethdb/database.go:49.15,51.3 1 0 -github.com/ethereum/go-ethereum/ethdb/database.go:56.51,58.2 1 0 -github.com/ethereum/go-ethereum/ethdb/database.go:60.47,63.20 2 0 -github.com/ethereum/go-ethereum/ethdb/database.go:67.2,67.13 1 0 -github.com/ethereum/go-ethereum/ethdb/database.go:63.20,65.3 1 0 -github.com/ethereum/go-ethereum/ethdb/database.go:70.58,72.2 1 0 -github.com/ethereum/go-ethereum/ethdb/database.go:74.34,77.2 1 0 -github.com/ethereum/go-ethereum/ethdb/database.go:79.34,81.18 2 0 -github.com/ethereum/go-ethereum/ethdb/database.go:81.18,88.3 5 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:14.35,16.2 1 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:18.60,19.22 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:25.2,25.10 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:19.22,20.34 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:20.34,22.4 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:31.54,34.16 3 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:38.2,38.41 1 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:34.16,36.3 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:44.37,53.16 6 2 -github.com/ethereum/go-ethereum/ethutil/bytes.go:57.2,57.15 1 2 -github.com/ethereum/go-ethereum/ethutil/bytes.go:53.16,55.3 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:63.43,64.25 1 5 -github.com/ethereum/go-ethereum/ethutil/bytes.go:84.2,84.8 1 5 -github.com/ethereum/go-ethereum/ethutil/bytes.go:65.2,67.58 2 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:68.2,72.20 4 2 -github.com/ethereum/go-ethereum/ethutil/bytes.go:73.2,77.20 4 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:78.2,81.20 3 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:90.32,91.14 1 7 -github.com/ethereum/go-ethereum/ethutil/bytes.go:95.2,95.33 1 5 -github.com/ethereum/go-ethereum/ethutil/bytes.go:91.14,93.3 1 2 -github.com/ethereum/go-ethereum/ethutil/bytes.go:101.47,106.2 3 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:108.29,111.2 2 5 -github.com/ethereum/go-ethereum/ethutil/bytes.go:113.33,115.2 1 2 -github.com/ethereum/go-ethereum/ethutil/bytes.go:117.35,121.2 2 3 -github.com/ethereum/go-ethereum/ethutil/bytes.go:123.76,124.70 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:130.2,130.8 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:124.70,126.3 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:126.4,128.3 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:133.37,134.20 1 4 -github.com/ethereum/go-ethereum/ethutil/bytes.go:138.2,139.53 2 3 -github.com/ethereum/go-ethereum/ethutil/bytes.go:147.2,147.27 1 2 -github.com/ethereum/go-ethereum/ethutil/bytes.go:134.20,136.3 1 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:139.53,141.3 1 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:141.4,141.46 1 2 -github.com/ethereum/go-ethereum/ethutil/bytes.go:141.46,143.3 1 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:143.4,145.3 1 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:150.50,151.28 1 2 -github.com/ethereum/go-ethereum/ethutil/bytes.go:167.2,167.8 1 2 -github.com/ethereum/go-ethereum/ethutil/bytes.go:151.28,152.27 1 4 -github.com/ethereum/go-ethereum/ethutil/bytes.go:153.3,155.16 2 3 -github.com/ethereum/go-ethereum/ethutil/bytes.go:161.4,161.48 1 3 -github.com/ethereum/go-ethereum/ethutil/bytes.go:162.3,163.45 1 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:155.16,157.5 1 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:157.6,159.5 1 2 -github.com/ethereum/go-ethereum/ethutil/bytes.go:170.48,171.20 1 6 -github.com/ethereum/go-ethereum/ethutil/bytes.go:175.2,178.15 3 5 -github.com/ethereum/go-ethereum/ethutil/bytes.go:171.20,173.3 1 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:181.47,182.20 1 7 -github.com/ethereum/go-ethereum/ethutil/bytes.go:186.2,189.15 3 6 -github.com/ethereum/go-ethereum/ethutil/bytes.go:182.20,184.3 1 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:192.46,193.18 1 2 -github.com/ethereum/go-ethereum/ethutil/bytes.go:197.2,199.20 2 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:193.18,195.3 1 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:203.47,204.18 1 2 -github.com/ethereum/go-ethereum/ethutil/bytes.go:208.2,210.20 2 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:204.18,206.3 1 1 -github.com/ethereum/go-ethereum/ethutil/bytes.go:214.42,215.21 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:223.2,225.8 2 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:215.21,217.3 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:217.4,217.28 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:217.28,219.3 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:219.4,221.3 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:228.63,229.26 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:233.2,233.8 1 0 -github.com/ethereum/go-ethereum/ethutil/bytes.go:229.26,231.3 1 0 -github.com/ethereum/go-ethereum/ethutil/path.go:10.45,14.22 2 2 -github.com/ethereum/go-ethereum/ethutil/path.go:21.2,21.8 1 2 -github.com/ethereum/go-ethereum/ethutil/path.go:14.22,19.3 3 1 -github.com/ethereum/go-ethereum/ethutil/path.go:24.38,26.38 2 2 -github.com/ethereum/go-ethereum/ethutil/path.go:30.2,30.13 1 1 -github.com/ethereum/go-ethereum/ethutil/path.go:26.38,28.3 1 1 -github.com/ethereum/go-ethereum/ethutil/path.go:33.51,35.16 2 2 -github.com/ethereum/go-ethereum/ethutil/path.go:39.2,40.16 2 1 -github.com/ethereum/go-ethereum/ethutil/path.go:44.2,44.26 1 1 -github.com/ethereum/go-ethereum/ethutil/path.go:35.16,37.3 1 1 -github.com/ethereum/go-ethereum/ethutil/path.go:40.16,42.3 1 0 -github.com/ethereum/go-ethereum/ethutil/path.go:47.55,49.16 2 2 -github.com/ethereum/go-ethereum/ethutil/path.go:52.2,55.16 3 1 -github.com/ethereum/go-ethereum/ethutil/path.go:59.2,59.12 1 1 -github.com/ethereum/go-ethereum/ethutil/path.go:49.16,51.3 1 1 -github.com/ethereum/go-ethereum/ethutil/path.go:55.16,57.3 1 0 -github.com/ethereum/go-ethereum/ethutil/script_unix.go:15.66,16.21 1 0 -github.com/ethereum/go-ethereum/ethutil/script_unix.go:48.2,48.17 1 0 -github.com/ethereum/go-ethereum/ethutil/script_unix.go:16.21,19.41 2 0 -github.com/ethereum/go-ethereum/ethutil/script_unix.go:19.41,20.16 1 0 -github.com/ethereum/go-ethereum/ethutil/script_unix.go:21.4,23.19 2 0 -github.com/ethereum/go-ethereum/ethutil/script_unix.go:27.5,27.25 1 0 -github.com/ethereum/go-ethereum/ethutil/script_unix.go:23.19,25.6 1 0 -github.com/ethereum/go-ethereum/ethutil/script_unix.go:29.5,34.23 4 0 -github.com/ethereum/go-ethereum/ethutil/script_unix.go:44.4,44.24 1 0 -github.com/ethereum/go-ethereum/ethutil/script_unix.go:34.23,36.31 2 0 -github.com/ethereum/go-ethereum/ethutil/script_unix.go:41.5,41.39 1 0 -github.com/ethereum/go-ethereum/ethutil/script_unix.go:36.31,37.19 1 0 -github.com/ethereum/go-ethereum/ethutil/script_unix.go:37.19,39.7 1 0 -github.com/ethereum/go-ethereum/ethutil/size.go:7.41,8.20 1 3 -github.com/ethereum/go-ethereum/ethutil/size.go:8.20,10.3 1 1 -github.com/ethereum/go-ethereum/ethutil/size.go:10.4,10.24 1 2 -github.com/ethereum/go-ethereum/ethutil/size.go:10.24,12.3 1 1 -github.com/ethereum/go-ethereum/ethutil/size.go:12.4,14.3 1 1 -github.com/ethereum/go-ethereum/ethutil/rlp.go:22.36,24.2 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:30.34,34.2 2 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:35.65,37.2 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:46.25,47.16 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:51.2,51.15 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:47.16,49.3 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:54.57,59.9 3 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:91.2,91.14 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:60.2,61.14 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:63.2,64.39 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:66.2,69.34 2 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:71.2,73.31 2 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:78.3,78.15 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:79.2,81.39 2 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:86.3,86.15 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:87.2,88.53 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:73.31,76.4 2 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:81.39,84.4 2 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:100.40,103.19 2 59 -github.com/ethereum/go-ethereum/ethutil/rlp.go:177.2,177.21 1 59 -github.com/ethereum/go-ethereum/ethutil/rlp.go:103.19,104.29 1 59 -github.com/ethereum/go-ethereum/ethutil/rlp.go:105.3,106.31 1 2 -github.com/ethereum/go-ethereum/ethutil/rlp.go:107.3,108.35 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:110.3,111.44 1 10 -github.com/ethereum/go-ethereum/ethutil/rlp.go:112.3,113.44 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:114.3,115.44 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:116.3,117.44 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:118.3,119.44 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:120.3,121.37 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:122.3,123.44 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:124.3,125.44 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:126.3,127.44 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:128.3,129.44 1 1 -github.com/ethereum/go-ethereum/ethutil/rlp.go:130.3,132.16 1 12 -github.com/ethereum/go-ethereum/ethutil/rlp.go:137.3,138.33 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:139.3,140.35 1 20 -github.com/ethereum/go-ethereum/ethutil/rlp.go:151.3,152.33 1 6 -github.com/ethereum/go-ethereum/ethutil/rlp.go:153.3,155.41 1 8 -github.com/ethereum/go-ethereum/ethutil/rlp.go:165.4,166.26 2 8 -github.com/ethereum/go-ethereum/ethutil/rlp.go:169.4,170.25 2 8 -github.com/ethereum/go-ethereum/ethutil/rlp.go:132.16,134.5 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:134.6,136.5 1 12 -github.com/ethereum/go-ethereum/ethutil/rlp.go:140.35,142.5 1 11 -github.com/ethereum/go-ethereum/ethutil/rlp.go:142.6,142.26 1 9 -github.com/ethereum/go-ethereum/ethutil/rlp.go:142.26,145.5 2 8 -github.com/ethereum/go-ethereum/ethutil/rlp.go:145.6,150.5 4 1 -github.com/ethereum/go-ethereum/ethutil/rlp.go:155.41,156.20 1 8 -github.com/ethereum/go-ethereum/ethutil/rlp.go:156.20,158.6 1 8 -github.com/ethereum/go-ethereum/ethutil/rlp.go:158.7,162.6 3 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:166.26,168.5 1 19 -github.com/ethereum/go-ethereum/ethutil/rlp.go:172.4,175.3 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:182.60,185.9 3 16 -github.com/ethereum/go-ethereum/ethutil/rlp.go:241.2,241.17 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:186.2,187.28 1 3 -github.com/ethereum/go-ethereum/ethutil/rlp.go:189.2,192.44 2 9 -github.com/ethereum/go-ethereum/ethutil/rlp.go:194.2,199.54 3 1 -github.com/ethereum/go-ethereum/ethutil/rlp.go:201.2,205.30 4 3 -github.com/ethereum/go-ethereum/ethutil/rlp.go:217.3,217.20 1 3 -github.com/ethereum/go-ethereum/ethutil/rlp.go:219.2,226.38 5 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:235.3,235.20 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:237.2,238.53 1 0 -github.com/ethereum/go-ethereum/ethutil/rlp.go:205.30,216.4 5 9 -github.com/ethereum/go-ethereum/ethutil/rlp.go:226.38,234.4 5 0 -github.com/ethereum/go-ethereum/ethutil/set.go:13.40,15.24 2 0 -github.com/ethereum/go-ethereum/ethutil/set.go:19.2,19.12 1 0 -github.com/ethereum/go-ethereum/ethutil/set.go:15.24,17.3 1 0 -github.com/ethereum/go-ethereum/ethutil/set.go:22.54,26.2 2 0 -github.com/ethereum/go-ethereum/ethutil/set.go:28.50,32.2 2 0 -github.com/ethereum/go-ethereum/ethutil/set.go:34.32,36.2 1 0 -github.com/ethereum/go-ethereum/ethutil/big.go:8.32,13.2 3 18 -github.com/ethereum/go-ethereum/ethutil/big.go:18.31,23.2 3 8 -github.com/ethereum/go-ethereum/ethutil/big.go:28.33,33.2 3 1 -github.com/ethereum/go-ethereum/ethutil/big.go:35.40,37.2 1 1 -github.com/ethereum/go-ethereum/ethutil/big.go:46.32,54.2 2 2 -github.com/ethereum/go-ethereum/ethutil/big.go:56.32,57.22 1 2 -github.com/ethereum/go-ethereum/ethutil/big.go:57.22,59.3 1 1 -github.com/ethereum/go-ethereum/ethutil/big.go:59.4,62.3 1 1 -github.com/ethereum/go-ethereum/ethutil/big.go:69.48,72.31 2 4 -github.com/ethereum/go-ethereum/ethutil/big.go:76.2,76.64 1 3 -github.com/ethereum/go-ethereum/ethutil/big.go:72.31,74.3 1 1 -github.com/ethereum/go-ethereum/ethutil/big.go:82.37,84.2 1 1 -github.com/ethereum/go-ethereum/ethutil/big.go:89.37,90.19 1 2 -github.com/ethereum/go-ethereum/ethutil/big.go:94.2,94.10 1 1 -github.com/ethereum/go-ethereum/ethutil/big.go:90.19,92.3 1 1 -github.com/ethereum/go-ethereum/ethutil/big.go:100.37,101.19 1 2 -github.com/ethereum/go-ethereum/ethutil/big.go:105.2,105.10 1 1 -github.com/ethereum/go-ethereum/ethutil/big.go:101.19,103.3 1 1 -github.com/ethereum/go-ethereum/ethutil/config.go:30.85,31.19 1 0 -github.com/ethereum/go-ethereum/ethutil/config.go:48.2,48.15 1 0 -github.com/ethereum/go-ethereum/ethutil/config.go:31.19,33.29 1 0 -github.com/ethereum/go-ethereum/ethutil/config.go:37.3,41.17 2 0 -github.com/ethereum/go-ethereum/ethutil/config.go:46.3,46.83 1 0 -github.com/ethereum/go-ethereum/ethutil/config.go:33.29,36.4 2 0 -github.com/ethereum/go-ethereum/ethutil/config.go:41.17,43.4 1 0 -github.com/ethereum/go-ethereum/ethutil/config.go:43.5,45.4 1 0 -github.com/ethereum/go-ethereum/ethutil/config.go:52.61,55.2 2 0 -github.com/ethereum/go-ethereum/ethutil/config.go:57.44,59.2 1 0 -github.com/ethereum/go-ethereum/ethutil/config.go:67.49,69.2 1 0 -github.com/ethereum/go-ethereum/ethutil/config.go:71.43,71.64 1 0 -github.com/ethereum/go-ethereum/ethutil/config.go:72.43,72.73 2 0 -github.com/ethereum/go-ethereum/ethutil/list.go:20.35,22.34 2 0 -github.com/ethereum/go-ethereum/ethutil/list.go:26.2,26.49 1 0 -github.com/ethereum/go-ethereum/ethutil/list.go:22.34,24.3 1 0 -github.com/ethereum/go-ethereum/ethutil/list.go:29.24,31.2 1 0 -github.com/ethereum/go-ethereum/ethutil/list.go:34.42,35.25 1 0 -github.com/ethereum/go-ethereum/ethutil/list.go:44.2,44.12 1 0 -github.com/ethereum/go-ethereum/ethutil/list.go:35.25,42.3 4 0 -github.com/ethereum/go-ethereum/ethutil/list.go:47.48,53.2 3 0 -github.com/ethereum/go-ethereum/ethutil/list.go:57.41,63.2 4 0 -github.com/ethereum/go-ethereum/ethutil/list.go:66.43,68.2 1 0 -github.com/ethereum/go-ethereum/ethutil/list.go:71.35,74.35 2 0 -github.com/ethereum/go-ethereum/ethutil/list.go:78.2,80.21 2 0 -github.com/ethereum/go-ethereum/ethutil/list.go:74.35,76.3 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:33.44,35.16 2 0 -github.com/ethereum/go-ethereum/ethutil/package.go:38.2,41.16 3 0 -github.com/ethereum/go-ethereum/ethutil/package.go:45.2,45.21 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:35.16,37.3 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:41.16,43.3 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:51.48,55.49 3 0 -github.com/ethereum/go-ethereum/ethutil/package.go:60.2,60.23 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:55.49,56.3 0 0 -github.com/ethereum/go-ethereum/ethutil/package.go:56.4,56.23 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:56.23,58.3 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:66.66,69.26 2 0 -github.com/ethereum/go-ethereum/ethutil/package.go:75.2,75.8 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:69.26,70.19 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:70.19,72.4 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:83.50,85.16 2 0 -github.com/ethereum/go-ethereum/ethutil/package.go:88.2,92.23 3 0 -github.com/ethereum/go-ethereum/ethutil/package.go:96.2,97.16 2 0 -github.com/ethereum/go-ethereum/ethutil/package.go:101.2,102.16 2 0 -github.com/ethereum/go-ethereum/ethutil/package.go:106.2,106.26 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:110.2,111.20 2 0 -github.com/ethereum/go-ethereum/ethutil/package.go:115.2,116.16 2 0 -github.com/ethereum/go-ethereum/ethutil/package.go:120.2,122.24 2 0 -github.com/ethereum/go-ethereum/ethutil/package.go:85.16,87.3 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:92.23,94.3 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:97.16,99.3 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:102.16,104.3 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:106.26,108.3 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:111.20,113.3 1 0 -github.com/ethereum/go-ethereum/ethutil/package.go:116.16,118.3 1 0 -github.com/ethereum/go-ethereum/ethutil/common.go:9.23,11.2 1 2 -github.com/ethereum/go-ethereum/ethutil/common.go:13.40,14.43 1 1 -github.com/ethereum/go-ethereum/ethutil/common.go:17.2,17.13 1 1 -github.com/ethereum/go-ethereum/ethutil/common.go:14.43,16.3 1 0 -github.com/ethereum/go-ethereum/ethutil/common.go:36.44,42.9 2 12 -github.com/ethereum/go-ethereum/ethutil/common.go:70.2,70.27 1 12 -github.com/ethereum/go-ethereum/ethutil/common.go:74.2,74.41 1 10 -github.com/ethereum/go-ethereum/ethutil/common.go:43.2,45.20 2 2 -github.com/ethereum/go-ethereum/ethutil/common.go:46.2,48.21 2 2 -github.com/ethereum/go-ethereum/ethutil/common.go:49.2,51.18 2 1 -github.com/ethereum/go-ethereum/ethutil/common.go:52.2,54.19 2 1 -github.com/ethereum/go-ethereum/ethutil/common.go:55.2,57.18 2 1 -github.com/ethereum/go-ethereum/ethutil/common.go:58.2,60.20 2 1 -github.com/ethereum/go-ethereum/ethutil/common.go:61.2,63.20 2 2 -github.com/ethereum/go-ethereum/ethutil/common.go:64.2,66.16 2 1 -github.com/ethereum/go-ethereum/ethutil/common.go:70.27,72.3 1 2 -github.com/ethereum/go-ethereum/ethutil/rand.go:9.48,12.17 3 2 -github.com/ethereum/go-ethereum/ethutil/rand.go:15.2,15.16 1 2 -github.com/ethereum/go-ethereum/ethutil/rand.go:18.2,18.40 1 2 -github.com/ethereum/go-ethereum/ethutil/rand.go:12.17,14.3 1 0 -github.com/ethereum/go-ethereum/ethutil/rand.go:15.16,17.3 1 0 -github.com/ethereum/go-ethereum/ethutil/rand.go:22.37,24.2 1 2 -github.com/ethereum/go-ethereum/ethutil/value.go:19.35,21.2 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:23.39,25.31 2 39 -github.com/ethereum/go-ethereum/ethutil/value.go:29.2,29.23 1 39 -github.com/ethereum/go-ethereum/ethutil/value.go:25.31,27.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:32.39,34.2 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:36.32,38.2 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:40.29,42.45 1 8 -github.com/ethereum/go-ethereum/ethutil/value.go:46.2,46.25 1 1 -github.com/ethereum/go-ethereum/ethutil/value.go:42.45,44.3 1 7 -github.com/ethereum/go-ethereum/ethutil/value.go:49.37,51.2 1 2 -github.com/ethereum/go-ethereum/ethutil/value.go:53.43,55.2 1 1 -github.com/ethereum/go-ethereum/ethutil/value.go:57.33,58.36 1 11 -github.com/ethereum/go-ethereum/ethutil/value.go:80.2,80.10 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:58.36,60.3 1 1 -github.com/ethereum/go-ethereum/ethutil/value.go:60.4,60.44 1 10 -github.com/ethereum/go-ethereum/ethutil/value.go:60.44,62.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:62.4,62.44 1 10 -github.com/ethereum/go-ethereum/ethutil/value.go:62.44,64.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:64.4,64.44 1 10 -github.com/ethereum/go-ethereum/ethutil/value.go:64.44,66.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:66.4,66.45 1 10 -github.com/ethereum/go-ethereum/ethutil/value.go:66.45,68.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:68.4,68.45 1 10 -github.com/ethereum/go-ethereum/ethutil/value.go:68.45,70.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:70.4,70.41 1 10 -github.com/ethereum/go-ethereum/ethutil/value.go:70.41,72.3 1 10 -github.com/ethereum/go-ethereum/ethutil/value.go:72.4,72.42 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:72.42,74.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:74.4,74.44 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:74.44,76.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:76.4,76.46 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:76.46,78.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:83.31,84.35 1 3 -github.com/ethereum/go-ethereum/ethutil/value.go:107.2,107.10 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:84.35,86.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:86.4,86.43 1 3 -github.com/ethereum/go-ethereum/ethutil/value.go:86.43,88.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:88.4,88.43 1 3 -github.com/ethereum/go-ethereum/ethutil/value.go:88.43,90.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:90.4,90.43 1 3 -github.com/ethereum/go-ethereum/ethutil/value.go:90.43,92.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:92.4,92.41 1 3 -github.com/ethereum/go-ethereum/ethutil/value.go:92.41,94.3 1 2 -github.com/ethereum/go-ethereum/ethutil/value.go:94.4,94.45 1 1 -github.com/ethereum/go-ethereum/ethutil/value.go:94.45,96.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:96.4,96.45 1 1 -github.com/ethereum/go-ethereum/ethutil/value.go:96.45,98.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:98.4,98.44 1 1 -github.com/ethereum/go-ethereum/ethutil/value.go:98.44,100.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:100.4,100.46 1 1 -github.com/ethereum/go-ethereum/ethutil/value.go:100.46,102.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:102.4,102.44 1 1 -github.com/ethereum/go-ethereum/ethutil/value.go:102.44,105.3 2 1 -github.com/ethereum/go-ethereum/ethutil/value.go:110.31,111.35 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:115.2,115.12 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:111.35,113.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:118.37,119.35 1 10 -github.com/ethereum/go-ethereum/ethutil/value.go:131.2,131.22 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:119.35,123.3 2 1 -github.com/ethereum/go-ethereum/ethutil/value.go:123.4,123.44 1 9 -github.com/ethereum/go-ethereum/ethutil/value.go:123.44,125.3 1 3 -github.com/ethereum/go-ethereum/ethutil/value.go:125.4,125.42 1 6 -github.com/ethereum/go-ethereum/ethutil/value.go:125.42,127.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:127.4,129.3 1 6 -github.com/ethereum/go-ethereum/ethutil/value.go:134.32,135.35 1 2 -github.com/ethereum/go-ethereum/ethutil/value.go:143.2,143.11 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:135.35,137.3 1 1 -github.com/ethereum/go-ethereum/ethutil/value.go:137.4,137.42 1 1 -github.com/ethereum/go-ethereum/ethutil/value.go:137.42,139.3 1 1 -github.com/ethereum/go-ethereum/ethutil/value.go:139.4,139.40 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:139.40,141.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:146.34,147.35 1 10 -github.com/ethereum/go-ethereum/ethutil/value.go:159.2,159.17 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:147.35,149.3 1 6 -github.com/ethereum/go-ethereum/ethutil/value.go:149.4,149.40 1 4 -github.com/ethereum/go-ethereum/ethutil/value.go:149.40,151.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:151.4,151.42 1 4 -github.com/ethereum/go-ethereum/ethutil/value.go:151.42,153.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:153.4,153.44 1 4 -github.com/ethereum/go-ethereum/ethutil/value.go:153.44,155.3 1 2 -github.com/ethereum/go-ethereum/ethutil/value.go:155.4,157.3 1 2 -github.com/ethereum/go-ethereum/ethutil/value.go:162.31,163.36 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:167.2,167.12 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:163.36,165.3 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:170.41,171.42 1 10 -github.com/ethereum/go-ethereum/ethutil/value.go:175.2,175.24 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:171.42,173.3 1 10 -github.com/ethereum/go-ethereum/ethutil/value.go:178.46,182.2 2 1 -github.com/ethereum/go-ethereum/ethutil/value.go:184.42,188.2 2 1 -github.com/ethereum/go-ethereum/ethutil/value.go:190.52,194.2 2 1 -github.com/ethereum/go-ethereum/ethutil/value.go:197.34,199.2 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:201.32,203.2 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:205.33,208.2 2 0 -github.com/ethereum/go-ethereum/ethutil/value.go:213.33,217.2 2 0 -github.com/ethereum/go-ethereum/ethutil/value.go:219.34,221.2 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:224.39,225.42 1 5 -github.com/ethereum/go-ethereum/ethutil/value.go:239.2,239.22 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:225.42,227.20 1 5 -github.com/ethereum/go-ethereum/ethutil/value.go:231.3,231.14 1 5 -github.com/ethereum/go-ethereum/ethutil/value.go:235.3,235.26 1 5 -github.com/ethereum/go-ethereum/ethutil/value.go:227.20,229.4 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:231.14,233.4 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:242.34,243.32 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:252.2,252.12 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:244.2,245.41 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:246.2,247.34 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:248.2,249.28 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:255.38,257.2 1 4 -github.com/ethereum/go-ethereum/ethutil/value.go:259.43,261.2 1 2 -github.com/ethereum/go-ethereum/ethutil/value.go:263.35,265.2 1 3 -github.com/ethereum/go-ethereum/ethutil/value.go:268.29,272.2 2 4 -github.com/ethereum/go-ethereum/ethutil/value.go:274.44,275.20 1 3 -github.com/ethereum/go-ethereum/ethutil/value.go:282.2,282.22 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:275.20,280.3 3 3 -github.com/ethereum/go-ethereum/ethutil/value.go:286.42,289.14 2 0 -github.com/ethereum/go-ethereum/ethutil/value.go:301.2,301.13 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:289.14,290.41 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:290.41,291.30 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:291.30,293.5 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:294.5,294.43 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:294.43,295.30 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:295.30,297.5 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:304.26,306.2 1 3 -github.com/ethereum/go-ethereum/ethutil/value.go:308.39,313.2 3 2 -github.com/ethereum/go-ethereum/ethutil/value.go:315.48,319.2 2 5 -github.com/ethereum/go-ethereum/ethutil/value.go:330.59,334.12 3 4 -github.com/ethereum/go-ethereum/ethutil/value.go:347.2,347.13 1 4 -github.com/ethereum/go-ethereum/ethutil/value.go:335.2,336.35 1 2 -github.com/ethereum/go-ethereum/ethutil/value.go:337.2,338.35 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:339.2,340.35 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:341.2,342.41 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:343.2,344.35 1 2 -github.com/ethereum/go-ethereum/ethutil/value.go:350.50,352.2 1 2 -github.com/ethereum/go-ethereum/ethutil/value.go:354.50,356.2 1 2 -github.com/ethereum/go-ethereum/ethutil/value.go:358.50,360.2 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:362.50,364.2 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:366.50,368.2 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:376.48,378.2 1 1 -github.com/ethereum/go-ethereum/ethutil/value.go:380.36,382.2 1 0 -github.com/ethereum/go-ethereum/ethutil/value.go:384.38,385.30 1 4 -github.com/ethereum/go-ethereum/ethutil/value.go:389.2,392.13 3 3 -github.com/ethereum/go-ethereum/ethutil/value.go:385.30,387.3 1 1 -github.com/ethereum/go-ethereum/ethutil/value.go:395.41,397.2 1 3 -github.com/ethereum/go-ethereum/ethutil/value.go:399.36,401.2 1 0 -github.com/ethereum/go-ethereum/event/event.go:41.66,45.17 4 1005 -github.com/ethereum/go-ethereum/event/event.go:63.2,63.12 1 1004 -github.com/ethereum/go-ethereum/event/event.go:45.17,47.3 1 1 -github.com/ethereum/go-ethereum/event/event.go:47.4,48.22 1 1004 -github.com/ethereum/go-ethereum/event/event.go:51.3,51.27 1 1004 -github.com/ethereum/go-ethereum/event/event.go:48.22,50.4 1 5 -github.com/ethereum/go-ethereum/event/event.go:51.27,54.32 3 1006 -github.com/ethereum/go-ethereum/event/event.go:57.4,60.25 4 1005 -github.com/ethereum/go-ethereum/event/event.go:54.32,56.5 1 1 -github.com/ethereum/go-ethereum/event/event.go:68.48,71.17 3 6657815 -github.com/ethereum/go-ethereum/event/event.go:75.2,77.27 3 6657811 -github.com/ethereum/go-ethereum/event/event.go:80.2,80.12 1 6657811 -github.com/ethereum/go-ethereum/event/event.go:71.17,74.3 2 4 -github.com/ethereum/go-ethereum/event/event.go:77.27,79.3 1 4004 -github.com/ethereum/go-ethereum/event/event.go:86.28,88.32 2 5 -github.com/ethereum/go-ethereum/event/event.go:93.2,95.20 3 5 -github.com/ethereum/go-ethereum/event/event.go:88.32,89.28 1 3 -github.com/ethereum/go-ethereum/event/event.go:89.28,91.4 1 3 -github.com/ethereum/go-ethereum/event/event.go:98.36,100.34 2 1001 -github.com/ethereum/go-ethereum/event/event.go:109.2,109.22 1 1001 -github.com/ethereum/go-ethereum/event/event.go:100.34,101.37 1 1001 -github.com/ethereum/go-ethereum/event/event.go:101.37,102.22 1 1001 -github.com/ethereum/go-ethereum/event/event.go:102.22,104.5 1 5 -github.com/ethereum/go-ethereum/event/event.go:104.6,106.5 1 996 -github.com/ethereum/go-ethereum/event/event.go:112.46,113.26 1 2007 -github.com/ethereum/go-ethereum/event/event.go:118.2,118.11 1 1005 -github.com/ethereum/go-ethereum/event/event.go:113.26,114.16 1 17982 -github.com/ethereum/go-ethereum/event/event.go:114.16,116.4 1 1002 -github.com/ethereum/go-ethereum/event/event.go:121.52,126.2 4 996 -github.com/ethereum/go-ethereum/event/event.go:142.35,150.2 2 1005 -github.com/ethereum/go-ethereum/event/event.go:152.44,154.2 1 1003 -github.com/ethereum/go-ethereum/event/event.go:156.32,159.2 2 1001 -github.com/ethereum/go-ethereum/event/event.go:161.30,164.14 3 1004 -github.com/ethereum/go-ethereum/event/event.go:167.2,173.19 6 1003 -github.com/ethereum/go-ethereum/event/event.go:164.14,166.3 1 1 -github.com/ethereum/go-ethereum/event/event.go:176.42,178.9 2 4004 -github.com/ethereum/go-ethereum/event/event.go:182.2,182.20 1 4004 -github.com/ethereum/go-ethereum/event/event.go:179.2,179.21 0 1004 -github.com/ethereum/go-ethereum/event/event.go:180.2,180.19 0 3000 -github.com/ethereum/go-ethereum/logger/loggers.go:56.13,58.2 1 1 -github.com/ethereum/go-ethereum/logger/loggers.go:64.21,70.36 2 1 -github.com/ethereum/go-ethereum/logger/loggers.go:77.2,77.6 1 1 -github.com/ethereum/go-ethereum/logger/loggers.go:70.36,75.3 4 22 -github.com/ethereum/go-ethereum/logger/loggers.go:77.6,78.10 1 52 -github.com/ethereum/go-ethereum/logger/loggers.go:79.3,80.31 1 20 -github.com/ethereum/go-ethereum/logger/loggers.go:84.3,86.19 2 16 -github.com/ethereum/go-ethereum/logger/loggers.go:88.3,90.31 1 7 -github.com/ethereum/go-ethereum/logger/loggers.go:93.4,96.17 4 7 -github.com/ethereum/go-ethereum/logger/loggers.go:98.3,100.31 1 8 -github.com/ethereum/go-ethereum/logger/loggers.go:103.4,105.32 3 8 -github.com/ethereum/go-ethereum/logger/loggers.go:108.4,108.17 1 8 -github.com/ethereum/go-ethereum/logger/loggers.go:80.31,82.5 1 19 -github.com/ethereum/go-ethereum/logger/loggers.go:90.31,92.5 1 6 -github.com/ethereum/go-ethereum/logger/loggers.go:100.31,102.5 1 6 -github.com/ethereum/go-ethereum/logger/loggers.go:105.32,107.5 1 6 -github.com/ethereum/go-ethereum/logger/loggers.go:113.68,114.22 1 22 -github.com/ethereum/go-ethereum/logger/loggers.go:119.2,119.11 1 12 -github.com/ethereum/go-ethereum/logger/loggers.go:114.22,115.37 1 19 -github.com/ethereum/go-ethereum/logger/loggers.go:115.37,117.4 1 14 -github.com/ethereum/go-ethereum/logger/loggers.go:124.14,128.2 3 7 -github.com/ethereum/go-ethereum/logger/loggers.go:132.14,136.2 3 8 -github.com/ethereum/go-ethereum/logger/loggers.go:139.34,141.2 1 16 -github.com/ethereum/go-ethereum/logger/loggers.go:150.36,152.2 1 7 -github.com/ethereum/go-ethereum/logger/loggers.go:154.64,156.2 1 10 -github.com/ethereum/go-ethereum/logger/loggers.go:158.78,160.2 1 10 -github.com/ethereum/go-ethereum/logger/loggers.go:163.49,165.2 1 2 -github.com/ethereum/go-ethereum/logger/loggers.go:168.48,170.2 1 4 -github.com/ethereum/go-ethereum/logger/loggers.go:173.48,175.2 1 3 -github.com/ethereum/go-ethereum/logger/loggers.go:178.49,180.2 1 1 -github.com/ethereum/go-ethereum/logger/loggers.go:183.55,185.2 1 0 -github.com/ethereum/go-ethereum/logger/loggers.go:188.63,190.2 1 7 -github.com/ethereum/go-ethereum/logger/loggers.go:193.62,195.2 1 1 -github.com/ethereum/go-ethereum/logger/loggers.go:198.62,200.2 1 1 -github.com/ethereum/go-ethereum/logger/loggers.go:203.63,205.2 1 1 -github.com/ethereum/go-ethereum/logger/loggers.go:208.69,210.2 1 0 -github.com/ethereum/go-ethereum/logger/loggers.go:213.49,217.2 3 0 -github.com/ethereum/go-ethereum/logger/loggers.go:220.63,224.2 3 0 -github.com/ethereum/go-ethereum/logger/loggers.go:228.77,231.2 2 11 -github.com/ethereum/go-ethereum/logger/loggers.go:238.61,240.2 1 2 -github.com/ethereum/go-ethereum/logger/loggers.go:242.48,244.2 1 0 -github.com/ethereum/go-ethereum/logger/loggers.go:246.47,248.2 1 2 -github.com/ethereum/go-ethereum/p2p/client_identity.go:23.133,34.2 2 6 -github.com/ethereum/go-ethereum/p2p/client_identity.go:36.39,37.2 0 0 -github.com/ethereum/go-ethereum/p2p/client_identity.go:39.48,41.33 2 11 -github.com/ethereum/go-ethereum/p2p/client_identity.go:45.2,50.20 1 11 -github.com/ethereum/go-ethereum/p2p/client_identity.go:41.33,43.3 1 11 -github.com/ethereum/go-ethereum/p2p/client_identity.go:53.48,55.2 1 23 -github.com/ethereum/go-ethereum/p2p/client_identity.go:57.77,59.2 1 1 -github.com/ethereum/go-ethereum/p2p/client_identity.go:61.61,63.2 1 2 -github.com/ethereum/go-ethereum/p2p/natpmp.go:21.42,23.2 1 0 -github.com/ethereum/go-ethereum/p2p/natpmp.go:25.70,27.16 2 0 -github.com/ethereum/go-ethereum/p2p/natpmp.go:30.2,32.8 3 0 -github.com/ethereum/go-ethereum/p2p/natpmp.go:27.16,29.3 1 0 -github.com/ethereum/go-ethereum/p2p/natpmp.go:36.71,37.18 1 0 -github.com/ethereum/go-ethereum/p2p/natpmp.go:42.2,43.16 2 0 -github.com/ethereum/go-ethereum/p2p/natpmp.go:46.2,47.8 2 0 -github.com/ethereum/go-ethereum/p2p/natpmp.go:37.18,40.3 2 0 -github.com/ethereum/go-ethereum/p2p/natpmp.go:43.16,45.3 1 0 -github.com/ethereum/go-ethereum/p2p/natpmp.go:50.103,55.2 2 0 -github.com/ethereum/go-ethereum/p2p/peer_error.go:60.79,62.9 2 17 -github.com/ethereum/go-ethereum/p2p/peer_error.go:65.2,67.34 3 17 -github.com/ethereum/go-ethereum/p2p/peer_error.go:62.9,64.3 1 0 -github.com/ethereum/go-ethereum/p2p/peer_error.go:70.39,72.2 1 15 -github.com/ethereum/go-ethereum/p2p/peer_error.go:74.44,76.2 1 19 -github.com/ethereum/go-ethereum/p2p/protocol.go:81.37,82.38 1 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:86.2,86.30 1 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:82.38,84.3 1 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:95.48,101.2 2 10 -github.com/ethereum/go-ethereum/p2p/protocol.go:103.35,104.22 1 10 -github.com/ethereum/go-ethereum/p2p/protocol.go:104.22,112.3 2 7 -github.com/ethereum/go-ethereum/p2p/protocol.go:115.34,116.2 0 10 -github.com/ethereum/go-ethereum/p2p/protocol.go:118.34,121.2 2 6 -github.com/ethereum/go-ethereum/p2p/protocol.go:123.37,125.2 1 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:127.41,129.2 1 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:131.44,133.2 1 16 -github.com/ethereum/go-ethereum/p2p/protocol.go:135.64,138.25 3 8 -github.com/ethereum/go-ethereum/p2p/protocol.go:138.25,140.3 1 8 -github.com/ethereum/go-ethereum/p2p/protocol.go:140.4,142.3 1 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:145.66,146.32 1 3 -github.com/ethereum/go-ethereum/p2p/protocol.go:176.2,176.17 1 1 -github.com/ethereum/go-ethereum/p2p/protocol.go:146.32,148.3 1 1 -github.com/ethereum/go-ethereum/p2p/protocol.go:148.4,149.42 1 2 -github.com/ethereum/go-ethereum/p2p/protocol.go:154.3,154.21 1 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:149.42,153.4 3 2 -github.com/ethereum/go-ethereum/p2p/protocol.go:155.3,160.5 2 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:161.3,163.19 2 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:164.3,164.16 0 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:165.3,167.65 1 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:170.3,171.25 1 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:172.3,173.73 1 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:167.65,169.5 1 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:179.62,183.2 2 21 -github.com/ethereum/go-ethereum/p2p/protocol.go:185.91,189.22 4 2 -github.com/ethereum/go-ethereum/p2p/protocol.go:189.22,191.3 1 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:194.49,196.16 2 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:196.16,201.3 4 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:204.53,207.29 3 1 -github.com/ethereum/go-ethereum/p2p/protocol.go:212.2,224.30 4 1 -github.com/ethereum/go-ethereum/p2p/protocol.go:230.2,230.22 1 1 -github.com/ethereum/go-ethereum/p2p/protocol.go:235.2,235.23 1 1 -github.com/ethereum/go-ethereum/p2p/protocol.go:241.2,241.82 1 1 -github.com/ethereum/go-ethereum/p2p/protocol.go:247.2,247.77 1 1 -github.com/ethereum/go-ethereum/p2p/protocol.go:253.2,253.23 1 1 -github.com/ethereum/go-ethereum/p2p/protocol.go:263.2,264.20 2 1 -github.com/ethereum/go-ethereum/p2p/protocol.go:268.2,277.8 5 1 -github.com/ethereum/go-ethereum/p2p/protocol.go:207.29,210.3 2 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:224.30,227.3 2 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:230.22,233.3 2 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:235.23,238.3 2 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:241.82,244.3 2 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:247.77,250.3 2 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:253.23,255.57 2 1 -github.com/ethereum/go-ethereum/p2p/protocol.go:255.57,258.4 2 0 -github.com/ethereum/go-ethereum/p2p/protocol.go:258.5,260.4 1 1 -github.com/ethereum/go-ethereum/p2p/protocol.go:264.20,267.3 2 3 -github.com/ethereum/go-ethereum/p2p/server.go:32.35,36.2 1 6 -github.com/ethereum/go-ethereum/p2p/server.go:38.60,43.9 5 0 -github.com/ethereum/go-ethereum/p2p/server.go:46.2,46.15 1 0 -github.com/ethereum/go-ethereum/p2p/server.go:43.9,45.3 1 0 -github.com/ethereum/go-ethereum/p2p/server.go:49.59,54.2 4 1 -github.com/ethereum/go-ethereum/p2p/server.go:56.52,61.2 4 0 -github.com/ethereum/go-ethereum/p2p/server.go:63.55,68.2 4 0 -github.com/ethereum/go-ethereum/p2p/server.go:98.129,101.33 2 5 -github.com/ethereum/go-ethereum/p2p/server.go:104.2,130.32 5 5 -github.com/ethereum/go-ethereum/p2p/server.go:133.2,133.13 1 5 -github.com/ethereum/go-ethereum/p2p/server.go:101.33,103.3 1 3 -github.com/ethereum/go-ethereum/p2p/server.go:130.32,132.3 1 10 -github.com/ethereum/go-ethereum/p2p/server.go:136.79,139.2 2 0 -github.com/ethereum/go-ethereum/p2p/server.go:141.74,144.2 2 0 -github.com/ethereum/go-ethereum/p2p/server.go:146.53,148.2 1 1 -github.com/ethereum/go-ethereum/p2p/server.go:150.58,155.16 4 1 -github.com/ethereum/go-ethereum/p2p/server.go:168.2,168.8 1 1 -github.com/ethereum/go-ethereum/p2p/server.go:155.16,157.37 2 1 -github.com/ethereum/go-ethereum/p2p/server.go:161.3,161.25 1 1 -github.com/ethereum/go-ethereum/p2p/server.go:157.37,160.4 2 2 -github.com/ethereum/go-ethereum/p2p/server.go:161.25,163.4 1 0 -github.com/ethereum/go-ethereum/p2p/server.go:163.5,166.4 2 1 -github.com/ethereum/go-ethereum/p2p/server.go:171.45,174.34 3 0 -github.com/ethereum/go-ethereum/p2p/server.go:179.2,179.8 1 0 -github.com/ethereum/go-ethereum/p2p/server.go:174.34,175.18 1 0 -github.com/ethereum/go-ethereum/p2p/server.go:175.18,177.4 1 0 -github.com/ethereum/go-ethereum/p2p/server.go:182.37,186.2 3 1 -github.com/ethereum/go-ethereum/p2p/server.go:190.48,193.9 1 0 -github.com/ethereum/go-ethereum/p2p/server.go:194.2,195.34 1 0 -github.com/ethereum/go-ethereum/p2p/server.go:196.2,196.10 0 0 -github.com/ethereum/go-ethereum/p2p/server.go:200.61,202.2 1 7 -github.com/ethereum/go-ethereum/p2p/server.go:204.43,206.2 1 7 -github.com/ethereum/go-ethereum/p2p/server.go:208.41,210.2 1 7 -github.com/ethereum/go-ethereum/p2p/server.go:212.58,215.34 3 1 -github.com/ethereum/go-ethereum/p2p/server.go:215.34,216.18 1 2 -github.com/ethereum/go-ethereum/p2p/server.go:216.18,218.4 1 2 -github.com/ethereum/go-ethereum/p2p/server.go:223.51,225.12 2 4 -github.com/ethereum/go-ethereum/p2p/server.go:237.2,237.10 1 4 -github.com/ethereum/go-ethereum/p2p/server.go:249.2,249.33 1 4 -github.com/ethereum/go-ethereum/p2p/server.go:225.12,227.17 2 3 -github.com/ethereum/go-ethereum/p2p/server.go:227.17,231.4 3 0 -github.com/ethereum/go-ethereum/p2p/server.go:231.5,235.4 3 3 -github.com/ethereum/go-ethereum/p2p/server.go:237.10,239.17 2 3 -github.com/ethereum/go-ethereum/p2p/server.go:239.17,243.4 3 0 -github.com/ethereum/go-ethereum/p2p/server.go:243.5,247.4 3 3 -github.com/ethereum/go-ethereum/p2p/server.go:252.28,255.18 2 4 -github.com/ethereum/go-ethereum/p2p/server.go:263.2,263.20 1 4 -github.com/ethereum/go-ethereum/p2p/server.go:271.2,277.34 6 4 -github.com/ethereum/go-ethereum/p2p/server.go:282.2,283.32 2 4 -github.com/ethereum/go-ethereum/p2p/server.go:291.2,295.6 3 4 -github.com/ethereum/go-ethereum/p2p/server.go:305.2,305.33 1 4 -github.com/ethereum/go-ethereum/p2p/server.go:255.18,261.3 5 3 -github.com/ethereum/go-ethereum/p2p/server.go:263.20,269.3 5 3 -github.com/ethereum/go-ethereum/p2p/server.go:277.34,278.18 1 8 -github.com/ethereum/go-ethereum/p2p/server.go:278.18,280.4 1 6 -github.com/ethereum/go-ethereum/p2p/server.go:283.32,288.3 1 6 -github.com/ethereum/go-ethereum/p2p/server.go:295.6,296.10 1 8 -github.com/ethereum/go-ethereum/p2p/server.go:297.3,300.26 3 8 -github.com/ethereum/go-ethereum/p2p/server.go:300.26,301.14 1 4 -github.com/ethereum/go-ethereum/p2p/server.go:309.63,310.6 1 3 -github.com/ethereum/go-ethereum/p2p/server.go:310.6,311.10 1 2591 -github.com/ethereum/go-ethereum/p2p/server.go:312.3,313.46 1 2588 -github.com/ethereum/go-ethereum/p2p/server.go:314.3,318.10 4 3 -github.com/ethereum/go-ethereum/p2p/server.go:325.56,330.6 4 3 -github.com/ethereum/go-ethereum/p2p/server.go:330.6,331.10 1 10 -github.com/ethereum/go-ethereum/p2p/server.go:332.3,338.15 3 4 -github.com/ethereum/go-ethereum/p2p/server.go:339.3,346.21 3 3 -github.com/ethereum/go-ethereum/p2p/server.go:347.3,348.31 1 0 -github.com/ethereum/go-ethereum/p2p/server.go:349.3,350.41 1 3 -github.com/ethereum/go-ethereum/p2p/server.go:353.4,355.10 3 3 -github.com/ethereum/go-ethereum/p2p/server.go:350.41,352.5 1 1 -github.com/ethereum/go-ethereum/p2p/server.go:361.61,366.11 4 6 -github.com/ethereum/go-ethereum/p2p/server.go:369.2,369.8 1 6 -github.com/ethereum/go-ethereum/p2p/server.go:366.11,368.3 1 0 -github.com/ethereum/go-ethereum/p2p/server.go:373.73,376.16 3 2588 -github.com/ethereum/go-ethereum/p2p/server.go:383.2,383.16 1 2588 -github.com/ethereum/go-ethereum/p2p/server.go:376.16,379.17 3 3 -github.com/ethereum/go-ethereum/p2p/server.go:379.17,381.4 1 0 -github.com/ethereum/go-ethereum/p2p/server.go:383.16,386.3 2 2585 -github.com/ethereum/go-ethereum/p2p/server.go:386.4,389.3 2 3 -github.com/ethereum/go-ethereum/p2p/server.go:393.84,396.16 3 3 -github.com/ethereum/go-ethereum/p2p/server.go:399.2,399.16 1 3 -github.com/ethereum/go-ethereum/p2p/server.go:396.16,398.3 1 3 -github.com/ethereum/go-ethereum/p2p/server.go:399.16,402.3 2 0 -github.com/ethereum/go-ethereum/p2p/server.go:402.4,404.3 1 3 -github.com/ethereum/go-ethereum/p2p/server.go:408.86,411.17 3 6 -github.com/ethereum/go-ethereum/p2p/server.go:411.17,415.3 3 0 -github.com/ethereum/go-ethereum/p2p/server.go:415.4,424.3 7 6 -github.com/ethereum/go-ethereum/p2p/server.go:428.59,435.17 6 6 -github.com/ethereum/go-ethereum/p2p/server.go:441.2,459.24 13 6 -github.com/ethereum/go-ethereum/p2p/server.go:435.17,439.3 3 0 -github.com/ethereum/go-ethereum/p2p/server.go:463.38,467.2 3 8 -github.com/ethereum/go-ethereum/p2p/server.go:469.74,471.35 1 1 -github.com/ethereum/go-ethereum/p2p/server.go:475.2,477.34 3 1 -github.com/ethereum/go-ethereum/p2p/server.go:482.2,483.12 2 1 -github.com/ethereum/go-ethereum/p2p/server.go:471.35,473.3 1 0 -github.com/ethereum/go-ethereum/p2p/server.go:477.34,478.82 1 2 -github.com/ethereum/go-ethereum/p2p/server.go:478.82,480.4 1 0 -github.com/ethereum/go-ethereum/p2p/connection.go:32.32,35.2 2 18 -github.com/ethereum/go-ethereum/p2p/connection.go:37.33,40.2 2 18 -github.com/ethereum/go-ethereum/p2p/connection.go:42.35,46.2 3 18 -github.com/ethereum/go-ethereum/p2p/connection.go:48.36,52.2 3 18 -github.com/ethereum/go-ethereum/p2p/connection.go:54.72,64.2 1 18 -github.com/ethereum/go-ethereum/p2p/connection.go:66.46,68.2 1 18 -github.com/ethereum/go-ethereum/p2p/connection.go:70.47,72.2 1 19 -github.com/ethereum/go-ethereum/p2p/connection.go:74.51,76.2 1 8 -github.com/ethereum/go-ethereum/p2p/connection.go:78.37,86.6 7 18 -github.com/ethereum/go-ethereum/p2p/connection.go:86.6,89.23 2 304 -github.com/ethereum/go-ethereum/p2p/connection.go:96.3,96.10 1 304 -github.com/ethereum/go-ethereum/p2p/connection.go:89.23,92.4 2 12 -github.com/ethereum/go-ethereum/p2p/connection.go:92.5,94.4 1 292 -github.com/ethereum/go-ethereum/p2p/connection.go:97.3,98.32 1 136 -github.com/ethereum/go-ethereum/p2p/connection.go:99.3,100.18 1 136 -github.com/ethereum/go-ethereum/p2p/connection.go:112.4,112.46 1 136 -github.com/ethereum/go-ethereum/p2p/connection.go:113.3,115.42 2 7 -github.com/ethereum/go-ethereum/p2p/connection.go:120.4,120.46 1 7 -github.com/ethereum/go-ethereum/p2p/connection.go:121.3,122.25 1 7 -github.com/ethereum/go-ethereum/p2p/connection.go:123.3,126.10 3 18 -github.com/ethereum/go-ethereum/p2p/connection.go:100.18,101.43 1 133 -github.com/ethereum/go-ethereum/p2p/connection.go:101.43,103.6 1 129 -github.com/ethereum/go-ethereum/p2p/connection.go:103.7,103.25 1 4 -github.com/ethereum/go-ethereum/p2p/connection.go:103.25,105.6 1 0 -github.com/ethereum/go-ethereum/p2p/connection.go:105.7,107.6 1 4 -github.com/ethereum/go-ethereum/p2p/connection.go:108.6,111.5 2 3 -github.com/ethereum/go-ethereum/p2p/connection.go:115.42,117.5 1 0 -github.com/ethereum/go-ethereum/p2p/connection.go:117.6,119.5 1 7 -github.com/ethereum/go-ethereum/p2p/connection.go:132.38,136.6 4 18 -github.com/ethereum/go-ethereum/p2p/connection.go:136.6,137.35 1 56 -github.com/ethereum/go-ethereum/p2p/connection.go:141.3,141.10 1 56 -github.com/ethereum/go-ethereum/p2p/connection.go:137.35,140.4 2 19 -github.com/ethereum/go-ethereum/p2p/connection.go:142.3,143.38 1 19 -github.com/ethereum/go-ethereum/p2p/connection.go:144.3,145.18 1 19 -github.com/ethereum/go-ethereum/p2p/connection.go:151.3,154.10 3 18 -github.com/ethereum/go-ethereum/p2p/connection.go:145.18,148.5 2 19 -github.com/ethereum/go-ethereum/p2p/connection.go:148.6,150.5 1 0 -github.com/ethereum/go-ethereum/p2p/connection.go:159.43,166.2 4 19 -github.com/ethereum/go-ethereum/p2p/connection.go:168.39,169.34 1 19 -github.com/ethereum/go-ethereum/p2p/connection.go:169.34,173.3 3 0 -github.com/ethereum/go-ethereum/p2p/connection.go:176.69,180.15 4 19 -github.com/ethereum/go-ethereum/p2p/connection.go:184.2,184.13 1 19 -github.com/ethereum/go-ethereum/p2p/connection.go:180.15,183.3 2 0 -github.com/ethereum/go-ethereum/p2p/connection.go:187.74,199.6 8 136 -github.com/ethereum/go-ethereum/p2p/connection.go:248.2,248.13 1 136 -github.com/ethereum/go-ethereum/p2p/connection.go:199.6,203.28 1 152 -github.com/ethereum/go-ethereum/p2p/connection.go:218.3,218.12 1 17 -github.com/ethereum/go-ethereum/p2p/connection.go:203.28,205.11 2 145 -github.com/ethereum/go-ethereum/p2p/connection.go:216.4,216.39 1 10 -github.com/ethereum/go-ethereum/p2p/connection.go:205.11,207.38 2 135 -github.com/ethereum/go-ethereum/p2p/connection.go:214.5,214.14 1 135 -github.com/ethereum/go-ethereum/p2p/connection.go:207.38,208.15 1 2 -github.com/ethereum/go-ethereum/p2p/connection.go:208.15,210.7 1 1 -github.com/ethereum/go-ethereum/p2p/connection.go:210.8,212.7 1 1 -github.com/ethereum/go-ethereum/p2p/connection.go:218.12,220.50 1 10 -github.com/ethereum/go-ethereum/p2p/connection.go:224.4,227.18 3 9 -github.com/ethereum/go-ethereum/p2p/connection.go:220.50,222.10 2 1 -github.com/ethereum/go-ethereum/p2p/connection.go:227.18,229.5 1 8 -github.com/ethereum/go-ethereum/p2p/connection.go:229.6,232.5 2 1 -github.com/ethereum/go-ethereum/p2p/connection.go:233.5,239.4 4 7 -github.com/ethereum/go-ethereum/p2p/connection.go:251.82,253.6 2 136 -github.com/ethereum/go-ethereum/p2p/connection.go:274.2,274.13 1 136 -github.com/ethereum/go-ethereum/p2p/connection.go:253.6,259.41 4 136 -github.com/ethereum/go-ethereum/p2p/connection.go:259.41,260.21 1 136 -github.com/ethereum/go-ethereum/p2p/connection.go:263.4,263.42 1 136 -github.com/ethereum/go-ethereum/p2p/connection.go:260.21,262.5 1 10 -github.com/ethereum/go-ethereum/p2p/connection.go:263.42,264.10 1 136 -github.com/ethereum/go-ethereum/p2p/connection.go:266.5,272.4 4 0 -github.com/ethereum/go-ethereum/p2p/message.go:16.33,18.2 1 54 -github.com/ethereum/go-ethereum/p2p/message.go:20.40,22.2 1 5 -github.com/ethereum/go-ethereum/p2p/message.go:24.72,43.2 1 37 -github.com/ethereum/go-ethereum/p2p/message.go:45.60,59.2 5 5 -github.com/ethereum/go-ethereum/p2p/message.go:61.41,63.2 1 5 -github.com/ethereum/go-ethereum/p2p/message.go:67.54,68.28 1 28 -github.com/ethereum/go-ethereum/p2p/message.go:74.2,74.8 1 28 -github.com/ethereum/go-ethereum/p2p/message.go:68.28,71.3 2 27 -github.com/ethereum/go-ethereum/p2p/message.go:71.4,73.3 1 1 -github.com/ethereum/go-ethereum/p2p/messenger.go:28.104,41.2 2 10 -github.com/ethereum/go-ethereum/p2p/messenger.go:43.32,49.2 5 10 -github.com/ethereum/go-ethereum/p2p/messenger.go:51.31,56.42 4 10 -github.com/ethereum/go-ethereum/p2p/messenger.go:59.2,62.19 4 10 -github.com/ethereum/go-ethereum/p2p/messenger.go:56.42,58.3 1 14 -github.com/ethereum/go-ethereum/p2p/messenger.go:65.36,67.6 2 10 -github.com/ethereum/go-ethereum/p2p/messenger.go:67.6,68.10 1 14 -github.com/ethereum/go-ethereum/p2p/messenger.go:69.3,71.10 1 4 -github.com/ethereum/go-ethereum/p2p/messenger.go:76.3,78.10 2 10 -github.com/ethereum/go-ethereum/p2p/messenger.go:71.10,73.5 1 4 -github.com/ethereum/go-ethereum/p2p/messenger.go:73.6,75.5 1 0 -github.com/ethereum/go-ethereum/p2p/messenger.go:88.47,97.16 3 4 -github.com/ethereum/go-ethereum/p2p/messenger.go:102.2,103.16 2 4 -github.com/ethereum/go-ethereum/p2p/messenger.go:108.2,114.6 5 4 -github.com/ethereum/go-ethereum/p2p/messenger.go:97.16,100.3 2 0 -github.com/ethereum/go-ethereum/p2p/messenger.go:103.16,106.3 2 0 -github.com/ethereum/go-ethereum/p2p/messenger.go:114.6,115.10 1 4 -github.com/ethereum/go-ethereum/p2p/messenger.go:116.3,118.10 1 4 -github.com/ethereum/go-ethereum/p2p/messenger.go:123.3,124.10 1 0 -github.com/ethereum/go-ethereum/p2p/messenger.go:118.10,120.5 1 0 -github.com/ethereum/go-ethereum/p2p/messenger.go:120.6,122.5 1 4 -github.com/ethereum/go-ethereum/p2p/messenger.go:134.82,138.42 4 4 -github.com/ethereum/go-ethereum/p2p/messenger.go:144.2,144.67 1 0 -github.com/ethereum/go-ethereum/p2p/messenger.go:138.42,139.20 1 5 -github.com/ethereum/go-ethereum/p2p/messenger.go:142.3,142.16 1 1 -github.com/ethereum/go-ethereum/p2p/messenger.go:139.20,141.4 1 4 -github.com/ethereum/go-ethereum/p2p/messenger.go:147.128,152.6 4 8 -github.com/ethereum/go-ethereum/p2p/messenger.go:152.6,153.10 1 19 -github.com/ethereum/go-ethereum/p2p/messenger.go:154.3,155.10 1 10 -github.com/ethereum/go-ethereum/p2p/messenger.go:162.3,163.14 1 9 -github.com/ethereum/go-ethereum/p2p/messenger.go:155.10,158.5 2 3 -github.com/ethereum/go-ethereum/p2p/messenger.go:158.6,161.5 1 7 -github.com/ethereum/go-ethereum/p2p/messenger.go:163.14,167.5 3 1 -github.com/ethereum/go-ethereum/p2p/messenger.go:167.6,172.5 4 8 -github.com/ethereum/go-ethereum/p2p/messenger.go:177.57,182.33 5 3 -github.com/ethereum/go-ethereum/p2p/messenger.go:182.33,184.9 2 5 -github.com/ethereum/go-ethereum/p2p/messenger.go:184.9,194.4 8 4 -github.com/ethereum/go-ethereum/p2p/messenger.go:194.5,197.4 1 1 -github.com/ethereum/go-ethereum/p2p/messenger.go:201.63,206.23 5 26 -github.com/ethereum/go-ethereum/p2p/messenger.go:214.2,216.28 2 24 -github.com/ethereum/go-ethereum/p2p/messenger.go:219.2,219.12 1 24 -github.com/ethereum/go-ethereum/p2p/messenger.go:206.23,209.10 3 5 -github.com/ethereum/go-ethereum/p2p/messenger.go:212.3,212.29 1 3 -github.com/ethereum/go-ethereum/p2p/messenger.go:209.10,211.4 1 2 -github.com/ethereum/go-ethereum/p2p/messenger.go:216.28,218.3 1 18 -github.com/ethereum/go-ethereum/p2p/natupnp.go:23.54,25.16 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:28.2,29.16 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:32.2,36.16 4 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:40.2,49.32 5 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:92.2,93.8 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:25.16,27.3 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:29.16,31.3 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:36.16,38.3 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:49.32,51.17 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:54.3,56.17 3 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:61.3,62.43 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:67.3,70.19 4 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:73.3,75.19 3 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:78.3,81.17 4 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:84.3,86.17 3 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:89.3,90.9 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:51.17,53.4 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:56.17,57.12 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:62.43,63.12 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:70.19,71.12 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:75.19,76.12 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:81.17,83.4 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:86.17,88.4 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:148.59,150.31 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:155.2,155.12 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:150.31,151.37 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:151.37,153.4 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:158.62,160.31 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:165.2,165.12 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:160.31,161.39 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:161.39,163.4 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:168.40,170.16 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:173.2,174.30 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:177.2,177.27 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:170.16,172.3 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:174.30,176.3 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:180.60,182.16 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:185.2,186.25 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:190.2,193.16 3 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:196.2,197.75 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:201.2,202.14 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:206.2,207.14 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:211.2,212.14 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:216.2,217.8 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:182.16,184.3 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:186.25,189.3 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:193.16,195.3 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:197.75,200.3 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:202.14,205.3 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:207.14,210.3 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:212.14,215.3 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:220.48,226.2 5 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:228.79,234.16 3 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:237.2,246.16 8 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:250.2,250.19 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:254.2,254.25 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:260.2,260.8 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:234.16,236.3 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:246.16,248.3 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:250.19,252.3 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:254.25,259.3 3 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:267.64,274.16 4 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:280.2,281.8 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:274.16,276.3 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:284.65,286.16 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:289.2,290.8 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:286.16,288.3 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:293.152,307.16 7 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:313.2,315.8 3 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:307.16,309.3 1 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:318.98,327.16 4 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:333.2,334.8 2 0 -github.com/ethereum/go-ethereum/p2p/natupnp.go:327.16,329.3 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:57.55,62.2 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:64.63,70.2 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:72.71,73.26 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:81.2,81.50 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:73.26,75.23 2 0 -github.com/ethereum/go-ethereum/p2p/network.go:79.3,79.21 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:75.23,78.4 2 0 -github.com/ethereum/go-ethereum/p2p/network.go:84.45,85.22 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:99.2,99.8 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:86.2,86.12 0 0 -github.com/ethereum/go-ethereum/p2p/network.go:87.2,89.18 2 0 -github.com/ethereum/go-ethereum/p2p/network.go:94.2,95.42 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:96.2,97.57 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:89.18,91.4 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:91.5,93.4 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:102.32,106.2 3 0 -github.com/ethereum/go-ethereum/p2p/network.go:108.63,110.16 2 0 -github.com/ethereum/go-ethereum/p2p/network.go:115.2,115.8 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:110.16,112.3 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:112.4,114.3 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:118.46,122.6 3 0 -github.com/ethereum/go-ethereum/p2p/network.go:141.2,142.28 2 0 -github.com/ethereum/go-ethereum/p2p/network.go:122.6,123.10 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:124.3,127.53 3 0 -github.com/ethereum/go-ethereum/p2p/network.go:130.3,131.30 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:135.3,137.13 2 0 -github.com/ethereum/go-ethereum/p2p/network.go:127.53,129.5 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:131.30,132.54 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:132.54,133.6 0 0 -github.com/ethereum/go-ethereum/p2p/network.go:142.28,143.73 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:143.73,145.4 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:145.5,147.4 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:151.74,153.16 2 0 -github.com/ethereum/go-ethereum/p2p/network.go:159.2,159.17 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:153.16,158.3 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:162.69,164.16 2 0 -github.com/ethereum/go-ethereum/p2p/network.go:169.2,169.17 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:164.16,168.3 3 0 -github.com/ethereum/go-ethereum/p2p/network.go:172.65,173.39 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:177.2,179.16 3 0 -github.com/ethereum/go-ethereum/p2p/network.go:183.2,183.19 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:188.2,188.18 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:195.2,195.8 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:173.39,175.3 1 0 -github.com/ethereum/go-ethereum/p2p/network.go:179.16,182.3 2 0 -github.com/ethereum/go-ethereum/p2p/network.go:183.19,187.3 3 0 -github.com/ethereum/go-ethereum/p2p/network.go:188.18,192.3 2 0 -github.com/ethereum/go-ethereum/p2p/network.go:192.4,194.3 1 0 -github.com/ethereum/go-ethereum/p2p/peer.go:24.42,26.2 1 9 -github.com/ethereum/go-ethereum/p2p/peer.go:28.51,30.2 1 0 -github.com/ethereum/go-ethereum/p2p/peer.go:32.36,34.2 1 9 -github.com/ethereum/go-ethereum/p2p/peer.go:36.83,52.2 8 7 -github.com/ethereum/go-ethereum/p2p/peer.go:54.35,56.18 2 20 -github.com/ethereum/go-ethereum/p2p/peer.go:61.2,61.89 1 18 -github.com/ethereum/go-ethereum/p2p/peer.go:56.18,58.3 1 9 -github.com/ethereum/go-ethereum/p2p/peer.go:58.4,60.3 1 9 -github.com/ethereum/go-ethereum/p2p/peer.go:64.58,66.2 1 24 -github.com/ethereum/go-ethereum/p2p/peer.go:68.27,71.2 2 7 -github.com/ethereum/go-ethereum/p2p/peer.go:73.26,79.2 2 7 -github.com/ethereum/go-ethereum/p2p/peer.go:81.39,83.2 1 2 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:25.153,33.2 1 8 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:35.39,37.2 1 8 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:39.38,43.2 3 8 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:45.40,46.6 1 8 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:46.6,47.10 1 19 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:48.3,49.10 1 11 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:55.3,57.10 2 8 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:49.10,52.5 2 11 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:52.6,54.5 1 0 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:62.60,64.24 2 11 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:83.2,83.40 1 11 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:86.2,86.31 1 11 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:65.2,66.35 1 0 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:67.2,68.31 1 0 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:69.2,70.27 1 0 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:71.2,72.29 1 0 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:73.2,74.27 1 0 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:75.2,76.28 1 11 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:77.2,78.32 1 0 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:79.2,80.47 1 0 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:83.40,85.3 1 0 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:86.31,91.3 1 11 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:94.69,95.24 1 0 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:96.2,97.11 1 0 -github.com/ethereum/go-ethereum/p2p/peer_error_handler.go:98.2,99.11 1 0 -github.com/ethereum/go-ethereum/pow/ar/ops.go:11.13,21.2 9 1 -github.com/ethereum/go-ethereum/pow/ar/ops.go:23.34,25.2 1 899964 -github.com/ethereum/go-ethereum/pow/ar/ops.go:26.34,28.2 1 6 -github.com/ethereum/go-ethereum/pow/ar/ops.go:29.34,31.2 1 12 -github.com/ethereum/go-ethereum/pow/ar/ops.go:32.34,34.2 1 12 -github.com/ethereum/go-ethereum/pow/ar/ops.go:35.34,37.2 1 0 -github.com/ethereum/go-ethereum/pow/ar/ops.go:38.33,40.2 1 0 -github.com/ethereum/go-ethereum/pow/ar/ops.go:41.35,46.2 3 6 -github.com/ethereum/go-ethereum/pow/ar/ops.go:47.37,51.2 2 6 -github.com/ethereum/go-ethereum/pow/ar/ops.go:52.34,54.2 1 0 -github.com/ethereum/go-ethereum/pow/ar/pow.go:19.33,21.2 1 1 -github.com/ethereum/go-ethereum/pow/ar/pow.go:23.56,26.32 2 1 -github.com/ethereum/go-ethereum/pow/ar/pow.go:26.32,31.23 4 150000 -github.com/ethereum/go-ethereum/pow/ar/pow.go:37.3,38.49 2 150000 -github.com/ethereum/go-ethereum/pow/ar/pow.go:31.23,33.4 1 149979 -github.com/ethereum/go-ethereum/pow/ar/pow.go:33.5,35.4 1 21 -github.com/ethereum/go-ethereum/pow/ar/pow.go:42.69,44.32 2 6 -github.com/ethereum/go-ethereum/pow/ar/pow.go:48.2,48.30 1 6 -github.com/ethereum/go-ethereum/pow/ar/pow.go:55.2,56.34 2 6 -github.com/ethereum/go-ethereum/pow/ar/pow.go:74.2,74.18 1 6 -github.com/ethereum/go-ethereum/pow/ar/pow.go:44.32,46.3 1 60000 -github.com/ethereum/go-ethereum/pow/ar/pow.go:48.30,53.3 3 900000 -github.com/ethereum/go-ethereum/pow/ar/pow.go:56.34,58.10 2 9000 -github.com/ethereum/go-ethereum/pow/ar/pow.go:68.3,69.65 2 9000 -github.com/ethereum/go-ethereum/pow/ar/pow.go:58.10,59.29 1 9000 -github.com/ethereum/go-ethereum/pow/ar/pow.go:59.29,61.5 1 900000 -github.com/ethereum/go-ethereum/pow/ar/pow.go:62.5,63.29 1 0 -github.com/ethereum/go-ethereum/pow/ar/pow.go:63.29,65.5 1 0 -github.com/ethereum/go-ethereum/pow/ar/pow.go:69.65,71.4 1 0 -github.com/ethereum/go-ethereum/pow/ar/pow.go:77.53,94.2 12 0 -github.com/ethereum/go-ethereum/pow/ar/pow.go:96.45,104.6 6 1 -github.com/ethereum/go-ethereum/pow/ar/pow.go:104.6,105.54 1 6 -github.com/ethereum/go-ethereum/pow/ar/pow.go:110.3,116.51 5 6 -github.com/ethereum/go-ethereum/pow/ar/pow.go:105.54,108.4 2 1 -github.com/ethereum/go-ethereum/pow/ar/pow.go:116.51,118.4 1 1 -github.com/ethereum/go-ethereum/pow/ar/pow.go:118.5,120.4 1 5 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:18.37,20.2 1 0 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:22.35,23.31 1 510007 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:36.2,36.12 1 0 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:23.31,25.3 1 509988 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:25.4,25.43 1 19 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:25.43,27.3 1 13 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:27.4,27.40 1 6 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:27.40,29.23 2 6 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:33.3,33.54 1 6 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:29.23,31.4 1 60000 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:48.26,50.2 1 7 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:52.43,57.46 3 510021 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:61.2,61.10 1 510021 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:57.46,59.3 1 509988 -github.com/ethereum/go-ethereum/pow/ar/rnd.go:64.42,66.2 1 450021 -github.com/ethereum/go-ethereum/ptrie/hashnode.go:7.36,9.2 1 0 -github.com/ethereum/go-ethereum/ptrie/hashnode.go:11.45,13.2 1 0 -github.com/ethereum/go-ethereum/ptrie/hashnode.go:15.42,17.2 1 2 -github.com/ethereum/go-ethereum/ptrie/hashnode.go:20.36,20.50 1 0 -github.com/ethereum/go-ethereum/ptrie/hashnode.go:21.36,21.51 1 0 -github.com/ethereum/go-ethereum/ptrie/hashnode.go:22.36,22.51 1 0 -github.com/ethereum/go-ethereum/ptrie/node.go:17.51,17.78 1 0 -github.com/ethereum/go-ethereum/ptrie/node.go:18.51,18.78 1 0 -github.com/ethereum/go-ethereum/ptrie/node.go:19.51,19.78 1 2 -github.com/ethereum/go-ethereum/ptrie/node.go:20.51,20.91 1 81 -github.com/ethereum/go-ethereum/ptrie/node.go:21.51,21.90 1 18 -github.com/ethereum/go-ethereum/ptrie/node.go:24.50,26.34 2 12 -github.com/ethereum/go-ethereum/ptrie/node.go:34.2,34.42 1 12 -github.com/ethereum/go-ethereum/ptrie/node.go:26.34,27.18 1 204 -github.com/ethereum/go-ethereum/ptrie/node.go:27.18,29.4 1 95 -github.com/ethereum/go-ethereum/ptrie/node.go:29.5,31.4 1 109 -github.com/ethereum/go-ethereum/ptrie/node.go:38.51,40.2 1 49 -github.com/ethereum/go-ethereum/ptrie/shortnode.go:11.63,13.2 1 147 -github.com/ethereum/go-ethereum/ptrie/shortnode.go:14.37,18.2 2 85 -github.com/ethereum/go-ethereum/ptrie/shortnode.go:19.37,19.52 1 0 -github.com/ethereum/go-ethereum/ptrie/shortnode.go:20.37,20.52 1 0 -github.com/ethereum/go-ethereum/ptrie/shortnode.go:22.46,24.2 1 97 -github.com/ethereum/go-ethereum/ptrie/shortnode.go:25.43,27.2 1 76 -github.com/ethereum/go-ethereum/ptrie/shortnode.go:29.37,31.2 1 85 -github.com/ethereum/go-ethereum/ptrie/trie.go:19.42,21.2 1 7 -github.com/ethereum/go-ethereum/ptrie/trie.go:22.48,24.2 1 76 -github.com/ethereum/go-ethereum/ptrie/trie.go:33.23,35.2 1 6 -github.com/ethereum/go-ethereum/ptrie/trie.go:37.46,46.2 6 2 -github.com/ethereum/go-ethereum/ptrie/trie.go:49.33,49.55 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:50.33,52.22 2 7 -github.com/ethereum/go-ethereum/ptrie/trie.go:63.2,65.13 2 7 -github.com/ethereum/go-ethereum/ptrie/trie.go:52.22,54.33 2 7 -github.com/ethereum/go-ethereum/ptrie/trie.go:54.33,56.4 1 7 -github.com/ethereum/go-ethereum/ptrie/trie.go:56.5,58.4 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:59.4,61.3 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:68.56,68.106 1 74 -github.com/ethereum/go-ethereum/ptrie/trie.go:69.50,75.21 4 74 -github.com/ethereum/go-ethereum/ptrie/trie.go:81.2,81.18 1 74 -github.com/ethereum/go-ethereum/ptrie/trie.go:75.21,77.3 1 70 -github.com/ethereum/go-ethereum/ptrie/trie.go:77.4,79.3 1 4 -github.com/ethereum/go-ethereum/ptrie/trie.go:84.48,84.80 1 4 -github.com/ethereum/go-ethereum/ptrie/trie.go:85.42,92.14 5 4 -github.com/ethereum/go-ethereum/ptrie/trie.go:96.2,96.12 1 1 -github.com/ethereum/go-ethereum/ptrie/trie.go:92.14,94.3 1 3 -github.com/ethereum/go-ethereum/ptrie/trie.go:99.49,99.84 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:100.43,108.2 5 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:110.66,111.19 1 298 -github.com/ethereum/go-ethereum/ptrie/trie.go:115.2,115.17 1 285 -github.com/ethereum/go-ethereum/ptrie/trie.go:119.2,119.29 1 206 -github.com/ethereum/go-ethereum/ptrie/trie.go:111.19,113.3 1 13 -github.com/ethereum/go-ethereum/ptrie/trie.go:115.17,117.3 1 79 -github.com/ethereum/go-ethereum/ptrie/trie.go:120.2,123.26 3 76 -github.com/ethereum/go-ethereum/ptrie/trie.go:127.3,129.28 3 76 -github.com/ethereum/go-ethereum/ptrie/trie.go:139.3,139.23 1 76 -github.com/ethereum/go-ethereum/ptrie/trie.go:143.3,143.50 1 63 -github.com/ethereum/go-ethereum/ptrie/trie.go:145.2,149.13 3 130 -github.com/ethereum/go-ethereum/ptrie/trie.go:151.2,152.24 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:123.26,125.4 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:129.28,131.4 1 54 -github.com/ethereum/go-ethereum/ptrie/trie.go:131.5,138.4 6 22 -github.com/ethereum/go-ethereum/ptrie/trie.go:139.23,141.4 1 13 -github.com/ethereum/go-ethereum/ptrie/trie.go:156.51,157.19 1 15 -github.com/ethereum/go-ethereum/ptrie/trie.go:161.2,161.17 1 12 -github.com/ethereum/go-ethereum/ptrie/trie.go:165.2,165.29 1 12 -github.com/ethereum/go-ethereum/ptrie/trie.go:157.19,159.3 1 3 -github.com/ethereum/go-ethereum/ptrie/trie.go:161.17,163.3 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:166.2,170.57 3 5 -github.com/ethereum/go-ethereum/ptrie/trie.go:174.3,174.13 1 1 -github.com/ethereum/go-ethereum/ptrie/trie.go:175.2,176.45 1 7 -github.com/ethereum/go-ethereum/ptrie/trie.go:177.2,178.24 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:170.57,172.4 1 4 -github.com/ethereum/go-ethereum/ptrie/trie.go:182.54,183.19 1 10 -github.com/ethereum/go-ethereum/ptrie/trie.go:187.2,187.29 1 10 -github.com/ethereum/go-ethereum/ptrie/trie.go:183.19,185.3 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:188.2,191.26 3 4 -github.com/ethereum/go-ethereum/ptrie/trie.go:210.2,215.27 4 6 -github.com/ethereum/go-ethereum/ptrie/trie.go:225.3,226.16 2 6 -github.com/ethereum/go-ethereum/ptrie/trie.go:242.3,242.15 1 6 -github.com/ethereum/go-ethereum/ptrie/trie.go:244.2,245.24 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:191.26,193.4 1 4 -github.com/ethereum/go-ethereum/ptrie/trie.go:193.5,193.42 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:193.42,197.33 3 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:205.4,205.12 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:198.4,200.48 2 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:201.4,202.44 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:206.5,208.4 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:215.27,216.29 1 102 -github.com/ethereum/go-ethereum/ptrie/trie.go:216.29,217.18 1 10 -github.com/ethereum/go-ethereum/ptrie/trie.go:217.18,219.6 1 6 -github.com/ethereum/go-ethereum/ptrie/trie.go:219.7,221.6 1 4 -github.com/ethereum/go-ethereum/ptrie/trie.go:226.16,228.4 1 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:228.5,228.22 1 6 -github.com/ethereum/go-ethereum/ptrie/trie.go:228.22,230.33 2 2 -github.com/ethereum/go-ethereum/ptrie/trie.go:231.4,234.49 2 0 -github.com/ethereum/go-ethereum/ptrie/trie.go:235.4,236.68 1 2 -github.com/ethereum/go-ethereum/ptrie/trie.go:238.5,240.4 1 4 -github.com/ethereum/go-ethereum/ptrie/trie.go:250.53,252.11 2 95 -github.com/ethereum/go-ethereum/ptrie/trie.go:253.2,254.105 1 3 -github.com/ethereum/go-ethereum/ptrie/trie.go:255.2,257.26 2 5 -github.com/ethereum/go-ethereum/ptrie/trie.go:260.3,260.15 1 5 -github.com/ethereum/go-ethereum/ptrie/trie.go:261.2,262.34 1 25 -github.com/ethereum/go-ethereum/ptrie/trie.go:263.2,264.41 1 62 -github.com/ethereum/go-ethereum/ptrie/trie.go:257.26,259.4 1 85 -github.com/ethereum/go-ethereum/ptrie/trie.go:268.41,269.29 1 200 -github.com/ethereum/go-ethereum/ptrie/trie.go:270.2,272.28 2 5 -github.com/ethereum/go-ethereum/ptrie/trie.go:273.2,274.14 1 195 -github.com/ethereum/go-ethereum/ptrie/trie.go:278.48,280.21 2 103 -github.com/ethereum/go-ethereum/ptrie/trie.go:287.2,287.23 1 27 -github.com/ethereum/go-ethereum/ptrie/trie.go:280.21,285.3 3 76 -github.com/ethereum/go-ethereum/ptrie/valuenode.go:8.46,8.61 1 0 -github.com/ethereum/go-ethereum/ptrie/valuenode.go:9.46,9.66 1 3 -github.com/ethereum/go-ethereum/ptrie/valuenode.go:10.46,10.61 1 0 -github.com/ethereum/go-ethereum/ptrie/valuenode.go:11.46,11.61 1 0 -github.com/ethereum/go-ethereum/ptrie/valuenode.go:12.46,12.66 1 0 -github.com/ethereum/go-ethereum/ptrie/valuenode.go:13.46,13.66 1 135 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:8.37,10.2 1 27 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:12.36,12.51 1 0 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:13.36,16.2 2 0 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:18.35,18.50 1 136 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:21.42,22.34 1 0 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:28.2,28.8 1 0 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:22.34,23.18 1 0 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:23.18,25.4 1 0 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:31.42,33.2 1 27 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:35.45,37.34 2 33 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:45.2,45.10 1 33 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:37.34,38.18 1 561 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:38.18,40.4 1 136 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:40.5,42.4 1 425 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:48.47,50.2 1 265 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:52.40,53.31 1 249 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:58.2,58.12 1 134 -github.com/ethereum/go-ethereum/ptrie/fullnode.go:53.31,57.3 2 115 -github.com/ethereum/go-ethereum/rlp/decode.go:69.50,71.2 1 73 -github.com/ethereum/go-ethereum/rlp/decode.go:73.47,75.9 2 2 -github.com/ethereum/go-ethereum/rlp/decode.go:76.2,77.19 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:78.2,79.20 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:80.2,81.23 1 0 -github.com/ethereum/go-ethereum/rlp/decode.go:85.52,87.16 2 36 -github.com/ethereum/go-ethereum/rlp/decode.go:90.2,91.12 2 31 -github.com/ethereum/go-ethereum/rlp/decode.go:87.16,89.3 1 5 -github.com/ethereum/go-ethereum/rlp/decode.go:94.53,96.16 2 24 -github.com/ethereum/go-ethereum/rlp/decode.go:99.2,100.12 2 16 -github.com/ethereum/go-ethereum/rlp/decode.go:96.16,98.3 1 8 -github.com/ethereum/go-ethereum/rlp/decode.go:103.55,105.16 2 7 -github.com/ethereum/go-ethereum/rlp/decode.go:108.2,109.12 2 5 -github.com/ethereum/go-ethereum/rlp/decode.go:105.16,107.3 1 2 -github.com/ethereum/go-ethereum/rlp/decode.go:112.60,114.2 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:116.55,118.16 2 4 -github.com/ethereum/go-ethereum/rlp/decode.go:121.2,122.14 2 3 -github.com/ethereum/go-ethereum/rlp/decode.go:126.2,127.12 2 3 -github.com/ethereum/go-ethereum/rlp/decode.go:118.16,120.3 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:122.14,125.3 2 2 -github.com/ethereum/go-ethereum/rlp/decode.go:132.57,134.89 2 8 -github.com/ethereum/go-ethereum/rlp/decode.go:141.2,142.16 2 5 -github.com/ethereum/go-ethereum/rlp/decode.go:145.2,146.33 2 5 -github.com/ethereum/go-ethereum/rlp/decode.go:149.2,149.50 1 5 -github.com/ethereum/go-ethereum/rlp/decode.go:152.2,152.17 1 5 -github.com/ethereum/go-ethereum/rlp/decode.go:134.89,135.34 1 3 -github.com/ethereum/go-ethereum/rlp/decode.go:135.34,137.4 1 2 -github.com/ethereum/go-ethereum/rlp/decode.go:137.5,139.4 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:142.16,144.3 1 0 -github.com/ethereum/go-ethereum/rlp/decode.go:146.33,148.3 1 2 -github.com/ethereum/go-ethereum/rlp/decode.go:149.50,151.3 1 9 -github.com/ethereum/go-ethereum/rlp/decode.go:161.83,163.16 2 20 -github.com/ethereum/go-ethereum/rlp/decode.go:166.2,166.15 1 20 -github.com/ethereum/go-ethereum/rlp/decode.go:175.2,176.6 2 14 -github.com/ethereum/go-ethereum/rlp/decode.go:203.2,203.19 1 11 -github.com/ethereum/go-ethereum/rlp/decode.go:211.2,211.20 1 11 -github.com/ethereum/go-ethereum/rlp/decode.go:163.16,165.3 1 0 -github.com/ethereum/go-ethereum/rlp/decode.go:166.15,167.34 1 6 -github.com/ethereum/go-ethereum/rlp/decode.go:172.3,172.21 1 6 -github.com/ethereum/go-ethereum/rlp/decode.go:167.34,169.4 1 3 -github.com/ethereum/go-ethereum/rlp/decode.go:169.5,171.4 1 3 -github.com/ethereum/go-ethereum/rlp/decode.go:176.6,177.18 1 49 -github.com/ethereum/go-ethereum/rlp/decode.go:180.3,180.34 1 48 -github.com/ethereum/go-ethereum/rlp/decode.go:196.3,196.50 1 48 -github.com/ethereum/go-ethereum/rlp/decode.go:201.3,201.6 1 35 -github.com/ethereum/go-ethereum/rlp/decode.go:177.18,179.4 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:180.34,182.22 1 23 -github.com/ethereum/go-ethereum/rlp/decode.go:191.4,191.22 1 23 -github.com/ethereum/go-ethereum/rlp/decode.go:182.22,184.19 2 9 -github.com/ethereum/go-ethereum/rlp/decode.go:187.5,189.18 3 9 -github.com/ethereum/go-ethereum/rlp/decode.go:184.19,186.6 1 7 -github.com/ethereum/go-ethereum/rlp/decode.go:191.22,193.5 1 23 -github.com/ethereum/go-ethereum/rlp/decode.go:196.50,197.9 1 11 -github.com/ethereum/go-ethereum/rlp/decode.go:198.5,198.24 1 37 -github.com/ethereum/go-ethereum/rlp/decode.go:198.24,200.4 1 2 -github.com/ethereum/go-ethereum/rlp/decode.go:203.19,204.34 1 9 -github.com/ethereum/go-ethereum/rlp/decode.go:204.34,207.4 1 3 -github.com/ethereum/go-ethereum/rlp/decode.go:207.5,209.4 1 6 -github.com/ethereum/go-ethereum/rlp/decode.go:214.58,216.16 2 8 -github.com/ethereum/go-ethereum/rlp/decode.go:219.2,219.18 1 7 -github.com/ethereum/go-ethereum/rlp/decode.go:222.2,223.16 2 4 -github.com/ethereum/go-ethereum/rlp/decode.go:226.2,226.12 1 4 -github.com/ethereum/go-ethereum/rlp/decode.go:216.16,218.3 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:219.18,221.3 1 3 -github.com/ethereum/go-ethereum/rlp/decode.go:223.16,225.3 1 4 -github.com/ethereum/go-ethereum/rlp/decode.go:231.58,233.16 2 18 -github.com/ethereum/go-ethereum/rlp/decode.go:236.2,236.14 1 18 -github.com/ethereum/go-ethereum/rlp/decode.go:256.2,256.12 1 8 -github.com/ethereum/go-ethereum/rlp/decode.go:233.16,235.3 1 0 -github.com/ethereum/go-ethereum/rlp/decode.go:237.2,238.21 1 3 -github.com/ethereum/go-ethereum/rlp/decode.go:241.3,243.15 3 2 -github.com/ethereum/go-ethereum/rlp/decode.go:244.2,245.31 1 9 -github.com/ethereum/go-ethereum/rlp/decode.go:248.3,249.43 2 7 -github.com/ethereum/go-ethereum/rlp/decode.go:252.3,252.23 1 6 -github.com/ethereum/go-ethereum/rlp/decode.go:253.2,254.51 1 6 -github.com/ethereum/go-ethereum/rlp/decode.go:238.21,240.4 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:245.31,247.4 1 2 -github.com/ethereum/go-ethereum/rlp/decode.go:249.43,251.4 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:259.41,261.37 2 14 -github.com/ethereum/go-ethereum/rlp/decode.go:261.37,263.3 1 35 -github.com/ethereum/go-ethereum/rlp/decode.go:271.59,273.38 2 4 -github.com/ethereum/go-ethereum/rlp/decode.go:282.2,282.56 1 4 -github.com/ethereum/go-ethereum/rlp/decode.go:300.2,300.17 1 4 -github.com/ethereum/go-ethereum/rlp/decode.go:273.38,274.41 1 11 -github.com/ethereum/go-ethereum/rlp/decode.go:274.41,276.18 2 10 -github.com/ethereum/go-ethereum/rlp/decode.go:279.4,279.43 1 10 -github.com/ethereum/go-ethereum/rlp/decode.go:276.18,278.5 1 0 -github.com/ethereum/go-ethereum/rlp/decode.go:282.56,283.36 1 9 -github.com/ethereum/go-ethereum/rlp/decode.go:286.3,286.28 1 9 -github.com/ethereum/go-ethereum/rlp/decode.go:295.3,295.44 1 9 -github.com/ethereum/go-ethereum/rlp/decode.go:298.3,298.13 1 9 -github.com/ethereum/go-ethereum/rlp/decode.go:283.36,285.4 1 0 -github.com/ethereum/go-ethereum/rlp/decode.go:286.28,288.18 2 19 -github.com/ethereum/go-ethereum/rlp/decode.go:288.18,290.10 1 3 -github.com/ethereum/go-ethereum/rlp/decode.go:291.6,291.25 1 16 -github.com/ethereum/go-ethereum/rlp/decode.go:291.25,293.5 1 0 -github.com/ethereum/go-ethereum/rlp/decode.go:295.44,297.4 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:303.56,306.16 3 5 -github.com/ethereum/go-ethereum/rlp/decode.go:309.2,309.56 1 5 -github.com/ethereum/go-ethereum/rlp/decode.go:324.2,324.17 1 5 -github.com/ethereum/go-ethereum/rlp/decode.go:306.16,308.3 1 0 -github.com/ethereum/go-ethereum/rlp/decode.go:309.56,311.48 2 13 -github.com/ethereum/go-ethereum/rlp/decode.go:315.3,316.18 2 8 -github.com/ethereum/go-ethereum/rlp/decode.go:319.3,319.60 1 8 -github.com/ethereum/go-ethereum/rlp/decode.go:322.3,322.13 1 8 -github.com/ethereum/go-ethereum/rlp/decode.go:311.48,314.4 2 5 -github.com/ethereum/go-ethereum/rlp/decode.go:316.18,318.4 1 8 -github.com/ethereum/go-ethereum/rlp/decode.go:319.60,321.4 1 8 -github.com/ethereum/go-ethereum/rlp/decode.go:329.58,331.16 2 9 -github.com/ethereum/go-ethereum/rlp/decode.go:334.2,334.18 1 8 -github.com/ethereum/go-ethereum/rlp/decode.go:347.2,347.12 1 8 -github.com/ethereum/go-ethereum/rlp/decode.go:331.16,333.3 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:334.18,336.71 2 2 -github.com/ethereum/go-ethereum/rlp/decode.go:339.3,339.17 1 2 -github.com/ethereum/go-ethereum/rlp/decode.go:336.71,338.4 1 0 -github.com/ethereum/go-ethereum/rlp/decode.go:340.4,342.17 2 6 -github.com/ethereum/go-ethereum/rlp/decode.go:345.3,345.30 1 6 -github.com/ethereum/go-ethereum/rlp/decode.go:342.17,344.4 1 0 -github.com/ethereum/go-ethereum/rlp/decode.go:352.61,354.2 1 5 -github.com/ethereum/go-ethereum/rlp/decode.go:356.56,361.46 1 2 -github.com/ethereum/go-ethereum/rlp/decode.go:364.2,364.47 1 2 -github.com/ethereum/go-ethereum/rlp/decode.go:361.46,363.3 1 2 -github.com/ethereum/go-ethereum/rlp/decode.go:376.31,377.11 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:378.2,379.16 1 0 -github.com/ethereum/go-ethereum/rlp/decode.go:380.2,381.18 1 0 -github.com/ethereum/go-ethereum/rlp/decode.go:382.2,383.16 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:384.2,385.39 1 0 -github.com/ethereum/go-ethereum/rlp/decode.go:435.38,437.2 1 109 -github.com/ethereum/go-ethereum/rlp/decode.go:442.42,444.16 2 25 -github.com/ethereum/go-ethereum/rlp/decode.go:447.2,447.14 1 23 -github.com/ethereum/go-ethereum/rlp/decode.go:444.16,446.3 1 2 -github.com/ethereum/go-ethereum/rlp/decode.go:448.2,450.32 2 8 -github.com/ethereum/go-ethereum/rlp/decode.go:451.2,453.38 2 12 -github.com/ethereum/go-ethereum/rlp/decode.go:456.3,456.16 1 11 -github.com/ethereum/go-ethereum/rlp/decode.go:457.2,458.32 1 3 -github.com/ethereum/go-ethereum/rlp/decode.go:453.38,455.4 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:465.41,467.2 1 31 -github.com/ethereum/go-ethereum/rlp/decode.go:469.52,471.16 2 91 -github.com/ethereum/go-ethereum/rlp/decode.go:474.2,474.14 1 75 -github.com/ethereum/go-ethereum/rlp/decode.go:471.16,473.3 1 16 -github.com/ethereum/go-ethereum/rlp/decode.go:475.2,477.32 2 62 -github.com/ethereum/go-ethereum/rlp/decode.go:478.2,479.31 1 11 -github.com/ethereum/go-ethereum/rlp/decode.go:482.3,482.32 1 7 -github.com/ethereum/go-ethereum/rlp/decode.go:483.2,484.30 1 2 -github.com/ethereum/go-ethereum/rlp/decode.go:479.31,481.4 1 4 -github.com/ethereum/go-ethereum/rlp/decode.go:491.50,493.16 2 40 -github.com/ethereum/go-ethereum/rlp/decode.go:496.2,496.18 1 39 -github.com/ethereum/go-ethereum/rlp/decode.go:499.2,502.18 4 37 -github.com/ethereum/go-ethereum/rlp/decode.go:493.16,495.3 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:496.18,498.3 1 2 -github.com/ethereum/go-ethereum/rlp/decode.go:507.34,508.23 1 31 -github.com/ethereum/go-ethereum/rlp/decode.go:511.2,512.25 2 30 -github.com/ethereum/go-ethereum/rlp/decode.go:515.2,516.22 2 28 -github.com/ethereum/go-ethereum/rlp/decode.go:519.2,521.12 3 28 -github.com/ethereum/go-ethereum/rlp/decode.go:508.23,510.3 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:512.25,514.3 1 2 -github.com/ethereum/go-ethereum/rlp/decode.go:516.22,518.3 1 3 -github.com/ethereum/go-ethereum/rlp/decode.go:527.48,528.16 1 73 -github.com/ethereum/go-ethereum/rlp/decode.go:531.2,533.32 3 72 -github.com/ethereum/go-ethereum/rlp/decode.go:536.2,536.18 1 71 -github.com/ethereum/go-ethereum/rlp/decode.go:539.2,540.16 2 70 -github.com/ethereum/go-ethereum/rlp/decode.go:543.2,543.37 1 69 -github.com/ethereum/go-ethereum/rlp/decode.go:528.16,530.3 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:533.32,535.3 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:536.18,538.3 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:540.16,542.3 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:557.61,559.22 2 224 -github.com/ethereum/go-ethereum/rlp/decode.go:562.2,562.16 1 224 -github.com/ethereum/go-ethereum/rlp/decode.go:572.2,572.45 1 201 -github.com/ethereum/go-ethereum/rlp/decode.go:575.2,575.28 1 200 -github.com/ethereum/go-ethereum/rlp/decode.go:559.22,561.3 1 94 -github.com/ethereum/go-ethereum/rlp/decode.go:562.16,563.40 1 192 -github.com/ethereum/go-ethereum/rlp/decode.go:566.3,567.17 2 175 -github.com/ethereum/go-ethereum/rlp/decode.go:570.3,570.30 1 169 -github.com/ethereum/go-ethereum/rlp/decode.go:563.40,565.4 1 17 -github.com/ethereum/go-ethereum/rlp/decode.go:567.17,569.4 1 6 -github.com/ethereum/go-ethereum/rlp/decode.go:572.45,574.3 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:578.65,580.16 2 175 -github.com/ethereum/go-ethereum/rlp/decode.go:583.2,584.9 2 170 -github.com/ethereum/go-ethereum/rlp/decode.go:580.16,582.3 1 5 -github.com/ethereum/go-ethereum/rlp/decode.go:585.2,589.22 2 76 -github.com/ethereum/go-ethereum/rlp/decode.go:590.2,595.39 1 37 -github.com/ethereum/go-ethereum/rlp/decode.go:596.2,604.27 2 6 -github.com/ethereum/go-ethereum/rlp/decode.go:605.2,611.37 1 47 -github.com/ethereum/go-ethereum/rlp/decode.go:612.2,620.25 2 4 -github.com/ethereum/go-ethereum/rlp/decode.go:624.54,625.15 1 17 -github.com/ethereum/go-ethereum/rlp/decode.go:632.2,633.29 2 11 -github.com/ethereum/go-ethereum/rlp/decode.go:636.2,637.48 2 11 -github.com/ethereum/go-ethereum/rlp/decode.go:625.15,627.20 2 6 -github.com/ethereum/go-ethereum/rlp/decode.go:630.3,630.24 1 6 -github.com/ethereum/go-ethereum/rlp/decode.go:627.20,629.4 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:633.29,635.3 1 44 -github.com/ethereum/go-ethereum/rlp/decode.go:640.51,643.33 3 30 -github.com/ethereum/go-ethereum/rlp/decode.go:647.2,647.19 1 30 -github.com/ethereum/go-ethereum/rlp/decode.go:650.2,650.12 1 30 -github.com/ethereum/go-ethereum/rlp/decode.go:643.33,646.3 2 27 -github.com/ethereum/go-ethereum/rlp/decode.go:647.19,649.3 1 3 -github.com/ethereum/go-ethereum/rlp/decode.go:653.43,656.39 3 181 -github.com/ethereum/go-ethereum/rlp/decode.go:659.2,659.15 1 181 -github.com/ethereum/go-ethereum/rlp/decode.go:656.39,658.3 1 1 -github.com/ethereum/go-ethereum/rlp/decode.go:662.37,664.22 2 211 -github.com/ethereum/go-ethereum/rlp/decode.go:664.22,666.3 1 76 -github.com/ethereum/go-ethereum/rlp/typecache.go:21.58,25.17 4 70 -github.com/ethereum/go-ethereum/rlp/typecache.go:29.2,31.29 3 21 -github.com/ethereum/go-ethereum/rlp/typecache.go:25.17,27.3 1 49 -github.com/ethereum/go-ethereum/rlp/typecache.go:34.59,36.17 2 41 -github.com/ethereum/go-ethereum/rlp/typecache.go:43.2,45.16 3 27 -github.com/ethereum/go-ethereum/rlp/typecache.go:50.2,51.28 2 26 -github.com/ethereum/go-ethereum/rlp/typecache.go:36.17,39.3 1 14 -github.com/ethereum/go-ethereum/rlp/typecache.go:45.16,49.3 2 1 -github.com/ethereum/go-ethereum/rlp/typecache.go:59.64,62.9 3 27 -github.com/ethereum/go-ethereum/rlp/typecache.go:86.2,86.18 1 27 -github.com/ethereum/go-ethereum/rlp/typecache.go:63.2,64.31 1 1 -github.com/ethereum/go-ethereum/rlp/typecache.go:65.2,66.36 1 2 -github.com/ethereum/go-ethereum/rlp/typecache.go:67.2,68.30 1 1 -github.com/ethereum/go-ethereum/rlp/typecache.go:69.2,70.35 1 1 -github.com/ethereum/go-ethereum/rlp/typecache.go:71.2,72.37 1 2 -github.com/ethereum/go-ethereum/rlp/typecache.go:73.2,74.30 1 1 -github.com/ethereum/go-ethereum/rlp/typecache.go:75.2,76.43 1 8 -github.com/ethereum/go-ethereum/rlp/typecache.go:77.2,78.45 1 4 -github.com/ethereum/go-ethereum/rlp/typecache.go:79.2,80.42 1 5 -github.com/ethereum/go-ethereum/rlp/typecache.go:81.2,82.33 1 1 -github.com/ethereum/go-ethereum/rlp/typecache.go:83.2,84.64 1 1 -github.com/ethereum/go-ethereum/rlp/typecache.go:89.37,91.2 1 22 -github.com/ethereum/go-ethereum/state/dump.go:23.34,29.70 2 1 -github.com/ethereum/go-ethereum/state/dump.go:42.2,43.16 2 1 -github.com/ethereum/go-ethereum/state/dump.go:47.2,47.13 1 1 -github.com/ethereum/go-ethereum/state/dump.go:29.70,35.66 4 0 -github.com/ethereum/go-ethereum/state/dump.go:39.3,39.59 1 0 -github.com/ethereum/go-ethereum/state/dump.go:35.66,38.4 2 0 -github.com/ethereum/go-ethereum/state/dump.go:43.16,45.3 1 0 -github.com/ethereum/go-ethereum/state/dump.go:51.48,53.59 2 0 -github.com/ethereum/go-ethereum/state/dump.go:53.59,55.3 1 0 -github.com/ethereum/go-ethereum/state/errors.go:13.36,17.2 2 0 -github.com/ethereum/go-ethereum/state/errors.go:18.40,20.2 1 0 -github.com/ethereum/go-ethereum/state/errors.go:21.51,23.2 1 0 -github.com/ethereum/go-ethereum/state/log.go:16.51,23.16 3 0 -github.com/ethereum/go-ethereum/state/log.go:27.2,27.12 1 0 -github.com/ethereum/go-ethereum/state/log.go:23.16,25.3 1 0 -github.com/ethereum/go-ethereum/state/log.go:30.40,32.2 1 0 -github.com/ethereum/go-ethereum/state/log.go:34.34,36.2 1 0 -github.com/ethereum/go-ethereum/state/log.go:40.40,42.27 2 0 -github.com/ethereum/go-ethereum/state/log.go:46.2,46.13 1 0 -github.com/ethereum/go-ethereum/state/log.go:42.27,44.3 1 0 -github.com/ethereum/go-ethereum/state/log.go:49.34,51.27 2 0 -github.com/ethereum/go-ethereum/state/log.go:54.2,54.47 1 0 -github.com/ethereum/go-ethereum/state/log.go:51.27,53.3 1 0 -github.com/ethereum/go-ethereum/state/manifest.go:16.30,21.2 3 6 -github.com/ethereum/go-ethereum/state/manifest.go:23.28,25.2 1 6 -github.com/ethereum/go-ethereum/state/manifest.go:27.57,31.2 2 0 -github.com/ethereum/go-ethereum/state/manifest.go:49.52,51.2 1 0 -github.com/ethereum/go-ethereum/state/manifest.go:53.38,55.2 1 0 -github.com/ethereum/go-ethereum/state/state.go:32.34,34.2 1 6 -github.com/ethereum/go-ethereum/state/state.go:36.32,38.2 1 0 -github.com/ethereum/go-ethereum/state/state.go:40.37,42.2 1 0 -github.com/ethereum/go-ethereum/state/state.go:44.32,46.2 1 0 -github.com/ethereum/go-ethereum/state/state.go:49.53,51.24 2 0 -github.com/ethereum/go-ethereum/state/state.go:55.2,55.21 1 0 -github.com/ethereum/go-ethereum/state/state.go:51.24,53.3 1 0 -github.com/ethereum/go-ethereum/state/state.go:58.61,61.38 2 0 -github.com/ethereum/go-ethereum/state/state.go:65.2,65.66 1 0 -github.com/ethereum/go-ethereum/state/state.go:61.38,63.3 1 0 -github.com/ethereum/go-ethereum/state/state.go:68.61,70.24 2 0 -github.com/ethereum/go-ethereum/state/state.go:70.24,72.3 1 0 -github.com/ethereum/go-ethereum/state/state.go:75.49,77.24 2 0 -github.com/ethereum/go-ethereum/state/state.go:81.2,81.10 1 0 -github.com/ethereum/go-ethereum/state/state.go:77.24,79.3 1 0 -github.com/ethereum/go-ethereum/state/state.go:84.56,86.24 2 0 -github.com/ethereum/go-ethereum/state/state.go:86.24,88.3 1 0 -github.com/ethereum/go-ethereum/state/state.go:91.48,93.24 2 0 -github.com/ethereum/go-ethereum/state/state.go:97.2,97.12 1 0 -github.com/ethereum/go-ethereum/state/state.go:93.24,95.3 1 0 -github.com/ethereum/go-ethereum/state/state.go:100.49,102.24 2 0 -github.com/ethereum/go-ethereum/state/state.go:106.2,106.12 1 0 -github.com/ethereum/go-ethereum/state/state.go:102.24,104.3 1 0 -github.com/ethereum/go-ethereum/state/state.go:109.66,111.24 2 0 -github.com/ethereum/go-ethereum/state/state.go:111.24,113.3 1 0 -github.com/ethereum/go-ethereum/state/state.go:116.45,118.24 2 0 -github.com/ethereum/go-ethereum/state/state.go:124.2,124.14 1 0 -github.com/ethereum/go-ethereum/state/state.go:118.24,122.3 2 0 -github.com/ethereum/go-ethereum/state/state.go:132.64,135.37 2 0 -github.com/ethereum/go-ethereum/state/state.go:139.2,139.65 1 0 -github.com/ethereum/go-ethereum/state/state.go:135.37,137.3 1 0 -github.com/ethereum/go-ethereum/state/state.go:143.64,147.2 2 0 -github.com/ethereum/go-ethereum/state/state.go:150.61,154.24 3 3 -github.com/ethereum/go-ethereum/state/state.go:158.2,159.20 2 1 -github.com/ethereum/go-ethereum/state/state.go:163.2,166.20 3 0 -github.com/ethereum/go-ethereum/state/state.go:154.24,156.3 1 2 -github.com/ethereum/go-ethereum/state/state.go:159.20,161.3 1 1 -github.com/ethereum/go-ethereum/state/state.go:169.56,171.2 1 0 -github.com/ethereum/go-ethereum/state/state.go:174.66,176.24 2 1 -github.com/ethereum/go-ethereum/state/state.go:180.2,180.20 1 1 -github.com/ethereum/go-ethereum/state/state.go:176.24,178.3 1 1 -github.com/ethereum/go-ethereum/state/state.go:184.61,193.2 5 1 -github.com/ethereum/go-ethereum/state/state.go:196.57,198.2 1 0 -github.com/ethereum/go-ethereum/state/state.go:204.40,206.2 1 0 -github.com/ethereum/go-ethereum/state/state.go:208.34,209.22 1 2 -github.com/ethereum/go-ethereum/state/state.go:226.2,226.12 1 0 -github.com/ethereum/go-ethereum/state/state.go:209.22,211.49 2 2 -github.com/ethereum/go-ethereum/state/state.go:215.3,215.41 1 2 -github.com/ethereum/go-ethereum/state/state.go:219.3,223.15 4 2 -github.com/ethereum/go-ethereum/state/state.go:211.49,213.4 1 1 -github.com/ethereum/go-ethereum/state/state.go:215.41,217.4 1 0 -github.com/ethereum/go-ethereum/state/state.go:229.38,230.18 1 1 -github.com/ethereum/go-ethereum/state/state.go:234.2,237.24 4 1 -github.com/ethereum/go-ethereum/state/state.go:230.18,232.3 1 0 -github.com/ethereum/go-ethereum/state/state.go:240.31,242.2 1 0 -github.com/ethereum/go-ethereum/state/state.go:245.25,249.45 2 0 -github.com/ethereum/go-ethereum/state/state.go:258.2,258.11 1 0 -github.com/ethereum/go-ethereum/state/state.go:249.45,250.31 1 0 -github.com/ethereum/go-ethereum/state/state.go:255.3,255.22 1 0 -github.com/ethereum/go-ethereum/state/state.go:250.31,251.12 1 0 -github.com/ethereum/go-ethereum/state/state.go:262.24,264.45 1 0 -github.com/ethereum/go-ethereum/state/state.go:272.2,274.11 2 0 -github.com/ethereum/go-ethereum/state/state.go:264.45,265.31 1 0 -github.com/ethereum/go-ethereum/state/state.go:269.3,269.27 1 0 -github.com/ethereum/go-ethereum/state/state.go:265.31,266.12 1 0 -github.com/ethereum/go-ethereum/state/state.go:277.28,280.2 2 0 -github.com/ethereum/go-ethereum/state/state.go:282.29,286.40 2 0 -github.com/ethereum/go-ethereum/state/state.go:290.2,290.48 1 0 -github.com/ethereum/go-ethereum/state/state.go:302.2,302.13 1 0 -github.com/ethereum/go-ethereum/state/state.go:286.40,288.3 1 0 -github.com/ethereum/go-ethereum/state/state.go:290.48,291.25 1 0 -github.com/ethereum/go-ethereum/state/state.go:291.25,294.4 2 0 -github.com/ethereum/go-ethereum/state/state.go:294.5,298.4 2 0 -github.com/ethereum/go-ethereum/state/state.go:302.13,304.13 2 0 -github.com/ethereum/go-ethereum/state/state.go:304.13,308.4 2 0 -github.com/ethereum/go-ethereum/state/state.go:312.41,314.2 1 0 -github.com/ethereum/go-ethereum/state/state.go:317.42,318.48 1 0 -github.com/ethereum/go-ethereum/state/state.go:318.48,320.3 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:14.34,16.2 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:20.36,22.31 2 1 -github.com/ethereum/go-ethereum/state/state_object.go:27.2,27.12 1 1 -github.com/ethereum/go-ethereum/state/state_object.go:22.31,25.3 1 1 -github.com/ethereum/go-ethereum/state/state_object.go:55.34,58.2 2 0 -github.com/ethereum/go-ethereum/state/state_object.go:60.47,70.2 6 2 -github.com/ethereum/go-ethereum/state/state_object.go:72.78,78.2 4 0 -github.com/ethereum/go-ethereum/state/state_object.go:80.65,85.2 3 0 -github.com/ethereum/go-ethereum/state/state_object.go:87.44,90.2 2 0 -github.com/ethereum/go-ethereum/state/state_object.go:92.59,94.2 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:96.63,98.2 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:100.66,102.2 1 1 -github.com/ethereum/go-ethereum/state/state_object.go:103.73,105.2 1 2 -github.com/ethereum/go-ethereum/state/state_object.go:107.62,109.2 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:111.60,115.18 3 1 -github.com/ethereum/go-ethereum/state/state_object.go:123.2,123.14 1 1 -github.com/ethereum/go-ethereum/state/state_object.go:115.18,118.21 2 0 -github.com/ethereum/go-ethereum/state/state_object.go:118.21,120.4 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:126.67,129.2 2 2 -github.com/ethereum/go-ethereum/state/state_object.go:132.60,134.39 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:140.2,141.49 2 0 -github.com/ethereum/go-ethereum/state/state_object.go:134.39,138.3 2 0 -github.com/ethereum/go-ethereum/state/state_object.go:141.49,143.31 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:143.31,145.4 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:149.33,150.39 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:161.2,162.12 2 0 -github.com/ethereum/go-ethereum/state/state_object.go:150.39,151.23 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:158.3,158.35 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:151.23,155.12 2 0 -github.com/ethereum/go-ethereum/state/state_object.go:162.12,166.3 2 0 -github.com/ethereum/go-ethereum/state/state_object.go:169.60,170.39 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:174.2,174.62 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:170.39,172.3 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:177.51,181.2 2 0 -github.com/ethereum/go-ethereum/state/state_object.go:182.50,182.74 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:184.51,188.2 2 0 -github.com/ethereum/go-ethereum/state/state_object.go:189.50,189.74 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:191.51,193.2 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:195.45,195.68 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:202.54,202.56 0 0 -github.com/ethereum/go-ethereum/state/state_object.go:203.61,205.30 2 0 -github.com/ethereum/go-ethereum/state/state_object.go:209.2,211.12 2 0 -github.com/ethereum/go-ethereum/state/state_object.go:205.30,207.3 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:214.56,218.2 2 0 -github.com/ethereum/go-ethereum/state/state_object.go:220.60,221.31 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:225.2,230.12 4 0 -github.com/ethereum/go-ethereum/state/state_object.go:221.31,223.3 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:233.57,240.2 4 0 -github.com/ethereum/go-ethereum/state/state_object.go:242.46,247.23 5 1 -github.com/ethereum/go-ethereum/state/state_object.go:250.2,256.20 6 1 -github.com/ethereum/go-ethereum/state/state_object.go:247.23,249.3 1 1 -github.com/ethereum/go-ethereum/state/state_object.go:259.56,261.2 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:267.36,269.2 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:272.40,274.2 1 1 -github.com/ethereum/go-ethereum/state/state_object.go:277.35,279.2 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:282.48,284.2 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:286.40,288.2 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:295.42,297.2 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:299.48,301.2 1 0 -github.com/ethereum/go-ethereum/state/state_object.go:303.46,315.2 8 0 -github.com/ethereum/go-ethereum/trie/encoding.go:9.44,11.37 2 17 -github.com/ethereum/go-ethereum/trie/encoding.go:15.2,15.21 1 17 -github.com/ethereum/go-ethereum/trie/encoding.go:19.2,21.17 3 17 -github.com/ethereum/go-ethereum/trie/encoding.go:27.2,28.40 2 17 -github.com/ethereum/go-ethereum/trie/encoding.go:32.2,32.22 1 17 -github.com/ethereum/go-ethereum/trie/encoding.go:11.37,13.3 1 9 -github.com/ethereum/go-ethereum/trie/encoding.go:15.21,17.3 1 9 -github.com/ethereum/go-ethereum/trie/encoding.go:21.17,23.3 1 9 -github.com/ethereum/go-ethereum/trie/encoding.go:23.4,25.3 1 8 -github.com/ethereum/go-ethereum/trie/encoding.go:28.40,30.3 1 46 -github.com/ethereum/go-ethereum/trie/encoding.go:35.39,38.18 3 12 -github.com/ethereum/go-ethereum/trie/encoding.go:41.2,41.20 1 12 -github.com/ethereum/go-ethereum/trie/encoding.go:47.2,47.13 1 12 -github.com/ethereum/go-ethereum/trie/encoding.go:38.18,40.3 1 7 -github.com/ethereum/go-ethereum/trie/encoding.go:41.20,43.3 1 6 -github.com/ethereum/go-ethereum/trie/encoding.go:43.4,45.3 1 6 -github.com/ethereum/go-ethereum/trie/encoding.go:50.42,55.24 4 21 -github.com/ethereum/go-ethereum/trie/encoding.go:58.2,60.17 2 21 -github.com/ethereum/go-ethereum/trie/encoding.go:55.24,57.3 1 152 -github.com/ethereum/go-ethereum/trie/encoding.go:63.39,67.24 3 0 -github.com/ethereum/go-ethereum/trie/encoding.go:73.2,75.20 2 0 -github.com/ethereum/go-ethereum/trie/encoding.go:67.24,68.13 1 0 -github.com/ethereum/go-ethereum/trie/encoding.go:68.13,70.4 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:18.44,19.21 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:23.2,23.21 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:32.2,32.19 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:19.21,21.3 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:23.21,25.17 2 0 -github.com/ethereum/go-ethereum/trie/iterator.go:29.3,29.17 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:25.17,27.4 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:43.40,45.2 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:47.70,48.23 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:73.2,73.12 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:49.2,55.11 4 0 -github.com/ethereum/go-ethereum/trie/iterator.go:56.2,57.29 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:61.3,61.33 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:67.2,70.79 2 0 -github.com/ethereum/go-ethereum/trie/iterator.go:57.29,59.4 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:61.33,63.16 2 0 -github.com/ethereum/go-ethereum/trie/iterator.go:63.16,65.5 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:76.83,77.35 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:129.2,129.12 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:78.2,79.13 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:80.2,81.19 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:90.3,91.19 2 0 -github.com/ethereum/go-ethereum/trie/iterator.go:95.3,95.27 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:102.2,104.22 2 0 -github.com/ethereum/go-ethereum/trie/iterator.go:81.19,85.16 3 0 -github.com/ethereum/go-ethereum/trie/iterator.go:85.16,87.5 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:91.19,93.4 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:95.27,98.16 3 0 -github.com/ethereum/go-ethereum/trie/iterator.go:98.16,100.5 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:104.22,105.49 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:105.49,110.5 3 0 -github.com/ethereum/go-ethereum/trie/iterator.go:111.5,115.26 4 0 -github.com/ethereum/go-ethereum/trie/iterator.go:123.4,123.18 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:115.26,117.5 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:117.6,117.49 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:117.49,119.5 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:119.6,121.5 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:123.18,125.5 1 0 -github.com/ethereum/go-ethereum/trie/iterator.go:133.47,143.2 6 0 -github.com/ethereum/go-ethereum/trie/slice.go:9.39,10.22 1 0 -github.com/ethereum/go-ethereum/trie/slice.go:13.2,13.22 1 0 -github.com/ethereum/go-ethereum/trie/slice.go:18.2,18.13 1 0 -github.com/ethereum/go-ethereum/trie/slice.go:10.22,12.3 1 0 -github.com/ethereum/go-ethereum/trie/slice.go:13.22,14.16 1 0 -github.com/ethereum/go-ethereum/trie/slice.go:14.16,16.4 1 0 -github.com/ethereum/go-ethereum/trie/slice.go:22.44,25.17 2 6 -github.com/ethereum/go-ethereum/trie/slice.go:32.2,32.10 1 6 -github.com/ethereum/go-ethereum/trie/slice.go:25.17,26.19 1 11 -github.com/ethereum/go-ethereum/trie/slice.go:29.3,29.6 1 7 -github.com/ethereum/go-ethereum/trie/slice.go:26.19,27.9 1 4 -github.com/ethereum/go-ethereum/trie/slice.go:35.29,37.2 1 0 -github.com/ethereum/go-ethereum/trie/slice.go:39.31,40.16 1 0 -github.com/ethereum/go-ethereum/trie/slice.go:44.2,44.10 1 0 -github.com/ethereum/go-ethereum/trie/slice.go:40.16,42.3 1 0 -github.com/ethereum/go-ethereum/trie/slice.go:47.35,48.21 1 0 -github.com/ethereum/go-ethereum/trie/slice.go:52.2,52.35 1 0 -github.com/ethereum/go-ethereum/trie/slice.go:48.21,50.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:12.44,15.59 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:19.2,19.59 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:15.59,17.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:22.27,24.2 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:41.64,43.2 1 16 -github.com/ethereum/go-ethereum/trie/trie.go:45.29,47.2 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:55.43,57.2 1 1 -github.com/ethereum/go-ethereum/trie/trie.go:59.69,63.29 3 26 -github.com/ethereum/go-ethereum/trie/trie.go:72.2,72.10 1 10 -github.com/ethereum/go-ethereum/trie/trie.go:63.29,70.3 4 16 -github.com/ethereum/go-ethereum/trie/trie.go:75.52,77.2 1 25 -github.com/ethereum/go-ethereum/trie/trie.go:79.52,81.37 1 13 -github.com/ethereum/go-ethereum/trie/trie.go:86.2,90.15 3 0 -github.com/ethereum/go-ethereum/trie/trie.go:97.2,99.14 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:81.37,83.3 1 13 -github.com/ethereum/go-ethereum/trie/trie.go:90.15,91.31 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:91.31,94.4 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:102.40,106.2 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:108.30,110.20 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:114.2,114.37 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:120.2,124.28 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:110.20,112.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:114.37,115.17 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:115.17,118.4 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:124.28,126.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:129.28,130.37 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:135.2,135.23 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:130.37,131.17 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:131.17,133.4 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:152.45,154.32 2 2 -github.com/ethereum/go-ethereum/trie/trie.go:160.2,160.21 1 2 -github.com/ethereum/go-ethereum/trie/trie.go:154.32,156.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:156.4,158.3 1 2 -github.com/ethereum/go-ethereum/trie/trie.go:163.55,172.2 5 1 -github.com/ethereum/go-ethereum/trie/trie.go:174.45,175.26 1 9 -github.com/ethereum/go-ethereum/trie/trie.go:176.2,182.24 1 1 -github.com/ethereum/go-ethereum/trie/trie.go:183.2,184.19 1 7 -github.com/ethereum/go-ethereum/trie/trie.go:185.2,186.46 1 1 -github.com/ethereum/go-ethereum/trie/trie.go:194.42,201.17 5 8 -github.com/ethereum/go-ethereum/trie/trie.go:206.2,206.17 1 8 -github.com/ethereum/go-ethereum/trie/trie.go:201.17,203.3 1 6 -github.com/ethereum/go-ethereum/trie/trie.go:203.4,205.3 1 2 -github.com/ethereum/go-ethereum/trie/trie.go:209.39,217.2 5 0 -github.com/ethereum/go-ethereum/trie/trie.go:219.35,227.2 5 0 -github.com/ethereum/go-ethereum/trie/trie.go:229.36,230.31 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:231.2,232.14 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:235.3,235.19 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:236.2,237.18 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:241.3,241.11 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:242.2,243.72 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:232.14,234.4 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:237.18,239.4 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:248.37,250.2 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:253.29,255.39 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:259.2,259.13 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:255.39,257.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:263.23,266.2 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:268.23,271.2 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:273.31,275.2 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:277.67,280.48 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:284.2,287.17 3 0 -github.com/ethereum/go-ethereum/trie/trie.go:304.2,304.28 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:280.48,282.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:287.17,289.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:289.4,289.24 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:289.24,294.57 3 0 -github.com/ethereum/go-ethereum/trie/trie.go:294.57,296.4 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:296.5,298.4 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:299.4,299.25 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:299.25,301.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:307.57,310.23 2 18 -github.com/ethereum/go-ethereum/trie/trie.go:314.2,315.19 2 13 -github.com/ethereum/go-ethereum/trie/trie.go:321.2,323.13 2 13 -github.com/ethereum/go-ethereum/trie/trie.go:310.23,312.3 1 5 -github.com/ethereum/go-ethereum/trie/trie.go:315.19,317.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:317.4,317.26 1 13 -github.com/ethereum/go-ethereum/trie/trie.go:317.26,319.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:326.84,328.2 1 6 -github.com/ethereum/go-ethereum/trie/trie.go:330.50,333.2 1 25 -github.com/ethereum/go-ethereum/trie/trie.go:335.44,337.25 2 13 -github.com/ethereum/go-ethereum/trie/trie.go:340.2,340.14 1 13 -github.com/ethereum/go-ethereum/trie/trie.go:337.25,339.3 1 221 -github.com/ethereum/go-ethereum/trie/trie.go:343.89,344.19 1 22 -github.com/ethereum/go-ethereum/trie/trie.go:349.2,350.33 2 19 -github.com/ethereum/go-ethereum/trie/trie.go:356.2,358.28 2 12 -github.com/ethereum/go-ethereum/trie/trie.go:412.2,412.25 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:344.19,346.3 1 3 -github.com/ethereum/go-ethereum/trie/trie.go:350.33,354.3 2 7 -github.com/ethereum/go-ethereum/trie/trie.go:358.28,365.26 3 6 -github.com/ethereum/go-ethereum/trie/trie.go:370.3,372.31 3 6 -github.com/ethereum/go-ethereum/trie/trie.go:388.3,388.26 1 6 -github.com/ethereum/go-ethereum/trie/trie.go:365.26,368.4 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:372.31,375.4 1 2 -github.com/ethereum/go-ethereum/trie/trie.go:375.5,386.4 6 4 -github.com/ethereum/go-ethereum/trie/trie.go:388.26,391.4 1 1 -github.com/ethereum/go-ethereum/trie/trie.go:391.5,394.4 2 5 -github.com/ethereum/go-ethereum/trie/trie.go:395.4,400.27 2 6 -github.com/ethereum/go-ethereum/trie/trie.go:407.3,409.24 2 6 -github.com/ethereum/go-ethereum/trie/trie.go:400.27,402.18 2 102 -github.com/ethereum/go-ethereum/trie/trie.go:402.18,404.5 1 102 -github.com/ethereum/go-ethereum/trie/trie.go:415.70,416.19 1 5 -github.com/ethereum/go-ethereum/trie/trie.go:421.2,423.33 2 5 -github.com/ethereum/go-ethereum/trie/trie.go:430.2,432.28 2 5 -github.com/ethereum/go-ethereum/trie/trie.go:502.2,502.28 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:416.19,418.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:423.33,428.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:432.28,438.26 3 2 -github.com/ethereum/go-ethereum/trie/trie.go:438.26,442.4 1 2 -github.com/ethereum/go-ethereum/trie/trie.go:442.5,442.42 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:442.42,447.24 4 0 -github.com/ethereum/go-ethereum/trie/trie.go:456.4,456.25 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:447.24,450.5 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:450.6,452.5 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:457.5,459.4 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:460.4,465.27 3 3 -github.com/ethereum/go-ethereum/trie/trie.go:472.3,474.27 3 3 -github.com/ethereum/go-ethereum/trie/trie.go:483.3,483.19 1 3 -github.com/ethereum/go-ethereum/trie/trie.go:499.3,499.24 1 3 -github.com/ethereum/go-ethereum/trie/trie.go:465.27,467.18 2 51 -github.com/ethereum/go-ethereum/trie/trie.go:467.18,469.5 1 51 -github.com/ethereum/go-ethereum/trie/trie.go:474.27,475.18 1 51 -github.com/ethereum/go-ethereum/trie/trie.go:475.18,476.21 1 5 -github.com/ethereum/go-ethereum/trie/trie.go:476.21,478.6 1 3 -github.com/ethereum/go-ethereum/trie/trie.go:478.7,480.6 1 2 -github.com/ethereum/go-ethereum/trie/trie.go:483.19,485.4 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:485.5,485.25 1 3 -github.com/ethereum/go-ethereum/trie/trie.go:485.25,487.25 2 1 -github.com/ethereum/go-ethereum/trie/trie.go:487.25,489.5 1 1 -github.com/ethereum/go-ethereum/trie/trie.go:489.6,489.31 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:489.31,492.5 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:494.5,496.4 1 2 -github.com/ethereum/go-ethereum/trie/trie.go:516.44,518.2 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:520.40,522.2 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:526.62,527.28 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:527.28,530.37 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:530.37,532.4 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:532.5,533.25 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:533.25,535.5 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:535.6,538.5 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:540.4,541.42 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:541.42,542.48 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:542.48,544.5 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:544.6,545.39 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:545.39,547.6 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:547.7,549.19 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:549.19,552.7 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:559.46,562.2 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:564.44,565.24 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:569.2,571.16 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:565.24,567.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:574.37,576.27 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:579.2,579.23 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:576.27,578.3 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:582.38,584.2 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:586.40,588.2 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:592.47,594.2 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:596.77,598.2 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:600.94,601.28 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:601.28,605.70 3 0 -github.com/ethereum/go-ethereum/trie/trie.go:605.70,607.4 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:607.5,608.25 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:608.25,610.5 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:610.6,612.5 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:614.4,615.42 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:615.42,617.48 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:617.48,619.5 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:619.6,620.72 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:620.72,622.6 1 0 -github.com/ethereum/go-ethereum/trie/trie.go:622.7,624.19 2 0 -github.com/ethereum/go-ethereum/trie/trie.go:624.19,626.7 1 0 -github.com/ethereum/go-ethereum/vm/stack.go:25.24,27.2 1 4 -github.com/ethereum/go-ethereum/vm/stack.go:29.36,31.2 1 0 -github.com/ethereum/go-ethereum/vm/stack.go:33.28,35.2 1 141 -github.com/ethereum/go-ethereum/vm/stack.go:37.33,44.2 4 42 -github.com/ethereum/go-ethereum/vm/stack.go:46.46,53.2 4 20 -github.com/ethereum/go-ethereum/vm/stack.go:55.34,59.2 2 16 -github.com/ethereum/go-ethereum/vm/stack.go:61.47,65.2 2 0 -github.com/ethereum/go-ethereum/vm/stack.go:67.52,71.2 2 0 -github.com/ethereum/go-ethereum/vm/stack.go:73.39,77.2 2 0 -github.com/ethereum/go-ethereum/vm/stack.go:79.35,81.2 1 84 -github.com/ethereum/go-ethereum/vm/stack.go:83.50,86.29 2 0 -github.com/ethereum/go-ethereum/vm/stack.go:91.2,91.12 1 0 -github.com/ethereum/go-ethereum/vm/stack.go:86.29,89.3 2 0 -github.com/ethereum/go-ethereum/vm/stack.go:94.26,96.22 2 0 -github.com/ethereum/go-ethereum/vm/stack.go:103.2,103.30 1 0 -github.com/ethereum/go-ethereum/vm/stack.go:96.22,97.31 1 0 -github.com/ethereum/go-ethereum/vm/stack.go:97.31,99.4 1 0 -github.com/ethereum/go-ethereum/vm/stack.go:100.4,102.3 1 0 -github.com/ethereum/go-ethereum/vm/stack.go:110.26,112.2 1 3 -github.com/ethereum/go-ethereum/vm/stack.go:114.56,115.20 1 2 -github.com/ethereum/go-ethereum/vm/stack.go:115.20,118.24 3 2 -github.com/ethereum/go-ethereum/vm/stack.go:128.3,128.43 1 2 -github.com/ethereum/go-ethereum/vm/stack.go:118.24,121.16 2 2 -github.com/ethereum/go-ethereum/vm/stack.go:121.16,126.5 2 2 -github.com/ethereum/go-ethereum/vm/stack.go:132.38,133.28 1 28 -github.com/ethereum/go-ethereum/vm/stack.go:133.28,135.3 1 8 -github.com/ethereum/go-ethereum/vm/stack.go:138.49,139.32 1 4 -github.com/ethereum/go-ethereum/vm/stack.go:145.2,145.12 1 0 -github.com/ethereum/go-ethereum/vm/stack.go:139.32,143.3 2 4 -github.com/ethereum/go-ethereum/vm/stack.go:148.59,149.35 1 0 -github.com/ethereum/go-ethereum/vm/stack.go:157.2,157.8 1 0 -github.com/ethereum/go-ethereum/vm/stack.go:149.35,155.3 4 0 -github.com/ethereum/go-ethereum/vm/stack.go:160.28,162.2 1 139 -github.com/ethereum/go-ethereum/vm/stack.go:164.32,166.2 1 0 -github.com/ethereum/go-ethereum/vm/stack.go:168.26,170.22 2 0 -github.com/ethereum/go-ethereum/vm/stack.go:179.2,179.37 1 0 -github.com/ethereum/go-ethereum/vm/stack.go:170.22,172.45 2 0 -github.com/ethereum/go-ethereum/vm/stack.go:172.45,175.4 2 0 -github.com/ethereum/go-ethereum/vm/stack.go:176.4,178.3 1 0 -github.com/ethereum/go-ethereum/vm/address.go:19.55,21.2 1 2 -github.com/ethereum/go-ethereum/vm/address.go:29.35,31.2 1 1 -github.com/ethereum/go-ethereum/vm/address.go:33.38,35.2 1 1 -github.com/ethereum/go-ethereum/vm/address.go:37.38,39.15 1 0 -github.com/ethereum/go-ethereum/vm/address.go:41.2,41.29 1 0 -github.com/ethereum/go-ethereum/vm/address.go:39.15,39.28 1 0 -github.com/ethereum/go-ethereum/vm/execution.go:19.103,21.2 1 2 -github.com/ethereum/go-ethereum/vm/execution.go:23.38,25.2 1 0 -github.com/ethereum/go-ethereum/vm/execution.go:27.81,32.2 2 2 -github.com/ethereum/go-ethereum/vm/execution.go:34.92,39.15 4 2 -github.com/ethereum/go-ethereum/vm/execution.go:46.2,56.24 3 2 -github.com/ethereum/go-ethereum/vm/execution.go:60.2,60.16 1 2 -github.com/ethereum/go-ethereum/vm/execution.go:90.2,90.8 1 2 -github.com/ethereum/go-ethereum/vm/execution.go:39.15,40.39 1 2 -github.com/ethereum/go-ethereum/vm/execution.go:43.3,43.57 1 2 -github.com/ethereum/go-ethereum/vm/execution.go:40.39,42.4 1 0 -github.com/ethereum/go-ethereum/vm/execution.go:56.24,58.3 1 2 -github.com/ethereum/go-ethereum/vm/execution.go:60.16,64.3 2 0 -github.com/ethereum/go-ethereum/vm/execution.go:64.4,68.40 3 2 -github.com/ethereum/go-ethereum/vm/execution.go:68.40,69.32 1 2 -github.com/ethereum/go-ethereum/vm/execution.go:69.32,72.5 2 2 -github.com/ethereum/go-ethereum/vm/execution.go:73.5,78.39 3 0 -github.com/ethereum/go-ethereum/vm/execution.go:85.4,86.20 2 0 -github.com/ethereum/go-ethereum/vm/execution.go:78.39,82.5 2 0 -github.com/ethereum/go-ethereum/vm/execution.go:93.74,95.2 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:20.52,21.13 1 4 -github.com/ethereum/go-ethereum/vm/vm.go:22.2,23.25 1 3 -github.com/ethereum/go-ethereum/vm/vm.go:24.2,25.23 1 1 -github.com/ethereum/go-ethereum/vm/vm.go:29.70,33.15 2 1 -github.com/ethereum/go-ethereum/vm/vm.go:41.2,41.28 1 1 -github.com/ethereum/go-ethereum/vm/vm.go:45.2,52.25 1 1 -github.com/ethereum/go-ethereum/vm/vm.go:59.2,59.6 1 1 -github.com/ethereum/go-ethereum/vm/vm.go:33.15,34.31 1 1 -github.com/ethereum/go-ethereum/vm/vm.go:34.31,37.4 2 1 -github.com/ethereum/go-ethereum/vm/vm.go:41.28,43.3 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:52.25,53.23 1 15 -github.com/ethereum/go-ethereum/vm/vm.go:53.23,55.5 1 1 -github.com/ethereum/go-ethereum/vm/vm.go:59.6,68.44 5 22 -github.com/ethereum/go-ethereum/vm/vm.go:72.3,75.13 3 22 -github.com/ethereum/go-ethereum/vm/vm.go:144.3,144.39 1 22 -github.com/ethereum/go-ethereum/vm/vm.go:158.3,158.27 1 22 -github.com/ethereum/go-ethereum/vm/vm.go:166.3,168.13 2 22 -github.com/ethereum/go-ethereum/vm/vm.go:707.3,707.7 1 21 -github.com/ethereum/go-ethereum/vm/vm.go:68.44,70.4 1 24 -github.com/ethereum/go-ethereum/vm/vm.go:76.3,77.25 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:78.3,79.25 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:80.3,81.21 1 3 -github.com/ethereum/go-ethereum/vm/vm.go:82.3,86.65 4 0 -github.com/ethereum/go-ethereum/vm/vm.go:93.4,93.43 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:94.3,95.23 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:96.3,98.52 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:99.3,102.52 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:103.3,105.51 2 4 -github.com/ethereum/go-ethereum/vm/vm.go:106.3,109.69 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:110.3,115.69 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:116.3,119.69 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:120.3,123.69 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:124.3,127.82 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:128.3,136.37 6 0 -github.com/ethereum/go-ethereum/vm/vm.go:137.3,141.82 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:86.65,88.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:88.6,88.73 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:88.73,90.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:90.6,92.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:144.39,149.50 4 4 -github.com/ethereum/go-ethereum/vm/vm.go:149.50,155.5 4 2 -github.com/ethereum/go-ethereum/vm/vm.go:158.27,164.4 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:170.3,179.20 5 3 -github.com/ethereum/go-ethereum/vm/vm.go:180.3,189.20 5 0 -github.com/ethereum/go-ethereum/vm/vm.go:190.3,199.20 5 0 -github.com/ethereum/go-ethereum/vm/vm.go:200.3,204.32 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:208.4,211.20 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:212.3,216.32 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:231.4,231.20 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:232.3,240.20 5 0 -github.com/ethereum/go-ethereum/vm/vm.go:241.3,245.32 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:260.4,260.20 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:262.3,270.20 5 1 -github.com/ethereum/go-ethereum/vm/vm.go:271.3,277.20 4 0 -github.com/ethereum/go-ethereum/vm/vm.go:278.3,282.20 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:287.3,292.20 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:298.3,302.26 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:307.3,312.20 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:318.3,323.21 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:328.3,331.35 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:338.3,342.30 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:343.3,347.29 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:348.3,352.30 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:353.3,356.85 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:363.3,375.20 8 0 -github.com/ethereum/go-ethereum/vm/vm.go:376.3,388.20 8 0 -github.com/ethereum/go-ethereum/vm/vm.go:391.3,396.34 4 0 -github.com/ethereum/go-ethereum/vm/vm.go:399.3,400.47 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:402.3,408.23 4 0 -github.com/ethereum/go-ethereum/vm/vm.go:410.3,413.36 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:415.3,417.36 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:419.3,422.21 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:424.3,432.32 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:439.4,439.34 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:440.3,442.29 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:444.3,452.19 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:459.4,461.26 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:462.3,464.25 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:472.4,473.17 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:475.3,477.25 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:485.4,492.19 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:499.4,501.30 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:502.3,503.29 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:506.3,509.38 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:511.3,514.38 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:516.3,519.32 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:521.3,524.22 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:526.3,529.26 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:531.3,533.29 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:536.3,544.36 5 11 -github.com/ethereum/go-ethereum/vm/vm.go:545.3,547.15 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:548.3,550.17 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:551.3,553.18 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:555.3,559.19 4 0 -github.com/ethereum/go-ethereum/vm/vm.go:561.3,565.61 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:567.3,572.53 4 4 -github.com/ethereum/go-ethereum/vm/vm.go:574.3,579.28 4 3 -github.com/ethereum/go-ethereum/vm/vm.go:581.3,586.49 4 0 -github.com/ethereum/go-ethereum/vm/vm.go:588.3,593.12 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:594.3,597.38 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:606.3,606.17 0 0 -github.com/ethereum/go-ethereum/vm/vm.go:607.3,608.31 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:609.3,610.44 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:611.3,612.27 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:614.3,637.18 8 0 -github.com/ethereum/go-ethereum/vm/vm.go:649.3,664.22 8 0 -github.com/ethereum/go-ethereum/vm/vm.go:670.4,672.18 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:680.3,685.35 4 0 -github.com/ethereum/go-ethereum/vm/vm.go:686.3,695.15 5 0 -github.com/ethereum/go-ethereum/vm/vm.go:696.3,698.35 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:699.3,704.67 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:204.32,206.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:216.32,218.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:218.6,220.53 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:226.5,228.15 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:220.53,222.6 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:222.7,224.6 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:245.32,247.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:247.6,249.32 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:255.5,257.15 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:249.32,251.6 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:251.7,253.6 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:282.20,284.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:284.6,286.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:292.20,294.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:294.6,296.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:302.26,304.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:304.6,306.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:312.20,314.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:314.6,316.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:323.21,325.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:325.6,327.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:331.35,333.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:333.6,335.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:356.85,360.5 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:360.6,362.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:432.32,437.5 3 0 -github.com/ethereum/go-ethereum/vm/vm.go:452.19,455.5 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:455.6,455.28 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:455.28,457.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:464.25,468.5 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:468.6,470.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:477.25,481.5 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:481.6,483.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:492.19,495.5 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:495.6,495.28 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:495.28,497.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:597.38,600.43 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:604.5,604.13 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:600.43,602.6 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:637.18,643.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:643.6,647.5 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:664.22,666.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:666.6,668.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:672.18,674.5 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:674.6,678.5 2 0 -github.com/ethereum/go-ethereum/vm/vm.go:711.35,713.2 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:715.29,717.2 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:719.72,719.87 1 0 -github.com/ethereum/go-ethereum/vm/vm.go:720.72,720.87 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:32.43,34.25 2 3 -github.com/ethereum/go-ethereum/vm/vm_debug.go:38.2,38.57 1 3 -github.com/ethereum/go-ethereum/vm/vm_debug.go:34.25,36.3 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:41.75,44.22 2 3 -github.com/ethereum/go-ethereum/vm/vm_debug.go:60.2,70.30 1 3 -github.com/ethereum/go-ethereum/vm/vm_debug.go:100.2,100.21 1 3 -github.com/ethereum/go-ethereum/vm/vm_debug.go:105.2,105.28 1 3 -github.com/ethereum/go-ethereum/vm/vm_debug.go:109.2,111.6 2 3 -github.com/ethereum/go-ethereum/vm/vm_debug.go:44.22,46.16 1 3 -github.com/ethereum/go-ethereum/vm/vm_debug.go:46.16,47.32 1 3 -github.com/ethereum/go-ethereum/vm/vm_debug.go:47.32,56.5 4 1 -github.com/ethereum/go-ethereum/vm/vm_debug.go:70.30,71.23 1 33 -github.com/ethereum/go-ethereum/vm/vm_debug.go:71.23,73.5 1 1 -github.com/ethereum/go-ethereum/vm/vm_debug.go:76.34,81.14 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:95.4,95.15 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:81.14,83.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:83.6,85.64 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:91.5,91.12 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:85.64,87.6 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:87.7,87.43 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:87.43,89.6 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:100.21,102.3 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:105.28,107.3 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:111.6,122.30 5 80 -github.com/ethereum/go-ethereum/vm/vm_debug.go:139.3,140.44 2 80 -github.com/ethereum/go-ethereum/vm/vm_debug.go:146.3,150.13 3 80 -github.com/ethereum/go-ethereum/vm/vm_debug.go:253.3,253.39 1 79 -github.com/ethereum/go-ethereum/vm/vm_debug.go:270.3,273.27 3 79 -github.com/ethereum/go-ethereum/vm/vm_debug.go:283.3,283.13 1 79 -github.com/ethereum/go-ethereum/vm/vm_debug.go:917.3,921.22 3 77 -github.com/ethereum/go-ethereum/vm/vm_debug.go:122.30,123.14 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:131.4,132.19 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:136.4,136.92 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:124.4,125.98 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:125.98,128.6 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:132.19,134.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:140.44,141.37 1 88 -github.com/ethereum/go-ethereum/vm/vm_debug.go:141.37,143.5 1 88 -github.com/ethereum/go-ethereum/vm/vm_debug.go:152.3,153.14 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:154.3,155.14 1 10 -github.com/ethereum/go-ethereum/vm/vm_debug.go:156.3,157.14 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:158.3,160.14 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:161.3,163.14 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:164.3,171.52 6 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:173.3,174.25 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:175.3,178.25 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:179.3,182.21 2 9 -github.com/ethereum/go-ethereum/vm/vm_debug.go:184.3,190.65 5 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:201.4,201.46 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:202.3,204.23 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:205.3,207.52 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:208.3,211.52 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:212.3,214.51 2 10 -github.com/ethereum/go-ethereum/vm/vm_debug.go:215.3,218.69 2 2 -github.com/ethereum/go-ethereum/vm/vm_debug.go:219.3,224.69 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:225.3,228.69 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:229.3,232.69 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:233.3,236.82 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:237.3,245.37 6 2 -github.com/ethereum/go-ethereum/vm/vm_debug.go:246.3,250.82 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:190.65,193.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:193.6,193.73 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:193.73,197.5 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:197.6,200.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:253.39,258.50 4 12 -github.com/ethereum/go-ethereum/vm/vm_debug.go:258.50,266.5 5 6 -github.com/ethereum/go-ethereum/vm/vm_debug.go:273.27,281.4 4 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:285.3,295.20 6 9 -github.com/ethereum/go-ethereum/vm/vm_debug.go:296.3,306.20 6 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:307.3,317.20 6 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:318.3,322.32 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:326.4,330.20 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:331.3,336.32 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:351.4,352.20 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:353.3,358.32 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:364.4,367.20 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:368.3,373.32 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:388.4,389.20 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:391.3,402.20 6 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:403.3,405.17 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:422.3,428.20 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:429.3,433.20 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:438.3,443.20 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:449.3,453.26 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:458.3,463.20 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:469.3,474.21 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:479.3,481.35 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:488.3,492.30 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:493.3,497.29 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:498.3,502.30 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:503.3,506.34 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:514.4,516.20 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:517.3,530.20 8 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:531.3,544.20 8 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:547.3,553.31 4 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:555.3,558.44 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:559.3,566.45 4 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:567.3,572.33 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:573.3,577.33 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:578.3,583.32 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:584.3,591.32 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:598.4,600.34 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:601.3,605.28 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:606.3,614.19 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:621.4,625.72 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:626.3,628.25 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:636.4,639.28 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:640.3,642.25 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:650.4,657.19 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:664.4,668.72 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:669.3,672.40 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:675.3,680.37 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:681.3,686.37 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:687.3,692.33 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:693.3,698.43 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:699.3,704.47 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:705.3,706.35 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:709.3,720.41 8 47 -github.com/ethereum/go-ethereum/vm/vm_debug.go:721.3,722.15 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:723.3,729.151 4 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:732.3,736.62 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:737.3,742.27 5 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:746.4,749.30 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:750.3,755.40 4 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:756.3,761.32 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:762.3,768.42 4 10 -github.com/ethereum/go-ethereum/vm/vm_debug.go:769.3,774.59 4 9 -github.com/ethereum/go-ethereum/vm/vm_debug.go:775.3,780.30 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:784.4,784.59 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:785.3,789.12 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:790.3,793.38 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:799.3,799.17 0 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:800.3,801.18 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:802.3,803.44 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:804.3,805.27 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:807.3,831.18 9 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:844.4,847.23 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:850.3,865.22 8 2 -github.com/ethereum/go-ethereum/vm/vm_debug.go:871.4,873.18 3 2 -github.com/ethereum/go-ethereum/vm/vm_debug.go:882.4,885.23 2 2 -github.com/ethereum/go-ethereum/vm/vm_debug.go:889.3,895.35 4 2 -github.com/ethereum/go-ethereum/vm/vm_debug.go:896.3,903.15 4 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:904.3,907.35 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:908.3,914.67 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:322.32,324.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:336.32,338.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:338.6,340.53 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:346.5,348.15 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:340.53,342.6 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:342.7,344.6 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:358.32,360.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:360.6,362.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:373.32,375.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:375.6,377.32 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:383.5,385.15 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:377.32,379.6 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:379.7,381.6 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:405.17,410.39 5 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:416.5,420.20 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:410.39,412.6 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:412.7,414.6 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:433.20,435.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:435.6,437.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:443.20,445.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:445.6,447.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:453.26,455.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:455.6,457.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:463.20,465.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:465.6,467.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:474.21,476.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:476.6,478.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:481.35,483.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:483.6,485.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:506.34,510.5 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:510.6,512.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:591.32,596.5 3 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:614.19,617.5 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:617.6,617.28 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:617.28,619.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:628.25,632.5 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:632.6,634.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:642.25,646.5 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:646.6,648.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:657.19,660.5 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:660.6,660.28 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:660.28,662.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:729.151,731.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:742.27,744.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:780.30,782.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:793.38,796.13 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:831.18,838.5 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:838.6,842.5 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:847.23,849.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:865.22,867.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:867.6,869.5 1 2 -github.com/ethereum/go-ethereum/vm/vm_debug.go:873.18,877.5 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:877.6,881.5 2 2 -github.com/ethereum/go-ethereum/vm/vm_debug.go:885.23,887.5 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:921.22,922.51 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:922.51,923.41 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:923.41,926.98 2 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:926.98,928.7 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:929.7,929.29 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:929.29,930.97 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:930.97,932.7 1 0 -github.com/ethereum/go-ethereum/vm/vm_debug.go:940.77,941.31 1 248 -github.com/ethereum/go-ethereum/vm/vm_debug.go:945.2,945.13 1 248 -github.com/ethereum/go-ethereum/vm/vm_debug.go:941.31,943.3 1 248 -github.com/ethereum/go-ethereum/vm/vm_debug.go:948.44,949.31 1 82 -github.com/ethereum/go-ethereum/vm/vm_debug.go:954.2,954.13 1 82 -github.com/ethereum/go-ethereum/vm/vm_debug.go:949.31,952.3 2 82 -github.com/ethereum/go-ethereum/vm/vm_debug.go:957.40,959.2 1 4 -github.com/ethereum/go-ethereum/vm/vm_debug.go:961.34,963.2 1 0 -github.com/ethereum/go-ethereum/vm/closure.go:34.126,46.2 5 4 -github.com/ethereum/go-ethereum/vm/closure.go:49.57,51.14 2 3 -github.com/ethereum/go-ethereum/vm/closure.go:55.2,55.10 1 3 -github.com/ethereum/go-ethereum/vm/closure.go:51.14,53.3 1 0 -github.com/ethereum/go-ethereum/vm/closure.go:58.50,60.2 1 0 -github.com/ethereum/go-ethereum/vm/closure.go:62.39,64.2 1 102 -github.com/ethereum/go-ethereum/vm/closure.go:66.39,67.21 1 102 -github.com/ethereum/go-ethereum/vm/closure.go:71.2,71.10 1 0 -github.com/ethereum/go-ethereum/vm/closure.go:67.21,69.3 1 102 -github.com/ethereum/go-ethereum/vm/closure.go:74.45,75.42 1 11 -github.com/ethereum/go-ethereum/vm/closure.go:79.2,79.24 1 11 -github.com/ethereum/go-ethereum/vm/closure.go:75.42,77.3 1 0 -github.com/ethereum/go-ethereum/vm/closure.go:82.54,83.72 1 47 -github.com/ethereum/go-ethereum/vm/closure.go:87.2,89.34 2 47 -github.com/ethereum/go-ethereum/vm/closure.go:83.72,85.3 1 0 -github.com/ethereum/go-ethereum/vm/closure.go:92.62,94.2 1 0 -github.com/ethereum/go-ethereum/vm/closure.go:96.36,98.2 1 16 -github.com/ethereum/go-ethereum/vm/closure.go:100.82,106.2 3 4 -github.com/ethereum/go-ethereum/vm/closure.go:108.45,113.2 2 4 -github.com/ethereum/go-ethereum/vm/closure.go:115.45,116.24 1 102 -github.com/ethereum/go-ethereum/vm/closure.go:121.2,124.13 3 102 -github.com/ethereum/go-ethereum/vm/closure.go:116.24,118.3 1 0 -github.com/ethereum/go-ethereum/vm/closure.go:128.50,132.2 2 0 -github.com/ethereum/go-ethereum/vm/closure.go:134.47,136.2 1 2 -github.com/ethereum/go-ethereum/vm/closure.go:138.39,140.2 1 0 -github.com/ethereum/go-ethereum/vm/closure.go:142.51,144.2 1 0 -github.com/ethereum/go-ethereum/vm/common.go:46.44,47.30 1 20 -github.com/ethereum/go-ethereum/vm/common.go:51.2,51.33 1 18 -github.com/ethereum/go-ethereum/vm/common.go:47.30,49.3 1 2 -github.com/ethereum/go-ethereum/vm/common.go:55.29,57.2 1 94 -github.com/ethereum/go-ethereum/vm/common.go:60.40,63.59 2 0 -github.com/ethereum/go-ethereum/vm/common.go:67.2,67.12 1 0 -github.com/ethereum/go-ethereum/vm/common.go:63.59,65.3 1 0 -github.com/ethereum/go-ethereum/vm/types.go:328.33,330.19 2 81 -github.com/ethereum/go-ethereum/vm/types.go:334.2,334.12 1 81 -github.com/ethereum/go-ethereum/vm/types.go:330.19,332.3 1 0 -github.com/ethereum/go-ethereum/vm/asm.go:10.48,12.6 2 0 -github.com/ethereum/go-ethereum/vm/asm.go:44.2,44.8 1 0 -github.com/ethereum/go-ethereum/vm/asm.go:12.6,13.50 1 0 -github.com/ethereum/go-ethereum/vm/asm.go:18.3,24.13 4 0 -github.com/ethereum/go-ethereum/vm/asm.go:41.3,41.27 1 0 -github.com/ethereum/go-ethereum/vm/asm.go:13.50,15.4 1 0 -github.com/ethereum/go-ethereum/vm/asm.go:25.3,28.39 3 0 -github.com/ethereum/go-ethereum/vm/asm.go:32.4,33.22 2 0 -github.com/ethereum/go-ethereum/vm/asm.go:36.4,38.31 2 0 -github.com/ethereum/go-ethereum/vm/asm.go:28.39,30.5 1 0 -github.com/ethereum/go-ethereum/vm/asm.go:33.22,35.5 1 0 -github.com/ethereum/go-ethereum/vm/errors.go:12.43,14.2 1 0 -github.com/ethereum/go-ethereum/vm/errors.go:16.42,18.2 1 0 -github.com/ethereum/go-ethereum/vm/errors.go:20.31,23.2 2 2 -github.com/ethereum/go-ethereum/vm/errors.go:29.40,31.2 1 0 -github.com/ethereum/go-ethereum/vm/errors.go:33.39,35.2 1 0 -github.com/ethereum/go-ethereum/vm/errors.go:37.30,40.2 2 0 -github.com/ethereum/go-ethereum/vm/errors.go:44.39,46.2 1 0 -github.com/ethereum/go-ethereum/vm/errors.go:48.33,51.2 2 2 -github.com/ethereum/go-ethereum/vm/analysis.go:9.63,14.50 4 3 -github.com/ethereum/go-ethereum/vm/analysis.go:34.2,34.8 1 3 -github.com/ethereum/go-ethereum/vm/analysis.go:14.50,16.13 2 117 -github.com/ethereum/go-ethereum/vm/analysis.go:17.3,19.33 2 61 -github.com/ethereum/go-ethereum/vm/analysis.go:23.4,24.13 2 61 -github.com/ethereum/go-ethereum/vm/analysis.go:25.3,26.10 1 0 -github.com/ethereum/go-ethereum/vm/analysis.go:30.3,31.14 1 56 -github.com/ethereum/go-ethereum/vm/analysis.go:19.33,21.5 1 61 -github.com/ethereum/go-ethereum/vm/analysis.go:26.10,28.5 1 0 -github.com/ethereum/go-ethereum/vm/environment.go:38.56,39.36 1 0 -github.com/ethereum/go-ethereum/vm/environment.go:43.2,50.12 3 0 -github.com/ethereum/go-ethereum/vm/environment.go:39.36,41.3 1 0 -github.com/ethereum/go-ethereum/wire/client_identity.go:21.118,31.2 2 1 -github.com/ethereum/go-ethereum/wire/client_identity.go:33.39,34.2 0 0 -github.com/ethereum/go-ethereum/wire/client_identity.go:36.48,38.33 2 2 -github.com/ethereum/go-ethereum/wire/client_identity.go:42.2,47.20 1 2 -github.com/ethereum/go-ethereum/wire/client_identity.go:38.33,40.3 1 2 -github.com/ethereum/go-ethereum/wire/client_identity.go:50.77,52.2 1 1 -github.com/ethereum/go-ethereum/wire/client_identity.go:54.61,56.2 1 2 -github.com/ethereum/go-ethereum/wire/messages2.go:23.37,25.2 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:28.37,29.36 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:33.2,36.12 3 0 -github.com/ethereum/go-ethereum/wire/messages2.go:29.36,31.3 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:43.68,47.26 3 0 -github.com/ethereum/go-ethereum/wire/messages2.go:58.2,67.16 6 0 -github.com/ethereum/go-ethereum/wire/messages2.go:71.2,71.12 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:47.26,48.59 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:48.59,50.4 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:50.5,50.50 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:50.50,52.4 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:52.5,54.4 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:67.16,69.3 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:74.101,75.20 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:79.2,79.20 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:84.2,84.46 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:88.2,90.40 3 0 -github.com/ethereum/go-ethereum/wire/messages2.go:94.2,106.8 6 0 -github.com/ethereum/go-ethereum/wire/messages2.go:75.20,77.3 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:79.20,81.3 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:84.46,86.3 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:90.40,92.3 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:112.52,114.15 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:122.2,124.6 3 0 -github.com/ethereum/go-ethereum/wire/messages2.go:149.2,151.78 3 0 -github.com/ethereum/go-ethereum/wire/messages2.go:159.2,159.8 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:114.15,115.31 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:115.31,117.4 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:124.6,131.27 4 0 -github.com/ethereum/go-ethereum/wire/messages2.go:144.3,145.18 2 0 -github.com/ethereum/go-ethereum/wire/messages2.go:131.27,132.28 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:132.28,135.5 2 0 -github.com/ethereum/go-ethereum/wire/messages2.go:135.6,136.10 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:140.5,140.20 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:140.20,141.9 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:151.78,154.17 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:154.17,156.4 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:162.82,163.20 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:167.2,167.20 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:172.2,172.46 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:176.2,178.40 3 0 -github.com/ethereum/go-ethereum/wire/messages2.go:182.2,194.8 6 0 -github.com/ethereum/go-ethereum/wire/messages2.go:163.20,165.3 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:167.20,169.3 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:172.46,174.3 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:178.40,180.3 1 0 -github.com/ethereum/go-ethereum/wire/messages2.go:197.50,199.2 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:62.35,64.2 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:72.57,77.2 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:84.59,86.15 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:92.2,98.6 2 0 -github.com/ethereum/go-ethereum/wire/messaging.go:145.2,145.29 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:155.2,155.8 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:86.15,87.31 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:87.31,89.4 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:98.6,104.27 4 0 -github.com/ethereum/go-ethereum/wire/messaging.go:113.3,113.31 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:120.3,121.21 2 0 -github.com/ethereum/go-ethereum/wire/messaging.go:134.3,134.29 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:104.27,105.28 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:105.28,108.5 2 0 -github.com/ethereum/go-ethereum/wire/messaging.go:108.6,109.10 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:113.31,117.12 2 0 -github.com/ethereum/go-ethereum/wire/messaging.go:121.21,123.48 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:128.4,131.19 2 0 -github.com/ethereum/go-ethereum/wire/messaging.go:123.48,125.5 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:134.29,139.22 4 0 -github.com/ethereum/go-ethereum/wire/messaging.go:139.22,140.10 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:145.29,153.3 4 0 -github.com/ethereum/go-ethereum/wire/messaging.go:160.50,174.16 7 0 -github.com/ethereum/go-ethereum/wire/messaging.go:178.2,178.12 1 0 -github.com/ethereum/go-ethereum/wire/messaging.go:174.16,176.3 1 0 diff --git a/ptrie/iterator.go b/ptrie/iterator.go deleted file mode 100644 index 5714bdbc8a..0000000000 --- a/ptrie/iterator.go +++ /dev/null @@ -1,115 +0,0 @@ -package ptrie - -import ( - "bytes" - - "github.com/ethereum/go-ethereum/trie" -) - -type Iterator struct { - trie *Trie - - Key []byte - Value []byte -} - -func NewIterator(trie *Trie) *Iterator { - return &Iterator{trie: trie, Key: []byte{0}} -} - -func (self *Iterator) Next() bool { - self.trie.mu.Lock() - defer self.trie.mu.Unlock() - - key := trie.RemTerm(trie.CompactHexDecode(string(self.Key))) - k := self.next(self.trie.root, key) - - self.Key = []byte(trie.DecodeCompact(k)) - - return len(k) > 0 - -} - -func (self *Iterator) next(node Node, key []byte) []byte { - if node == nil { - return nil - } - - switch node := node.(type) { - case *FullNode: - if len(key) > 0 { - k := self.next(node.branch(key[0]), key[1:]) - if k != nil { - return append([]byte{key[0]}, k...) - } - } - - var r byte - if len(key) > 0 { - r = key[0] + 1 - } - - for i := r; i < 16; i++ { - k := self.key(node.branch(byte(i))) - if k != nil { - return append([]byte{i}, k...) - } - } - - case *ShortNode: - k := trie.RemTerm(node.Key()) - if vnode, ok := node.Value().(*ValueNode); ok { - if bytes.Compare([]byte(k), key) > 0 { - self.Value = vnode.Val() - return k - } - } else { - cnode := node.Value() - - var ret []byte - skey := key[len(k):] - if trie.BeginsWith(key, k) { - ret = self.next(cnode, skey) - } else if bytes.Compare(k, key[:len(k)]) > 0 { - ret = self.key(node) - } - - if ret != nil { - return append(k, ret...) - } - } - } - - return nil -} - -func (self *Iterator) key(node Node) []byte { - switch node := node.(type) { - case *ShortNode: - // Leaf node - if vnode, ok := node.Value().(*ValueNode); ok { - k := trie.RemTerm(node.Key()) - self.Value = vnode.Val() - - return k - } else { - k := trie.RemTerm(node.Key()) - return append(k, self.key(node.Value())...) - } - case *FullNode: - if node.Value() != nil { - self.Value = node.Value().(*ValueNode).Val() - - return []byte{16} - } - - for i := 0; i < 16; i++ { - k := self.key(node.branch(byte(i))) - if k != nil { - return append([]byte{byte(i)}, k...) - } - } - } - - return nil -} diff --git a/ptrie/trie.go b/ptrie/trie.go deleted file mode 100644 index 9fe9ea52a5..0000000000 --- a/ptrie/trie.go +++ /dev/null @@ -1,312 +0,0 @@ -package ptrie - -import ( - "bytes" - "container/list" - "fmt" - "sync" - - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethutil" - "github.com/ethereum/go-ethereum/trie" -) - -func ParanoiaCheck(t1 *Trie, backend Backend) (bool, *Trie) { - t2 := New(nil, backend) - - it := t1.Iterator() - for it.Next() { - t2.Update(it.Key, it.Value) - } - - return bytes.Compare(t2.Hash(), t1.Hash()) == 0, t2 -} - -type Trie struct { - mu sync.Mutex - root Node - roothash []byte - cache *Cache - - revisions *list.List -} - -func New(root []byte, backend Backend) *Trie { - trie := &Trie{} - trie.revisions = list.New() - trie.roothash = root - trie.cache = NewCache(backend) - - if root != nil { - value := ethutil.NewValueFromBytes(trie.cache.Get(root)) - trie.root = trie.mknode(value) - } - - return trie -} - -func (self *Trie) Iterator() *Iterator { - return NewIterator(self) -} - -// Legacy support -func (self *Trie) Root() []byte { return self.Hash() } -func (self *Trie) Hash() []byte { - var hash []byte - if self.root != nil { - //hash = self.root.Hash().([]byte) - t := self.root.Hash() - if byts, ok := t.([]byte); ok { - hash = byts - } else { - hash = crypto.Sha3(ethutil.Encode(self.root.RlpData())) - } - } else { - hash = crypto.Sha3(ethutil.Encode("")) - } - - if !bytes.Equal(hash, self.roothash) { - self.revisions.PushBack(self.roothash) - self.roothash = hash - } - - return hash -} -func (self *Trie) Commit() { - // Hash first - self.Hash() - - self.cache.Flush() -} - -// Reset should only be called if the trie has been hashed -func (self *Trie) Reset() { - self.cache.Reset() - - revision := self.revisions.Remove(self.revisions.Back()).([]byte) - self.roothash = revision - value := ethutil.NewValueFromBytes(self.cache.Get(self.roothash)) - self.root = self.mknode(value) -} - -func (self *Trie) UpdateString(key, value string) Node { return self.Update([]byte(key), []byte(value)) } -func (self *Trie) Update(key, value []byte) Node { - self.mu.Lock() - defer self.mu.Unlock() - - k := trie.CompactHexDecode(string(key)) - - if len(value) != 0 { - self.root = self.insert(self.root, k, &ValueNode{self, value}) - } else { - self.root = self.delete(self.root, k) - } - - return self.root -} - -func (self *Trie) GetString(key string) []byte { return self.Get([]byte(key)) } -func (self *Trie) Get(key []byte) []byte { - self.mu.Lock() - defer self.mu.Unlock() - - k := trie.CompactHexDecode(string(key)) - - n := self.get(self.root, k) - if n != nil { - return n.(*ValueNode).Val() - } - - return nil -} - -func (self *Trie) DeleteString(key string) Node { return self.Delete([]byte(key)) } -func (self *Trie) Delete(key []byte) Node { - self.mu.Lock() - defer self.mu.Unlock() - - k := trie.CompactHexDecode(string(key)) - self.root = self.delete(self.root, k) - - return self.root -} - -func (self *Trie) insert(node Node, key []byte, value Node) Node { - if len(key) == 0 { - return value - } - - if node == nil { - return NewShortNode(self, key, value) - } - - switch node := node.(type) { - case *ShortNode: - k := node.Key() - cnode := node.Value() - if bytes.Equal(k, key) { - return NewShortNode(self, key, value) - } - - var n Node - matchlength := trie.MatchingNibbleLength(key, k) - if matchlength == len(k) { - n = self.insert(cnode, key[matchlength:], value) - } else { - pnode := self.insert(nil, k[matchlength+1:], cnode) - nnode := self.insert(nil, key[matchlength+1:], value) - fulln := NewFullNode(self) - fulln.set(k[matchlength], pnode) - fulln.set(key[matchlength], nnode) - n = fulln - } - if matchlength == 0 { - return n - } - - return NewShortNode(self, key[:matchlength], n) - - case *FullNode: - cpy := node.Copy().(*FullNode) - cpy.set(key[0], self.insert(node.branch(key[0]), key[1:], value)) - - return cpy - - default: - panic("Invalid node") - } -} - -func (self *Trie) get(node Node, key []byte) Node { - if len(key) == 0 { - return node - } - - if node == nil { - return nil - } - - switch node := node.(type) { - case *ShortNode: - k := node.Key() - cnode := node.Value() - - if len(key) >= len(k) && bytes.Equal(k, key[:len(k)]) { - return self.get(cnode, key[len(k):]) - } - - return nil - case *FullNode: - return self.get(node.branch(key[0]), key[1:]) - default: - panic(fmt.Sprintf("%T: invalid node: %v", node, node)) - } -} - -func (self *Trie) delete(node Node, key []byte) Node { - if len(key) == 0 { - return nil - } - - switch node := node.(type) { - case *ShortNode: - k := node.Key() - cnode := node.Value() - if bytes.Equal(key, k) { - return nil - } else if bytes.Equal(key[:len(k)], k) { - child := self.delete(cnode, key[len(k):]) - - var n Node - switch child := child.(type) { - case *ShortNode: - nkey := append(k, child.Key()...) - n = NewShortNode(self, nkey, child.Value()) - case *FullNode: - n = NewShortNode(self, node.key, child) - } - - return n - } else { - return node - } - - case *FullNode: - n := node.Copy().(*FullNode) - n.set(key[0], self.delete(n.branch(key[0]), key[1:])) - - pos := -1 - for i := 0; i < 17; i++ { - if n.branch(byte(i)) != nil { - if pos == -1 { - pos = i - } else { - pos = -2 - } - } - } - - var nnode Node - if pos == 16 { - nnode = NewShortNode(self, []byte{16}, n.branch(byte(pos))) - } else if pos >= 0 { - cnode := n.branch(byte(pos)) - switch cnode := cnode.(type) { - case *ShortNode: - // Stitch keys - k := append([]byte{byte(pos)}, cnode.Key()...) - nnode = NewShortNode(self, k, cnode.Value()) - case *FullNode: - nnode = NewShortNode(self, []byte{byte(pos)}, n.branch(byte(pos))) - } - } else { - nnode = n - } - - return nnode - - default: - panic("Invalid node") - } -} - -// casting functions and cache storing -func (self *Trie) mknode(value *ethutil.Value) Node { - l := value.Len() - switch l { - case 2: - return NewShortNode(self, trie.CompactDecode(string(value.Get(0).Bytes())), self.mknode(value.Get(1))) - case 17: - fnode := NewFullNode(self) - for i := 0; i < l; i++ { - fnode.set(byte(i), self.mknode(value.Get(i))) - } - return fnode - case 32: - return &HashNode{value.Bytes()} - default: - return &ValueNode{self, value.Bytes()} - } -} - -func (self *Trie) trans(node Node) Node { - switch node := node.(type) { - case *HashNode: - value := ethutil.NewValueFromBytes(self.cache.Get(node.key)) - return self.mknode(value) - default: - return node - } -} - -func (self *Trie) store(node Node) interface{} { - data := ethutil.Encode(node) - if len(data) >= 32 { - key := crypto.Sha3(data) - self.cache.Put(key, data) - - return key - } - - return node.RlpData() -} diff --git a/ptrie/trie_test.go b/ptrie/trie_test.go deleted file mode 100644 index 5b1c641401..0000000000 --- a/ptrie/trie_test.go +++ /dev/null @@ -1,259 +0,0 @@ -package ptrie - -import ( - "bytes" - "fmt" - "testing" - - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethutil" -) - -type Db map[string][]byte - -func (self Db) Get(k []byte) ([]byte, error) { return self[string(k)], nil } -func (self Db) Put(k, v []byte) { self[string(k)] = v } - -// Used for testing -func NewEmpty() *Trie { - return New(nil, make(Db)) -} - -func TestEmptyTrie(t *testing.T) { - trie := NewEmpty() - res := trie.Hash() - exp := crypto.Sha3(ethutil.Encode("")) - if !bytes.Equal(res, exp) { - t.Errorf("expected %x got %x", exp, res) - } -} - -func TestInsert(t *testing.T) { - trie := NewEmpty() - - trie.UpdateString("doe", "reindeer") - trie.UpdateString("dog", "puppy") - trie.UpdateString("dogglesworth", "cat") - - exp := ethutil.Hex2Bytes("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3") - root := trie.Hash() - if !bytes.Equal(root, exp) { - t.Errorf("exp %x got %x", exp, root) - } - - trie = NewEmpty() - trie.UpdateString("A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") - - exp = ethutil.Hex2Bytes("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab") - root = trie.Hash() - if !bytes.Equal(root, exp) { - t.Errorf("exp %x got %x", exp, root) - } -} - -func TestGet(t *testing.T) { - trie := NewEmpty() - - trie.UpdateString("doe", "reindeer") - trie.UpdateString("dog", "puppy") - trie.UpdateString("dogglesworth", "cat") - - res := trie.GetString("dog") - if !bytes.Equal(res, []byte("puppy")) { - t.Errorf("expected puppy got %x", res) - } - - unknown := trie.GetString("unknown") - if unknown != nil { - t.Errorf("expected nil got %x", unknown) - } -} - -func TestDelete(t *testing.T) { - trie := NewEmpty() - - vals := []struct{ k, v string }{ - {"do", "verb"}, - {"ether", "wookiedoo"}, - {"horse", "stallion"}, - {"shaman", "horse"}, - {"doge", "coin"}, - {"ether", ""}, - {"dog", "puppy"}, - {"shaman", ""}, - } - for _, val := range vals { - if val.v != "" { - trie.UpdateString(val.k, val.v) - } else { - trie.DeleteString(val.k) - } - } - - hash := trie.Hash() - exp := ethutil.Hex2Bytes("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84") - if !bytes.Equal(hash, exp) { - t.Errorf("expected %x got %x", exp, hash) - } -} - -func TestEmptyValues(t *testing.T) { - trie := NewEmpty() - - vals := []struct{ k, v string }{ - {"do", "verb"}, - {"ether", "wookiedoo"}, - {"horse", "stallion"}, - {"shaman", "horse"}, - {"doge", "coin"}, - {"ether", ""}, - {"dog", "puppy"}, - {"shaman", ""}, - } - for _, val := range vals { - trie.UpdateString(val.k, val.v) - } - - hash := trie.Hash() - exp := ethutil.Hex2Bytes("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84") - if !bytes.Equal(hash, exp) { - t.Errorf("expected %x got %x", exp, hash) - } -} - -func TestReplication(t *testing.T) { - trie := NewEmpty() - vals := []struct{ k, v string }{ - {"do", "verb"}, - {"ether", "wookiedoo"}, - {"horse", "stallion"}, - {"shaman", "horse"}, - {"doge", "coin"}, - {"ether", ""}, - {"dog", "puppy"}, - {"shaman", ""}, - {"somethingveryoddindeedthis is", "myothernodedata"}, - } - for _, val := range vals { - trie.UpdateString(val.k, val.v) - } - trie.Commit() - - trie2 := New(trie.roothash, trie.cache.backend) - if string(trie2.GetString("horse")) != "stallion" { - t.Error("expected to have harse => stallion") - } - - hash := trie2.Hash() - exp := trie.Hash() - if !bytes.Equal(hash, exp) { - t.Errorf("root failure. expected %x got %x", exp, hash) - } - -} - -func TestReset(t *testing.T) { - trie := NewEmpty() - vals := []struct{ k, v string }{ - {"do", "verb"}, - {"ether", "wookiedoo"}, - {"horse", "stallion"}, - } - for _, val := range vals { - trie.UpdateString(val.k, val.v) - } - trie.Commit() - - before := ethutil.CopyBytes(trie.roothash) - trie.UpdateString("should", "revert") - trie.Hash() - // Should have no effect - trie.Hash() - trie.Hash() - // ### - - trie.Reset() - after := ethutil.CopyBytes(trie.roothash) - - if !bytes.Equal(before, after) { - t.Errorf("expected roots to be equal. %x - %x", before, after) - } -} - -func TestParanoia(t *testing.T) { - t.Skip() - trie := NewEmpty() - - vals := []struct{ k, v string }{ - {"do", "verb"}, - {"ether", "wookiedoo"}, - {"horse", "stallion"}, - {"shaman", "horse"}, - {"doge", "coin"}, - {"ether", ""}, - {"dog", "puppy"}, - {"shaman", ""}, - {"somethingveryoddindeedthis is", "myothernodedata"}, - } - for _, val := range vals { - trie.UpdateString(val.k, val.v) - } - trie.Commit() - - ok, t2 := ParanoiaCheck(trie, trie.cache.backend) - if !ok { - t.Errorf("trie paranoia check failed %x %x", trie.roothash, t2.roothash) - } -} - -// Not an actual test -func TestOutput(t *testing.T) { - t.Skip() - - base := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - trie := NewEmpty() - for i := 0; i < 50; i++ { - trie.UpdateString(fmt.Sprintf("%s%d", base, i), "valueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") - } - fmt.Println("############################## FULL ################################") - fmt.Println(trie.root) - - trie.Commit() - fmt.Println("############################## SMALL ################################") - trie2 := New(trie.roothash, trie.cache.backend) - trie2.GetString(base + "20") - fmt.Println(trie2.root) -} - -func BenchmarkGets(b *testing.B) { - trie := NewEmpty() - vals := []struct{ k, v string }{ - {"do", "verb"}, - {"ether", "wookiedoo"}, - {"horse", "stallion"}, - {"shaman", "horse"}, - {"doge", "coin"}, - {"ether", ""}, - {"dog", "puppy"}, - {"shaman", ""}, - {"somethingveryoddindeedthis is", "myothernodedata"}, - } - for _, val := range vals { - trie.UpdateString(val.k, val.v) - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - trie.Get([]byte("horse")) - } -} - -func BenchmarkUpdate(b *testing.B) { - trie := NewEmpty() - - b.ResetTimer() - for i := 0; i < b.N; i++ { - trie.UpdateString(fmt.Sprintf("aaaaaaaaa%d", i), "value") - } - trie.Hash() -} diff --git a/rlp/decode.go b/rlp/decode.go index 712d9fcf18..a2bd042859 100644 --- a/rlp/decode.go +++ b/rlp/decode.go @@ -76,22 +76,37 @@ func Decode(r io.Reader, val interface{}) error { type decodeError struct { msg string typ reflect.Type + ctx []string } -func (err decodeError) Error() string { - return fmt.Sprintf("rlp: %s for %v", err.msg, err.typ) +func (err *decodeError) Error() string { + ctx := "" + if len(err.ctx) > 0 { + ctx = ", decoding into " + for i := len(err.ctx) - 1; i >= 0; i-- { + ctx += err.ctx[i] + } + } + return fmt.Sprintf("rlp: %s for %v%s", err.msg, err.typ, ctx) } func wrapStreamError(err error, typ reflect.Type) error { switch err { case ErrExpectedList: - return decodeError{"expected input list", typ} + return &decodeError{msg: "expected input list", typ: typ} case ErrExpectedString: - return decodeError{"expected input string or byte", typ} + return &decodeError{msg: "expected input string or byte", typ: typ} case errUintOverflow: - return decodeError{"input string too long", typ} + return &decodeError{msg: "input string too long", typ: typ} case errNotAtEOL: - return decodeError{"input list has too many elements", typ} + return &decodeError{msg: "input list has too many elements", typ: typ} + } + return err +} + +func addErrorContext(err error, ctx string) error { + if decErr, ok := err.(*decodeError); ok { + decErr.ctx = append(decErr.ctx, ctx) } return err } @@ -180,13 +195,13 @@ func makeListDecoder(typ reflect.Type) (decoder, error) { return nil, err } - if typ.Kind() == reflect.Array { - return func(s *Stream, val reflect.Value) error { - return decodeListArray(s, val, etypeinfo.decoder) - }, nil - } + isArray := typ.Kind() == reflect.Array return func(s *Stream, val reflect.Value) error { - return decodeListSlice(s, val, etypeinfo.decoder) + if isArray { + return decodeListArray(s, val, etypeinfo.decoder) + } else { + return decodeListSlice(s, val, etypeinfo.decoder) + } }, nil } @@ -219,7 +234,7 @@ func decodeListSlice(s *Stream, val reflect.Value, elemdec decoder) error { if err := elemdec(s, val.Index(i)); err == EOL { break } else if err != nil { - return err + return addErrorContext(err, fmt.Sprint("[", i, "]")) } } if i < val.Len() { @@ -248,7 +263,7 @@ func decodeListArray(s *Stream, val reflect.Value, elemdec decoder) error { if err := elemdec(s, val.Index(i)); err == EOL { break } else if err != nil { - return err + return addErrorContext(err, fmt.Sprint("[", i, "]")) } } if i < vlen { @@ -280,14 +295,14 @@ func decodeByteArray(s *Stream, val reflect.Value) error { switch kind { case Byte: if val.Len() == 0 { - return decodeError{"input string too long", val.Type()} + return &decodeError{msg: "input string too long", typ: val.Type()} } bv, _ := s.Uint() val.Index(0).SetUint(bv) zero(val, 1) case String: if uint64(val.Len()) < size { - return decodeError{"input string too long", val.Type()} + return &decodeError{msg: "input string too long", typ: val.Type()} } slice := val.Slice(0, int(size)).Interface().([]byte) if err := s.readFull(slice); err != nil { @@ -334,7 +349,7 @@ func makeStructDecoder(typ reflect.Type) (decoder, error) { // too few elements. leave the rest at their zero value. break } else if err != nil { - return err + return addErrorContext(err, "."+typ.Field(f.index).Name) } } return wrapStreamError(s.ListEnd(), typ) @@ -599,7 +614,13 @@ func (s *Stream) Decode(val interface{}) error { if err != nil { return err } - return info.decoder(s, rval.Elem()) + + err = info.decoder(s, rval.Elem()) + if decErr, ok := err.(*decodeError); ok && len(decErr.ctx) > 0 { + // add decode target type to error so context has more meaning + decErr.ctx = append(decErr.ctx, fmt.Sprint("(", rtyp.Elem(), ")")) + } + return err } // Reset discards any information about the current decoding context diff --git a/rlp/decode_test.go b/rlp/decode_test.go index 7a1743937d..18ea63a090 100644 --- a/rlp/decode_test.go +++ b/rlp/decode_test.go @@ -231,7 +231,12 @@ var decodeTests = []decodeTest{ {input: "8D6162636465666768696A6B6C6D", ptr: new([]byte), value: []byte("abcdefghijklm")}, {input: "C0", ptr: new([]byte), value: []byte{}}, {input: "C3010203", ptr: new([]byte), value: []byte{1, 2, 3}}, - {input: "C3820102", ptr: new([]byte), error: "rlp: input string too long for uint8"}, + + { + input: "C3820102", + ptr: new([]byte), + error: "rlp: input string too long for uint8, decoding into ([]uint8)[0]", + }, // byte arrays {input: "01", ptr: new([5]byte), value: [5]byte{1}}, @@ -239,9 +244,22 @@ var decodeTests = []decodeTest{ {input: "850102030405", ptr: new([5]byte), value: [5]byte{1, 2, 3, 4, 5}}, {input: "C0", ptr: new([5]byte), value: [5]byte{}}, {input: "C3010203", ptr: new([5]byte), value: [5]byte{1, 2, 3, 0, 0}}, - {input: "C3820102", ptr: new([5]byte), error: "rlp: input string too long for uint8"}, - {input: "86010203040506", ptr: new([5]byte), error: "rlp: input string too long for [5]uint8"}, - {input: "850101", ptr: new([5]byte), error: io.ErrUnexpectedEOF.Error()}, + + { + input: "C3820102", + ptr: new([5]byte), + error: "rlp: input string too long for uint8, decoding into ([5]uint8)[0]", + }, + { + input: "86010203040506", + ptr: new([5]byte), + error: "rlp: input string too long for [5]uint8", + }, + { + input: "850101", + ptr: new([5]byte), + error: io.ErrUnexpectedEOF.Error(), + }, // byte array reuse (should be zeroed) {input: "850102030405", ptr: &sharedByteArray, value: [5]byte{1, 2, 3, 4, 5}}, @@ -272,13 +290,23 @@ var decodeTests = []decodeTest{ {input: "C0", ptr: new(simplestruct), value: simplestruct{0, ""}}, {input: "C105", ptr: new(simplestruct), value: simplestruct{5, ""}}, {input: "C50583343434", ptr: new(simplestruct), value: simplestruct{5, "444"}}, - {input: "C3010101", ptr: new(simplestruct), error: "rlp: input list has too many elements for rlp.simplestruct"}, { input: "C501C302C103", ptr: new(recstruct), value: recstruct{1, &recstruct{2, &recstruct{3, nil}}}, }, + { + input: "C3010101", + ptr: new(simplestruct), + error: "rlp: input list has too many elements for rlp.simplestruct", + }, + { + input: "C501C3C00000", + ptr: new(recstruct), + error: "rlp: expected input string or byte for uint, decoding into (rlp.recstruct).Child.I", + }, + // pointers {input: "00", ptr: new(*uint), value: (*uint)(nil)}, {input: "80", ptr: new(*uint), value: (*uint)(nil)}, diff --git a/state/dump.go b/state/dump.go index c1f5ecf3a0..ac646480c7 100644 --- a/state/dump.go +++ b/state/dump.go @@ -22,22 +22,23 @@ type World struct { func (self *StateDB) Dump() []byte { world := World{ - Root: ethutil.Bytes2Hex(self.Trie.GetRoot()), + Root: ethutil.Bytes2Hex(self.trie.Root()), Accounts: make(map[string]Account), } - self.Trie.NewIterator().Each(func(key string, value *ethutil.Value) { - stateObject := NewStateObjectFromBytes([]byte(key), value.Bytes()) + it := self.trie.Iterator() + for it.Next() { + stateObject := NewStateObjectFromBytes(it.Key, it.Value, self.db) account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.Nonce, Root: ethutil.Bytes2Hex(stateObject.Root()), CodeHash: ethutil.Bytes2Hex(stateObject.codeHash)} account.Storage = make(map[string]string) - stateObject.EachStorage(func(key string, value *ethutil.Value) { - value.Decode() - account.Storage[ethutil.Bytes2Hex([]byte(key))] = ethutil.Bytes2Hex(value.Bytes()) - }) - world.Accounts[ethutil.Bytes2Hex([]byte(key))] = account - }) + storageIt := stateObject.State.trie.Iterator() + for storageIt.Next() { + account.Storage[ethutil.Bytes2Hex(it.Key)] = ethutil.Bytes2Hex(it.Value) + } + world.Accounts[ethutil.Bytes2Hex(it.Key)] = account + } json, err := json.MarshalIndent(world, "", " ") if err != nil { @@ -50,7 +51,8 @@ func (self *StateDB) Dump() []byte { // Debug stuff func (self *StateObject) CreateOutputForDiff() { fmt.Printf("%x %x %x %x\n", self.Address(), self.State.Root(), self.balance.Bytes(), self.Nonce) - self.EachStorage(func(addr string, value *ethutil.Value) { - fmt.Printf("%x %x\n", addr, value.Bytes()) - }) + it := self.State.trie.Iterator() + for it.Next() { + fmt.Printf("%x %x\n", it.Key, it.Value) + } } diff --git a/state/manifest.go b/state/manifest.go index 21cd04a1a9..994019a086 100644 --- a/state/manifest.go +++ b/state/manifest.go @@ -30,6 +30,12 @@ func (self *Manifest) AddMessage(msg *Message) *Message { return msg } +func (self *Manifest) SetHash(hash []byte) { + for _, message := range self.Messages { + message.Block = hash + } +} + type Messages []*Message type Message struct { To, From []byte diff --git a/state/state_object.go b/state/state_object.go index b8af4e702a..913c57a316 100644 --- a/state/state_object.go +++ b/state/state_object.go @@ -28,6 +28,7 @@ func (self Storage) Copy() Storage { } type StateObject struct { + db ethutil.Database // Address of the object address []byte // Shared attributes @@ -57,28 +58,20 @@ func (self *StateObject) Reset() { self.State.Reset() } -func NewStateObject(addr []byte) *StateObject { +func NewStateObject(addr []byte, db ethutil.Database) *StateObject { // This to ensure that it has 20 bytes (and not 0 bytes), thus left or right pad doesn't matter. address := ethutil.Address(addr) - object := &StateObject{address: address, balance: new(big.Int), gasPool: new(big.Int)} - object.State = New(trie.New(ethutil.Config.Db, "")) + object := &StateObject{db: db, address: address, balance: new(big.Int), gasPool: new(big.Int)} + object.State = New(nil, db) //New(trie.New(ethutil.Config.Db, "")) object.storage = make(Storage) object.gasPool = new(big.Int) return object } -func NewContract(address []byte, balance *big.Int, root []byte) *StateObject { - contract := NewStateObject(address) - contract.balance = balance - contract.State = New(trie.New(ethutil.Config.Db, string(root))) - - return contract -} - -func NewStateObjectFromBytes(address, data []byte) *StateObject { - object := &StateObject{address: address} +func NewStateObjectFromBytes(address, data []byte, db ethutil.Database) *StateObject { + object := &StateObject{address: address, db: db} object.RlpDecode(data) return object @@ -89,12 +82,12 @@ func (self *StateObject) MarkForDeletion() { statelogger.DebugDetailf("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.balance) } -func (c *StateObject) GetAddr(addr []byte) *ethutil.Value { - return ethutil.NewValueFromBytes([]byte(c.State.Trie.Get(string(addr)))) +func (c *StateObject) getAddr(addr []byte) *ethutil.Value { + return ethutil.NewValueFromBytes([]byte(c.State.trie.Get(addr))) } -func (c *StateObject) SetAddr(addr []byte, value interface{}) { - c.State.Trie.Update(string(addr), string(ethutil.NewValue(value).Encode())) +func (c *StateObject) setAddr(addr []byte, value interface{}) { + c.State.trie.Update(addr, ethutil.Encode(value)) } func (self *StateObject) GetStorage(key *big.Int) *ethutil.Value { @@ -113,7 +106,7 @@ func (self *StateObject) GetState(k []byte) *ethutil.Value { value := self.storage[string(key)] if value == nil { - value = self.GetAddr(key) + value = self.getAddr(key) if !value.IsNil() { self.storage[string(key)] = value @@ -128,6 +121,7 @@ func (self *StateObject) SetState(k []byte, value *ethutil.Value) { self.storage[string(key)] = value.Copy() } +/* // Iterate over each storage address and yield callback func (self *StateObject) EachStorage(cb trie.EachCallback) { // First loop over the uncommit/cached values in storage @@ -145,23 +139,26 @@ func (self *StateObject) EachStorage(cb trie.EachCallback) { } }) } +*/ func (self *StateObject) Sync() { for key, value := range self.storage { if value.Len() == 0 { - self.State.Trie.Delete(string(key)) + self.State.trie.Delete([]byte(key)) continue } - self.SetAddr([]byte(key), value) + self.setAddr([]byte(key), value) } - valid, t2 := trie.ParanoiaCheck(self.State.Trie) - if !valid { - statelogger.Infof("Warn: PARANOIA: Different state storage root during copy %x vs %x\n", self.State.Root(), t2.GetRoot()) + /* + valid, t2 := trie.ParanoiaCheck(self.State.trie, ethutil.Config.Db) + if !valid { + statelogger.Infof("Warn: PARANOIA: Different state storage root during copy %x vs %x\n", self.State.Root(), t2.Root()) - self.State.Trie = t2 - } + self.State.trie = t2 + } + */ } func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value { @@ -238,7 +235,7 @@ func (self *StateObject) RefundGas(gas, price *big.Int) { } func (self *StateObject) Copy() *StateObject { - stateObject := NewStateObject(self.Address()) + stateObject := NewStateObject(self.Address(), self.db) stateObject.balance.Set(self.balance) stateObject.codeHash = ethutil.CopyBytes(self.codeHash) stateObject.Nonce = self.Nonce @@ -276,8 +273,12 @@ func (c *StateObject) Init() Code { return c.InitCode } +func (self *StateObject) Trie() *trie.Trie { + return self.State.trie +} + func (self *StateObject) Root() []byte { - return self.State.Trie.GetRoot() + return self.Trie().Root() } func (self *StateObject) SetCode(code []byte) { @@ -302,13 +303,13 @@ func (c *StateObject) RlpDecode(data []byte) { c.Nonce = decoder.Get(0).Uint() c.balance = decoder.Get(1).BigInt() - c.State = New(trie.New(ethutil.Config.Db, decoder.Get(2).Interface())) + c.State = New(decoder.Get(2).Bytes(), c.db) //New(trie.New(ethutil.Config.Db, decoder.Get(2).Interface())) c.storage = make(map[string]*ethutil.Value) c.gasPool = new(big.Int) c.codeHash = decoder.Get(3).Bytes() - c.Code, _ = ethutil.Config.Db.Get(c.codeHash) + c.Code, _ = c.db.Get(c.codeHash) } // Storage change object. Used by the manifest for notifying changes to diff --git a/state/state_test.go b/state/state_test.go index 28e4fc5da1..7c54cedc0e 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -5,7 +5,6 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" - "github.com/ethereum/go-ethereum/trie" ) type StateSuite struct { @@ -18,18 +17,16 @@ var _ = checker.Suite(&StateSuite{}) func (s *StateSuite) TestDump(c *checker.C) { key := []byte{0x01} - value := "foo" - node := []interface{}{key, value} - s.state.Trie.Put(node) + value := []byte("foo") + s.state.trie.Update(key, value) dump := s.state.Dump() c.Assert(dump, checker.NotNil) } func (s *StateSuite) SetUpTest(c *checker.C) { - db, _ := ethdb.NewMemDatabase() ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "") - ethutil.Config.Db = db - s.state = New(trie.New(db, "")) + db, _ := ethdb.NewMemDatabase() + s.state = New(nil, db) } func (s *StateSuite) TestSnapshot(c *checker.C) { diff --git a/state/state.go b/state/statedb.go similarity index 85% rename from state/state.go rename to state/statedb.go index a8d6116685..3176ab7555 100644 --- a/state/state.go +++ b/state/statedb.go @@ -1,6 +1,7 @@ package state import ( + "bytes" "math/big" "github.com/ethereum/go-ethereum/ethutil" @@ -16,8 +17,8 @@ var statelogger = logger.NewLogger("STATE") // * Contracts // * Accounts type StateDB struct { - // The trie for this structure - Trie *trie.Trie + db ethutil.Database + trie *trie.Trie stateObjects map[string]*StateObject @@ -29,8 +30,9 @@ type StateDB struct { } // Create a new state from a given trie -func New(trie *trie.Trie) *StateDB { - return &StateDB{Trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest(), refund: make(map[string]*big.Int)} +func New(root []byte, db ethutil.Database) *StateDB { + trie := trie.New(root, db) + return &StateDB{db: db, trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest(), refund: make(map[string]*big.Int)} } func (self *StateDB) EmptyLogs() { @@ -94,6 +96,13 @@ func (self *StateDB) GetCode(addr []byte) []byte { return nil } +func (self *StateDB) SetCode(addr, code []byte) { + stateObject := self.GetStateObject(addr) + if stateObject != nil { + stateObject.SetCode(code) + } +} + func (self *StateDB) GetState(a, b []byte) []byte { stateObject := self.GetStateObject(a) if stateObject != nil { @@ -130,15 +139,15 @@ func (self *StateDB) UpdateStateObject(stateObject *StateObject) { addr := stateObject.Address() if len(stateObject.CodeHash()) > 0 { - ethutil.Config.Db.Put(stateObject.CodeHash(), stateObject.Code) + self.db.Put(stateObject.CodeHash(), stateObject.Code) } - self.Trie.Update(string(addr), string(stateObject.RlpEncode())) + self.trie.Update(addr, stateObject.RlpEncode()) } // Delete the given state object and delete it from the state trie func (self *StateDB) DeleteStateObject(stateObject *StateObject) { - self.Trie.Delete(string(stateObject.Address())) + self.trie.Delete(stateObject.Address()) delete(self.stateObjects, string(stateObject.Address())) } @@ -152,12 +161,12 @@ func (self *StateDB) GetStateObject(addr []byte) *StateObject { return stateObject } - data := self.Trie.Get(string(addr)) + data := self.trie.Get(addr) if len(data) == 0 { return nil } - stateObject = NewStateObjectFromBytes(addr, []byte(data)) + stateObject = NewStateObjectFromBytes(addr, []byte(data), self.db) self.SetStateObject(stateObject) return stateObject @@ -183,7 +192,7 @@ func (self *StateDB) NewStateObject(addr []byte) *StateObject { statelogger.Debugf("(+) %x\n", addr) - stateObject := NewStateObject(addr) + stateObject := NewStateObject(addr, self.db) self.stateObjects[string(addr)] = stateObject return stateObject @@ -199,12 +208,13 @@ func (self *StateDB) GetAccount(addr []byte) *StateObject { // func (s *StateDB) Cmp(other *StateDB) bool { - return s.Trie.Cmp(other.Trie) + return bytes.Equal(s.trie.Root(), other.trie.Root()) } func (self *StateDB) Copy() *StateDB { - if self.Trie != nil { - state := New(self.Trie.Copy()) + if self.trie != nil { + state := New(nil, self.db) + state.trie = self.trie.Copy() for k, stateObject := range self.stateObjects { state.stateObjects[k] = stateObject.Copy() } @@ -228,19 +238,19 @@ func (self *StateDB) Set(state *StateDB) { panic("Tried setting 'state' to nil through 'Set'") } - self.Trie = state.Trie + self.trie = state.trie self.stateObjects = state.stateObjects self.refund = state.refund self.logs = state.logs } func (s *StateDB) Root() []byte { - return s.Trie.GetRoot() + return s.trie.Root() } // Resets the trie and all siblings func (s *StateDB) Reset() { - s.Trie.Undo() + s.trie.Reset() // Reset all nested states for _, stateObject := range s.stateObjects { @@ -265,7 +275,7 @@ func (s *StateDB) Sync() { stateObject.State.Sync() } - s.Trie.Sync() + s.trie.Commit() s.Empty() } @@ -297,11 +307,11 @@ func (self *StateDB) Update(gasUsed *big.Int) { // FIXME trie delete is broken if deleted { - valid, t2 := trie.ParanoiaCheck(self.Trie) + valid, t2 := trie.ParanoiaCheck(self.trie, self.db) if !valid { - statelogger.Infof("Warn: PARANOIA: Different state root during copy %x vs %x\n", self.Trie.GetRoot(), t2.GetRoot()) + statelogger.Infof("Warn: PARANOIA: Different state root during copy %x vs %x\n", self.trie.Root(), t2.Root()) - self.Trie = t2 + self.trie = t2 } } } diff --git a/tests/files/StateTests/stInitCodeTest.json b/tests/files/StateTests/stInitCodeTest.json index 67aa42853b..c44d710391 100644 --- a/tests/files/StateTests/stInitCodeTest.json +++ b/tests/files/StateTests/stInitCodeTest.json @@ -1,4 +1,356 @@ { + "CallContractToCreateContractAndCallItOOG" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "100000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "998", + "code" : "0x74600c60005566602060406000f060205260076039f36000526015600b6001f0600055600060006000600060016000546000f1", + "nonce" : "1", + "storage" : { + "0x" : "0xd2571607e241ecf590ed94b12d87c94babe36db6" + } + }, + "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { + "balance" : "1301", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "99998699", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + }, + "d2571607e241ecf590ed94b12d87c94babe36db6" : { + "balance" : "2", + "code" : "0x602060406000f0", + "nonce" : "0", + "storage" : { + "0x" : "0x0c" + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000", + "code" : "0x74600c60005566602060406000f060205260076039f36000526015600b6001f0600055600060006000600060016000546000f1", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x00", + "gasLimit" : "20000000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0" + } + }, + "CallContractToCreateContractNoCash" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "100000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000", + "code" : "0x74600c60005566602060406000f060205260076039f36000526015600b6103e9f0600055", + "nonce" : "0", + "storage" : { + } + }, + "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { + "balance" : "709", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "99999291", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000", + "code" : "0x74600c60005566602060406000f060205260076039f36000526015600b6103e9f0600055", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x00", + "gasLimit" : "20000000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0" + } + }, + "CallContractToCreateContractOOG" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "100000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "0000000000000000000000000000000000000000" : { + "balance" : "0", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x74600c60005566602060406000f060205260076039f36000526015600b6001f0600055600060006000600060006000546000f1", + "nonce" : "0", + "storage" : { + } + }, + "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { + "balance" : "756", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "99999244", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0", + "code" : "0x74600c60005566602060406000f060205260076039f36000526015600b6001f0600055600060006000600060006000546000f1", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x00", + "gasLimit" : "20000000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0" + } + }, + "CallContractToCreateContractWhichWouldCreateContractIfCalled" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "100000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "998", + "code" : "0x74600c60005566602060406000f060205260076039f36000526015600b6001f0600055600060006000600060016000546101f4f1", + "nonce" : "1", + "storage" : { + "0x" : "0xd2571607e241ecf590ed94b12d87c94babe36db6" + } + }, + "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { + "balance" : "1407", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "62c01474f089b07dae603491675dc5b5748f7049" : { + "balance" : "0", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "99998593", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + }, + "d2571607e241ecf590ed94b12d87c94babe36db6" : { + "balance" : "2", + "code" : "0x602060406000f0", + "nonce" : "1", + "storage" : { + "0x" : "0x0c" + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000", + "code" : "0x74600c60005566602060406000f060205260076039f36000526015600b6001f0600055600060006000600060016000546101f4f1", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x00", + "gasLimit" : "20000000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0" + } + }, + "CallContractToCreateContractWhichWouldCreateContractInInitCode" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "100000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1", + "code" : "0x6b600c600055602060406000f0600052600c60146000f0", + "nonce" : "1", + "storage" : { + } + }, + "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { + "balance" : "1016", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "62c01474f089b07dae603491675dc5b5748f7049" : { + "balance" : "0", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "99998984", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + }, + "d2571607e241ecf590ed94b12d87c94babe36db6" : { + "balance" : "0", + "code" : "0x", + "nonce" : "1", + "storage" : { + "0x" : "0x0c" + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1", + "code" : "0x6b600c600055602060406000f0600052600c60146000f0", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x00", + "gasLimit" : "20000000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0" + } + }, "CallRecursiveContract" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", @@ -244,251 +596,6 @@ "value" : "1" } }, - "CallTheContractToCreateContractWithInitCode" : { - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "45678256", - "currentGasLimit" : "1000000", - "currentNumber" : "0", - "currentTimestamp" : 1, - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "logs" : [ - ], - "out" : "0x", - "post" : { - "04110d816c380812a427968ece99b1c963dfbce6" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x04110d816c380812a427968ece99b1c963dfbce6" - } - }, - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "10001", - "code" : "0x3060025560206000600039602060006000f0", - "nonce" : "1", - "storage" : { - "0x02" : "0x095e7baea6a6c7c4c2dfeb977efac326af552d87" - } - }, - "0a517d755cebbf66312b30fff713666a9cb917e0" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x0a517d755cebbf66312b30fff713666a9cb917e0" - } - }, - "24dd378f51adc67a50e339e8031fe9bd4aafab36" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x24dd378f51adc67a50e339e8031fe9bd4aafab36" - } - }, - "293f982d000532a7861ab122bdc4bbfd26bf9030" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x293f982d000532a7861ab122bdc4bbfd26bf9030" - } - }, - "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "10000", - "code" : "0x", - "nonce" : "0", - "storage" : { - } - }, - "2cf5732f017b0cf1b1f13a1478e10239716bf6b5" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x2cf5732f017b0cf1b1f13a1478e10239716bf6b5" - } - }, - "31c640b92c21a1f1465c91070b4b3b4d6854195f" : { - "balance" : "0", - "code" : "0x", - "nonce" : "0", - "storage" : { - } - }, - "37f998764813b136ddf5a754f34063fd03065e36" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x37f998764813b136ddf5a754f34063fd03065e36" - } - }, - "37fa399a749c121f8a15ce77e3d9f9bec8020d7a" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x37fa399a749c121f8a15ce77e3d9f9bec8020d7a" - } - }, - "4f36659fa632310b6ec438dea4085b522a2dd077" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x4f36659fa632310b6ec438dea4085b522a2dd077" - } - }, - "62c01474f089b07dae603491675dc5b5748f7049" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x62c01474f089b07dae603491675dc5b5748f7049" - } - }, - "729af7294be595a0efd7d891c9e51f89c07950c7" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x729af7294be595a0efd7d891c9e51f89c07950c7" - } - }, - "83e3e5a16d3b696a0314b30b2534804dd5e11197" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x83e3e5a16d3b696a0314b30b2534804dd5e11197" - } - }, - "8703df2417e0d7c59d063caa9583cb10a4d20532" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x8703df2417e0d7c59d063caa9583cb10a4d20532" - } - }, - "8dffcd74e5b5923512916c6a64b502689cfa65e1" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x8dffcd74e5b5923512916c6a64b502689cfa65e1" - } - }, - "95a4d7cccb5204733874fa87285a176fe1e9e240" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x95a4d7cccb5204733874fa87285a176fe1e9e240" - } - }, - "99b2fcba8120bedd048fe79f5262a6690ed38c39" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0x99b2fcba8120bedd048fe79f5262a6690ed38c39" - } - }, - "a4202b8b8afd5354e3e40a219bdc17f6001bf2cf" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0xa4202b8b8afd5354e3e40a219bdc17f6001bf2cf" - } - }, - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "89999", - "code" : "0x", - "nonce" : "1", - "storage" : { - } - }, - "a9647f4a0a14042d91dc33c0328030a7157c93ae" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0xa9647f4a0a14042d91dc33c0328030a7157c93ae" - } - }, - "aa6cffe5185732689c18f37a7f86170cb7304c2a" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0xaa6cffe5185732689c18f37a7f86170cb7304c2a" - } - }, - "aae4a2e3c51c04606dcb3723456e58f3ed214f45" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0xaae4a2e3c51c04606dcb3723456e58f3ed214f45" - } - }, - "c37a43e940dfb5baf581a0b82b351d48305fc885" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0xc37a43e940dfb5baf581a0b82b351d48305fc885" - } - }, - "d2571607e241ecf590ed94b12d87c94babe36db6" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0xd2571607e241ecf590ed94b12d87c94babe36db6" - } - }, - "f735071cbee190d76b704ce68384fc21e389fbe7" : { - "balance" : "0", - "code" : "0x", - "nonce" : "1", - "storage" : { - "0x02" : "0xf735071cbee190d76b704ce68384fc21e389fbe7" - } - } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "10000", - "code" : "0x3060025560206000600039602060006000f0", - "nonce" : "0", - "storage" : { - } - }, - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "100000", - "code" : "0x", - "nonce" : "0", - "storage" : { - } - } - }, - "transaction" : { - "data" : "0x00", - "gasLimit" : "10000", - "gasPrice" : "1", - "nonce" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", - "value" : "1" - } - }, "CallTheContractToCreateEmptyContract" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", @@ -651,6 +758,60 @@ "value" : "1" } }, + "StackUnderFlowContractCreation" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { + "balance" : "1000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { + "balance" : "0", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "9000", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x6000f1", + "gasLimit" : "1000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "", + "value" : "0" + } + }, "TransactionContractCreation" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", diff --git a/tests/files/StateTests/stRecursiveCreate.json b/tests/files/StateTests/stRecursiveCreate.json index 9834314848..a478663292 100644 --- a/tests/files/StateTests/stRecursiveCreate.json +++ b/tests/files/StateTests/stRecursiveCreate.json @@ -1266,7 +1266,7 @@ } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "465224", + "balance" : "112225", "code" : "0x", "nonce" : "0", "storage" : { @@ -4759,7 +4759,7 @@ } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "999999999999434776", + "balance" : "999999999999787775", "code" : "0x", "nonce" : "1", "storage" : { diff --git a/tests/files/StateTests/stSystemOperationsTest.json b/tests/files/StateTests/stSystemOperationsTest.json index 612331ae36..4120f3cab6 100644 --- a/tests/files/StateTests/stSystemOperationsTest.json +++ b/tests/files/StateTests/stSystemOperationsTest.json @@ -171,11 +171,11 @@ "code" : "0x6001600054016000556000600060006000600173945304eb96065b2a98b57a48a06ae28d285a71b56103e85a03f1", "nonce" : "0", "storage" : { - "0x" : "0x0200" + "0x" : "0x0201" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "8997504", + "balance" : "157725", "code" : "0x", "nonce" : "0", "storage" : { @@ -190,7 +190,7 @@ } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "999999999990902496", + "balance" : "999999999999742275", "code" : "0x", "nonce" : "1", "storage" : { @@ -248,11 +248,11 @@ "code" : "0x6001600054016000556000600060006000600173945304eb96065b2a98b57a48a06ae28d285a71b56103e85a03f1", "nonce" : "0", "storage" : { - "0x" : "0x0200" + "0x" : "0x0201" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "8997504", + "balance" : "157725", "code" : "0x", "nonce" : "0", "storage" : { @@ -267,7 +267,7 @@ } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "999999999990902496", + "balance" : "999999999999742275", "code" : "0x", "nonce" : "1", "storage" : { @@ -552,14 +552,14 @@ } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "261077", + "balance" : "261097", "code" : "0x", "nonce" : "0", "storage" : { } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "999999999999638923", + "balance" : "999999999999638903", "code" : "0x", "nonce" : "1", "storage" : { @@ -584,7 +584,7 @@ }, "transaction" : { "data" : "", - "gasLimit" : "365223", + "gasLimit" : "365243", "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -610,19 +610,19 @@ "code" : "0x600160005401600055600060006000600060003060e05a03f1600155", "nonce" : "0", "storage" : { - "0x" : "0x03ff", + "0x" : "0x0400", "0x01" : "0x01" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "261078", + "balance" : "260996", "code" : "0x", "nonce" : "0", "storage" : { } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "999999999999638922", + "balance" : "999999999999639004", "code" : "0x", "nonce" : "1", "storage" : { @@ -647,7 +647,7 @@ }, "transaction" : { "data" : "", - "gasLimit" : "365224", + "gasLimit" : "365244", "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -673,19 +673,19 @@ "code" : "0x600160005401600055600060006000600060003060e05a03f1600155", "nonce" : "0", "storage" : { - "0x" : "0x0400", + "0x" : "0x0401", "0x01" : "0x01" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "895752", + "balance" : "261250", "code" : "0x", "nonce" : "0", "storage" : { } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "999999999999004248", + "balance" : "999999999999638750", "code" : "0x", "nonce" : "1", "storage" : { @@ -4166,11 +4166,10 @@ "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000604060406000601773945304eb96065b2a98b57a48a06ae28d285a71b56103e8f1600055", "nonce" : "0", "storage" : { - "0x" : "0x01" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "1165", + "balance" : "1636", "code" : "0x", "nonce" : "0", "storage" : { @@ -4181,11 +4180,10 @@ "code" : "0x60003554156009570060203560003555", "nonce" : "0", "storage" : { - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" : "0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa" } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "999999999999898835", + "balance" : "999999999999898364", "code" : "0x", "nonce" : "1", "storage" : { @@ -4243,11 +4241,10 @@ "code" : "0x7feeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000620f120660406000601773945304eb96065b2a98b57a48a06ae28d285a71b56101f4f1600055", "nonce" : "0", "storage" : { - "0x" : "0x01" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "1165", + "balance" : "1136", "code" : "0x", "nonce" : "0", "storage" : { @@ -4258,11 +4255,10 @@ "code" : "0x60003554156009570060203560003555", "nonce" : "0", "storage" : { - "0xeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00" : "0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa" } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "999999999999898835", + "balance" : "999999999999898864", "code" : "0x", "nonce" : "1", "storage" : { @@ -4320,11 +4316,10 @@ "code" : "0x7feeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa602052600060406000620f1206601773945304eb96065b2a98b57a48a06ae28d285a71b56101f4f1600055", "nonce" : "0", "storage" : { - "0x" : "0x01" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "965", + "balance" : "1136", "code" : "0x", "nonce" : "0", "storage" : { @@ -4338,7 +4333,7 @@ } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "999999999999899035", + "balance" : "999999999999898864", "code" : "0x", "nonce" : "1", "storage" : { @@ -4678,6 +4673,81 @@ "value" : "100000" } }, + "CallToNameRegistratorZeorSizeMemExpansion" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000099977", + "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000600060006000601773945304eb96065b2a98b57a48a06ae28d285a71b56103e8f1600055", + "nonce" : "0", + "storage" : { + } + }, + "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { + "balance" : "1636", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "46", + "code" : "0x60003554156009570060203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999999999898364", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000600060006000601773945304eb96065b2a98b57a48a06ae28d285a71b56103e8f1600055", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x60003554156009570060203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "", + "gasLimit" : "10000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000" + } + }, "CallToReturn1" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", @@ -4848,18 +4918,17 @@ "code" : "0x60003554156009570060203560003555", "nonce" : "0", "storage" : { - "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa" : "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "1149", + "balance" : "1000000", "code" : "0x", "nonce" : "0", "storage" : { } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "999999999999898851", + "balance" : "999999999998900000", "code" : "0x", "nonce" : "1", "storage" : { @@ -4892,6 +4961,68 @@ "value" : "100000" } }, + "callValue" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000100000", + "code" : "0x34600055", + "nonce" : "0", + "storage" : { + "0x" : "0x0186a0" + } + }, + "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { + "balance" : "802", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999999999899198", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "code" : "0x34600055", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "", + "gasLimit" : "10000000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000" + } + }, "callcodeToNameRegistrator0" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", @@ -4910,12 +5041,10 @@ "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000604060406000601773945304eb96065b2a98b57a48a06ae28d285a71b56103e8f2600055", "nonce" : "0", "storage" : { - "0x" : "0x01", - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" : "0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa" } }, "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "1165", + "balance" : "1636", "code" : "0x", "nonce" : "0", "storage" : { @@ -4929,7 +5058,7 @@ } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "999999999999898835", + "balance" : "999999999999898364", "code" : "0x", "nonce" : "1", "storage" : { @@ -4969,6 +5098,81 @@ "value" : "100000" } }, + "callcodeToNameRegistratorZeroMemExpanion" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000100000", + "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000600060006000601773945304eb96065b2a98b57a48a06ae28d285a71b56103e8f2600055", + "nonce" : "0", + "storage" : { + } + }, + "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { + "balance" : "1636", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x60003554156009570060203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999999999898364", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000600060006000601773945304eb96065b2a98b57a48a06ae28d285a71b56103e8f2600055", + "nonce" : "0", + "storage" : { + } + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x60003554156009570060203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "", + "gasLimit" : "1000000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000" + } + }, "callcodeToReturn1" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", @@ -5046,6 +5250,68 @@ "value" : "100000" } }, + "callerAccountBalance" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000100000", + "code" : "0x3331600055", + "nonce" : "0", + "storage" : { + "0x" : "0x0de0b6b3a6c9e2e0" + } + }, + "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { + "balance" : "822", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999999999899178", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "code" : "0x3331600055", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "", + "gasLimit" : "10000000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000" + } + }, "callstatelessToReturn1" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", @@ -5367,6 +5633,68 @@ "value" : "100000" } }, + "currentAccountBalance" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000100000", + "code" : "0x3031600055", + "nonce" : "0", + "storage" : { + "0x" : "0x0de0b6b3a76586a0" + } + }, + "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { + "balance" : "822", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "999999999999899178", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "code" : "0x3031600055", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "", + "gasLimit" : "10000000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000" + } + }, "return0" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", diff --git a/tests/files/StateTests/stTransactionTest.json b/tests/files/StateTests/stTransactionTest.json index 0de8507979..56f43a7333 100644 --- a/tests/files/StateTests/stTransactionTest.json +++ b/tests/files/StateTests/stTransactionTest.json @@ -1,4 +1,156 @@ { + "ContractStoreClearsOOG" : { + "env" : { + "currentCoinbase" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "currentDifficulty" : "45678256", + "currentGasLimit" : "10000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "6390", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + }, + "b94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "600", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "d2571607e241ecf590ed94b12d87c94babe36db6" : { + "balance" : "10", + "code" : "0x600060005560006001556000600255600060035560006004556000600555600060065560006007556000600855600c600955", + "nonce" : "0", + "storage" : { + "0x" : "0x0c", + "0x01" : "0x0c", + "0x02" : "0x0c", + "0x03" : "0x0c", + "0x04" : "0x0c", + "0x05" : "0x0c", + "0x06" : "0x0c", + "0x07" : "0x0c", + "0x08" : "0x0c", + "0x09" : "0x0c" + } + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "7000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "d2571607e241ecf590ed94b12d87c94babe36db6" : { + "balance" : "0", + "code" : "0x600060005560006001556000600255600060035560006004556000600555600060065560006007556000600855600c600955", + "nonce" : "0", + "storage" : { + "0x" : "0x0c", + "0x01" : "0x0c", + "0x02" : "0x0c", + "0x03" : "0x0c", + "0x04" : "0x0c", + "0x05" : "0x0c", + "0x06" : "0x0c", + "0x07" : "0x0c", + "0x08" : "0x0c", + "0x09" : "0x0c" + } + } + }, + "transaction" : { + "data" : "", + "gasLimit" : "600", + "gasPrice" : "1", + "nonce" : "", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "d2571607e241ecf590ed94b12d87c94babe36db6", + "value" : "10" + } + }, + "ContractStoreClearsSuccess" : { + "env" : { + "currentCoinbase" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "currentDifficulty" : "45678256", + "currentGasLimit" : "10000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "6730", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + }, + "b94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "260", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "d2571607e241ecf590ed94b12d87c94babe36db6" : { + "balance" : "10", + "code" : "0x6000600055600060015560006002556000600355600060045560006005556000600655600060075560006008556000600955", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "7000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "d2571607e241ecf590ed94b12d87c94babe36db6" : { + "balance" : "0", + "code" : "0x6000600055600060015560006002556000600355600060045560006005556000600655600060075560006008556000600955", + "nonce" : "0", + "storage" : { + "0x" : "0x0c", + "0x01" : "0x0c", + "0x02" : "0x0c", + "0x03" : "0x0c", + "0x04" : "0x0c", + "0x05" : "0x0c", + "0x06" : "0x0c", + "0x07" : "0x0c", + "0x08" : "0x0c", + "0x09" : "0x0c" + } + } + }, + "transaction" : { + "data" : "", + "gasLimit" : "600", + "gasPrice" : "1", + "nonce" : "", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "d2571607e241ecf590ed94b12d87c94babe36db6", + "value" : "10" + } + }, "EmptyTransaction" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", @@ -273,5 +425,59 @@ "to" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b", "value" : "502" } + }, + "TransactionTooManyRlpElements" : { + "env" : { + "currentCoinbase" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "currentDifficulty" : "45678256", + "currentGasLimit" : "10000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "logs" : [ + ], + "out" : "0x", + "post" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "93990", + "code" : "0x", + "nonce" : "1", + "storage" : { + } + }, + "b94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "6000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "d2571607e241ecf590ed94b12d87c94babe36db6" : { + "balance" : "10", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "", + "gasLimit" : "1600", + "gasPrice" : "12", + "nonce" : "", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "d2571607e241ecf590ed94b12d87c94babe36db6", + "value" : "10" + } } } \ No newline at end of file diff --git a/tests/files/TrieTests/trietest.json b/tests/files/TrieTests/trietest.json index ce5c2d191b..d871a8a813 100644 --- a/tests/files/TrieTests/trietest.json +++ b/tests/files/TrieTests/trietest.json @@ -12,6 +12,61 @@ ], "root": "0x5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84" }, + "branchingTests": { + "in":[ + ["0x04110d816c380812a427968ece99b1c963dfbce6", "something"], + ["0x095e7baea6a6c7c4c2dfeb977efac326af552d87", "something"], + ["0x0a517d755cebbf66312b30fff713666a9cb917e0", "something"], + ["0x24dd378f51adc67a50e339e8031fe9bd4aafab36", "something"], + ["0x293f982d000532a7861ab122bdc4bbfd26bf9030", "something"], + ["0x2cf5732f017b0cf1b1f13a1478e10239716bf6b5", "something"], + ["0x31c640b92c21a1f1465c91070b4b3b4d6854195f", "something"], + ["0x37f998764813b136ddf5a754f34063fd03065e36", "something"], + ["0x37fa399a749c121f8a15ce77e3d9f9bec8020d7a", "something"], + ["0x4f36659fa632310b6ec438dea4085b522a2dd077", "something"], + ["0x62c01474f089b07dae603491675dc5b5748f7049", "something"], + ["0x729af7294be595a0efd7d891c9e51f89c07950c7", "something"], + ["0x83e3e5a16d3b696a0314b30b2534804dd5e11197", "something"], + ["0x8703df2417e0d7c59d063caa9583cb10a4d20532", "something"], + ["0x8dffcd74e5b5923512916c6a64b502689cfa65e1", "something"], + ["0x95a4d7cccb5204733874fa87285a176fe1e9e240", "something"], + ["0x99b2fcba8120bedd048fe79f5262a6690ed38c39", "something"], + ["0xa4202b8b8afd5354e3e40a219bdc17f6001bf2cf", "something"], + ["0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "something"], + ["0xa9647f4a0a14042d91dc33c0328030a7157c93ae", "something"], + ["0xaa6cffe5185732689c18f37a7f86170cb7304c2a", "something"], + ["0xaae4a2e3c51c04606dcb3723456e58f3ed214f45", "something"], + ["0xc37a43e940dfb5baf581a0b82b351d48305fc885", "something"], + ["0xd2571607e241ecf590ed94b12d87c94babe36db6", "something"], + ["0xf735071cbee190d76b704ce68384fc21e389fbe7", "something"], + ["0x04110d816c380812a427968ece99b1c963dfbce6", null], + ["0x095e7baea6a6c7c4c2dfeb977efac326af552d87", null], + ["0x0a517d755cebbf66312b30fff713666a9cb917e0", null], + ["0x24dd378f51adc67a50e339e8031fe9bd4aafab36", null], + ["0x293f982d000532a7861ab122bdc4bbfd26bf9030", null], + ["0x2cf5732f017b0cf1b1f13a1478e10239716bf6b5", null], + ["0x31c640b92c21a1f1465c91070b4b3b4d6854195f", null], + ["0x37f998764813b136ddf5a754f34063fd03065e36", null], + ["0x37fa399a749c121f8a15ce77e3d9f9bec8020d7a", null], + ["0x4f36659fa632310b6ec438dea4085b522a2dd077", null], + ["0x62c01474f089b07dae603491675dc5b5748f7049", null], + ["0x729af7294be595a0efd7d891c9e51f89c07950c7", null], + ["0x83e3e5a16d3b696a0314b30b2534804dd5e11197", null], + ["0x8703df2417e0d7c59d063caa9583cb10a4d20532", null], + ["0x8dffcd74e5b5923512916c6a64b502689cfa65e1", null], + ["0x95a4d7cccb5204733874fa87285a176fe1e9e240", null], + ["0x99b2fcba8120bedd048fe79f5262a6690ed38c39", null], + ["0xa4202b8b8afd5354e3e40a219bdc17f6001bf2cf", null], + ["0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", null], + ["0xa9647f4a0a14042d91dc33c0328030a7157c93ae", null], + ["0xaa6cffe5185732689c18f37a7f86170cb7304c2a", null], + ["0xaae4a2e3c51c04606dcb3723456e58f3ed214f45", null], + ["0xc37a43e940dfb5baf581a0b82b351d48305fc885", null], + ["0xd2571607e241ecf590ed94b12d87c94babe36db6", null], + ["0xf735071cbee190d76b704ce68384fc21e389fbe7", null] + ], + "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + }, "jeff": { "in": [ ["0x0000000000000000000000000000000000000000000000000000000000000045", "0x22b224a1420a802ab51d326e29fa98e34c4f24ea"], diff --git a/tests/files/VMTests/RandomTests/201412232335.json b/tests/files/VMTests/RandomTests/201412232335.json new file mode 100644 index 0000000000..e9894c621f --- /dev/null +++ b/tests/files/VMTests/RandomTests/201412232335.json @@ -0,0 +1,46 @@ +{ + "randomVMtest" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x67f1821654409b73036481f36613", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9998", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x67f1821654409b73036481f36613", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x67f1821654409b73036481f36613", + "nonce" : "0", + "storage" : { + } + } + } + } +} diff --git a/tests/files/VMTests/vmArithmeticTest.json b/tests/files/VMTests/vmArithmeticTest.json index 88d209dfaf..9d7cac99fc 100644 --- a/tests/files/VMTests/vmArithmeticTest.json +++ b/tests/files/VMTests/vmArithmeticTest.json @@ -1114,6 +1114,3634 @@ } } }, + "expPowerOf256Of256_0" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60006101000a6101000a600055600060ff0a6101000a60015560006101010a6101000a60025560006101000a60ff0a600355600060ff0a60ff0a60045560006101010a60ff0a60055560006101000a6101010a600655600060ff0a6101010a60075560006101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7237", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60006101000a6101000a600055600060ff0a6101000a60015560006101010a6101000a60025560006101000a60ff0a600355600060ff0a60ff0a60045560006101010a60ff0a60055560006101000a6101010a600655600060ff0a6101010a60075560006101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x" : "0x0100", + "0x01" : "0x0100", + "0x02" : "0x0100", + "0x03" : "0xff", + "0x04" : "0xff", + "0x05" : "0xff", + "0x06" : "0x0101", + "0x07" : "0x0101", + "0x08" : "0x0101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60006101000a6101000a600055600060ff0a6101000a60015560006101010a6101000a60025560006101000a60ff0a600355600060ff0a60ff0a60045560006101010a60ff0a60055560006101000a6101010a600655600060ff0a6101010a60075560006101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_1" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60016101000a6101000a600055600160ff0a6101000a60015560016101010a6101000a60025560016101000a60ff0a600355600160ff0a60ff0a60045560016101010a60ff0a60055560016101000a6101010a600655600160ff0a6101010a60075560016101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7822", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60016101000a6101000a600055600160ff0a6101000a60015560016101010a6101000a60025560016101000a60ff0a600355600160ff0a60ff0a60045560016101010a60ff0a60055560016101000a6101010a600655600160ff0a6101010a60075560016101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x06c3acd330b959ad6efabce6d2d2125e73a88a65a9880d203dddf5957f7f0001", + "0x04" : "0x8f965a06da0ac41dcb3a34f1d8ab7d8fee620a94faa42c395997756b007ffeff", + "0x05" : "0xbce9265d88a053c18bc229ebff404c1534e1db43de85131da0179fe9ff8100ff", + "0x06" : "0x02b5e9d7a094c19f5ebdd4f2e618f859ed15e4f1f0351f286bf849eb7f810001", + "0x07" : "0xc73b7a6f68385c653a24993bb72eea0e4ba17470816ec658cf9c5bedfd81ff01", + "0x08" : "0xb89fc178355660fe1c92c7d8ff11524702fad6e2255447946442356b00810101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60016101000a6101000a600055600160ff0a6101000a60015560016101010a6101000a60025560016101000a60ff0a600355600160ff0a60ff0a60045560016101010a60ff0a60055560016101000a6101010a600655600160ff0a6101010a60075560016101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_10" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600a6101000a6101000a600055600a60ff0a6101000a600155600a6101010a6101000a600255600a6101000a60ff0a600355600a60ff0a60ff0a600455600a6101010a60ff0a600555600a6101000a6101010a600655600a60ff0a6101010a600755600a6101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7741", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600a6101000a6101000a600055600a60ff0a6101000a600155600a6101010a6101000a600255600a6101000a60ff0a600355600a60ff0a60ff0a600455600a6101010a60ff0a600555600a6101000a6101010a600655600a60ff0a6101010a600755600a6101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0xfe0f60957dc223578a0298879ec55c33085514ff7f0000000000000000000001", + "0x04" : "0xc1ea45f348b5d351c4d8fe5c77da979cadc33d866acc42e981278896b1f600ff", + "0x05" : "0x56ddb29bca94fb986ac0a40188b3b53f3216b3559bd8324a77ea8bd8a80a00ff", + "0x06" : "0x2d49ff6b0bbe177ae9317000b68fb921f7aa6aff810000000000000000000001", + "0x07" : "0x185fa9eab94cfe3016b69657e83b23fd24cc6960218254231c3db627a7f60101", + "0x08" : "0xa7a0223829f26d6c635368034320563df4aa5eb62efc87a42bb35f69b20a0101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600a6101000a6101000a600055600a60ff0a6101000a600155600a6101010a6101000a600255600a6101000a60ff0a600355600a60ff0a60ff0a600455600a6101010a60ff0a600555600a6101000a6101010a600655600a60ff0a6101010a600755600a6101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_11" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600b6101000a6101000a600055600b60ff0a6101000a600155600b6101010a6101000a600255600b6101000a60ff0a600355600b60ff0a60ff0a600455600b6101010a60ff0a600555600b6101000a6101010a600655600b60ff0a6101010a600755600b6101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7732", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600b6101000a6101000a600055600b60ff0a6101000a600155600b6101010a6101000a600255600b6101000a60ff0a600355600b60ff0a60ff0a600455600b6101010a60ff0a600555600b6101000a6101010a600655600b60ff0a6101010a600755600b6101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0xe1440264b8ee0cea0218879ec55c33085514ff7f000000000000000000000001", + "0x04" : "0x29575fdce377b23043e489e358581474bc863187fa85f9945473a2be5889feff", + "0x05" : "0x3df8c030ec521fb109c4d887dbbc14c7c9c9921b27058e3503971b60b18b00ff", + "0x06" : "0x67799740340daf4a30f000b68fb921f7aa6aff81000000000000000000000001", + "0x07" : "0x540a4e4635b40585e09ff10b63ffe310dd717fca5c0a51570091e25e378bff01", + "0x08" : "0xdbbaef5c49ffee61b08cde6ebc8dba6e9a62d56c2355d1980cb9e790bc8b0101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600b6101000a6101000a600055600b60ff0a6101000a600155600b6101010a6101000a600255600b6101000a60ff0a600355600b60ff0a60ff0a600455600b6101010a60ff0a600555600b6101000a6101010a600655600b60ff0a6101010a600755600b6101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_12" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600c6101000a6101000a600055600c60ff0a6101000a600155600c6101010a6101000a600255600c6101000a60ff0a600355600c60ff0a60ff0a600455600c6101010a60ff0a600555600c6101000a6101010a600655600c60ff0a6101010a600755600c6101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7723", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600c6101000a6101000a600055600c60ff0a6101000a600155600c6101010a6101000a600255600c6101000a60ff0a600355600c60ff0a60ff0a600455600c6101010a60ff0a600555600c6101000a6101010a600655600c60ff0a6101010a600755600c6101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0xb0e95b83a36ce98218879ec55c33085514ff7f00000000000000000000000001", + "0x04" : "0xc482ab56ec19186dc48c88f30861a850b2253b1ea6dc021589e569bd47f400ff", + "0x05" : "0xcf45c7f9af4bbe4a83055b55b97777ad5e0a3f08b129c9ae208c5d713c0c00ff", + "0x06" : "0xa5cbb62a421049b0f000b68fb921f7aa6aff8100000000000000000000000001", + "0x07" : "0x3bde6ca66dffe1bf5d727c3edea74c7a4af43b3912e6256d37705c8f3bf40101", + "0x08" : "0x3f49a1e40c5213aa4ffed57eb4c1ad2d181b2aaa289e9d59c2256c43480c0101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600c6101000a6101000a600055600c60ff0a6101000a600155600c6101010a6101000a600255600c6101000a60ff0a600355600c60ff0a60ff0a600455600c6101010a60ff0a600555600c6101000a6101010a600655600c60ff0a6101010a600755600c6101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_13" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600d6101000a6101000a600055600d60ff0a6101000a600155600d6101010a6101000a600255600d6101000a60ff0a600355600d60ff0a60ff0a600455600d6101010a60ff0a600555600d6101000a6101010a600655600d60ff0a6101010a600755600d6101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7714", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600d6101000a6101000a600055600d60ff0a6101000a600155600d6101010a6101000a600255600d6101000a60ff0a600355600d60ff0a60ff0a600455600d6101010a60ff0a600555600d6101000a6101010a600655600d60ff0a6101010a600755600d6101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0xe02639036c698218879ec55c33085514ff7f0000000000000000000000000001", + "0x04" : "0x8be664bde946d939ce551b948b503787942d2a7734509288c1b62fd5c48bfeff", + "0x05" : "0xa923a28e7a75aef26c51580ffc686879e4a0b404b089bdbcd751d88b478d00ff", + "0x06" : "0x41ac5ea30fc9b0f000b68fb921f7aa6aff810000000000000000000000000001", + "0x07" : "0x0daa3a177ec975cb69bb4acf4a6e1be7bcc1ad33d1ffad97510f9fea9d8dff01", + "0x08" : "0x19e6822beb889be28310060f4fb9741bfd50a31fa81ec65de21f7b02548d0101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600d6101000a6101000a600055600d60ff0a6101000a600155600d6101010a6101000a600255600d6101000a60ff0a600355600d60ff0a60ff0a600455600d6101010a60ff0a600555600d6101000a6101010a600655600d60ff0a6101010a600755600d6101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_14" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600e6101000a6101000a600055600e60ff0a6101000a600155600e6101010a6101000a600255600e6101000a60ff0a600355600e60ff0a60ff0a600455600e6101010a60ff0a600555600e6101000a6101010a600655600e60ff0a6101010a600755600e6101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7705", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600e6101000a6101000a600055600e60ff0a6101000a600155600e6101010a6101000a600255600e6101000a60ff0a600355600e60ff0a60ff0a600455600e6101010a60ff0a600555600e6101000a6101010a600655600e60ff0a6101010a600755600e6101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0xdb9902ec698218879ec55c33085514ff7f000000000000000000000000000001", + "0x04" : "0x83fab06c6c8fef761ebbb9534c06ac2a9d61820623008069062ff3b1e1f200ff", + "0x05" : "0x3f791dd183ed5b963bd86e0dba1a9dd5b8ceeb078f15c73062f1942fd40e00ff", + "0x06" : "0xe0bfa28fc9b0f000b68fb921f7aa6aff81000000000000000000000000000001", + "0x07" : "0x8133b760dfae27560eb490f235ddfa301f058dee4f01f3fe4b3567d0d3f20101", + "0x08" : "0xcd4cd0124e983af71620fb5f98275965c6a8bebc4b8adc288b63224ee20e0101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600e6101000a6101000a600055600e60ff0a6101000a600155600e6101010a6101000a600255600e6101000a60ff0a600355600e60ff0a60ff0a600455600e6101010a60ff0a600555600e6101000a6101010a600655600e60ff0a6101010a600755600e6101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_15" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600f6101000a6101000a600055600f60ff0a6101000a600155600f6101010a6101000a600255600f6101000a60ff0a600355600f60ff0a60ff0a600455600f6101010a60ff0a600555600f6101000a6101010a600655600f60ff0a6101010a600755600f6101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7696", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600f6101000a6101000a600055600f60ff0a6101000a600155600f6101010a6101000a600255600f6101000a60ff0a600355600f60ff0a60ff0a600455600f6101010a60ff0a600555600f6101000a6101010a600655600f60ff0a6101010a600755600f6101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x9882ec698218879ec55c33085514ff7f00000000000000000000000000000001", + "0x04" : "0x75c4915e18b96704209738f5ca765568bb4dc4113d56683977825a132c8dfeff", + "0x05" : "0x5c76839bf5a80b1da705dbdf43e4dd6770cd7501af11ff2dab7918dfe18f00ff", + "0x06" : "0xbf228fc9b0f000b68fb921f7aa6aff8100000000000000000000000000000001", + "0x07" : "0xc6a29131e7594004bc2aa79f0d2c402a1409c57c77d284c14b1a3ab0ff8fff01", + "0x08" : "0xe6b3e5cf6ec90e532fef7d08455ebf92a03e9e3f6e224ea0febdf1a9f08f0101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600f6101000a6101000a600055600f60ff0a6101000a600155600f6101010a6101000a600255600f6101000a60ff0a600355600f60ff0a60ff0a600455600f6101010a60ff0a600555600f6101000a6101010a600655600f60ff0a6101010a600755600f6101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_16" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60106101000a6101000a600055601060ff0a6101000a60015560106101010a6101000a60025560106101000a60ff0a600355601060ff0a60ff0a60045560106101010a60ff0a60055560106101000a6101010a600655601060ff0a6101010a60075560106101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7687", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60106101000a6101000a600055601060ff0a6101000a60015560106101010a6101000a60025560106101000a60ff0a600355601060ff0a60ff0a60045560106101010a60ff0a60055560106101000a6101010a600655601060ff0a6101010a60075560106101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x82ec698218879ec55c33085514ff7f0000000000000000000000000000000001", + "0x04" : "0x3122f4bcdf6dd8b265cd18eb6af28c879aed44a35e0bf59273e39e6c7ff000ff", + "0x05" : "0x6a2b3bc87a02c29b9d27757df43047ecd0f15485270fca27417a701c701000ff", + "0x06" : "0x228fc9b0f000b68fb921f7aa6aff810000000000000000000000000000000001", + "0x07" : "0x88e1259502eef93d46060aacc9e2ff506c734dade0b6714ab12d17e46ff00101", + "0x08" : "0x4a103813c12c12169b218296bb0a9eae80cf8d2b158aa70eb990f99480100101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60106101000a6101000a600055601060ff0a6101000a60015560106101010a6101000a60025560106101000a60ff0a600355601060ff0a60ff0a60045560106101010a60ff0a60055560106101000a6101010a600655601060ff0a6101010a60075560106101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_17" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60116101000a6101000a600055601160ff0a6101000a60015560116101010a6101000a60025560116101000a60ff0a600355601160ff0a60ff0a60045560116101010a60ff0a60055560116101000a6101010a600655601160ff0a6101010a60075560116101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7678", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60116101000a6101000a600055601160ff0a6101000a60015560116101010a6101000a60025560116101000a60ff0a600355601160ff0a60ff0a60045560116101010a60ff0a60055560116101000a6101010a600655601160ff0a6101010a60075560116101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0xec698218879ec55c33085514ff7f000000000000000000000000000000000001", + "0x04" : "0x722ad218eb1995a2d257c4c06d8de993c203cfc8e3512df7d633e17e908ffeff", + "0x05" : "0x8ac9b5ec08d74612cb29f941481d274b51721af2296207c0da8d24667f9100ff", + "0x06" : "0x8fc9b0f000b68fb921f7aa6aff81000000000000000000000000000000000001", + "0x07" : "0x81d5ff63680841482299f3eab616446dcd336f537c0c565aa4112ab95d91ff01", + "0x08" : "0x9c6ca90dac4e97dea02ac969e8649ee9e6232e0c3f4797411151cb8f90910101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60116101000a6101000a600055601160ff0a6101000a60015560116101010a6101000a60025560116101000a60ff0a600355601160ff0a60ff0a60045560116101010a60ff0a60055560116101000a6101010a600655601160ff0a6101010a60075560116101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_18" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60126101000a6101000a600055601260ff0a6101000a60015560126101010a6101000a60025560126101000a60ff0a600355601260ff0a60ff0a60045560126101010a60ff0a60055560126101000a6101010a600655601260ff0a6101010a60075560126101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7669", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60126101000a6101000a600055601260ff0a6101000a60015560126101010a6101000a60025560126101000a60ff0a600355601260ff0a60ff0a60045560126101010a60ff0a60055560126101000a6101010a600655601260ff0a6101010a60075560126101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x698218879ec55c33085514ff7f00000000000000000000000000000000000001", + "0x04" : "0x8a2cbd9f40794e2205b13306f2aa0a43c60823c64b95d8601fa4f1e521ee00ff", + "0x05" : "0xc1b5a1e3a81da51b10d84e880f0113ff67b863ddad3faf1f4ecf413f101200ff", + "0x06" : "0xc9b0f000b68fb921f7aa6aff8100000000000000000000000000000000000001", + "0x07" : "0x410be68e49452a1fbcd863bf6e8d637f8eae4979c34c88d552afbcc20fee0101", + "0x08" : "0xf540cb714754b5b1eb0373833833bd7fb0ee925ce8b92962500b7a1c22120101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60126101000a6101000a600055601260ff0a6101000a60015560126101010a6101000a60025560126101000a60ff0a600355601260ff0a60ff0a60045560126101010a60ff0a60055560126101000a6101010a600655601260ff0a6101010a60075560126101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_19" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60136101000a6101000a600055601360ff0a6101000a60015560136101010a6101000a60025560136101000a60ff0a600355601360ff0a60ff0a60045560136101010a60ff0a60055560136101000a6101010a600655601360ff0a6101010a60075560136101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7660", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60136101000a6101000a600055601360ff0a6101000a60015560136101010a6101000a60025560136101000a60ff0a600355601360ff0a60ff0a60045560136101010a60ff0a60055560136101000a6101010a600655601360ff0a6101010a60075560136101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x8218879ec55c33085514ff7f0000000000000000000000000000000000000001", + "0x04" : "0xb795ad7ac24cfbb7435cf53bd3584f3d4b2709935635c3ceb66e761ff091feff", + "0x05" : "0x1f0bb7be91a0ccd0cca93d75cf03de3e6b56fe8f1c54242617665327219300ff", + "0x06" : "0xb0f000b68fb921f7aa6aff810000000000000000000000000000000000000001", + "0x07" : "0xad571756ecbff1bfdef064861e5e92c5d897a9cc380e54bdbaabd80bb793ff01", + "0x08" : "0xd8b5b531989e689f700dcdb43ab90e79a49dfbbb5a13dbf751df98bb34930101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60136101000a6101000a600055601360ff0a6101000a60015560136101010a6101000a60025560136101000a60ff0a600355601360ff0a60ff0a60045560136101010a60ff0a60055560136101000a6101010a600655601360ff0a6101010a60075560136101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_2" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60026101000a6101000a600055600260ff0a6101000a60015560026101010a6101000a60025560026101000a60ff0a600355600260ff0a60ff0a60045560026101010a60ff0a60055560026101000a6101010a600655600260ff0a6101010a60075560026101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7813", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60026101000a6101000a600055600260ff0a6101000a60015560026101010a6101000a60025560026101000a60ff0a600355600260ff0a60ff0a60045560026101010a60ff0a60055560026101000a6101010a600655600260ff0a6101010a60075560026101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x4ee4ceeaac565c81f55a87c43f82f7c889ef4fc7c679671e28d594ff7f000001", + "0x04" : "0x82f46a1b4e34d66712910615d2571d75606ceac51fa8ca8c58cf6ca881fe00ff", + "0x05" : "0x81c9fcefa5de158ae2007f25d35c0d11cd735342a48905955a5a6852800200ff", + "0x06" : "0x666ac362902470ed850709e2a29969d10cba09debc03c38d172aeaff81000001", + "0x07" : "0xeb30a3c678a01bde914548f98f3366dc0ffe9f85384ebf1111d03dad7ffe0101", + "0x08" : "0x72d0a7939b6303ce1d46e6e3f1b8be303bfdb2b00f41ad8076b0975782020101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60026101000a6101000a600055600260ff0a6101000a60015560026101010a6101000a60025560026101000a60ff0a600355600260ff0a60ff0a60045560026101010a60ff0a60055560026101000a6101010a600655600260ff0a6101010a60075560026101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_20" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60146101000a6101000a600055601460ff0a6101000a60015560146101010a6101000a60025560146101000a60ff0a600355601460ff0a60ff0a60045560146101010a60ff0a60055560146101000a6101010a600655601460ff0a6101010a60075560146101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7651", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60146101000a6101000a600055601460ff0a6101000a60015560146101010a6101000a60025560146101000a60ff0a600355601460ff0a60ff0a60045560146101010a60ff0a60055560146101000a6101010a600655601460ff0a6101010a60075560146101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x18879ec55c33085514ff7f000000000000000000000000000000000000000001", + "0x04" : "0x67e4797dc21f02ce4a7c52218c7dbea5d212e6c244e24f0ba4c08613c7ec00ff", + "0x05" : "0xa1ce1a085f258785846939cc1d2e8725ac94ad4dff8913234e00679fb41400ff", + "0x06" : "0xf000b68fb921f7aa6aff81000000000000000000000000000000000000000001", + "0x07" : "0xcce501857a1cb45473915a28082af950e0f78f7e2de68ce748adb661b3ec0101", + "0x08" : "0x3b2e28d274a16c08b58a23bad63bba6d7b09685769d1f68ca3873bedc8140101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60146101000a6101000a600055601460ff0a6101000a60015560146101010a6101000a60025560146101000a60ff0a600355601460ff0a60ff0a60045560146101010a60ff0a60055560146101000a6101010a600655601460ff0a6101010a60075560146101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_21" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60156101000a6101000a600055601560ff0a6101000a60015560156101010a6101000a60025560156101000a60ff0a600355601560ff0a60ff0a60045560156101010a60ff0a60055560156101000a6101010a600655601560ff0a6101010a60075560156101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7642", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60156101000a6101000a600055601560ff0a6101000a60015560156101010a6101000a60025560156101000a60ff0a600355601560ff0a60ff0a60045560156101010a60ff0a60055560156101000a6101010a600655601560ff0a6101010a60075560156101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x879ec55c33085514ff7f00000000000000000000000000000000000000000001", + "0x04" : "0x7fd07055ff50cdfe4b4bd9a15133d72d3607d92eb7ac81bac93db7ff4c93feff", + "0x05" : "0x665ac5c769e87f61d5993abc26522fbfca2734d76a63216b2d550d29c79500ff", + "0x06" : "0xb68fb921f7aa6aff8100000000000000000000000000000000000000000001", + "0x07" : "0x1c93db67c9884bc694686d69a25a5d7ed089841d5ce147fdd7199ab00d95ff01", + "0x08" : "0x485053d8ff66be52036597520344fac87b6a305426a9e49221d3f934dc950101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60156101000a6101000a600055601560ff0a6101000a60015560156101010a6101000a60025560156101000a60ff0a600355601560ff0a60ff0a60045560156101010a60ff0a60055560156101000a6101010a600655601560ff0a6101010a60075560156101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_22" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60166101000a6101000a600055601660ff0a6101000a60015560166101010a6101000a60025560166101000a60ff0a600355601660ff0a60ff0a60045560166101010a60ff0a60055560166101000a6101010a600655601660ff0a6101010a60075560166101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7633", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60166101000a6101000a600055601660ff0a6101000a60015560166101010a6101000a60025560166101000a60ff0a600355601660ff0a60ff0a60045560166101010a60ff0a60055560166101000a6101010a600655601660ff0a6101010a60075560166101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x9ec55c33085514ff7f0000000000000000000000000000000000000000000001", + "0x04" : "0xec447e662ac08957d7e290a421dbf54c0aaf43aadc9cc465ad0b02f071ea00ff", + "0x05" : "0xdc9178d3bab470096f01477c859b5f4173986640b659426412a653465c1600ff", + "0x06" : "0xb68fb921f7aa6aff810000000000000000000000000000000000000000000001", + "0x07" : "0xdcf0a770777610503596ae0311af46c171151ed45107d7e7bb8f74bb5bea0101", + "0x08" : "0x4d65773387993928c95c861274232d3fb6f6b7fe1b22e4e61a30e71172160101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60166101000a6101000a600055601660ff0a6101000a60015560166101010a6101000a60025560166101000a60ff0a600355601660ff0a60ff0a60045560166101010a60ff0a60055560166101000a6101010a600655601660ff0a6101010a60075560166101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_23" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60176101000a6101000a600055601760ff0a6101000a60015560176101010a6101000a60025560176101000a60ff0a600355601760ff0a60ff0a60045560176101010a60ff0a60055560176101000a6101010a600655601760ff0a6101010a60075560176101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7624", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60176101000a6101000a600055601760ff0a6101000a60015560176101010a6101000a60025560176101000a60ff0a600355601760ff0a60ff0a60045560176101010a60ff0a60055560176101000a6101010a600655601760ff0a6101010a60075560176101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0xc55c33085514ff7f000000000000000000000000000000000000000000000001", + "0x04" : "0x537ca0f03f974303005f1e6693b55b72315a166841732e42b8353724a495feff", + "0x05" : "0x86418797ec60058de6cca47dfdbee79923ac49d7801e01840041ca76719700ff", + "0x06" : "0x8fb921f7aa6aff81000000000000000000000000000000000000000000000001", + "0x07" : "0x56a55341ab8d4318f1cfb55d5f21e2ba35d7e070a72bac6b2b21baae5f97ff01", + "0x08" : "0x55ddd0ec77909de6d8311116cf520398e816f928b06fdd90ec239d0488970101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60176101000a6101000a600055601760ff0a6101000a60015560176101010a6101000a60025560176101000a60ff0a600355601760ff0a60ff0a60045560176101010a60ff0a60055560176101000a6101010a600655601760ff0a6101010a60075560176101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_24" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60186101000a6101000a600055601860ff0a6101000a60015560186101010a6101000a60025560186101000a60ff0a600355601860ff0a60ff0a60045560186101010a60ff0a60055560186101000a6101010a600655601860ff0a6101010a60075560186101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7615", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60186101000a6101000a600055601860ff0a6101000a60015560186101010a6101000a60025560186101000a60ff0a600355601860ff0a60ff0a60045560186101010a60ff0a60055560186101000a6101010a600655601860ff0a6101010a60075560186101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x5c33085514ff7f00000000000000000000000000000000000000000000000001", + "0x04" : "0xd542e526003539ead104274aff2d78332366e29d328c2161f0c120731fe800ff", + "0x05" : "0xc706cb25e8384ce9bb5c9cb48415238ba03e16c448e292c0a101843b081800ff", + "0x06" : "0xb921f7aa6aff8100000000000000000000000000000000000000000000000001", + "0x07" : "0x4ca55f89202c524cb0f1cb3195d13c8d94a9f7a05c59e1d4031577c707e80101", + "0x08" : "0x8c4b0574e9156b80035f3ecdcf1fe79d273ed7559747a4322bcd338f20180101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60186101000a6101000a600055601860ff0a6101000a60015560186101010a6101000a60025560186101000a60ff0a600355601860ff0a60ff0a60045560186101010a60ff0a60055560186101000a6101010a600655601860ff0a6101010a60075560186101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_25" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60196101000a6101000a600055601960ff0a6101000a60015560196101010a6101000a60025560196101000a60ff0a600355601960ff0a60ff0a60045560196101010a60ff0a60055560196101000a6101010a600655601960ff0a6101010a60075560196101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7606", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60196101000a6101000a600055601960ff0a6101000a60015560196101010a6101000a60025560196101000a60ff0a600355601960ff0a60ff0a60045560196101010a60ff0a60055560196101000a6101010a600655601960ff0a6101010a60075560196101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x33085514ff7f0000000000000000000000000000000000000000000000000001", + "0x04" : "0x7f510dd7198cac0a92ff7ea80451838c0dfa12114c41a0ef05907397f897feff", + "0x05" : "0x1275e752b6aee228ecba5e9b57ef1111deff3c651e2cfbf2cccd13151f9900ff", + "0x06" : "0x21f7aa6aff810000000000000000000000000000000000000000000000000001", + "0x07" : "0x6646340ad51a03bb710caf05756b685b33c7dad62ae68d369243700ead99ff01", + "0x08" : "0x29d80e8060ef2221929bb18215586c742686d6860e028ca0456b443238990101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60196101000a6101000a600055601960ff0a6101000a60015560196101010a6101000a60025560196101000a60ff0a600355601960ff0a60ff0a60045560196101010a60ff0a60055560196101000a6101010a600655601960ff0a6101010a60075560196101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_26" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x601a6101000a6101000a600055601a60ff0a6101000a600155601a6101010a6101000a600255601a6101000a60ff0a600355601a60ff0a60ff0a600455601a6101010a60ff0a600555601a6101000a6101010a600655601a60ff0a6101010a600755601a6101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7597", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601a6101000a6101000a600055601a60ff0a6101000a600155601a6101010a6101000a600255601a6101000a60ff0a600355601a60ff0a60ff0a600455601a6101010a60ff0a600555601a6101000a6101010a600655601a60ff0a6101010a600755601a6101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x085514ff7f000000000000000000000000000000000000000000000000000001", + "0x04" : "0x1d164db738eb6893868b361ad2803f97be35764456e82a837667a693d1e600ff", + "0x05" : "0x8b92c24abebf376a5aab5ff4dfd3538a03d38a10bced2aae8e1a8a85b81a00ff", + "0x06" : "0xf7aa6aff81000000000000000000000000000000000000000000000000000001", + "0x07" : "0x6931bda98c70e860a1f6a5224940f1ec7e6734cd9456c95806384f7cb7e60101", + "0x08" : "0x3402a9db66492dfc2a220715e76243469462f24edc56903ba1d8e96ed21a0101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601a6101000a6101000a600055601a60ff0a6101000a600155601a6101010a6101000a600255601a6101000a60ff0a600355601a60ff0a60ff0a600455601a6101010a60ff0a600555601a6101000a6101010a600655601a60ff0a6101010a600755601a6101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_27" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x601b6101000a6101000a600055601b60ff0a6101000a600155601b6101010a6101000a600255601b6101000a60ff0a600355601b60ff0a60ff0a600455601b6101010a60ff0a600555601b6101000a6101010a600655601b60ff0a6101010a600755601b6101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7588", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601b6101000a6101000a600055601b60ff0a6101000a600155601b6101010a6101000a600255601b6101000a60ff0a600355601b60ff0a60ff0a600455601b6101010a60ff0a600555601b6101000a6101010a600655601b60ff0a6101010a600755601b6101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x5514ff7f00000000000000000000000000000000000000000000000000000001", + "0x04" : "0x178918ffbcb401d4efd2f7dfb4d01a897172267f0f491121ac52dd614899feff", + "0x05" : "0x38ecff71480ca0b422f2ed6f780d5fead2ae234a49104b10a86f7f0dd19b00ff", + "0x06" : "0xaa6aff8100000000000000000000000000000000000000000000000000000001", + "0x07" : "0xd02811cb5dc1d80567e810532b235b7672f5c78cd6e89bb511d5e2d8f79bff01", + "0x08" : "0x1b4e6404f474c18055d30bb8987672f59e97980d6f9de1764c0fbec5ec9b0101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601b6101000a6101000a600055601b60ff0a6101000a600155601b6101010a6101000a600255601b6101000a60ff0a600355601b60ff0a60ff0a600455601b6101010a60ff0a600555601b6101000a6101010a600655601b60ff0a6101010a600755601b6101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_28" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x601c6101000a6101000a600055601c60ff0a6101000a600155601c6101010a6101000a600255601c6101000a60ff0a600355601c60ff0a60ff0a600455601c6101010a60ff0a600555601c6101000a6101010a600655601c60ff0a6101010a600755601c6101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7579", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601c6101000a6101000a600055601c60ff0a6101000a600155601c6101010a6101000a600255601c6101000a60ff0a600355601c60ff0a60ff0a600455601c6101010a60ff0a600555601c6101000a6101010a600655601c60ff0a6101010a600755601c6101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x14ff7f0000000000000000000000000000000000000000000000000000000001", + "0x04" : "0xffd368e44b3f85cb81ae394c9809ca9fa2db46a83d7880a912ab6d4a87e400ff", + "0x05" : "0x0981ad53c19b15a94bcf0bf20235dd0da9df25f46ae635029fe2062e6c1c00ff", + "0x06" : "0x6aff810000000000000000000000000000000000000000000000000000000001", + "0x07" : "0x19df06ffa28250867006726405fbc05d43dc2f9d2f025006db089bd46be40101", + "0x08" : "0x243fffe3a4f2982f45055c08f379648ab886da8027a7401117a8e0b8881c0101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601c6101000a6101000a600055601c60ff0a6101000a600155601c6101010a6101000a600255601c6101000a60ff0a600355601c60ff0a60ff0a600455601c6101010a60ff0a600555601c6101000a6101010a600655601c60ff0a6101010a600755601c6101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_29" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x601d6101000a6101000a600055601d60ff0a6101000a600155601d6101010a6101000a600255601d6101000a60ff0a600355601d60ff0a60ff0a600455601d6101010a60ff0a600555601d6101000a6101010a600655601d60ff0a6101010a600755601d6101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7570", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601d6101000a6101000a600055601d60ff0a6101000a600155601d6101010a6101000a600255601d6101000a60ff0a600355601d60ff0a60ff0a600455601d6101010a60ff0a600555601d6101000a6101010a600655601d60ff0a6101010a600755601d6101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0xff7f000000000000000000000000000000000000000000000000000000000001", + "0x04" : "0x41e065d46e0349cfe624c4e8a2034aea1f7edfff80e511cd8067d488949bfeff", + "0x05" : "0xa84162ca6675a22c4c79dfc4ea15f760db5a04dbf04246764199b668879d00ff", + "0x06" : "0xff81000000000000000000000000000000000000000000000000000000000001", + "0x07" : "0x1226984faa6b05ebdbd45d8477fa4fd5b55bfd5061de03c319282b153d9dff01", + "0x08" : "0x5cc9e6b0b749fd94541ad00364bdec2fca7816981ca3e38f485decc7a49d0101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601d6101000a6101000a600055601d60ff0a6101000a600155601d6101010a6101000a600255601d6101000a60ff0a600355601d60ff0a60ff0a600455601d6101010a60ff0a600555601d6101000a6101010a600655601d60ff0a6101010a600755601d6101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_3" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60036101000a6101000a600055600360ff0a6101000a60015560036101010a6101000a60025560036101000a60ff0a600355600360ff0a60ff0a60045560036101010a60ff0a60055560036101000a6101010a600655600360ff0a6101010a60075560036101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7804", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60036101000a6101000a600055600360ff0a6101000a60015560036101010a6101000a60025560036101000a60ff0a600355600360ff0a60ff0a60045560036101010a60ff0a60055560036101000a6101010a600655600360ff0a6101010a60075560036101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x109a00e1370d2d2922bf892e85becb54297354b2e5c75388d514ff7f00000001", + "0x04" : "0x54a792f15e9aba7e4ad9e716bc169eea3a6e2e9c49bf9b335874613c8081feff", + "0x05" : "0x5d24a14d8e5e039372cd0f6a0f31e9ed6b75adba9f16b1c5b3edd5ba818300ff", + "0x06" : "0x298e2f316b4ccded5ebf515998d9ec20df69404b04a441782a6aff8100000001", + "0x07" : "0x4335694e98f372183c62a2339fa4ad161e9b4c42240bdc9452abffd07783ff01", + "0x08" : "0xf0f0820797315acd063056bba76f6a9c3e281cdb5197a233967ca94684830101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60036101000a6101000a600055600360ff0a6101000a60015560036101010a6101000a60025560036101000a60ff0a600355600360ff0a60ff0a60045560036101010a60ff0a60055560036101000a6101010a600655600360ff0a6101010a60075560036101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_30" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x601e6101000a6101000a600055601e60ff0a6101000a600155601e6101010a6101000a600255601e6101000a60ff0a600355601e60ff0a60ff0a600455601e6101010a60ff0a600555601e6101000a6101010a600655601e60ff0a6101010a600755601e6101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7561", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601e6101000a6101000a600055601e60ff0a6101000a600155601e6101010a6101000a600255601e6101000a60ff0a600355601e60ff0a60ff0a600455601e6101010a60ff0a600555601e6101000a6101010a600655601e60ff0a6101010a600755601e6101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x7f00000000000000000000000000000000000000000000000000000000000001", + "0x04" : "0xe9772778f50fa0a69cd10fa019ac56d72ac7a7d7af26c4ba28415c8f41e200ff", + "0x05" : "0x33f0385ef73feebdb952e5adb643dd0fa178fd9271578219ad50a73d241e00ff", + "0x06" : "0x8100000000000000000000000000000000000000000000000000000000000001", + "0x07" : "0xfd405cce8f73dffc04a6f0ff6ffc6bf7961876d09c5b4933a68f0cc623e20101", + "0x08" : "0xc5a8f4566fd2e96e4ce3a8b3ec0863e7b20bc3b2f3dc5261ba8a0174421e0101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601e6101000a6101000a600055601e60ff0a6101000a600155601e6101010a6101000a600255601e6101000a60ff0a600355601e60ff0a60ff0a600455601e6101010a60ff0a600555601e6101000a6101010a600655601e60ff0a6101010a600755601e6101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_31" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x601f6101000a6101000a600055601f60ff0a6101000a600155601f6101010a6101000a600255601f6101000a60ff0a600355601f60ff0a60ff0a600455601f6101010a60ff0a600555601f6101000a6101010a600655601f60ff0a6101010a600755601f6101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7552", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601f6101000a6101000a600055601f60ff0a6101000a600155601f6101010a6101000a600255601f6101000a60ff0a600355601f60ff0a60ff0a600455601f6101010a60ff0a600555601f6101000a6101010a600655601f60ff0a6101010a600755601f6101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x01", + "0x04" : "0xf9cb87f5b1ab58602f52a1e9d392e5675b86a59a53943a8d4ec2a915dc9dfeff", + "0x05" : "0x893d729a64e318860ec5047e70e598da163eb41e71e74b04dfd4712d419f00ff", + "0x06" : "0x01", + "0x07" : "0xee5f2839c1b4f6ca05e6fdb04e2fb49c0f860b3765c27dc781a150cb7f9fff01", + "0x08" : "0xb4c358e3c6bcddfb509ea487d733df0e1854f29c3b6bfd4a8caabe3f609f0101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601f6101000a6101000a600055601f60ff0a6101000a600155601f6101010a6101000a600255601f6101000a60ff0a600355601f60ff0a60ff0a600455601f6101010a60ff0a600555601f6101000a6101010a600655601f60ff0a6101010a600755601f6101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_32" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60206101000a6101000a600055602060ff0a6101000a60015560206101010a6101000a60025560206101000a60ff0a600355602060ff0a60ff0a60045560206101010a60ff0a60055560206101000a6101010a600655602060ff0a6101010a60075560206101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7445", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60206101000a6101000a600055602060ff0a6101000a60015560206101010a6101000a60025560206101000a60ff0a600355602060ff0a60ff0a60045560206101010a60ff0a60055560206101000a6101010a600655602060ff0a6101010a60075560206101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x" : "0x01", + "0x03" : "0x01", + "0x04" : "0xb8247842bb5ce75c08d0c251669ed5870fa24a22952e5db3a7c66c59ffe000ff", + "0x05" : "0xee526e5a06f2a990b2bf6c951e5feabf0e07ee16877296e1be872db9e02000ff", + "0x06" : "0x01", + "0x07" : "0xeda7d024b6de40a9d3b966e71f10a4667edc5b71cab07aeabcac6249dfe00101", + "0x08" : "0x512ecfaeeb11205f0833e1054dcb1300488e0954be5af77a49e143aa00200101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60206101000a6101000a600055602060ff0a6101000a60015560206101010a6101000a60025560206101000a60ff0a600355602060ff0a60ff0a60045560206101010a60ff0a60055560206101000a6101010a600655602060ff0a6101010a60075560206101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_33" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60216101000a6101000a600055602160ff0a6101000a60015560216101010a6101000a60025560216101000a60ff0a600355602160ff0a60ff0a60045560216101010a60ff0a60055560216101000a6101010a600655602160ff0a6101010a60075560216101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7445", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60216101000a6101000a600055602160ff0a6101000a60015560216101010a6101000a60025560216101000a60ff0a600355602160ff0a60ff0a60045560216101010a60ff0a60055560216101000a6101010a600655602160ff0a6101010a60075560216101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x" : "0x01", + "0x03" : "0x01", + "0x04" : "0x8dcb65b5494eba78cd6756a6f9851f6e26d0f2bb9ecd7e9abd7e9b11209ffeff", + "0x05" : "0x6694bb31b20cd625f3756897dae6d738f2e64467b5b6f10fa3e07763ffa100ff", + "0x06" : "0x01", + "0x07" : "0xe678999aeffd1f1f45081f64de7f80ab083dd7df04721ed64ee04c03bda1ff01", + "0x08" : "0x39b68fb9898dd7568abd178397251ce8226a25c1d305a4e79573333520a10101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60216101000a6101000a600055602160ff0a6101000a60015560216101010a6101000a60025560216101000a60ff0a600355602160ff0a60ff0a60045560216101010a60ff0a60055560216101000a6101010a600655602160ff0a6101010a60075560216101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_4" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60046101000a6101000a600055600460ff0a6101000a60015560046101010a6101000a60025560046101000a60ff0a600355600460ff0a60ff0a60045560046101010a60ff0a60055560046101000a6101010a600655600460ff0a6101010a60075560046101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7795", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60046101000a6101000a600055600460ff0a6101000a60015560046101010a6101000a60025560046101000a60ff0a600355600460ff0a60ff0a60045560046101010a60ff0a60055560046101000a6101010a600655600460ff0a6101010a60075560046101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0xe6540ce46eaf70da9d644015a661e0e245b13f307cb3885514ff7f0000000001", + "0x04" : "0x6526b38b05a6325b80e1c84ab41dc934fd70f33f1bd0eab3d1f61a4707fc00ff", + "0x05" : "0xe959516cd27e5d8fd487b72db2989b3ec2ba9fb7ead41554526fe5a3040400ff", + "0x06" : "0xe7498a48c6ce2530bbe814ee3440c8c44fffab7ad8a277aa6aff810000000001", + "0x07" : "0x2dffa3e901e5a392d15b79f4193d2168147d2aa7c55870b46c3a905d03fc0101", + "0x08" : "0xe16ea721c96539edb4f7fb82de0dad8cccb1e7a6966a6777635f6fb908040101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60046101000a6101000a600055600460ff0a6101000a60015560046101010a6101000a60025560046101000a60ff0a600355600460ff0a60ff0a60045560046101010a60ff0a60055560046101000a6101010a600655600460ff0a6101010a60075560046101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_5" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60056101000a6101000a600055600560ff0a6101000a60015560056101010a6101000a60025560056101000a60ff0a600355600560ff0a60ff0a60045560056101010a60ff0a60055560056101000a6101010a600655600560ff0a6101010a60075560056101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7786", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60056101000a6101000a600055600560ff0a6101000a60015560056101010a6101000a60025560056101000a60ff0a600355600560ff0a60ff0a60045560056101010a60ff0a60055560056101000a6101010a600655600560ff0a6101010a60075560056101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0xb581ac185aad71db2d177c286929c4c22809e5dcb3085514ff7f000000000001", + "0x04" : "0x75789eb2a64bc971389fbd11a1e6d7abbf95ad25e23fb9aa25e73a0bfc83feff", + "0x05" : "0xfc403fa42ceb6a0d0d3321bd9b2d8af25b1b667f87a04f496c78168d078500ff", + "0x06" : "0xcec5ec213b9cb5811f6ae00428fd7b6ef5a1af39a1f7aa6aff81000000000001", + "0x07" : "0x70ab32233202b98d382d17713fa0be391eaf74f85ba1740c9c3238c4ed85ff01", + "0x08" : "0xb622672a213faa79b32185ff93a7b27a8499e48f7b032cdb4d1a70300c850101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60056101000a6101000a600055600560ff0a6101000a60015560056101010a6101000a60025560056101000a60ff0a600355600560ff0a60ff0a60045560056101010a60ff0a60055560056101000a6101010a600655600560ff0a6101010a60075560056101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_6" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60066101000a6101000a600055600660ff0a6101000a60015560066101010a6101000a60025560066101000a60ff0a600355600660ff0a60ff0a60045560066101010a60ff0a60055560066101000a6101010a600655600660ff0a6101010a60075560066101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7777", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60066101000a6101000a600055600660ff0a6101000a60015560066101010a6101000a60025560066101000a60ff0a600355600660ff0a60ff0a60045560066101010a60ff0a60055560066101000a6101010a600655600660ff0a6101010a60075560066101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x1948059de1def03c4ec35fc22c2bb8f2bf45dc33085514ff7f00000000000001", + "0x04" : "0x41f818a8e24eb6d7bb7b193b4f2b5fdcf4bd0d453f2ac3499d8830d391fa00ff", + "0x05" : "0xede6fe4a943dfb5d967a2b85d6728759d40d2ef0ae4bc28bbb1867f98c0600ff", + "0x06" : "0x083c936cbaad5de592badc2e142fe4ebd6103921f7aa6aff8100000000000001", + "0x07" : "0x57385019fe4e0939ca3f35c37cadfaf52fba5b1cdfb02def3866e8068bfa0101", + "0x08" : "0x810ac878bd98428f6be8c6426ba9f9da09e3e33bf4fe10bfa3f8b12c92060101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60066101000a6101000a600055600660ff0a6101000a60015560066101010a6101000a60025560066101000a60ff0a600355600660ff0a60ff0a60045560066101010a60ff0a60055560066101000a6101010a600655600660ff0a6101010a60075560066101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_7" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60076101000a6101000a600055600760ff0a6101000a60015560076101010a6101000a60025560076101000a60ff0a600355600760ff0a60ff0a60045560076101010a60ff0a60055560076101000a6101010a600655600760ff0a6101010a60075560076101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7768", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60076101000a6101000a600055600760ff0a6101000a60015560076101010a6101000a60025560076101000a60ff0a600355600760ff0a60ff0a60045560076101010a60ff0a60055560076101000a6101010a600655600760ff0a6101010a60075560076101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x8bb02654111ad8c60ad8af132283a81f455c33085514ff7f0000000000000001", + "0x04" : "0xa8f75c129dbb8466d6703a2a0b8212131b3248d70e2478862ac40fe17485feff", + "0x05" : "0x5fd4d2de580383ee59f5e800ddb3f1717ceae03aede19d3dec5e5a69918700ff", + "0x06" : "0xc8624230b524b85d6340da48a5db20370fb921f7aa6aff810000000000000001", + "0x07" : "0x287b58a5a13cd7f454468ca616c181712f5ed25433a7d5a894b6ced35f87ff01", + "0x08" : "0x09930d11ac2804fa977bf951593c8dff8498779cc0cdc5812a4fba2f98870101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60076101000a6101000a600055600760ff0a6101000a60015560076101010a6101000a60025560076101000a60ff0a600355600760ff0a60ff0a60045560076101010a60ff0a60055560076101000a6101010a600655600760ff0a6101010a60075560076101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_8" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60086101000a6101000a600055600860ff0a6101000a60015560086101010a6101000a60025560086101000a60ff0a600355600860ff0a60ff0a60045560086101010a60ff0a60055560086101000a6101010a600655600860ff0a6101010a60075560086101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7759", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60086101000a6101000a600055600860ff0a6101000a60015560086101010a6101000a60025560086101000a60ff0a600355600860ff0a60ff0a60045560086101010a60ff0a60055560086101000a6101010a600655600860ff0a6101010a60075560086101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x230041a0e7602d6e459609ed39081ec55c33085514ff7f000000000000000001", + "0x04" : "0xc407d8a413ef9079ead457ed686a05ac81039c0cae0a7f6afd01e8461ff800ff", + "0x05" : "0x67a397e0692385e4cd83853aabce220a94d449e885fa867e96d3ef5e180800ff", + "0x06" : "0x70add926e753655d6d0ebe9c0f81368fb921f7aa6aff81000000000000000001", + "0x07" : "0x0bdce80b8378e43f13d454b9d0a4c83cf311b8eaa45d5122cfd544a217f80101", + "0x08" : "0x629c25790e1488998877a9ecdf0fb69637e77d8a4bdc1b46270093ba20080101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60086101000a6101000a600055600860ff0a6101000a60015560086101010a6101000a60025560086101000a60ff0a600355600860ff0a60ff0a60045560086101010a60ff0a60055560086101000a6101010a600655600860ff0a6101010a60075560086101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256Of256_9" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60096101000a6101000a600055600960ff0a6101000a60015560096101010a6101000a60025560096101000a60ff0a600355600960ff0a60ff0a60045560096101010a60ff0a60055560096101000a6101010a600655600960ff0a6101010a60075560096101010a6101010a600855", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "7750", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60096101000a6101000a600055600960ff0a6101000a60015560096101010a6101000a60025560096101000a60ff0a600355600960ff0a60ff0a60045560096101010a60ff0a60055560096101000a6101010a600655600960ff0a6101010a60075560096101010a6101010a600855", + "nonce" : "0", + "storage" : { + "0x03" : "0x53017d8eb210db2c8cd4a299079ec55c33085514ff7f00000000000000000001", + "0x04" : "0x48be09b6c6ae2aa660f1972125cecbb1038b5d236ecf766ba786e2c4e887feff", + "0x05" : "0x2e350d847ba73dc2099f83f532951c47269d9fd7e411b50bae00a9581f8900ff", + "0x06" : "0x013ab9e1f0df89a184b4d07080b68fb921f7aa6aff8100000000000000000001", + "0x07" : "0xf387ed41c1050f9da667f429a3e8fb30b61a55ede97d7b8acd797a03cd89ff01", + "0x08" : "0x525696c22bb3ce00fd2e3f6bbb9b4ea1046a5e31fcff2fedf8f8c74d28890101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60096101000a6101000a600055600960ff0a6101000a60015560096101010a6101000a60025560096101000a60ff0a600355600960ff0a60ff0a60045560096101010a60ff0a60055560096101000a6101010a600655600960ff0a6101010a60075560096101010a6101010a600855", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_1" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60016101000a600055600160ff0a60015560016101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60016101000a600055600160ff0a60015560016101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x0100", + "0x01" : "0xff", + "0x02" : "0x0101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60016101000a600055600160ff0a60015560016101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_10" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600a6101000a600055600a60ff0a600155600a6101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600a6101000a600055600a60ff0a600155600a6101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x0100000000000000000000", + "0x01" : "0xf62c88d104d1882cf601", + "0x02" : "0x010a2d78d2fcd2782d0a01" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600a6101000a600055600a60ff0a600155600a6101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_11" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600b6101000a600055600b60ff0a600155600b6101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600b6101000a600055600b60ff0a600155600b6101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x010000000000000000000000", + "0x01" : "0xf5365c4833ccb6a4c90aff", + "0x02" : "0x010b37a64bcfcf4aa5370b01" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600b6101000a600055600b60ff0a600155600b6101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_12" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600c6101000a600055600c60ff0a600155600c6101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600c6101000a600055600c60ff0a600155600c6101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x01000000000000000000000000", + "0x01" : "0xf44125ebeb98e9ee2441f401", + "0x02" : "0x010c42ddf21b9f19efdc420c01" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600c6101000a600055600c60ff0a600155600c6101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_13" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600d6101000a600055600d60ff0a600155600d6101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600d6101000a600055600d60ff0a600155600d6101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x0100000000000000000000000000", + "0x01" : "0xf34ce4c5ffad5104361db20cff", + "0x02" : "0x010d4f20d00dbab909cc1e4e0d01" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600d6101000a600055600d60ff0a600155600d6101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_14" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600e6101000a600055600e60ff0a600155600e6101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600e6101000a600055600e60ff0a600155600e6101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x010000000000000000000000000000", + "0x01" : "0xf25997e139ada3b331e7945af201", + "0x02" : "0x010e5c6ff0ddc873c2d5ea6c5b0e01" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600e6101000a600055600e60ff0a600155600e6101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_15" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600f6101000a600055600f60ff0a600155600f6101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600f6101000a600055600f60ff0a600155600f6101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x01000000000000000000000000000000", + "0x01" : "0xf1673e495873f60f7eb5acc6970eff", + "0x02" : "0x010f6acc60cea63c3698c056c7690f01" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600f6101000a600055600f60ff0a600155600f6101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_16" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60106101000a600055601060ff0a60015560106101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60106101000a600055601060ff0a60015560106101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x0100000000000000000000000000000000", + "0x01" : "0xf075d70b0f1b82196f36f719d077f001", + "0x02" : "0x01107a372d2f74e272cf59171e30781001" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60106101000a600055601060ff0a60015560106101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_17" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60116101000a600055601160ff0a60015560116101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60116101000a600055601160ff0a60015560116101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x010000000000000000000000000000000000", + "0x01" : "0xef856134040c669755c7c022b6a77810ff", + "0x02" : "0x01118ab1645ca45755422870354ea8881101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60116101000a600055601160ff0a60015560116101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_18" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60126101000a600055601260ff0a60015560126101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60126101000a600055601260ff0a60015560126101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x01000000000000000000000000000000000000", + "0x01" : "0xee95dbd2d0085a30be71f86293f0d098ee01", + "0x02" : "0x01129c3c15c100fbac976a98a583f730991201" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60126101000a600055601260ff0a60015560126101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_19" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60136101000a600055601360ff0a60015560136101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60136101000a600055601360ff0a60015560136101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x0100000000000000000000000000000000000000", + "0x01" : "0xeda745f6fd3851d68db3866a315cdfc85512ff", + "0x02" : "0x0113aed851d6c1fca84402033e297b27c9ab1301" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60136101000a600055601360ff0a60015560136101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_2" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60026101000a600055600260ff0a60015560026101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60026101000a600055600260ff0a60015560026101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x010000", + "0x01" : "0xfe01", + "0x02" : "0x010201" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60026101000a600055600260ff0a60015560026101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_20" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60146101000a600055601460ff0a60015560146101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60146101000a600055601460ff0a60015560146101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x010000000000000000000000000000000000000000", + "0x01" : "0xecb99eb1063b1984b725d2e3c72b82e88cbdec01", + "0x02" : "0x0114c2872a2898bea4ec46054167a4a2f174be1401" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60146101000a600055601460ff0a60015560146101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_21" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60156101000a600055601560ff0a60015560156101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60156101000a600055601560ff0a60015560156101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x01000000000000000000000000000000000000000000", + "0x01" : "0xebcce5125534de6b326ead10e3645765a4312e14ff", + "0x02" : "0x0115d749b152c1576391324b46a90c47946632d21501" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60156101000a600055601560ff0a60015560156101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_22" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60166101000a600055601660ff0a60015560166101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60166101000a600055601660ff0a60015560166101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x0100000000000000000000000000000000000000000000", + "0x01" : "0xeae1182d42dfa98cc73c3e63d280f30e3e8cfce6ea01", + "0x02" : "0x0116ed20fb041418baf4c37d91efb553dbfa9904e71601" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60166101000a600055601660ff0a60015560166101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_23" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60176101000a600055601760ff0a60015560176101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60176101000a600055601760ff0a60015560176101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x010000000000000000000000000000000000000000000000", + "0x01" : "0xe9f63715159cc9e33a7502256eae721b304e6fea0316ff", + "0x02" : "0x0118040e1bff182cd3afb8410f81a5092fd6939debfd1701" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60176101000a600055601760ff0a60015560176101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_24" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60186101000a600055601860ff0a60015560186101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60186101000a600055601860ff0a60015560186101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x01000000000000000000000000000000000000000000000000", + "0x01" : "0xe90c40de00872d19573a8d23493fc3a9151e217a1913e801", + "0x02" : "0x01191c122a1b1745008367f9509126ae39066a3189e9141801" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60186101000a600055601860ff0a60015560186101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_25" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60196101000a600055601960ff0a60015560196101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60196101000a600055601960ff0a60015560196101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x0100000000000000000000000000000000000000000000000000", + "0x01" : "0xe823349d2286a5ec3de3529625f683e56c0903589efad418ff", + "0x02" : "0x011a352e3c45325c4583eb6149e1b7d4e73f709bbb72fd2c1901" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60196101000a600055601960ff0a60015560196101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_26" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x601a6101000a600055601a60ff0a600155601a6101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601a6101000a600055601a60ff0a600155601a6101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x010000000000000000000000000000000000000000000000000000", + "0x01" : "0xe73b116885641f4651a56f438fd08d61869cfa55465bd944e601", + "0x02" : "0x011b4f636a81778ea1c96f4cab2b998cbc26b00c572e7029451a01" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601a6101000a600055601a60ff0a600155601a6101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_27" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x601b6101000a600055601b60ff0a600155601b6101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601b6101000a600055601b60ff0a600155601b6101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x01000000000000000000000000000000000000000000000000000000", + "0x01" : "0xe653d6571cdebb270b53c9d44c40bcd425165d5af1157d6ba11aff", + "0x02" : "0x011c6ab2cdebf906306b38bbf7d6c52648e2d6bc63859e996e5f1b01" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601b6101000a600055601b60ff0a600155601b6101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_28" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x601c6101000a600055601c60ff0a600155601c6101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601c6101000a600055601c60ff0a600155601c6101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x0100000000000000000000000000000000000000000000000000000000", + "0x01" : "0xe56d8280c5c1dc6be448760a77f47c1750f146fd962467ee3579e401", + "0x02" : "0x011d871d80b9e4ff369ba3f4b3ce9beb6f2bb9931fe9243807cd7a1c01" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601c6101000a600055601c60ff0a600155601c6101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_29" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x601d6101000a600055601d60ff0a600155601d6101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601d6101000a600055601d60ff0a600155601d6101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x010000000000000000000000000000000000000000000000000000000000", + "0x01" : "0xe48814fe44fc1a8f78642d946d7c879b39a055b6988e438647446a1cff", + "0x02" : "0x011ea4a49e3a9ee435d23f98a8826a875a9ae54cb3090d5c3fd547961d01" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601d6101000a600055601d60ff0a600155601d6101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_3" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60036101000a600055600360ff0a60015560036101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60036101000a600055600360ff0a60015560036101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x01000000", + "0x01" : "0xfd02ff", + "0x02" : "0x01030301" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60036101000a600055600360ff0a60015560036101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_30" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x601e6101000a600055601e60ff0a600155601e6101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601e6101000a600055601e60ff0a600155601e6101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x01000000000000000000000000000000000000000000000000000000000000", + "0x01" : "0xe3a38ce946b71e74e8ebc966d90f0b139e66b560e1f5b542c0fd25b2e201", + "0x02" : "0x011fc34942d8d9831a0811d8412aecf1e1f58031ffbc16699c151cddb31e01" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601e6101000a600055601e60ff0a600155601e6101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_31" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x601f6101000a600055601f60ff0a600155601f6101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601f6101000a600055601f60ff0a600155601f6101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x0100000000000000000000000000000000000000000000000000000000000000", + "0x01" : "0xe2bfe95c5d7067567402dd9d7235fc088ac84eab8113bf8d7e3c288d2f1eff", + "0x02" : "0x0120e30c8c1bb25c9d2219ea196c17ded3d775b231bbd28005b131fa90d11f01" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601f6101000a600055601f60ff0a600155601f6101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_32" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60206101000a600055602060ff0a60015560206101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9285", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60206101000a600055602060ff0a60015560206101010a600255", + "nonce" : "0", + "storage" : { + "0x01" : "0xe1dd29730112f6ef1d8edabfd4c3c60c823d865cd592abcdf0bdec64a1efe001", + "0x02" : "0x2203ef98a7ce0ef9bf3c04038583f6b2ab4d27e3ed8e5285b6e32c8b61f02001" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60206101000a600055602060ff0a60015560206101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_33" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60216101000a600055602160ff0a60015560216101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9285", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60216101000a600055602160ff0a60015560216101010a600255", + "nonce" : "0", + "storage" : { + "0x01" : "0xfb4c498e11e3f82e714be514ef024675bb48d678bd192222cd2e783d4df020ff", + "0x02" : "0x25f3884075dd08b8fb400789097aa95df8750bd17be0d83c9a0fb7ed52102101" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60216101000a600055602160ff0a60015560216101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_4" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60046101000a600055600460ff0a60015560046101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60046101000a600055600460ff0a60015560046101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x0100000000", + "0x01" : "0xfc05fc01", + "0x02" : "0x0104060401" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60046101000a600055600460ff0a60015560046101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_5" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60056101000a600055600560ff0a60015560056101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60056101000a600055600560ff0a60015560056101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x010000000000", + "0x01" : "0xfb09f604ff", + "0x02" : "0x01050a0a0501" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60056101000a600055600560ff0a60015560056101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_6" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60066101000a600055600660ff0a60015560066101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60066101000a600055600660ff0a60015560066101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x01000000000000", + "0x01" : "0xfa0eec0efa01", + "0x02" : "0x01060f140f0601" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60066101000a600055600660ff0a60015560066101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_7" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60076101000a600055600760ff0a60015560076101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60076101000a600055600760ff0a60015560076101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x0100000000000000", + "0x01" : "0xf914dd22eb06ff", + "0x02" : "0x0107152323150701" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60076101000a600055600760ff0a60015560076101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_8" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60086101000a600055600860ff0a60015560086101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60086101000a600055600860ff0a60015560086101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x010000000000000000", + "0x01" : "0xf81bc845c81bf801", + "0x02" : "0x01081c3846381c0801" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60086101000a600055600860ff0a60015560086101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf256_9" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x60096101000a600055600960ff0a60015560096101010a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60096101000a600055600960ff0a60015560096101010a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x01000000000000000000", + "0x01" : "0xf723ac7d8253dc08ff", + "0x02" : "0x010924547e7e54240901" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60096101000a600055600960ff0a60015560096101010a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf2_128" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x608060020a600055607f60020a600155608160020a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x608060020a600055607f60020a600155608160020a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x0100000000000000000000000000000000", + "0x01" : "0x80000000000000000000000000000000", + "0x02" : "0x0200000000000000000000000000000000" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x608060020a600055607f60020a600155608160020a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf2_16" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x601060020a600055600f60020a600155601160020a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601060020a600055600f60020a600155601160020a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x010000", + "0x01" : "0x8000", + "0x02" : "0x020000" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x601060020a600055600f60020a600155601160020a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf2_2" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600260020a600055600160020a600155600360020a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600260020a600055600160020a600155600360020a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x04", + "0x01" : "0x02", + "0x02" : "0x08" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600260020a600055600160020a600155600360020a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf2_256" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x61010060020a60005560ff60020a60015561010160020a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9483", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x61010060020a60005560ff60020a60015561010160020a600255", + "nonce" : "0", + "storage" : { + "0x01" : "0x8000000000000000000000000000000000000000000000000000000000000000" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x61010060020a60005560ff60020a60015561010160020a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf2_32" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x602060020a600055601f60020a600155602160020a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x602060020a600055601f60020a600155602160020a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x0100000000", + "0x01" : "0x80000000", + "0x02" : "0x0200000000" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x602060020a600055601f60020a600155602160020a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf2_4" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600460020a600055600360020a600155600560020a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600460020a600055600360020a600155600560020a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x10", + "0x01" : "0x08", + "0x02" : "0x20" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600460020a600055600360020a600155600560020a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf2_64" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x604060020a600055603f60020a600155604160020a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x604060020a600055603f60020a600155604160020a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x010000000000000000", + "0x01" : "0x8000000000000000", + "0x02" : "0x020000000000000000" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x604060020a600055603f60020a600155604160020a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, + "expPowerOf2_8" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x600860020a600055600760020a600155600960020a600255", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9085", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600860020a600055600760020a600155600960020a600255", + "nonce" : "0", + "storage" : { + "0x" : "0x0100", + "0x01" : "0x80", + "0x02" : "0x0200" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600860020a600055600760020a600155600960020a600255", + "nonce" : "0", + "storage" : { + } + } + } + }, "mod0" : { "callcreates" : [ ], @@ -3258,4 +6886,4 @@ } } } -} +} \ No newline at end of file diff --git a/tests/files/VMTests/vmBlockInfoTest.json b/tests/files/VMTests/vmBlockInfoTest.json index 90fa77a3de..67ec9dbf82 100644 --- a/tests/files/VMTests/vmBlockInfoTest.json +++ b/tests/files/VMTests/vmBlockInfoTest.json @@ -1,4 +1,180 @@ { + "blockhash257Block" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "257", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x600040600055", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9897", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600040600055", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600040600055", + "nonce" : "0", + "storage" : { + } + } + } + }, + "blockhash258Block" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "258", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x600140600055", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9897", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600140600055", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600140600055", + "nonce" : "0", + "storage" : { + } + } + } + }, + "blockhashMyBlock" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "1", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x600140600055", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9897", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600140600055", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600140600055", + "nonce" : "0", + "storage" : { + } + } + } + }, + "blockhashNotExistingBlock" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "1", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x600240600055", + "data" : "0x", + "gas" : "10000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "9897", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600240600055", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x600240600055", + "nonce" : "0", + "storage" : { + } + } + } + }, "coinbase" : { "callcreates" : [ ], @@ -178,51 +354,6 @@ } } }, - "prevhash" : { - "callcreates" : [ - ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "1000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x40600055", - "data" : "0x", - "gas" : "10000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "9698", - "logs" : [ - ], - "out" : "0x", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x40600055", - "nonce" : "0", - "storage" : { - "0x" : "0x5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x40600055", - "nonce" : "0", - "storage" : { - } - } - } - }, "timestamp" : { "callcreates" : [ ], diff --git a/tests/files/VMTests/vmEnvironmentalInfoTest.json b/tests/files/VMTests/vmEnvironmentalInfoTest.json index 37563707b5..88f22027ea 100644 --- a/tests/files/VMTests/vmEnvironmentalInfoTest.json +++ b/tests/files/VMTests/vmEnvironmentalInfoTest.json @@ -416,6 +416,50 @@ } } }, + "calldatacopyZeroMemExpansion" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x60006000600037600051600055", + "data" : "0x01234567890abcdef01234567890abcdef", + "gas" : "100000000000", + "gasPrice" : "1000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "99999999892", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60006000600037600051600055", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x60006000600037600051600055", + "nonce" : "0", + "storage" : { + } + } + } + }, "calldatacopy_DataIndexTooHigh" : { "callcreates" : [ ], @@ -953,7 +997,7 @@ } } }, - "codecopy1" : { + "codecopyZeroMemExpansion" : { "callcreates" : [ ], "env" : { @@ -967,31 +1011,30 @@ "exec" : { "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x386000600039600051600055", + "code" : "0x60006000600039600051600055", "data" : "0x01234567890abcdef01234567890abcdef", "gas" : "100000000000", "gasPrice" : "1000000000", "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", "value" : "1000000000000000000" }, - "gas" : "99999999691", + "gas" : "99999999892", "logs" : [ ], "out" : "0x", "post" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x386000600039600051600055", + "code" : "0x60006000600039600051600055", "nonce" : "0", "storage" : { - "0x" : "0x3860006000396000516000550000000000000000000000000000000000000000" } } }, "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", - "code" : "0x386000600039600051600055", + "code" : "0x60006000600039600051600055", "nonce" : "0", "storage" : { } @@ -1146,6 +1189,64 @@ } } }, + "extcodecopyZeroMemExpansion" : { + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "0x", + "data" : "0x01234567890abcdef01234567890abcdef", + "gas" : "100000000000", + "gasPrice" : "123456789", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "gas" : "100000000000", + "logs" : [ + ], + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "cd1722f3947def4cf144679da39c4c32bdc35681" : { + "balance" : "1000000000000000000", + "code" : "0x6005600055", + "nonce" : "0", + "storage" : { + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + }, + "cd1722f3947def4cf144679da39c4c32bdc35681" : { + "balance" : "1000000000000000000", + "code" : "0x6005600055", + "nonce" : "0", + "storage" : { + } + } + } + }, "extcodecopy_DataIndexTooHigh" : { "callcreates" : [ ], diff --git a/tests/files/VMTests/vmIOandFlowOperationsTest.json b/tests/files/VMTests/vmIOandFlowOperationsTest.json index 1209770864..24adc9d5dc 100644 --- a/tests/files/VMTests/vmIOandFlowOperationsTest.json +++ b/tests/files/VMTests/vmIOandFlowOperationsTest.json @@ -135,8 +135,6 @@ } }, "jump0" : { - "callcreates" : [ - ], "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty" : "256", @@ -155,20 +153,6 @@ "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", "value" : "1000000000000000000" }, - "gas" : "9696", - "logs" : [ - ], - "out" : "0x", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x60236007566001600255", - "nonce" : "0", - "storage" : { - "0x02" : "0x23" - } - } - }, "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", @@ -254,8 +238,6 @@ } }, "jump0_jumpdest1" : { - "callcreates" : [ - ], "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty" : "256", @@ -274,20 +256,6 @@ "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", "value" : "1000000000000000000" }, - "gas" : "9696", - "logs" : [ - ], - "out" : "0x", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x602360085660015b600255", - "nonce" : "0", - "storage" : { - "0x02" : "0x23" - } - } - }, "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", @@ -402,8 +370,6 @@ } }, "jumpi0" : { - "callcreates" : [ - ], "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty" : "256", @@ -422,20 +388,6 @@ "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", "value" : "1000000000000000000" }, - "gas" : "9695", - "logs" : [ - ], - "out" : "0x", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x602360016009576001600255", - "nonce" : "0", - "storage" : { - "0x02" : "0x23" - } - } - }, "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", @@ -492,8 +444,6 @@ } }, "jumpi1_jumpdest" : { - "callcreates" : [ - ], "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty" : "256", @@ -512,20 +462,6 @@ "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", "value" : "1000000000000000000" }, - "gas" : "9695", - "logs" : [ - ], - "out" : "0x", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x60236001600a5760015b600255", - "nonce" : "0", - "storage" : { - "0x02" : "0x23" - } - } - }, "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", @@ -537,8 +473,6 @@ } }, "jumpi2" : { - "callcreates" : [ - ], "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty" : "256", @@ -557,19 +491,6 @@ "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", "value" : "1000000000000000000" }, - "gas" : "9997", - "logs" : [ - ], - "out" : "0x", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff576002600355", - "nonce" : "0", - "storage" : { - } - } - }, "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", diff --git a/tests/files/index.js b/tests/files/index.js index 34a03d8b2b..99c19aa132 100644 --- a/tests/files/index.js +++ b/tests/files/index.js @@ -4,8 +4,11 @@ module.exports = { hexencode: require('./BasicTests/hexencodetest'), keyaddrtests: require('./BasicTests/keyaddrtest'), rlptest: require('./BasicTests/rlptest'), - trietest: require('./TrieTests/trietest'), - trietestnextprev: require('./TrieTests/trietestnextprev'), + trieTests: { + trietest: require('./TrieTests/trietest'), + trietestnextprev: require('./TrieTests/trietestnextprev'), + trieanyorder: require('./TrieTests/trieanyorder') + }, txtest: require('./BasicTests/txtest'), StateTests: { stExample: require('./StateTests/stExample.json'), @@ -13,6 +16,7 @@ module.exports = { stLogTests: require('./StateTests/stLogTests.json'), stPreCompiledContracts: require('./StateTests/stPreCompiledContracts'), stRecursiveCreate: require('./StateTests/stRecursiveCreate'), + stRefundTest: require('./StateTests/stRefundTest'), stSpecial: require('./StateTests/stSpecialTest'), stSystemOperationsTest: require('./StateTests/stSystemOperationsTest'), stTransactionTest: require('./StateTests/stTransactionTest') diff --git a/tests/helper/init.go b/tests/helper/init.go index 578314e20a..df98b9e422 100644 --- a/tests/helper/init.go +++ b/tests/helper/init.go @@ -16,5 +16,4 @@ func init() { logpkg.AddLogSystem(Logger) ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "") - ethutil.Config.Db, _ = NewMemDatabase() } diff --git a/tests/helper/trie.go b/tests/helper/trie.go index 32432cc7a5..9e666d333a 100644 --- a/tests/helper/trie.go +++ b/tests/helper/trie.go @@ -27,5 +27,5 @@ func (db *MemDatabase) LastKnownTD() []byte { return nil } func NewTrie() *trie.Trie { db, _ := NewMemDatabase() - return trie.New(db, "") + return trie.New(nil, db) } diff --git a/tests/helper/vm.go b/tests/helper/vm.go index e174e0892e..123003faa3 100644 --- a/tests/helper/vm.go +++ b/tests/helper/vm.go @@ -55,9 +55,11 @@ func (self *Env) PrevHash() []byte { return self.parent } func (self *Env) Coinbase() []byte { return self.coinbase } func (self *Env) Time() int64 { return self.time } func (self *Env) Difficulty() *big.Int { return self.difficulty } -func (self *Env) BlockHash() []byte { return nil } func (self *Env) State() *state.StateDB { return self.state } func (self *Env) GasLimit() *big.Int { return self.gasLimit } +func (self *Env) GetHash(n uint64) []byte { + return nil +} func (self *Env) AddLog(log state.Log) { self.logs = append(self.logs, log) } @@ -74,19 +76,19 @@ func (self *Env) vm(addr, data []byte, gas, price, value *big.Int) *core.Executi return exec } -func (self *Env) Call(caller vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { +func (self *Env) Call(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { exe := self.vm(addr, data, gas, price, value) ret, err := exe.Call(addr, caller) self.Gas = exe.Gas return ret, err } -func (self *Env) CallCode(caller vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { +func (self *Env) CallCode(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { exe := self.vm(caller.Address(), data, gas, price, value) return exe.Call(addr, caller) } -func (self *Env) Create(caller vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ClosureRef) { +func (self *Env) Create(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { exe := self.vm(addr, data, gas, price, value) return exe.Create(caller) } @@ -126,10 +128,9 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state. message := NewMessage(keyPair.Address(), to, data, value, gas, price) Log.DebugDetailf("message{ to: %x, from %x, value: %v, gas: %v, price: %v }\n", message.to[:4], message.from[:4], message.value, message.gas, message.price) - st := core.NewStateTransition(coinbase, message, statedb, nil) vmenv := NewEnvFromMap(statedb, env, tx) + st := core.NewStateTransition(vmenv, message, coinbase) vmenv.origin = keyPair.Address() - st.Env = vmenv ret, err := st.TransitionState() statedb.Update(vmenv.Gas) diff --git a/tests/vm/gh_test.go b/tests/vm/gh_test.go index 1efda7fe00..2aece215e8 100644 --- a/tests/vm/gh_test.go +++ b/tests/vm/gh_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/state" @@ -38,8 +39,8 @@ func (self Log) Topics() [][]byte { return t } -func StateObjectFromAccount(addr string, account Account) *state.StateObject { - obj := state.NewStateObject(ethutil.Hex2Bytes(addr)) +func StateObjectFromAccount(db ethutil.Database, addr string, account Account) *state.StateObject { + obj := state.NewStateObject(ethutil.Hex2Bytes(addr), db) obj.SetBalance(ethutil.Big(account.Balance)) if ethutil.IsHex(account.Code) { @@ -78,9 +79,16 @@ func RunVmTest(p string, t *testing.T) { helper.CreateFileTests(t, p, &tests) for name, test := range tests { - statedb := state.New(helper.NewTrie()) + /* + helper.Logger.SetLogLevel(5) + if name != "jump0_jumpdest2" { + continue + } + */ + db, _ := ethdb.NewMemDatabase() + statedb := state.New(nil, db) for addr, account := range test.Pre { - obj := StateObjectFromAccount(addr, account) + obj := StateObjectFromAccount(db, addr, account) statedb.SetStateObject(obj) for a, v := range account.Storage { obj.SetState(helper.FromHex(a), ethutil.NewValue(helper.FromHex(v))) @@ -107,16 +115,17 @@ func RunVmTest(p string, t *testing.T) { logs state.Logs ) - if len(test.Exec) > 0 { + isVmTest := len(test.Exec) > 0 + if isVmTest { ret, logs, gas, err = helper.RunVm(statedb, env, test.Exec) } else { ret, logs, gas, err = helper.RunState(statedb, env, test.Transaction) } - // When an error is returned it doesn't always mean the tests fails. - // Have to come up with some conditional failing mechanism. + // Log the error if there is one. Error does not mean failing test. + // A test fails if err != nil and post params are specified in the test. if err != nil { - helper.Log.Infoln(err) + helper.Log.Infof("%s's: %v\n", name, err) } rexp := helper.FromHex(test.Out) @@ -124,10 +133,14 @@ func RunVmTest(p string, t *testing.T) { t.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret) } - if len(test.Gas) > 0 { - gexp := ethutil.Big(test.Gas) - if gexp.Cmp(gas) != 0 { - t.Errorf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas) + if isVmTest { + if len(test.Gas) == 0 && err == nil { + t.Errorf("%s's gas unspecified, indicating an error. VM returned (incorrectly) successfull", name) + } else { + gexp := ethutil.Big(test.Gas) + if gexp.Cmp(gas) != 0 { + t.Errorf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas) + } } } @@ -154,7 +167,6 @@ func RunVmTest(p string, t *testing.T) { } if len(test.Logs) > 0 { - // Logs within the test itself aren't correct, missing empty fields (32 0s) for i, log := range test.Logs { genBloom := ethutil.LeftPadBytes(types.LogsBloom(state.Logs{logs[i]}).Bytes(), 64) if !bytes.Equal(genBloom, ethutil.Hex2Bytes(log.BloomF)) { diff --git a/ptrie/cache.go b/trie/cache.go similarity index 98% rename from ptrie/cache.go rename to trie/cache.go index 721dc4cf64..e03702b255 100644 --- a/ptrie/cache.go +++ b/trie/cache.go @@ -1,4 +1,4 @@ -package ptrie +package trie type Backend interface { Get([]byte) ([]byte, error) diff --git a/ptrie/fullnode.go b/trie/fullnode.go similarity index 88% rename from ptrie/fullnode.go rename to trie/fullnode.go index 7a7f7d22d4..ebbe7f3844 100644 --- a/ptrie/fullnode.go +++ b/trie/fullnode.go @@ -1,4 +1,6 @@ -package ptrie +package trie + +import "fmt" type FullNode struct { trie *Trie @@ -21,7 +23,9 @@ func (self *FullNode) Branches() []Node { func (self *FullNode) Copy() Node { nnode := NewFullNode(self.trie) for i, node := range self.nodes { - nnode.nodes[i] = node + if node != nil { + nnode.nodes[i] = node + } } return nnode @@ -56,6 +60,10 @@ func (self *FullNode) RlpData() interface{} { } func (self *FullNode) set(k byte, value Node) { + if _, ok := value.(*ValueNode); ok && k != 16 { + fmt.Println(value, k) + } + self.nodes[int(k)] = value } diff --git a/ptrie/hashnode.go b/trie/hashnode.go similarity index 97% rename from ptrie/hashnode.go rename to trie/hashnode.go index 4c17569d78..40ccd54c31 100644 --- a/ptrie/hashnode.go +++ b/trie/hashnode.go @@ -1,4 +1,4 @@ -package ptrie +package trie type HashNode struct { key []byte diff --git a/trie/iterator.go b/trie/iterator.go index 53d099a0c3..f0dae28bb0 100644 --- a/trie/iterator.go +++ b/trie/iterator.go @@ -1,123 +1,73 @@ package trie -import ( - "bytes" - - "github.com/ethereum/go-ethereum/ethutil" -) - -type NodeType byte - -const ( - EmptyNode NodeType = iota - BranchNode - LeafNode - ExtNode -) - -func getType(node *ethutil.Value) NodeType { - if node.Len() == 0 { - return EmptyNode - } - - if node.Len() == 2 { - k := CompactDecode(node.Get(0).Str()) - if HasTerm(k) { - return LeafNode - } - - return ExtNode - } - - return BranchNode -} +import "bytes" type Iterator struct { - Path [][]byte trie *Trie Key []byte - Value *ethutil.Value + Value []byte } func NewIterator(trie *Trie) *Iterator { - return &Iterator{trie: trie} + return &Iterator{trie: trie, Key: make([]byte, 32)} } -func (self *Iterator) key(node *ethutil.Value, path [][]byte) []byte { - switch getType(node) { - case LeafNode: - k := RemTerm(CompactDecode(node.Get(0).Str())) +func (self *Iterator) Next() bool { + self.trie.mu.Lock() + defer self.trie.mu.Unlock() - self.Path = append(path, k) - self.Value = node.Get(1) + key := RemTerm(CompactHexDecode(string(self.Key))) + k := self.next(self.trie.root, key) - return k - case BranchNode: - if node.Get(16).Len() > 0 { - return []byte{16} - } + self.Key = []byte(DecodeCompact(k)) - for i := byte(0); i < 16; i++ { - o := self.key(self.trie.getNode(node.Get(int(i)).Raw()), append(path, []byte{i})) - if o != nil { - return append([]byte{i}, o...) - } - } - case ExtNode: - currKey := node.Get(0).Bytes() + return len(k) > 0 - return self.key(self.trie.getNode(node.Get(1).Raw()), append(path, currKey)) +} + +func (self *Iterator) next(node Node, key []byte) []byte { + if node == nil { + return nil } - return nil -} - -func (self *Iterator) next(node *ethutil.Value, key []byte, path [][]byte) []byte { - switch typ := getType(node); typ { - case EmptyNode: - return nil - case BranchNode: + switch node := node.(type) { + case *FullNode: if len(key) > 0 { - subNode := self.trie.getNode(node.Get(int(key[0])).Raw()) - - o := self.next(subNode, key[1:], append(path, key[:1])) - if o != nil { - return append([]byte{key[0]}, o...) + k := self.next(node.branch(key[0]), key[1:]) + if k != nil { + return append([]byte{key[0]}, k...) } } - var r byte = 0 + var r byte if len(key) > 0 { r = key[0] + 1 } for i := r; i < 16; i++ { - subNode := self.trie.getNode(node.Get(int(i)).Raw()) - o := self.key(subNode, append(path, []byte{i})) - if o != nil { - return append([]byte{i}, o...) + k := self.key(node.branch(byte(i))) + if k != nil { + return append([]byte{i}, k...) } } - case LeafNode, ExtNode: - k := RemTerm(CompactDecode(node.Get(0).Str())) - if typ == LeafNode { - if bytes.Compare([]byte(k), []byte(key)) > 0 { - self.Value = node.Get(1) - self.Path = append(path, k) + case *ShortNode: + k := RemTerm(node.Key()) + if vnode, ok := node.Value().(*ValueNode); ok { + if bytes.Compare([]byte(k), key) > 0 { + self.Value = vnode.Val() return k } } else { - subNode := self.trie.getNode(node.Get(1).Raw()) - subKey := key[len(k):] + cnode := node.Value() + var ret []byte + skey := key[len(k):] if BeginsWith(key, k) { - ret = self.next(subNode, subKey, append(path, k)) + ret = self.next(cnode, skey) } else if bytes.Compare(k, key[:len(k)]) > 0 { - ret = self.key(node, append(path, k)) - } else { - ret = nil + ret = self.key(node) } if ret != nil { @@ -129,15 +79,33 @@ func (self *Iterator) next(node *ethutil.Value, key []byte, path [][]byte) []byt return nil } -// Get the next in keys -func (self *Iterator) Next(key string) []byte { - self.trie.mut.Lock() - defer self.trie.mut.Unlock() +func (self *Iterator) key(node Node) []byte { + switch node := node.(type) { + case *ShortNode: + // Leaf node + if vnode, ok := node.Value().(*ValueNode); ok { + k := RemTerm(node.Key()) + self.Value = vnode.Val() - k := RemTerm(CompactHexDecode(key)) - n := self.next(self.trie.getNode(self.trie.Root), k, nil) + return k + } else { + k := RemTerm(node.Key()) + return append(k, self.key(node.Value())...) + } + case *FullNode: + if node.Value() != nil { + self.Value = node.Value().(*ValueNode).Val() - self.Key = []byte(DecodeCompact(n)) + return []byte{16} + } - return self.Key + for i := 0; i < 16; i++ { + k := self.key(node.branch(byte(i))) + if k != nil { + return append([]byte{byte(i)}, k...) + } + } + } + + return nil } diff --git a/ptrie/iterator_test.go b/trie/iterator_test.go similarity index 97% rename from ptrie/iterator_test.go rename to trie/iterator_test.go index acfc03d633..74d9e903cd 100644 --- a/ptrie/iterator_test.go +++ b/trie/iterator_test.go @@ -1,4 +1,4 @@ -package ptrie +package trie import "testing" diff --git a/trie/main_test.go b/trie/main_test.go deleted file mode 100644 index f6f64c06f7..0000000000 --- a/trie/main_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package trie - -import ( - "testing" - - checker "gopkg.in/check.v1" -) - -func Test(t *testing.T) { checker.TestingT(t) } diff --git a/ptrie/node.go b/trie/node.go similarity index 91% rename from ptrie/node.go rename to trie/node.go index 2c85dbce72..a1f68480f2 100644 --- a/ptrie/node.go +++ b/trie/node.go @@ -1,4 +1,4 @@ -package ptrie +package trie import "fmt" @@ -17,7 +17,7 @@ type Node interface { func (self *ValueNode) String() string { return self.fstring("") } func (self *FullNode) String() string { return self.fstring("") } func (self *ShortNode) String() string { return self.fstring("") } -func (self *ValueNode) fstring(ind string) string { return fmt.Sprintf("%s ", self.data) } +func (self *ValueNode) fstring(ind string) string { return fmt.Sprintf("%x ", self.data) } func (self *HashNode) fstring(ind string) string { return fmt.Sprintf("%x ", self.key) } // Full node @@ -36,5 +36,5 @@ func (self *FullNode) fstring(ind string) string { // Short node func (self *ShortNode) fstring(ind string) string { - return fmt.Sprintf("[ %s: %v ] ", self.key, self.value.fstring(ind+" ")) + return fmt.Sprintf("[ %x: %v ] ", self.key, self.value.fstring(ind+" ")) } diff --git a/ptrie/shortnode.go b/trie/shortnode.go similarity index 78% rename from ptrie/shortnode.go rename to trie/shortnode.go index 73ff2914bf..f132b56d96 100644 --- a/ptrie/shortnode.go +++ b/trie/shortnode.go @@ -1,6 +1,4 @@ -package ptrie - -import "github.com/ethereum/go-ethereum/trie" +package trie type ShortNode struct { trie *Trie @@ -9,7 +7,7 @@ type ShortNode struct { } func NewShortNode(t *Trie, key []byte, value Node) *ShortNode { - return &ShortNode{t, []byte(trie.CompactEncode(key)), value} + return &ShortNode{t, []byte(CompactEncode(key)), value} } func (self *ShortNode) Value() Node { self.value = self.trie.trans(self.value) @@ -27,5 +25,5 @@ func (self *ShortNode) Hash() interface{} { } func (self *ShortNode) Key() []byte { - return trie.CompactDecode(string(self.key)) + return CompactDecode(string(self.key)) } diff --git a/trie/trie.go b/trie/trie.go index d89c397756..36f2af5d22 100644 --- a/trie/trie.go +++ b/trie/trie.go @@ -2,6 +2,7 @@ package trie import ( "bytes" + "container/list" "fmt" "sync" @@ -9,623 +10,325 @@ import ( "github.com/ethereum/go-ethereum/ethutil" ) -func ParanoiaCheck(t1 *Trie) (bool, *Trie) { - t2 := New(ethutil.Config.Db, "") +func ParanoiaCheck(t1 *Trie, backend Backend) (bool, *Trie) { + t2 := New(nil, backend) - t1.NewIterator().Each(func(key string, v *ethutil.Value) { - t2.Update(key, v.Str()) - }) - - return bytes.Compare(t2.GetRoot(), t1.GetRoot()) == 0, t2 -} - -func (s *Cache) Len() int { - return len(s.nodes) -} - -// TODO -// A StateObject is an object that has a state root -// This is goig to be the object for the second level caching (the caching of object which have a state such as contracts) -type StateObject interface { - State() *Trie - Sync() - Undo() -} - -type Node struct { - Key []byte - Value *ethutil.Value - Dirty bool -} - -func NewNode(key []byte, val *ethutil.Value, dirty bool) *Node { - return &Node{Key: key, Value: val, Dirty: dirty} -} - -func (n *Node) Copy() *Node { - return NewNode(n.Key, n.Value, n.Dirty) -} - -type Cache struct { - nodes map[string]*Node - db ethutil.Database - IsDirty bool -} - -func NewCache(db ethutil.Database) *Cache { - return &Cache{db: db, nodes: make(map[string]*Node)} -} - -func (cache *Cache) PutValue(v interface{}, force bool) interface{} { - value := ethutil.NewValue(v) - - enc := value.Encode() - if len(enc) >= 32 || force { - sha := crypto.Sha3(enc) - - cache.nodes[string(sha)] = NewNode(sha, value, true) - cache.IsDirty = true - - return sha + it := t1.Iterator() + for it.Next() { + t2.Update(it.Key, it.Value) } - return v + return bytes.Equal(t2.Hash(), t1.Hash()), t2 } -func (cache *Cache) Put(v interface{}) interface{} { - return cache.PutValue(v, false) -} - -func (cache *Cache) Get(key []byte) *ethutil.Value { - // First check if the key is the cache - if cache.nodes[string(key)] != nil { - return cache.nodes[string(key)].Value - } - - // Get the key of the database instead and cache it - data, _ := cache.db.Get(key) - // Create the cached value - value := ethutil.NewValueFromBytes(data) - - defer func() { - if r := recover(); r != nil { - fmt.Println("RECOVER GET", cache, cache.nodes) - panic("bye") - } - }() - // Create caching node - cache.nodes[string(key)] = NewNode(key, value, true) - - return value -} - -func (cache *Cache) Delete(key []byte) { - delete(cache.nodes, string(key)) - - cache.db.Delete(key) -} - -func (cache *Cache) Commit() { - // Don't try to commit if it isn't dirty - if !cache.IsDirty { - return - } - - for key, node := range cache.nodes { - if node.Dirty { - cache.db.Put([]byte(key), node.Value.Encode()) - node.Dirty = false - } - } - cache.IsDirty = false - - // If the nodes grows beyond the 200 entries we simple empty it - // FIXME come up with something better - if len(cache.nodes) > 200 { - cache.nodes = make(map[string]*Node) - } -} - -func (cache *Cache) Undo() { - for key, node := range cache.nodes { - if node.Dirty { - delete(cache.nodes, key) - } - } - cache.IsDirty = false -} - -// A (modified) Radix Trie implementation. The Trie implements -// a caching mechanism and will used cached values if they are -// present. If a node is not present in the cache it will try to -// fetch it from the database and store the cached value. -// Please note that the data isn't persisted unless `Sync` is -// explicitly called. type Trie struct { - mut sync.RWMutex - prevRoot interface{} - Root interface{} - //db Database - cache *Cache + mu sync.Mutex + root Node + roothash []byte + cache *Cache + + revisions *list.List } -func copyRoot(root interface{}) interface{} { - var prevRootCopy interface{} - if b, ok := root.([]byte); ok { - prevRootCopy = ethutil.CopyBytes(b) - } else { - prevRootCopy = root - } +func New(root []byte, backend Backend) *Trie { + trie := &Trie{} + trie.revisions = list.New() + trie.roothash = root + trie.cache = NewCache(backend) - return prevRootCopy -} - -func New(db ethutil.Database, Root interface{}) *Trie { - // Make absolute sure the root is copied - r := copyRoot(Root) - p := copyRoot(Root) - - trie := &Trie{cache: NewCache(db), Root: r, prevRoot: p} - trie.setRoot(Root) - - return trie -} - -func (self *Trie) setRoot(root interface{}) { - switch t := root.(type) { - case string: - /* - if t == "" { - root = crypto.Sha3(ethutil.Encode("")) - } - */ - self.Root = []byte(t) - case []byte: - self.Root = root - default: - self.Root = self.cache.PutValue(root, true) - } -} - -/* - * Public (query) interface functions - */ - -func (t *Trie) Update(key, value string) { - t.mut.Lock() - defer t.mut.Unlock() - - k := CompactHexDecode(key) - - var root interface{} - if value != "" { - root = t.UpdateState(t.Root, k, value) - } else { - root = t.deleteState(t.Root, k) - } - t.setRoot(root) -} - -func (t *Trie) Get(key string) string { - t.mut.Lock() - defer t.mut.Unlock() - - k := CompactHexDecode(key) - c := ethutil.NewValue(t.getState(t.Root, k)) - - return c.Str() -} - -func (t *Trie) Delete(key string) { - t.mut.Lock() - defer t.mut.Unlock() - - k := CompactHexDecode(key) - - root := t.deleteState(t.Root, k) - t.setRoot(root) -} - -func (self *Trie) GetRoot() []byte { - switch t := self.Root.(type) { - case string: - if t == "" { - return crypto.Sha3(ethutil.Encode("")) - } - return []byte(t) - case []byte: - if len(t) == 0 { - return crypto.Sha3(ethutil.Encode("")) - } - - return t - default: - panic(fmt.Sprintf("invalid root type %T (%v)", self.Root, self.Root)) - } -} - -// Simple compare function which creates a rlp value out of the evaluated objects -func (t *Trie) Cmp(trie *Trie) bool { - return ethutil.NewValue(t.Root).Cmp(ethutil.NewValue(trie.Root)) -} - -// Returns a copy of this trie -func (t *Trie) Copy() *Trie { - trie := New(t.cache.db, t.Root) - for key, node := range t.cache.nodes { - trie.cache.nodes[key] = node.Copy() + if root != nil { + value := ethutil.NewValueFromBytes(trie.cache.Get(root)) + trie.root = trie.mknode(value) } return trie } -// Save the cached value to the database. -func (t *Trie) Sync() { - t.cache.Commit() - t.prevRoot = copyRoot(t.Root) -} - -func (t *Trie) Undo() { - t.cache.Undo() - t.Root = t.prevRoot -} - -func (t *Trie) Cache() *Cache { - return t.cache -} - -func (t *Trie) getState(node interface{}, key []byte) interface{} { - n := ethutil.NewValue(node) - // Return the node if key is empty (= found) - if len(key) == 0 || n.IsNil() || n.Len() == 0 { - return node - } - - currentNode := t.getNode(node) - length := currentNode.Len() - - if length == 0 { - return "" - } else if length == 2 { - // Decode the key - k := CompactDecode(currentNode.Get(0).Str()) - v := currentNode.Get(1).Raw() - - if len(key) >= len(k) && bytes.Equal(k, key[:len(k)]) { //CompareIntSlice(k, key[:len(k)]) { - return t.getState(v, key[len(k):]) - } else { - return "" - } - } else if length == 17 { - return t.getState(currentNode.Get(int(key[0])).Raw(), key[1:]) - } - - // It shouldn't come this far - panic("unexpected return") -} - -func (t *Trie) getNode(node interface{}) *ethutil.Value { - n := ethutil.NewValue(node) - - if !n.Get(0).IsNil() { - return n - } - - str := n.Str() - if len(str) == 0 { - return n - } else if len(str) < 32 { - return ethutil.NewValueFromBytes([]byte(str)) - } - - data := t.cache.Get(n.Bytes()) - - return data -} - -func (t *Trie) UpdateState(node interface{}, key []byte, value string) interface{} { - return t.InsertState(node, key, value) -} - -func (t *Trie) Put(node interface{}) interface{} { - return t.cache.Put(node) - -} - -func EmptyStringSlice(l int) []interface{} { - slice := make([]interface{}, l) - for i := 0; i < l; i++ { - slice[i] = "" - } - return slice -} - -func (t *Trie) InsertState(node interface{}, key []byte, value interface{}) interface{} { - if len(key) == 0 { - return value - } - - // New node - n := ethutil.NewValue(node) - if node == nil || n.Len() == 0 { - newNode := []interface{}{CompactEncode(key), value} - - return t.Put(newNode) - } - - currentNode := t.getNode(node) - // Check for "special" 2 slice type node - if currentNode.Len() == 2 { - // Decode the key - - k := CompactDecode(currentNode.Get(0).Str()) - v := currentNode.Get(1).Raw() - - // Matching key pair (ie. there's already an object with this key) - if bytes.Equal(k, key) { //CompareIntSlice(k, key) { - newNode := []interface{}{CompactEncode(key), value} - return t.Put(newNode) - } - - var newHash interface{} - matchingLength := MatchingNibbleLength(key, k) - if matchingLength == len(k) { - // Insert the hash, creating a new node - newHash = t.InsertState(v, key[matchingLength:], value) - } else { - // Expand the 2 length slice to a 17 length slice - oldNode := t.InsertState("", k[matchingLength+1:], v) - newNode := t.InsertState("", key[matchingLength+1:], value) - // Create an expanded slice - scaledSlice := EmptyStringSlice(17) - // Set the copied and new node - scaledSlice[k[matchingLength]] = oldNode - scaledSlice[key[matchingLength]] = newNode - - newHash = t.Put(scaledSlice) - } - - if matchingLength == 0 { - // End of the chain, return - return newHash - } else { - newNode := []interface{}{CompactEncode(key[:matchingLength]), newHash} - return t.Put(newNode) - } - } else { - - // Copy the current node over to the new node and replace the first nibble in the key - newNode := EmptyStringSlice(17) - - for i := 0; i < 17; i++ { - cpy := currentNode.Get(i).Raw() - if cpy != nil { - newNode[i] = cpy - } - } - - newNode[key[0]] = t.InsertState(currentNode.Get(int(key[0])).Raw(), key[1:], value) - - return t.Put(newNode) - } - - panic("unexpected end") -} - -func (t *Trie) deleteState(node interface{}, key []byte) interface{} { - if len(key) == 0 { - return "" - } - - // New node - n := ethutil.NewValue(node) - //if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 { - if node == nil || n.Len() == 0 { - //return nil - //fmt.Printf(" %x %d\n", n, len(n.Bytes())) - - return "" - } - - currentNode := t.getNode(node) - // Check for "special" 2 slice type node - if currentNode.Len() == 2 { - // Decode the key - k := CompactDecode(currentNode.Get(0).Str()) - v := currentNode.Get(1).Raw() - - // Matching key pair (ie. there's already an object with this key) - if bytes.Equal(k, key) { //CompareIntSlice(k, key) { - //fmt.Printf(" %x\n", v) - - return "" - } else if bytes.Equal(key[:len(k)], k) { //CompareIntSlice(key[:len(k)], k) { - hash := t.deleteState(v, key[len(k):]) - child := t.getNode(hash) - - var newNode []interface{} - if child.Len() == 2 { - newKey := append(k, CompactDecode(child.Get(0).Str())...) - newNode = []interface{}{CompactEncode(newKey), child.Get(1).Raw()} - } else { - newNode = []interface{}{currentNode.Get(0).Str(), hash} - } - - //fmt.Printf("%x\n", newNode) - - return t.Put(newNode) - } else { - return node - } - } else { - // Copy the current node over to the new node and replace the first nibble in the key - n := EmptyStringSlice(17) - var newNode []interface{} - - for i := 0; i < 17; i++ { - cpy := currentNode.Get(i).Raw() - if cpy != nil { - n[i] = cpy - } - } - - n[key[0]] = t.deleteState(n[key[0]], key[1:]) - amount := -1 - for i := 0; i < 17; i++ { - if n[i] != "" { - if amount == -1 { - amount = i - } else { - amount = -2 - } - } - } - if amount == 16 { - newNode = []interface{}{CompactEncode([]byte{16}), n[amount]} - } else if amount >= 0 { - child := t.getNode(n[amount]) - if child.Len() == 17 { - newNode = []interface{}{CompactEncode([]byte{byte(amount)}), n[amount]} - } else if child.Len() == 2 { - key := append([]byte{byte(amount)}, CompactDecode(child.Get(0).Str())...) - newNode = []interface{}{CompactEncode(key), child.Get(1).Str()} - } - - } else { - newNode = n - } - - //fmt.Printf("%x\n", newNode) - return t.Put(newNode) - } - - panic("unexpected return") -} - -type TrieIterator struct { - trie *Trie - key string - value string - - shas [][]byte - values []string - - lastNode []byte -} - -func (t *Trie) NewIterator() *TrieIterator { - return &TrieIterator{trie: t} -} - func (self *Trie) Iterator() *Iterator { return NewIterator(self) } -// Some time in the near future this will need refactoring :-) -// XXX Note to self, IsSlice == inline node. Str == sha3 to node -func (it *TrieIterator) workNode(currentNode *ethutil.Value) { - if currentNode.Len() == 2 { - k := CompactDecode(currentNode.Get(0).Str()) +func (self *Trie) Copy() *Trie { + return New(self.roothash, self.cache.backend) +} - if currentNode.Get(1).Str() == "" { - it.workNode(currentNode.Get(1)) +// Legacy support +func (self *Trie) Root() []byte { return self.Hash() } +func (self *Trie) Hash() []byte { + var hash []byte + if self.root != nil { + t := self.root.Hash() + if byts, ok := t.([]byte); ok && len(byts) > 0 { + hash = byts } else { - if k[len(k)-1] == 16 { - it.values = append(it.values, currentNode.Get(1).Str()) - } else { - it.shas = append(it.shas, currentNode.Get(1).Bytes()) - it.getNode(currentNode.Get(1).Bytes()) - } + hash = crypto.Sha3(ethutil.Encode(self.root.RlpData())) } } else { - for i := 0; i < currentNode.Len(); i++ { - if i == 16 && currentNode.Get(i).Len() != 0 { - it.values = append(it.values, currentNode.Get(i).Str()) - } else { - if currentNode.Get(i).Str() == "" { - it.workNode(currentNode.Get(i)) - } else { - val := currentNode.Get(i).Str() - if val != "" { - it.shas = append(it.shas, currentNode.Get(1).Bytes()) - it.getNode([]byte(val)) - } - } - } + hash = crypto.Sha3(ethutil.Encode("")) + } + + if !bytes.Equal(hash, self.roothash) { + self.revisions.PushBack(self.roothash) + self.roothash = hash + } + + return hash +} +func (self *Trie) Commit() { + self.mu.Lock() + defer self.mu.Unlock() + + // Hash first + self.Hash() + + self.cache.Flush() +} + +// Reset should only be called if the trie has been hashed +func (self *Trie) Reset() { + self.mu.Lock() + defer self.mu.Unlock() + + self.cache.Reset() + + if self.revisions.Len() > 0 { + revision := self.revisions.Remove(self.revisions.Back()).([]byte) + self.roothash = revision + } + value := ethutil.NewValueFromBytes(self.cache.Get(self.roothash)) + self.root = self.mknode(value) +} + +func (self *Trie) UpdateString(key, value string) Node { return self.Update([]byte(key), []byte(value)) } +func (self *Trie) Update(key, value []byte) Node { + self.mu.Lock() + defer self.mu.Unlock() + + k := CompactHexDecode(string(key)) + + if len(value) != 0 { + self.root = self.insert(self.root, k, &ValueNode{self, value}) + } else { + self.root = self.delete(self.root, k) + } + + return self.root +} + +func (self *Trie) GetString(key string) []byte { return self.Get([]byte(key)) } +func (self *Trie) Get(key []byte) []byte { + self.mu.Lock() + defer self.mu.Unlock() + + k := CompactHexDecode(string(key)) + + n := self.get(self.root, k) + if n != nil { + return n.(*ValueNode).Val() + } + + return nil +} + +func (self *Trie) DeleteString(key string) Node { return self.Delete([]byte(key)) } +func (self *Trie) Delete(key []byte) Node { + self.mu.Lock() + defer self.mu.Unlock() + + k := CompactHexDecode(string(key)) + self.root = self.delete(self.root, k) + + return self.root +} + +func (self *Trie) insert(node Node, key []byte, value Node) Node { + if len(key) == 0 { + return value + } + + if node == nil { + return NewShortNode(self, key, value) + } + + switch node := node.(type) { + case *ShortNode: + k := node.Key() + cnode := node.Value() + if bytes.Equal(k, key) { + return NewShortNode(self, key, value) } + + var n Node + matchlength := MatchingNibbleLength(key, k) + if matchlength == len(k) { + n = self.insert(cnode, key[matchlength:], value) + } else { + pnode := self.insert(nil, k[matchlength+1:], cnode) + nnode := self.insert(nil, key[matchlength+1:], value) + fulln := NewFullNode(self) + fulln.set(k[matchlength], pnode) + fulln.set(key[matchlength], nnode) + n = fulln + } + if matchlength == 0 { + return n + } + + return NewShortNode(self, key[:matchlength], n) + + case *FullNode: + cpy := node.Copy().(*FullNode) + cpy.set(key[0], self.insert(node.branch(key[0]), key[1:], value)) + + return cpy + + default: + panic(fmt.Sprintf("%T: invalid node: %v", node, node)) } } -func (it *TrieIterator) getNode(node []byte) { - currentNode := it.trie.cache.Get(node) - it.workNode(currentNode) -} +func (self *Trie) get(node Node, key []byte) Node { + if len(key) == 0 { + return node + } -func (it *TrieIterator) Collect() [][]byte { - if it.trie.Root == "" { + if node == nil { return nil } - it.getNode(ethutil.NewValue(it.trie.Root).Bytes()) + switch node := node.(type) { + case *ShortNode: + k := node.Key() + cnode := node.Value() - return it.shas -} - -func (it *TrieIterator) Purge() int { - shas := it.Collect() - for _, sha := range shas { - it.trie.cache.Delete(sha) - } - return len(it.values) -} - -func (it *TrieIterator) Key() string { - return "" -} - -func (it *TrieIterator) Value() string { - return "" -} - -type EachCallback func(key string, node *ethutil.Value) - -func (it *TrieIterator) Each(cb EachCallback) { - it.fetchNode(nil, ethutil.NewValue(it.trie.Root).Bytes(), cb) -} - -func (it *TrieIterator) fetchNode(key []byte, node []byte, cb EachCallback) { - it.iterateNode(key, it.trie.cache.Get(node), cb) -} - -func (it *TrieIterator) iterateNode(key []byte, currentNode *ethutil.Value, cb EachCallback) { - if currentNode.Len() == 2 { - k := CompactDecode(currentNode.Get(0).Str()) - - pk := append(key, k...) - if currentNode.Get(1).Len() != 0 && currentNode.Get(1).Str() == "" { - it.iterateNode(pk, currentNode.Get(1), cb) - } else { - if k[len(k)-1] == 16 { - cb(DecodeCompact(pk), currentNode.Get(1)) - } else { - it.fetchNode(pk, currentNode.Get(1).Bytes(), cb) - } + if len(key) >= len(k) && bytes.Equal(k, key[:len(k)]) { + return self.get(cnode, key[len(k):]) } - } else { - for i := 0; i < currentNode.Len(); i++ { - pk := append(key, byte(i)) - if i == 16 && currentNode.Get(i).Len() != 0 { - cb(DecodeCompact(pk), currentNode.Get(i)) - } else { - if currentNode.Get(i).Len() != 0 && currentNode.Get(i).Str() == "" { - it.iterateNode(pk, currentNode.Get(i), cb) + + return nil + case *FullNode: + return self.get(node.branch(key[0]), key[1:]) + default: + panic(fmt.Sprintf("%T: invalid node: %v", node, node)) + } +} + +func (self *Trie) delete(node Node, key []byte) Node { + if len(key) == 0 && node == nil { + return nil + } + + switch node := node.(type) { + case *ShortNode: + k := node.Key() + cnode := node.Value() + if bytes.Equal(key, k) { + return nil + } else if bytes.Equal(key[:len(k)], k) { + child := self.delete(cnode, key[len(k):]) + + var n Node + switch child := child.(type) { + case *ShortNode: + nkey := append(k, child.Key()...) + n = NewShortNode(self, nkey, child.Value()) + case *FullNode: + sn := NewShortNode(self, node.Key(), child) + sn.key = node.key + n = sn + } + + return n + } else { + return node + } + + case *FullNode: + n := node.Copy().(*FullNode) + n.set(key[0], self.delete(n.branch(key[0]), key[1:])) + + pos := -1 + for i := 0; i < 17; i++ { + if n.branch(byte(i)) != nil { + if pos == -1 { + pos = i } else { - val := currentNode.Get(i).Str() - if val != "" { - it.fetchNode(pk, []byte(val), cb) - } + pos = -2 } } } + + var nnode Node + if pos == 16 { + nnode = NewShortNode(self, []byte{16}, n.branch(byte(pos))) + } else if pos >= 0 { + cnode := n.branch(byte(pos)) + switch cnode := cnode.(type) { + case *ShortNode: + // Stitch keys + k := append([]byte{byte(pos)}, cnode.Key()...) + nnode = NewShortNode(self, k, cnode.Value()) + case *FullNode: + nnode = NewShortNode(self, []byte{byte(pos)}, n.branch(byte(pos))) + } + } else { + nnode = n + } + + return nnode + case nil: + return nil + default: + panic(fmt.Sprintf("%T: invalid node: %v (%v)", node, node, key)) } } + +// casting functions and cache storing +func (self *Trie) mknode(value *ethutil.Value) Node { + l := value.Len() + switch l { + case 0: + return nil + case 2: + // A value node may consists of 2 bytes. + if value.Get(0).Len() != 0 { + return NewShortNode(self, CompactDecode(string(value.Get(0).Bytes())), self.mknode(value.Get(1))) + } + case 17: + fnode := NewFullNode(self) + for i := 0; i < l; i++ { + fnode.set(byte(i), self.mknode(value.Get(i))) + } + return fnode + case 32: + return &HashNode{value.Bytes()} + } + + return &ValueNode{self, value.Bytes()} +} + +func (self *Trie) trans(node Node) Node { + switch node := node.(type) { + case *HashNode: + value := ethutil.NewValueFromBytes(self.cache.Get(node.key)) + return self.mknode(value) + default: + return node + } +} + +func (self *Trie) store(node Node) interface{} { + data := ethutil.Encode(node) + if len(data) >= 32 { + key := crypto.Sha3(data) + self.cache.Put(key, data) + + return key + } + + return node.RlpData() +} + +func (self *Trie) PrintRoot() { + fmt.Println(self.root) +} diff --git a/trie/trie_test.go b/trie/trie_test.go index 207d41f30d..ffb78d4f2b 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -2,396 +2,75 @@ package trie import ( "bytes" - "encoding/hex" - "encoding/json" "fmt" - "io/ioutil" - "math/rand" - "net/http" "testing" - "time" - - checker "gopkg.in/check.v1" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" ) -const LONG_WORD = "1234567890abcdefghijklmnopqrstuvwxxzABCEFGHIJKLMNOPQRSTUVWXYZ" +type Db map[string][]byte -type TrieSuite struct { - db *MemDatabase - trie *Trie +func (self Db) Get(k []byte) ([]byte, error) { return self[string(k)], nil } +func (self Db) Put(k, v []byte) { self[string(k)] = v } + +// Used for testing +func NewEmpty() *Trie { + return New(nil, make(Db)) } -type MemDatabase struct { - db map[string][]byte -} - -func NewMemDatabase() (*MemDatabase, error) { - db := &MemDatabase{db: make(map[string][]byte)} - return db, nil -} -func (db *MemDatabase) Put(key []byte, value []byte) { - db.db[string(key)] = value -} -func (db *MemDatabase) Get(key []byte) ([]byte, error) { - return db.db[string(key)], nil -} -func (db *MemDatabase) Delete(key []byte) error { - delete(db.db, string(key)) - return nil -} -func (db *MemDatabase) Print() {} -func (db *MemDatabase) Close() {} -func (db *MemDatabase) LastKnownTD() []byte { return nil } - -func NewTrie() (*MemDatabase, *Trie) { - db, _ := NewMemDatabase() - return db, New(db, "") -} - -func (s *TrieSuite) SetUpTest(c *checker.C) { - s.db, s.trie = NewTrie() -} - -func (s *TrieSuite) TestTrieSync(c *checker.C) { - s.trie.Update("dog", LONG_WORD) - c.Assert(s.db.db, checker.HasLen, 0, checker.Commentf("Expected no data in database")) - s.trie.Sync() - c.Assert(s.db.db, checker.HasLen, 3) -} - -func (s *TrieSuite) TestTrieDirtyTracking(c *checker.C) { - s.trie.Update("dog", LONG_WORD) - c.Assert(s.trie.cache.IsDirty, checker.Equals, true, checker.Commentf("Expected no data in database")) - - s.trie.Sync() - c.Assert(s.trie.cache.IsDirty, checker.Equals, false, checker.Commentf("Expected trie to be dirty")) - - s.trie.Update("test", LONG_WORD) - s.trie.cache.Undo() - c.Assert(s.trie.cache.IsDirty, checker.Equals, false) -} - -func (s *TrieSuite) TestTrieReset(c *checker.C) { - s.trie.Update("cat", LONG_WORD) - c.Assert(s.trie.cache.nodes, checker.HasLen, 1, checker.Commentf("Expected cached nodes")) - - s.trie.cache.Undo() - c.Assert(s.trie.cache.nodes, checker.HasLen, 0, checker.Commentf("Expected no nodes after undo")) -} - -func (s *TrieSuite) TestTrieGet(c *checker.C) { - s.trie.Update("cat", LONG_WORD) - x := s.trie.Get("cat") - c.Assert(x, checker.DeepEquals, LONG_WORD) -} - -func (s *TrieSuite) TestTrieUpdating(c *checker.C) { - s.trie.Update("cat", LONG_WORD) - s.trie.Update("cat", LONG_WORD+"1") - x := s.trie.Get("cat") - c.Assert(x, checker.DeepEquals, LONG_WORD+"1") -} - -func (s *TrieSuite) TestTrieCmp(c *checker.C) { - _, trie1 := NewTrie() - _, trie2 := NewTrie() - - trie1.Update("doge", LONG_WORD) - trie2.Update("doge", LONG_WORD) - c.Assert(trie1, checker.DeepEquals, trie2) - - trie1.Update("dog", LONG_WORD) - trie2.Update("cat", LONG_WORD) - c.Assert(trie1, checker.Not(checker.DeepEquals), trie2) -} - -func (s *TrieSuite) TestTrieDelete(c *checker.C) { - s.trie.Update("cat", LONG_WORD) - exp := s.trie.Root - s.trie.Update("dog", LONG_WORD) - s.trie.Delete("dog") - c.Assert(s.trie.Root, checker.DeepEquals, exp) - - s.trie.Update("dog", LONG_WORD) - exp = s.trie.Root - s.trie.Update("dude", LONG_WORD) - s.trie.Delete("dude") - c.Assert(s.trie.Root, checker.DeepEquals, exp) -} - -func (s *TrieSuite) TestTrieDeleteWithValue(c *checker.C) { - s.trie.Update("c", LONG_WORD) - exp := s.trie.Root - s.trie.Update("ca", LONG_WORD) - s.trie.Update("cat", LONG_WORD) - s.trie.Delete("ca") - s.trie.Delete("cat") - c.Assert(s.trie.Root, checker.DeepEquals, exp) -} - -func (s *TrieSuite) TestTriePurge(c *checker.C) { - s.trie.Update("c", LONG_WORD) - s.trie.Update("ca", LONG_WORD) - s.trie.Update("cat", LONG_WORD) - - lenBefore := len(s.trie.cache.nodes) - it := s.trie.NewIterator() - num := it.Purge() - c.Assert(num, checker.Equals, 3) - c.Assert(len(s.trie.cache.nodes), checker.Equals, lenBefore) -} - -func h(str string) string { - d, err := hex.DecodeString(str) - if err != nil { - panic(err) - } - - return string(d) -} - -func get(in string) (out string) { - if len(in) > 2 && in[:2] == "0x" { - out = h(in[2:]) - } else { - out = in - } - - return -} - -type TrieTest struct { - Name string - In map[string]string - Root string -} - -func CreateTest(name string, data []byte) (TrieTest, error) { - t := TrieTest{Name: name} - err := json.Unmarshal(data, &t) - if err != nil { - return TrieTest{}, fmt.Errorf("%v", err) - } - - return t, nil -} - -func CreateTests(uri string, cb func(TrieTest)) map[string]TrieTest { - resp, err := http.Get(uri) - if err != nil { - panic(err) - } - defer resp.Body.Close() - - data, err := ioutil.ReadAll(resp.Body) - - var objmap map[string]*json.RawMessage - err = json.Unmarshal(data, &objmap) - if err != nil { - panic(err) - } - - tests := make(map[string]TrieTest) - for name, testData := range objmap { - test, err := CreateTest(name, *testData) - if err != nil { - panic(err) - } - - if cb != nil { - cb(test) - } - tests[name] = test - } - - return tests -} - -func RandomData() [][]string { - data := [][]string{ - {"0x000000000000000000000000ec4f34c97e43fbb2816cfd95e388353c7181dab1", "0x4e616d6552656700000000000000000000000000000000000000000000000000"}, - {"0x0000000000000000000000000000000000000000000000000000000000000045", "0x22b224a1420a802ab51d326e29fa98e34c4f24ea"}, - {"0x0000000000000000000000000000000000000000000000000000000000000046", "0x67706c2076330000000000000000000000000000000000000000000000000000"}, - {"0x000000000000000000000000697c7b8c961b56f675d570498424ac8de1a918f6", "0x6f6f6f6820736f2067726561742c207265616c6c6c793f000000000000000000"}, - {"0x0000000000000000000000007ef9e639e2733cb34e4dfc576d4b23f72db776b2", "0x4655474156000000000000000000000000000000000000000000000000000000"}, - {"0x6f6f6f6820736f2067726561742c207265616c6c6c793f000000000000000000", "0x697c7b8c961b56f675d570498424ac8de1a918f6"}, - {"0x4655474156000000000000000000000000000000000000000000000000000000", "0x7ef9e639e2733cb34e4dfc576d4b23f72db776b2"}, - {"0x4e616d6552656700000000000000000000000000000000000000000000000000", "0xec4f34c97e43fbb2816cfd95e388353c7181dab1"}, - } - - var c [][]string - for len(data) != 0 { - e := rand.Intn(len(data)) - c = append(c, data[e]) - - copy(data[e:], data[e+1:]) - data[len(data)-1] = nil - data = data[:len(data)-1] - } - - return c -} - -const MaxTest = 1000 - -// This test insert data in random order and seeks to find indifferences between the different tries -func (s *TrieSuite) TestRegression(c *checker.C) { - rand.Seed(time.Now().Unix()) - - roots := make(map[string]int) - for i := 0; i < MaxTest; i++ { - _, trie := NewTrie() - data := RandomData() - - for _, test := range data { - trie.Update(test[0], test[1]) - } - trie.Delete("0x4e616d6552656700000000000000000000000000000000000000000000000000") - - roots[string(trie.Root.([]byte))] += 1 - } - - c.Assert(len(roots) <= 1, checker.Equals, true) - // if len(roots) > 1 { - // for root, num := range roots { - // t.Errorf("%x => %d\n", root, num) - // } - // } -} - -func (s *TrieSuite) TestDelete(c *checker.C) { - s.trie.Update("a", "jeffreytestlongstring") - s.trie.Update("aa", "otherstring") - s.trie.Update("aaa", "othermorestring") - s.trie.Update("aabbbbccc", "hithere") - s.trie.Update("abbcccdd", "hstanoehutnaheoustnh") - s.trie.Update("rnthaoeuabbcccdd", "hstanoehutnaheoustnh") - s.trie.Update("rneuabbcccdd", "hstanoehutnaheoustnh") - s.trie.Update("rneuabboeusntahoeucccdd", "hstanoehutnaheoustnh") - s.trie.Update("rnxabboeusntahoeucccdd", "hstanoehutnaheoustnh") - s.trie.Delete("aaboaestnuhbccc") - s.trie.Delete("a") - s.trie.Update("a", "nthaonethaosentuh") - s.trie.Update("c", "shtaosntehua") - s.trie.Delete("a") - s.trie.Update("aaaa", "testmegood") - - _, t2 := NewTrie() - s.trie.NewIterator().Each(func(key string, v *ethutil.Value) { - if key == "aaaa" { - t2.Update(key, v.Str()) - } else { - t2.Update(key, v.Str()) - } - }) - - a := ethutil.NewValue(s.trie.Root).Bytes() - b := ethutil.NewValue(t2.Root).Bytes() - - c.Assert(a, checker.DeepEquals, b) -} - -func (s *TrieSuite) TestTerminator(c *checker.C) { - key := CompactDecode("hello") - c.Assert(HasTerm(key), checker.Equals, true, checker.Commentf("Expected %v to have a terminator", key)) -} - -func (s *TrieSuite) TestIt(c *checker.C) { - s.trie.Update("cat", "cat") - s.trie.Update("doge", "doge") - s.trie.Update("wallace", "wallace") - it := s.trie.Iterator() - - inputs := []struct { - In, Out string - }{ - {"", "cat"}, - {"bobo", "cat"}, - {"c", "cat"}, - {"car", "cat"}, - {"catering", "doge"}, - {"w", "wallace"}, - {"wallace123", ""}, - } - - for _, test := range inputs { - res := string(it.Next(test.In)) - c.Assert(res, checker.Equals, test.Out) +func TestEmptyTrie(t *testing.T) { + trie := NewEmpty() + res := trie.Hash() + exp := crypto.Sha3(ethutil.Encode("")) + if !bytes.Equal(res, exp) { + t.Errorf("expected %x got %x", exp, res) } } -func (s *TrieSuite) TestBeginsWith(c *checker.C) { - a := CompactDecode("hello") - b := CompactDecode("hel") +func TestInsert(t *testing.T) { + trie := NewEmpty() - c.Assert(BeginsWith(a, b), checker.Equals, false) - c.Assert(BeginsWith(b, a), checker.Equals, true) + trie.UpdateString("doe", "reindeer") + trie.UpdateString("dog", "puppy") + trie.UpdateString("dogglesworth", "cat") + + exp := ethutil.Hex2Bytes("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3") + root := trie.Hash() + if !bytes.Equal(root, exp) { + t.Errorf("exp %x got %x", exp, root) + } + + trie = NewEmpty() + trie.UpdateString("A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") + + exp = ethutil.Hex2Bytes("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab") + root = trie.Hash() + if !bytes.Equal(root, exp) { + t.Errorf("exp %x got %x", exp, root) + } } -func (s *TrieSuite) TestItems(c *checker.C) { - s.trie.Update("A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") - exp := "d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab" +func TestGet(t *testing.T) { + trie := NewEmpty() - c.Assert(s.trie.GetRoot(), checker.DeepEquals, ethutil.Hex2Bytes(exp)) + trie.UpdateString("doe", "reindeer") + trie.UpdateString("dog", "puppy") + trie.UpdateString("dogglesworth", "cat") + + res := trie.GetString("dog") + if !bytes.Equal(res, []byte("puppy")) { + t.Errorf("expected puppy got %x", res) + } + + unknown := trie.GetString("unknown") + if unknown != nil { + t.Errorf("expected nil got %x", unknown) + } } -/* -func TestRndCase(t *testing.T) { - _, trie := NewTrie() - - data := []struct{ k, v string }{ - {"0000000000000000000000000000000000000000000000000000000000000001", "a07573657264617461000000000000000000000000000000000000000000000000"}, - {"0000000000000000000000000000000000000000000000000000000000000003", "8453bb5b31"}, - {"0000000000000000000000000000000000000000000000000000000000000004", "850218711a00"}, - {"0000000000000000000000000000000000000000000000000000000000000005", "9462d7705bd0b3ecbc51a8026a25597cb28a650c79"}, - {"0000000000000000000000000000000000000000000000000000000000000010", "947e70f9460402290a3e487dae01f610a1a8218fda"}, - {"0000000000000000000000000000000000000000000000000000000000000111", "01"}, - {"0000000000000000000000000000000000000000000000000000000000000112", "a053656e6174650000000000000000000000000000000000000000000000000000"}, - {"0000000000000000000000000000000000000000000000000000000000000113", "a053656e6174650000000000000000000000000000000000000000000000000000"}, - {"53656e6174650000000000000000000000000000000000000000000000000000", "94977e3f62f5e1ed7953697430303a3cfa2b5b736e"}, - } - for _, e := range data { - trie.Update(string(ethutil.Hex2Bytes(e.k)), string(ethutil.Hex2Bytes(e.v))) - } - - fmt.Printf("root after update %x\n", trie.Root) - trie.NewIterator().Each(func(k string, v *ethutil.Value) { - fmt.Printf("%x %x\n", k, v.Bytes()) - }) - - data = []struct{ k, v string }{ - {"0000000000000000000000000000000000000000000000000000000000000112", ""}, - {"436974697a656e73000000000000000000000000000000000000000000000001", ""}, - {"436f757274000000000000000000000000000000000000000000000000000002", ""}, - {"53656e6174650000000000000000000000000000000000000000000000000000", ""}, - {"436f757274000000000000000000000000000000000000000000000000000000", ""}, - {"53656e6174650000000000000000000000000000000000000000000000000001", ""}, - {"0000000000000000000000000000000000000000000000000000000000000113", ""}, - {"436974697a656e73000000000000000000000000000000000000000000000000", ""}, - {"436974697a656e73000000000000000000000000000000000000000000000002", ""}, - {"436f757274000000000000000000000000000000000000000000000000000001", ""}, - {"0000000000000000000000000000000000000000000000000000000000000111", ""}, - {"53656e6174650000000000000000000000000000000000000000000000000002", ""}, - } - - for _, e := range data { - trie.Delete(string(ethutil.Hex2Bytes(e.k))) - } - - fmt.Printf("root after delete %x\n", trie.Root) - - trie.NewIterator().Each(func(k string, v *ethutil.Value) { - fmt.Printf("%x %x\n", k, v.Bytes()) - }) - - fmt.Printf("%x\n", trie.Get(string(ethutil.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")))) -} -*/ - -func TestOtherSomething(t *testing.T) { - _, trie := NewTrie() +func TestDelete(t *testing.T) { + trie := NewEmpty() vals := []struct{ k, v string }{ {"do", "verb"}, @@ -404,18 +83,46 @@ func TestOtherSomething(t *testing.T) { {"shaman", ""}, } for _, val := range vals { - trie.Update(val.k, val.v) + if val.v != "" { + trie.UpdateString(val.k, val.v) + } else { + trie.DeleteString(val.k) + } } + hash := trie.Hash() exp := ethutil.Hex2Bytes("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84") - hash := trie.Root.([]byte) if !bytes.Equal(hash, exp) { t.Errorf("expected %x got %x", exp, hash) } } -func BenchmarkGets(b *testing.B) { - _, trie := NewTrie() +func TestEmptyValues(t *testing.T) { + trie := NewEmpty() + + vals := []struct{ k, v string }{ + {"do", "verb"}, + {"ether", "wookiedoo"}, + {"horse", "stallion"}, + {"shaman", "horse"}, + {"doge", "coin"}, + {"ether", ""}, + {"dog", "puppy"}, + {"shaman", ""}, + } + for _, val := range vals { + trie.UpdateString(val.k, val.v) + } + + hash := trie.Hash() + exp := ethutil.Hex2Bytes("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84") + if !bytes.Equal(hash, exp) { + t.Errorf("expected %x got %x", exp, hash) + } +} + +func TestReplication(t *testing.T) { + trie := NewEmpty() vals := []struct{ k, v string }{ {"do", "verb"}, {"ether", "wookiedoo"}, @@ -428,20 +135,125 @@ func BenchmarkGets(b *testing.B) { {"somethingveryoddindeedthis is", "myothernodedata"}, } for _, val := range vals { - trie.Update(val.k, val.v) + trie.UpdateString(val.k, val.v) + } + trie.Commit() + + trie2 := New(trie.roothash, trie.cache.backend) + if string(trie2.GetString("horse")) != "stallion" { + t.Error("expected to have horse => stallion") + } + + hash := trie2.Hash() + exp := trie.Hash() + if !bytes.Equal(hash, exp) { + t.Errorf("root failure. expected %x got %x", exp, hash) + } + +} + +func TestReset(t *testing.T) { + trie := NewEmpty() + vals := []struct{ k, v string }{ + {"do", "verb"}, + {"ether", "wookiedoo"}, + {"horse", "stallion"}, + } + for _, val := range vals { + trie.UpdateString(val.k, val.v) + } + trie.Commit() + + before := ethutil.CopyBytes(trie.roothash) + trie.UpdateString("should", "revert") + trie.Hash() + // Should have no effect + trie.Hash() + trie.Hash() + // ### + + trie.Reset() + after := ethutil.CopyBytes(trie.roothash) + + if !bytes.Equal(before, after) { + t.Errorf("expected roots to be equal. %x - %x", before, after) + } +} + +func TestParanoia(t *testing.T) { + t.Skip() + trie := NewEmpty() + + vals := []struct{ k, v string }{ + {"do", "verb"}, + {"ether", "wookiedoo"}, + {"horse", "stallion"}, + {"shaman", "horse"}, + {"doge", "coin"}, + {"ether", ""}, + {"dog", "puppy"}, + {"shaman", ""}, + {"somethingveryoddindeedthis is", "myothernodedata"}, + } + for _, val := range vals { + trie.UpdateString(val.k, val.v) + } + trie.Commit() + + ok, t2 := ParanoiaCheck(trie, trie.cache.backend) + if !ok { + t.Errorf("trie paranoia check failed %x %x", trie.roothash, t2.roothash) + } +} + +// Not an actual test +func TestOutput(t *testing.T) { + t.Skip() + + base := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + trie := NewEmpty() + for i := 0; i < 50; i++ { + trie.UpdateString(fmt.Sprintf("%s%d", base, i), "valueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") + } + fmt.Println("############################## FULL ################################") + fmt.Println(trie.root) + + trie.Commit() + fmt.Println("############################## SMALL ################################") + trie2 := New(trie.roothash, trie.cache.backend) + trie2.GetString(base + "20") + fmt.Println(trie2.root) +} + +func BenchmarkGets(b *testing.B) { + trie := NewEmpty() + vals := []struct{ k, v string }{ + {"do", "verb"}, + {"ether", "wookiedoo"}, + {"horse", "stallion"}, + {"shaman", "horse"}, + {"doge", "coin"}, + {"ether", ""}, + {"dog", "puppy"}, + {"shaman", ""}, + {"somethingveryoddindeedthis is", "myothernodedata"}, + } + for _, val := range vals { + trie.UpdateString(val.k, val.v) } b.ResetTimer() for i := 0; i < b.N; i++ { - trie.Get("horse") + trie.Get([]byte("horse")) } } func BenchmarkUpdate(b *testing.B) { - _, trie := NewTrie() + trie := NewEmpty() b.ResetTimer() for i := 0; i < b.N; i++ { - trie.Update(fmt.Sprintf("aaaaaaaaaaaaaaa%d", i), "value") + trie.UpdateString(fmt.Sprintf("aaaaaaaaa%d", i), "value") } + trie.Hash() } diff --git a/ptrie/valuenode.go b/trie/valuenode.go similarity index 97% rename from ptrie/valuenode.go rename to trie/valuenode.go index c593eb6c60..689befb2ad 100644 --- a/ptrie/valuenode.go +++ b/trie/valuenode.go @@ -1,4 +1,4 @@ -package ptrie +package trie type ValueNode struct { trie *Trie diff --git a/ui/qt/qwhisper/message.go b/ui/qt/qwhisper/message.go new file mode 100644 index 0000000000..c876473996 --- /dev/null +++ b/ui/qt/qwhisper/message.go @@ -0,0 +1,23 @@ +package qwhisper + +import ( + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/whisper" +) + +type Message struct { + ref *whisper.Message + Flags int32 + Payload string + From string +} + +func ToQMessage(msg *whisper.Message) *Message { + return &Message{ + ref: msg, + Flags: int32(msg.Flags), + Payload: ethutil.Bytes2Hex(msg.Payload), + From: ethutil.Bytes2Hex(crypto.FromECDSAPub(msg.Recover())), + } +} diff --git a/ui/qt/qwhisper/watch.go b/ui/qt/qwhisper/watch.go new file mode 100644 index 0000000000..0ccedc7194 --- /dev/null +++ b/ui/qt/qwhisper/watch.go @@ -0,0 +1,13 @@ +package qwhisper + +import ( + "fmt" + "unsafe" +) + +type Watch struct { +} + +func (self *Watch) Arrived(v unsafe.Pointer) { + fmt.Println(v) +} diff --git a/ui/qt/qwhisper/whisper.go b/ui/qt/qwhisper/whisper.go index 8f05c06953..8b4628a1b6 100644 --- a/ui/qt/qwhisper/whisper.go +++ b/ui/qt/qwhisper/whisper.go @@ -1,16 +1,17 @@ package qwhisper import ( - "fmt" "time" - "unsafe" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/whisper" "gopkg.in/qml.v1" ) +var qlogger = logger.NewLogger("QSHH") + func fromHex(s string) []byte { if len(s) > 1 { return ethutil.Hex2Bytes(s[2:]) @@ -19,13 +20,6 @@ func fromHex(s string) []byte { } func toHex(b []byte) string { return "0x" + ethutil.Bytes2Hex(b) } -type Watch struct { -} - -func (self *Watch) Arrived(v unsafe.Pointer) { - fmt.Println(v) -} - type Whisper struct { *whisper.Whisper view qml.Object @@ -41,22 +35,27 @@ func (self *Whisper) SetView(view qml.Object) { self.view = view } -func (self *Whisper) Post(data string, to, from string, topics []string, pow, ttl uint32) { - msg := whisper.NewMessage(fromHex(data)) - envelope, err := msg.Seal(time.Duration(pow), whisper.Opts{ +func (self *Whisper) Post(payload []string, to, from string, topics []string, priority, ttl uint32) { + var data []byte + for _, d := range payload { + data = append(data, fromHex(d)...) + } + + msg := whisper.NewMessage(data) + envelope, err := msg.Seal(time.Duration(priority*100000), whisper.Opts{ Ttl: time.Duration(ttl), To: crypto.ToECDSAPub(fromHex(to)), From: crypto.ToECDSA(fromHex(from)), Topics: whisper.TopicsFromString(topics...), }) if err != nil { - fmt.Println(err) + qlogger.Infoln(err) // handle error return } if err := self.Whisper.Send(envelope); err != nil { - fmt.Println(err) + qlogger.Infoln(err) // handle error return } @@ -70,15 +69,19 @@ func (self *Whisper) HasIdentity(key string) bool { return self.Whisper.HasIdentity(crypto.ToECDSA(fromHex(key))) } -func (self *Whisper) Watch(opts map[string]interface{}) *Watch { +func (self *Whisper) Watch(opts map[string]interface{}, view *qml.Common) int { filter := filterFromMap(opts) + var i int filter.Fn = func(msg *whisper.Message) { - fmt.Println(msg) + if view != nil { + view.Call("onShhMessage", ToQMessage(msg), i) + } } - i := self.Whisper.Watch(filter) + + i = self.Whisper.Watch(filter) self.watches[i] = &Watch{} - return self.watches[i] + return i } func filterFromMap(opts map[string]interface{}) (f whisper.Filter) { diff --git a/update-license.go b/update-license.go new file mode 100644 index 0000000000..d5e21fdd3f --- /dev/null +++ b/update-license.go @@ -0,0 +1,247 @@ +// +build none +/* +This command generates GPL license headers on top of all source files. +You can run it once per month, before cutting a release or just +whenever you feel like it. + + go run update-license.go + +The copyright in each file is assigned to any authors for which git +can find commits in the file's history. It will try to follow renames +throughout history. The author names are mapped and deduplicated using +the .mailmap file. You can use .mailmap to set the canonical name and +address for each author. See git-shortlog(1) for an explanation +of the .mailmap format. + +Please review the resulting diff to check whether the correct +copyright assignments are performed. +*/ +package main + +import ( + "bufio" + "bytes" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path" + "regexp" + "runtime" + "sort" + "strings" + "sync" + "text/template" +) + +var ( + // only files with these extensions will be considered + extensions = []string{".go", ".js", ".qml"} + + // paths with any of these prefixes will be skipped + skipPrefixes = []string{"tests/files/", "cmd/mist/assets/ext/", "cmd/mist/assets/muted/"} + + // paths with this prefix are licensed as GPL. all other files are LGPL. + gplPrefixes = []string{"cmd/"} + + // this regexp must match the entire license comment at the + // beginning of each file. + licenseCommentRE = regexp.MustCompile(`(?s)^/\*\s*(Copyright|This file is part of) .*?\*/\n*`) + + // this line is used when git doesn't find any authors for a file + defaultCopyright = "Copyright (C) 2014 Jeffrey Wilcke " +) + +// this template generates the license comment. +// its input is an info structure. +var licenseT = template.Must(template.New("").Parse(`/* + {{.Copyrights}} + + 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 {{.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 {{.License}} for more details. + + You should have received a copy of the GNU {{.License}} + along with go-ethereum. If not, see . +*/ + +`)) + +type info struct { + file string + mode os.FileMode + authors map[string][]string // map keys are authors, values are years + gpl bool +} + +func (i info) Copyrights() string { + var lines []string + for name, years := range i.authors { + lines = append(lines, "Copyright (C) "+strings.Join(years, ", ")+" "+name) + } + if len(lines) == 0 { + lines = []string{defaultCopyright} + } + sort.Strings(lines) + return strings.Join(lines, "\n\t") +} + +func (i info) License() string { + if i.gpl { + return "General Public License" + } else { + return "Lesser General Public License" + } +} + +func (i info) ShortLicense() string { + if i.gpl { + return "GPL" + } else { + return "LGPL" + } +} + +func (i *info) addAuthorYear(name, year string) { + for _, y := range i.authors[name] { + if y == year { + return + } + } + i.authors[name] = append(i.authors[name], year) + sort.Strings(i.authors[name]) +} + +func main() { + files := make(chan string) + infos := make(chan *info) + wg := new(sync.WaitGroup) + + go getFiles(files) + for i := runtime.NumCPU(); i >= 0; i-- { + // getting file info is slow and needs to be parallel + wg.Add(1) + go getInfo(files, infos, wg) + } + go func() { wg.Wait(); close(infos) }() + writeLicenses(infos) +} + +func getFiles(out chan<- string) { + cmd := exec.Command("git", "ls-tree", "-r", "--name-only", "HEAD") + err := doLines(cmd, func(line string) { + for _, p := range skipPrefixes { + if strings.HasPrefix(line, p) { + return + } + } + ext := path.Ext(line) + for _, wantExt := range extensions { + if ext == wantExt { + goto send + } + } + return + + send: + out <- line + }) + if err != nil { + fmt.Println("error getting files:", err) + } + close(out) +} + +func getInfo(files <-chan string, out chan<- *info, wg *sync.WaitGroup) { + for file := range files { + stat, err := os.Lstat(file) + if err != nil { + fmt.Printf("ERROR %s: %v\n", file, err) + continue + } + if !stat.Mode().IsRegular() { + continue + } + info, err := fileInfo(file) + if err != nil { + fmt.Printf("ERROR %s: %v\n", file, err) + continue + } + info.mode = stat.Mode() + out <- info + } + wg.Done() +} + +func fileInfo(file string) (*info, error) { + info := &info{file: file, authors: make(map[string][]string)} + for _, p := range gplPrefixes { + if strings.HasPrefix(file, p) { + info.gpl = true + break + } + } + cmd := exec.Command("git", "log", "--follow", "--find-copies", "--pretty=format:%aI | %aN <%aE>", "--", file) + err := doLines(cmd, func(line string) { + sep := strings.IndexByte(line, '|') + year, name := line[:4], line[sep+2:] + info.addAuthorYear(name, year) + }) + return info, err +} + +func writeLicenses(infos <-chan *info) { + buf := new(bytes.Buffer) + for info := range infos { + content, err := ioutil.ReadFile(info.file) + if err != nil { + fmt.Printf("ERROR: couldn't read %s: %v\n", info.file, err) + continue + } + + // construct new file content + buf.Reset() + licenseT.Execute(buf, info) + if m := licenseCommentRE.FindIndex(content); m != nil && m[0] == 0 { + buf.Write(content[m[1]:]) + } else { + buf.Write(content) + } + + if !bytes.Equal(content, buf.Bytes()) { + fmt.Println("writing", info.ShortLicense(), info.file) + if err := ioutil.WriteFile(info.file, buf.Bytes(), info.mode); err != nil { + fmt.Printf("ERROR: couldn't write %s: %v", info.file, err) + } + } + } +} + +func doLines(cmd *exec.Cmd, f func(string)) error { + stdout, err := cmd.StdoutPipe() + if err != nil { + return err + } + if err := cmd.Start(); err != nil { + return err + } + s := bufio.NewScanner(stdout) + for s.Scan() { + f(s.Text()) + } + if s.Err() != nil { + return s.Err() + } + if err := cmd.Wait(); err != nil { + return fmt.Errorf("%v (for %s)", err, strings.Join(cmd.Args, " ")) + } + return nil +} diff --git a/vm/address.go b/vm/address.go index 611979c941..be4284421d 100644 --- a/vm/address.go +++ b/vm/address.go @@ -21,19 +21,31 @@ func (self PrecompiledAccount) Call(in []byte) []byte { } var Precompiled = map[string]*PrecompiledAccount{ + // ECRECOVER string(ethutil.LeftPadBytes([]byte{1}, 20)): &PrecompiledAccount{func(l int) *big.Int { return GasEcrecover }, ecrecoverFunc}, + + // SHA256 string(ethutil.LeftPadBytes([]byte{2}, 20)): &PrecompiledAccount{func(l int) *big.Int { n := big.NewInt(int64(l+31)/32 + 1) n.Mul(n, GasSha256) return n }, sha256Func}, + + // RIPEMD160 string(ethutil.LeftPadBytes([]byte{3}, 20)): &PrecompiledAccount{func(l int) *big.Int { n := big.NewInt(int64(l+31)/32 + 1) n.Mul(n, GasRipemd) return n }, ripemd160Func}, + + string(ethutil.LeftPadBytes([]byte{4}, 20)): &PrecompiledAccount{func(l int) *big.Int { + n := big.NewInt(int64(l+31)/32 + 1) + n.Mul(n, GasMemCpy) + + return n + }, memCpy}, } func sha256Func(in []byte) []byte { @@ -54,3 +66,7 @@ func ecrecoverFunc(in []byte) []byte { return ethutil.LeftPadBytes(crypto.Sha3(crypto.Ecrecover(append(hash, sig...))[1:])[12:], 32) } + +func memCpy(in []byte) []byte { + return in +} diff --git a/vm/analysis.go b/vm/analysis.go index fef448b7ba..411df56861 100644 --- a/vm/analysis.go +++ b/vm/analysis.go @@ -1,34 +1,19 @@ package vm -import ( - "math/big" +import "gopkg.in/fatih/set.v0" - "github.com/ethereum/go-ethereum/ethutil" -) +func analyseJumpDests(code []byte) (dests *set.Set) { + dests = set.New() -func analyseJumpDests(code []byte) (dests map[uint64]*big.Int) { - dests = make(map[uint64]*big.Int) - - lp := false - var lpv *big.Int for pc := uint64(0); pc < uint64(len(code)); pc++ { var op OpCode = OpCode(code[pc]) switch op { case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32: a := uint64(op) - uint64(PUSH1) + 1 - if uint64(len(code)) > pc+1+a { - lpv = ethutil.BigD(code[pc+1 : pc+1+a]) - } pc += a - lp = true - case JUMP, JUMPI: - if lp { - dests[pc] = lpv - } - - default: - lp = false + case JUMPDEST: + dests.Add(pc) } } return diff --git a/vm/closure.go b/vm/closure.go deleted file mode 100644 index 97b31ada04..0000000000 --- a/vm/closure.go +++ /dev/null @@ -1,107 +0,0 @@ -package vm - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/state" -) - -type ClosureRef interface { - ReturnGas(*big.Int, *big.Int) - Address() []byte - SetCode([]byte) -} - -type Closure struct { - caller ClosureRef - object ClosureRef - Code []byte - message *state.Message - - Gas, UsedGas, Price *big.Int - - Args []byte -} - -// Create a new closure for the given data items -func NewClosure(msg *state.Message, caller ClosureRef, object ClosureRef, code []byte, gas, price *big.Int) *Closure { - c := &Closure{message: msg, caller: caller, object: object, Code: code, Args: nil} - - // Gas should be a pointer so it can safely be reduced through the run - // This pointer will be off the state transition - c.Gas = gas //new(big.Int).Set(gas) - // In most cases price and value are pointers to transaction objects - // and we don't want the transaction's values to change. - c.Price = new(big.Int).Set(price) - c.UsedGas = new(big.Int) - - return c -} - -func (c *Closure) GetOp(x uint64) OpCode { - return OpCode(c.GetByte(x)) -} - -func (c *Closure) GetByte(x uint64) byte { - if x < uint64(len(c.Code)) { - return c.Code[x] - } - - return 0 -} - -func (c *Closure) GetBytes(x, y int) []byte { - if x >= len(c.Code) || y >= len(c.Code) { - return nil - } - - return c.Code[x : x+y] -} - -func (c *Closure) GetRangeValue(x, y uint64) []byte { - if x >= uint64(len(c.Code)) || y >= uint64(len(c.Code)) { - return nil - } - - return c.Code[x : x+y] -} - -func (c *Closure) Return(ret []byte) []byte { - // Return the remaining gas to the caller - c.caller.ReturnGas(c.Gas, c.Price) - - return ret -} - -/* - * Gas functions - */ -func (c *Closure) UseGas(gas *big.Int) bool { - if c.Gas.Cmp(gas) < 0 { - return false - } - - // Sub the amount of gas from the remaining - c.Gas.Sub(c.Gas, gas) - c.UsedGas.Add(c.UsedGas, gas) - - return true -} - -// Implement the caller interface -func (c *Closure) ReturnGas(gas, price *big.Int) { - // Return the gas to the closure - c.Gas.Add(c.Gas, gas) - c.UsedGas.Sub(c.UsedGas, gas) -} - -/* - * Set / Get - */ -func (c *Closure) Address() []byte { - return c.object.Address() -} - -func (self *Closure) SetCode(code []byte) { - self.Code = code -} diff --git a/vm/common.go b/vm/common.go index 529bbdeb18..f19b0fe4bc 100644 --- a/vm/common.go +++ b/vm/common.go @@ -38,6 +38,7 @@ var ( GasSha256 = big.NewInt(50) GasRipemd = big.NewInt(50) GasEcrecover = big.NewInt(500) + GasMemCpy = big.NewInt(1) Pow256 = ethutil.BigPow(2, 256) @@ -48,7 +49,7 @@ var ( S256 = ethutil.S256 ) -const MaxCallDepth = 1024 +const MaxCallDepth = 1025 func calcMemSize(off, l *big.Int) *big.Int { if l.Cmp(ethutil.Big0) == 0 { diff --git a/vm/context.go b/vm/context.go new file mode 100644 index 0000000000..d14df1aa77 --- /dev/null +++ b/vm/context.go @@ -0,0 +1,102 @@ +package vm + +import ( + "math" + "math/big" + + "github.com/ethereum/go-ethereum/ethutil" +) + +type ContextRef interface { + ReturnGas(*big.Int, *big.Int) + Address() []byte + SetCode([]byte) +} + +type Context struct { + caller ContextRef + object ContextRef + Code []byte + + Gas, UsedGas, Price *big.Int + + Args []byte +} + +// Create a new context for the given data items +func NewContext(caller ContextRef, object ContextRef, code []byte, gas, price *big.Int) *Context { + c := &Context{caller: caller, object: object, Code: code, Args: nil} + + // Gas should be a pointer so it can safely be reduced through the run + // This pointer will be off the state transition + c.Gas = gas //new(big.Int).Set(gas) + // In most cases price and value are pointers to transaction objects + // and we don't want the transaction's values to change. + c.Price = new(big.Int).Set(price) + c.UsedGas = new(big.Int) + + return c +} + +func (c *Context) GetOp(n uint64) OpCode { + return OpCode(c.GetByte(n)) +} + +func (c *Context) GetByte(n uint64) byte { + if n < uint64(len(c.Code)) { + return c.Code[n] + } + + return 0 +} + +func (c *Context) GetBytes(x, y int) []byte { + return c.GetRangeValue(uint64(x), uint64(y)) +} + +func (c *Context) GetRangeValue(x, size uint64) []byte { + x = uint64(math.Min(float64(x), float64(len(c.Code)))) + y := uint64(math.Min(float64(x+size), float64(len(c.Code)))) + + return ethutil.LeftPadBytes(c.Code[x:y], int(size)) +} + +func (c *Context) Return(ret []byte) []byte { + // Return the remaining gas to the caller + c.caller.ReturnGas(c.Gas, c.Price) + + return ret +} + +/* + * Gas functions + */ +func (c *Context) UseGas(gas *big.Int) bool { + if c.Gas.Cmp(gas) < 0 { + return false + } + + // Sub the amount of gas from the remaining + c.Gas.Sub(c.Gas, gas) + c.UsedGas.Add(c.UsedGas, gas) + + return true +} + +// Implement the caller interface +func (c *Context) ReturnGas(gas, price *big.Int) { + // Return the gas to the context + c.Gas.Add(c.Gas, gas) + c.UsedGas.Sub(c.UsedGas, gas) +} + +/* + * Set / Get + */ +func (c *Context) Address() []byte { + return c.object.Address() +} + +func (self *Context) SetCode(code []byte) { + self.Code = code +} diff --git a/vm/environment.go b/vm/environment.go index d77fb14193..8ec13ee412 100644 --- a/vm/environment.go +++ b/vm/environment.go @@ -2,6 +2,7 @@ package vm import ( "errors" + "fmt" "math/big" "github.com/ethereum/go-ethereum/ethutil" @@ -13,11 +14,10 @@ type Environment interface { Origin() []byte BlockNumber() *big.Int - PrevHash() []byte + GetHash(n uint64) []byte Coinbase() []byte Time() int64 Difficulty() *big.Int - BlockHash() []byte GasLimit() *big.Int Transfer(from, to Account, amount *big.Int) error AddLog(state.Log) @@ -25,14 +25,9 @@ type Environment interface { Depth() int SetDepth(i int) - Call(me ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) - CallCode(me ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) - Create(me ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, ClosureRef) -} - -type Object interface { - GetStorage(key *big.Int) *ethutil.Value - SetStorage(key *big.Int, value *ethutil.Value) + Call(me ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) + CallCode(me ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) + Create(me ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, ContextRef) } type Account interface { @@ -74,3 +69,7 @@ func (self *Log) Data() []byte { func (self *Log) RlpData() interface{} { return []interface{}{self.address, ethutil.ByteSliceToInterface(self.topics), self.data} } + +func (self *Log) String() string { + return fmt.Sprintf("[A=%x T=%x D=%x]", self.address, self.topics, self.data) +} diff --git a/vm/stack.go b/vm/stack.go index 6091479cb7..e31f3eb576 100644 --- a/vm/stack.go +++ b/vm/stack.go @@ -91,6 +91,12 @@ func (st *Stack) Get(amount *big.Int) []*big.Int { return nil } +func (st *Stack) require(n int) { + if st.Len() < n { + panic(fmt.Sprintf("stack underflow (%d <=> %d)", st.Len(), n)) + } +} + func (st *Stack) Print() { fmt.Println("### stack ###") if len(st.data) > 0 { @@ -136,6 +142,10 @@ func (m *Memory) Resize(size uint64) { } func (m *Memory) Get(offset, size int64) []byte { + if size == 0 { + return nil + } + if len(m.store) > int(offset) { end := int(math.Min(float64(len(m.store)), float64(offset+size))) @@ -146,6 +156,10 @@ func (m *Memory) Get(offset, size int64) []byte { } func (self *Memory) Geti(offset, size int64) (cpy []byte) { + if size == 0 { + return nil + } + if len(self.store) > int(offset) { cpy = make([]byte, size) copy(cpy, self.store[offset:offset+size]) diff --git a/vm/types.go b/vm/types.go index ec9c7e74e6..1ea80a212d 100644 --- a/vm/types.go +++ b/vm/types.go @@ -59,7 +59,7 @@ const ( const ( // 0x40 range - block operations - PREVHASH OpCode = 0x40 + iota + BLOCKHASH OpCode = 0x40 + iota COINBASE TIMESTAMP NUMBER @@ -216,7 +216,7 @@ var opCodeToString = map[OpCode]string{ GASPRICE: "TXGASPRICE", // 0x40 range - block operations - PREVHASH: "PREVHASH", + BLOCKHASH: "BLOCKHASH", COINBASE: "COINBASE", TIMESTAMP: "TIMESTAMP", NUMBER: "NUMBER", diff --git a/vm/virtual_machine.go b/vm/virtual_machine.go index 3b6f98ab2e..23ac4878f6 100644 --- a/vm/virtual_machine.go +++ b/vm/virtual_machine.go @@ -4,7 +4,7 @@ import "math/big" type VirtualMachine interface { Env() Environment - Run(me, caller ClosureRef, code []byte, value, gas, price *big.Int, data []byte) ([]byte, error) + Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, data []byte) ([]byte, error) Printf(string, ...interface{}) VirtualMachine Endl() VirtualMachine } diff --git a/vm/vm.go b/vm/vm.go index 22172cb3ae..a5ea297b32 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -20,7 +20,7 @@ func New(env Environment, typ Type) VirtualMachine { } } -func (self *Vm) Run(me, caller ClosureRef, code []byte, value, gas, price *big.Int, data []byte) (ret []byte, err error) { +func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, data []byte) (ret []byte, err error) { panic("not implemented") } diff --git a/vm/vm_debug.go b/vm/vm_debug.go index fd16a3895e..92e4154e4f 100644 --- a/vm/vm_debug.go +++ b/vm/vm_debug.go @@ -37,31 +37,27 @@ func NewDebugVm(env Environment) *DebugVm { return &DebugVm{env: env, logTy: lt, Recoverable: true} } -func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) { +func (self *DebugVm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) { self.env.SetDepth(self.env.Depth() + 1) msg := self.env.State().Manifest().AddMessage(&state.Message{ To: me.Address(), From: caller.Address(), - Input: callData, - Origin: self.env.Origin(), - Block: self.env.BlockHash(), Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(), + Input: callData, + Origin: self.env.Origin(), + Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(), Value: value, }) - closure := NewClosure(msg, caller, me, code, gas, price) - - if p := Precompiled[string(me.Address())]; p != nil { - return self.RunPrecompiled(p, callData, closure) - } + context := NewContext(caller, me, code, gas, price) if self.Recoverable { // Recover from any require exception defer func() { if r := recover(); r != nil { - self.Endl() + self.Printf(" %v", r).Endl() - closure.UseGas(closure.Gas) + context.UseGas(context.Gas) - ret = closure.Return(nil) + ret = context.Return(nil) err = fmt.Errorf("%v", r) @@ -69,52 +65,43 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * }() } + if p := Precompiled[string(me.Address())]; p != nil { + return self.RunPrecompiled(p, callData, context) + } + var ( op OpCode - destinations = analyseJumpDests(closure.Code) + destinations = analyseJumpDests(context.Code) mem = NewMemory() stack = NewStack() pc uint64 = 0 step = 0 prevStep = 0 statedb = self.env.State() - require = func(m int) { - if stack.Len() < m { - panic(fmt.Sprintf("%04v (%v) stack err size = %d, required = %d", pc, op, stack.Len(), m)) - } - } jump = func(from uint64, to *big.Int) { p := to.Uint64() - self.Printf(" ~> %v", to) - // Return to start - if p == 0 { - pc = 0 - } else { - nop := OpCode(closure.GetOp(p)) - if !(nop == JUMPDEST || destinations[from] != nil) { - panic(fmt.Sprintf("invalid jump destination (%v) %v", nop, p)) - } else if nop == JUMP || nop == JUMPI { - panic(fmt.Sprintf("not allowed to JUMP(I) in to JUMP")) - } - - pc = to.Uint64() - + nop := context.GetOp(p) + if !destinations.Has(p) { + panic(fmt.Sprintf("invalid jump destination (%v) %v", nop, p)) } + self.Printf(" ~> %v", to) + pc = to.Uint64() + self.Endl() } ) + vmlogger.Debugf("(%d) (%x) %x (code=%d) gas: %v (d) %x\n", self.env.Depth(), caller.Address()[:4], context.Address(), len(code), context.Gas, callData) + // Don't bother with the execution if there's no code. if len(code) == 0 { - return closure.Return(nil), nil + return context.Return(nil), nil } - vmlogger.Debugf("(%d) (%x) %x gas: %v (d) %x\n", self.env.Depth(), caller.Address()[:4], closure.Address(), closure.Gas, callData) - for { prevStep = step // The base for all big integer arithmetic @@ -122,165 +109,22 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * step++ // Get the memory location of pc - op = closure.GetOp(pc) + op = context.GetOp(pc) - gas := new(big.Int) - addStepGasUsage := func(amount *big.Int) { - if amount.Cmp(ethutil.Big0) >= 0 { - gas.Add(gas, amount) - } - } + self.Printf("(pc) %-3d -o- %-14s (m) %-4d (s) %-4d ", pc, op.String(), mem.Len(), stack.Len()) - addStepGasUsage(GasStep) + newMemSize, gas := self.calculateGasAndSize(context, caller, op, statedb, mem, stack) - var newMemSize *big.Int = ethutil.Big0 - // Stack Check, memory resize & gas phase - switch op { - // Stack checks only - case ISZERO, CALLDATALOAD, POP, JUMP, NOT: // 1 - require(1) - case ADD, SUB, DIV, SDIV, MOD, SMOD, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE: // 2 - require(2) - case ADDMOD, MULMOD: // 3 - require(3) - case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16: - n := int(op - SWAP1 + 2) - require(n) - case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16: - n := int(op - DUP1 + 1) - require(n) - case LOG0, LOG1, LOG2, LOG3, LOG4: - n := int(op - LOG0) - require(n + 2) + self.Printf("(g) %-3v (%v)", gas, context.Gas) - gas.Set(GasLog) - addStepGasUsage(new(big.Int).Mul(big.NewInt(int64(n)), GasLog)) - - mSize, mStart := stack.Peekn() - addStepGasUsage(mSize) - - newMemSize = calcMemSize(mStart, mSize) - case EXP: - require(2) - - gas.Set(big.NewInt(int64(len(stack.data[stack.Len()-2].Bytes()) + 1))) - // Gas only - case STOP: - gas.Set(ethutil.Big0) - case SUICIDE: - require(1) - - gas.Set(ethutil.Big0) - case SLOAD: - require(1) - - gas.Set(GasSLoad) - // Memory resize & Gas - case SSTORE: - require(2) - - var mult *big.Int - y, x := stack.Peekn() - val := statedb.GetState(closure.Address(), x.Bytes()) - if len(val) == 0 && len(y.Bytes()) > 0 { - // 0 => non 0 - mult = ethutil.Big3 - } else if len(val) > 0 && len(y.Bytes()) == 0 { - statedb.Refund(caller.Address(), GasSStoreRefund) - - mult = ethutil.Big0 - } else { - // non 0 => non 0 (or 0 => 0) - mult = ethutil.Big1 - } - gas.Set(new(big.Int).Mul(mult, GasSStore)) - case BALANCE: - require(1) - gas.Set(GasBalance) - case MSTORE: - require(2) - newMemSize = calcMemSize(stack.Peek(), u256(32)) - case MLOAD: - require(1) - - newMemSize = calcMemSize(stack.Peek(), u256(32)) - case MSTORE8: - require(2) - newMemSize = calcMemSize(stack.Peek(), u256(1)) - case RETURN: - require(2) - - newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2]) - case SHA3: - require(2) - - gas.Set(GasSha) - - newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2]) - case CALLDATACOPY: - require(2) - - newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3]) - case CODECOPY: - require(3) - - newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3]) - case EXTCODECOPY: - require(4) - - newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-4]) - case CALL, CALLCODE: - require(7) - gas.Set(GasCall) - addStepGasUsage(stack.data[stack.Len()-1]) - - x := calcMemSize(stack.data[stack.Len()-6], stack.data[stack.Len()-7]) - y := calcMemSize(stack.data[stack.Len()-4], stack.data[stack.Len()-5]) - - newMemSize = ethutil.BigMax(x, y) - case CREATE: - require(3) - gas.Set(GasCreate) - - newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-3]) - } - - if newMemSize.Cmp(ethutil.Big0) > 0 { - newMemSize.Add(newMemSize, u256(31)) - newMemSize.Div(newMemSize, u256(32)) - newMemSize.Mul(newMemSize, u256(32)) - - switch op { - case CALLDATACOPY, CODECOPY, EXTCODECOPY: - addStepGasUsage(new(big.Int).Div(newMemSize, u256(32))) - case SHA3: - g := new(big.Int).Div(newMemSize, u256(32)) - g.Mul(g, GasSha3Byte) - addStepGasUsage(g) - } - - if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 { - memGasUsage := new(big.Int).Sub(newMemSize, u256(int64(mem.Len()))) - memGasUsage.Mul(GasMemory, memGasUsage) - memGasUsage.Div(memGasUsage, u256(32)) - - addStepGasUsage(memGasUsage) - - } - - } - - self.Printf("(pc) %-3d -o- %-14s", pc, op.String()) - self.Printf(" (m) %-4d (s) %-4d (g) %-3v (%v)", mem.Len(), stack.Len(), gas, closure.Gas) - - if !closure.UseGas(gas) { + if !context.UseGas(gas) { self.Endl() - tmp := new(big.Int).Set(closure.Gas) + tmp := new(big.Int).Set(context.Gas) - closure.UseGas(closure.Gas) + context.UseGas(context.Gas) - return closure.Return(nil), OOG(gas, tmp) + return context.Return(nil), OOG(gas, tmp) } mem.Resize(newMemSize.Uint64()) @@ -558,9 +402,9 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * self.Printf(" => %x", data) // 0x30 range case ADDRESS: - stack.Push(ethutil.BigD(closure.Address())) + stack.Push(ethutil.BigD(context.Address())) - self.Printf(" => %x", closure.Address()) + self.Printf(" => %x", context.Address()) case BALANCE: addr := stack.Pop().Bytes() @@ -576,7 +420,7 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * self.Printf(" => %x", origin) case CALLER: - caller := closure.caller.Address() + caller := context.caller.Address() stack.Push(ethutil.BigD(caller)) self.Printf(" => %x", caller) @@ -633,7 +477,7 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * code = statedb.GetCode(addr) } else { - code = closure.Code + code = context.Code } l := big.NewInt(int64(len(code))) @@ -643,11 +487,9 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * case CODECOPY, EXTCODECOPY: var code []byte if op == EXTCODECOPY { - addr := stack.Pop().Bytes() - - code = statedb.GetCode(addr) + code = statedb.GetCode(stack.Pop().Bytes()) } else { - code = closure.Code + code = context.Code } var ( @@ -663,24 +505,26 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * } else if cOff+l > size { l = uint64(math.Min(float64(cOff+l), float64(size))) } - codeCopy := code[cOff : cOff+l] mem.Set(mOff, l, codeCopy) - self.Printf(" => [%v, %v, %v] %x", mOff, cOff, l, code[cOff:cOff+l]) + self.Printf(" => [%v, %v, %v] %x", mOff, cOff, l, codeCopy) case GASPRICE: - stack.Push(closure.Price) + stack.Push(context.Price) - self.Printf(" => %v", closure.Price) + self.Printf(" => %v", context.Price) // 0x40 range - case PREVHASH: - prevHash := self.env.PrevHash() + case BLOCKHASH: + num := stack.Pop() + if num.Cmp(new(big.Int).Sub(self.env.BlockNumber(), ethutil.Big256)) < 0 { + stack.Push(ethutil.Big0) + } else { + stack.Push(ethutil.BigD(self.env.GetHash(num.Uint64()))) + } - stack.Push(ethutil.BigD(prevHash)) - - self.Printf(" => 0x%x", prevHash) + self.Printf(" => 0x%x", stack.Peek().Bytes()) case COINBASE: coinbase := self.env.Coinbase() @@ -710,18 +554,15 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * // 0x50 range case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32: - //a := big.NewInt(int64(op) - int64(PUSH1) + 1) a := uint64(op - PUSH1 + 1) - //pc.Add(pc, ethutil.Big1) - val := ethutil.BigD(closure.GetRangeValue(pc+1, a)) + byts := context.GetRangeValue(pc+1, a) // Push value to stack - stack.Push(val) + stack.Push(ethutil.BigD(byts)) pc += a - //pc.Add(pc, a.Sub(a, big.NewInt(1))) step += int(op) - int(PUSH1) + 1 - self.Printf(" => 0x%x", val.Bytes()) + self.Printf(" => 0x%x", byts) case POP: stack.Pop() case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16: @@ -743,7 +584,7 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * } data := mem.Geti(mStart.Int64(), mSize.Int64()) - log := &Log{closure.Address(), topics, data} + log := &Log{context.Address(), topics, data} self.env.AddLog(log) self.Printf(" => %v", log) @@ -768,15 +609,15 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * self.Printf(" => [%v] 0x%x", off, val) case SLOAD: loc := stack.Pop() - val := ethutil.BigD(statedb.GetState(closure.Address(), loc.Bytes())) + val := ethutil.BigD(statedb.GetState(context.Address(), loc.Bytes())) stack.Push(val) self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes()) case SSTORE: val, loc := stack.Popn() - statedb.SetState(closure.Address(), loc.Bytes(), val) + statedb.SetState(context.Address(), loc.Bytes(), val) - closure.message.AddStorageChange(loc.Bytes()) + msg.AddStorageChange(loc.Bytes()) self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes()) case JUMP: @@ -798,7 +639,7 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * case MSIZE: stack.Push(big.NewInt(int64(mem.Len()))) case GAS: - stack.Push(closure.Gas) + stack.Push(context.Gas) // 0x60 range case CREATE: @@ -807,7 +648,7 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * value = stack.Pop() size, offset = stack.Popn() input = mem.Get(offset.Int64(), size.Int64()) - gas = new(big.Int).Set(closure.Gas) + gas = new(big.Int).Set(context.Gas) // Snapshot the current stack so we are able to // revert back to it later. @@ -815,15 +656,15 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * ) // Generate a new address - n := statedb.GetNonce(closure.Address()) - addr := crypto.CreateAddress(closure.Address(), n) - statedb.SetNonce(closure.Address(), n+1) + n := statedb.GetNonce(context.Address()) + addr := crypto.CreateAddress(context.Address(), n) + statedb.SetNonce(context.Address(), n+1) self.Printf(" (*) %x", addr).Endl() - closure.UseGas(closure.Gas) + context.UseGas(context.Gas) - ret, err, ref := self.env.Create(closure, addr, input, gas, price, value) + ret, err, ref := self.env.Create(context, addr, input, gas, price, value) if err != nil { stack.Push(ethutil.BigFalse) @@ -832,7 +673,7 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * // gas < len(ret) * CreateDataGas == NO_CODE dataGas := big.NewInt(int64(len(ret))) dataGas.Mul(dataGas, GasCreateByte) - if closure.UseGas(dataGas) { + if context.UseGas(dataGas) { ref.SetCode(ret) msg.Output = ret } @@ -844,7 +685,7 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * // Debug hook if self.Dbg != nil { - self.Dbg.SetCode(closure.Code) + self.Dbg.SetCode(context.Code) } case CALL, CALLCODE: self.Endl() @@ -865,9 +706,9 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * err error ) if op == CALLCODE { - ret, err = self.env.CallCode(closure, addr.Bytes(), args, gas, price, value) + ret, err = self.env.CallCode(context, addr.Bytes(), args, gas, price, value) } else { - ret, err = self.env.Call(closure, addr.Bytes(), args, gas, price, value) + ret, err = self.env.Call(context, addr.Bytes(), args, gas, price, value) } if err != nil { @@ -880,40 +721,40 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * mem.Set(retOffset.Uint64(), retSize.Uint64(), ret) } - self.Printf("resume %x (%v)", closure.Address(), closure.Gas) + self.Printf("resume %x (%v)", context.Address(), context.Gas) // Debug hook if self.Dbg != nil { - self.Dbg.SetCode(closure.Code) + self.Dbg.SetCode(context.Code) } case RETURN: size, offset := stack.Popn() ret := mem.Get(offset.Int64(), size.Int64()) - self.Printf(" => (%d) 0x%x", len(ret), ret).Endl() + self.Printf(" => [%v, %v] (%d) 0x%x", offset, size, len(ret), ret).Endl() - return closure.Return(ret), nil + return context.Return(ret), nil case SUICIDE: receiver := statedb.GetOrNewStateObject(stack.Pop().Bytes()) - balance := statedb.GetBalance(closure.Address()) + balance := statedb.GetBalance(context.Address()) self.Printf(" => (%x) %v", receiver.Address()[:4], balance) receiver.AddAmount(balance) - statedb.Delete(closure.Address()) + statedb.Delete(context.Address()) fallthrough - case STOP: // Stop the closure + case STOP: // Stop the context self.Endl() - return closure.Return(nil), nil + return context.Return(nil), nil default: vmlogger.Debugf("(pc) %-3v Invalid opcode %x\n", pc, op) - closure.ReturnGas(big.NewInt(1), nil) + context.ReturnGas(big.NewInt(1), nil) - return closure.Return(nil), fmt.Errorf("Invalid opcode %x", op) + return context.Return(nil), fmt.Errorf("Invalid opcode %x", op) } pc++ @@ -925,11 +766,11 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * if pc == uint64(instrNo) { self.Stepping = true - if !self.Dbg.BreakHook(prevStep, op, mem, stack, statedb.GetStateObject(closure.Address())) { + if !self.Dbg.BreakHook(prevStep, op, mem, stack, statedb.GetStateObject(context.Address())) { return nil, nil } } else if self.Stepping { - if !self.Dbg.StepHook(prevStep, op, mem, stack, statedb.GetStateObject(closure.Address())) { + if !self.Dbg.StepHook(prevStep, op, mem, stack, statedb.GetStateObject(context.Address())) { return nil, nil } } @@ -939,22 +780,177 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price * } } -func (self *DebugVm) RunPrecompiled(p *PrecompiledAccount, callData []byte, closure *Closure) (ret []byte, err error) { +func (self *DebugVm) calculateGasAndSize(context *Context, caller ContextRef, op OpCode, statedb *state.StateDB, mem *Memory, stack *Stack) (*big.Int, *big.Int) { + gas := new(big.Int) + addStepGasUsage := func(amount *big.Int) { + if amount.Cmp(ethutil.Big0) >= 0 { + gas.Add(gas, amount) + } + } + + addStepGasUsage(GasStep) + + var newMemSize *big.Int = ethutil.Big0 + var additionalGas *big.Int = new(big.Int) + // Stack Check, memory resize & gas phase + switch op { + // Stack checks only + case ISZERO, CALLDATALOAD, POP, JUMP, NOT: // 1 + stack.require(1) + case JUMPI, ADD, SUB, DIV, SDIV, MOD, SMOD, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE, SIGNEXTEND: // 2 + stack.require(2) + case ADDMOD, MULMOD: // 3 + stack.require(3) + case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16: + n := int(op - SWAP1 + 2) + stack.require(n) + case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16: + n := int(op - DUP1 + 1) + stack.require(n) + case LOG0, LOG1, LOG2, LOG3, LOG4: + n := int(op - LOG0) + stack.require(n + 2) + + gas.Set(GasLog) + addStepGasUsage(new(big.Int).Mul(big.NewInt(int64(n)), GasLog)) + + mSize, mStart := stack.Peekn() + addStepGasUsage(mSize) + + newMemSize = calcMemSize(mStart, mSize) + case EXP: + stack.require(2) + + gas.Set(big.NewInt(int64(len(stack.data[stack.Len()-2].Bytes()) + 1))) + // Gas only + case STOP: + gas.Set(ethutil.Big0) + case SUICIDE: + stack.require(1) + + gas.Set(ethutil.Big0) + case SLOAD: + stack.require(1) + + gas.Set(GasSLoad) + // Memory resize & Gas + case SSTORE: + stack.require(2) + + var mult *big.Int + y, x := stack.Peekn() + val := statedb.GetState(context.Address(), x.Bytes()) + if len(val) == 0 && len(y.Bytes()) > 0 { + // 0 => non 0 + mult = ethutil.Big3 + } else if len(val) > 0 && len(y.Bytes()) == 0 { + statedb.Refund(caller.Address(), GasSStoreRefund) + + mult = ethutil.Big0 + } else { + // non 0 => non 0 (or 0 => 0) + mult = ethutil.Big1 + } + gas.Set(new(big.Int).Mul(mult, GasSStore)) + case BALANCE: + stack.require(1) + gas.Set(GasBalance) + case MSTORE: + stack.require(2) + newMemSize = calcMemSize(stack.Peek(), u256(32)) + case MLOAD: + stack.require(1) + + newMemSize = calcMemSize(stack.Peek(), u256(32)) + case MSTORE8: + stack.require(2) + newMemSize = calcMemSize(stack.Peek(), u256(1)) + case RETURN: + stack.require(2) + + newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2]) + case SHA3: + stack.require(2) + gas.Set(GasSha) + newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2]) + additionalGas.Set(stack.data[stack.Len()-2]) + case CALLDATACOPY: + stack.require(2) + + newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3]) + additionalGas.Set(stack.data[stack.Len()-3]) + case CODECOPY: + stack.require(3) + + newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3]) + additionalGas.Set(stack.data[stack.Len()-3]) + case EXTCODECOPY: + stack.require(4) + + newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-4]) + additionalGas.Set(stack.data[stack.Len()-4]) + case CALL, CALLCODE: + stack.require(7) + gas.Set(GasCall) + addStepGasUsage(stack.data[stack.Len()-1]) + + x := calcMemSize(stack.data[stack.Len()-6], stack.data[stack.Len()-7]) + y := calcMemSize(stack.data[stack.Len()-4], stack.data[stack.Len()-5]) + + newMemSize = ethutil.BigMax(x, y) + case CREATE: + stack.require(3) + gas.Set(GasCreate) + + newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-3]) + } + + switch op { + case CALLDATACOPY, CODECOPY, EXTCODECOPY: + additionalGas.Add(additionalGas, u256(31)) + additionalGas.Div(additionalGas, u256(32)) + addStepGasUsage(additionalGas) + case SHA3: + additionalGas.Add(additionalGas, u256(31)) + additionalGas.Div(additionalGas, u256(32)) + additionalGas.Mul(additionalGas, GasSha3Byte) + addStepGasUsage(additionalGas) + } + + if newMemSize.Cmp(ethutil.Big0) > 0 { + newMemSize.Add(newMemSize, u256(31)) + newMemSize.Div(newMemSize, u256(32)) + newMemSize.Mul(newMemSize, u256(32)) + + if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 { + memGasUsage := new(big.Int).Sub(newMemSize, u256(int64(mem.Len()))) + memGasUsage.Mul(GasMemory, memGasUsage) + memGasUsage.Div(memGasUsage, u256(32)) + + addStepGasUsage(memGasUsage) + } + + } + + return newMemSize, gas +} + +func (self *DebugVm) RunPrecompiled(p *PrecompiledAccount, callData []byte, context *Context) (ret []byte, err error) { gas := p.Gas(len(callData)) - if closure.UseGas(gas) { + if context.UseGas(gas) { ret = p.Call(callData) self.Printf("NATIVE_FUNC => %x", ret) self.Endl() - return closure.Return(ret), nil + return context.Return(ret), nil } else { self.Endl() - tmp := new(big.Int).Set(closure.Gas) + tmp := new(big.Int).Set(context.Gas) - closure.UseGas(closure.Gas) + context.UseGas(context.Gas) - return closure.Return(nil), OOG(gas, tmp) + return context.Return(nil), OOG(gas, tmp) } } diff --git a/websocket/client.go b/websocket/client.go index d961816e8d..db2c8e5c91 100644 --- a/websocket/client.go +++ b/websocket/client.go @@ -50,8 +50,8 @@ func (c *Client) Conn() *ws.Conn { return c.ws } -func (c *Client) Write(data interface{}, seed int) { - msg := &Message{Seed: seed, Data: data} +func (c *Client) Write(data interface{}, id int) { + msg := &Message{Id: id, Data: data} select { case c.ch <- msg: default: @@ -73,7 +73,6 @@ func (c *Client) Listen() { // Listen write request via chanel func (c *Client) listenWrite() { - wslogger.Debugln("Listening write to client") for { select { @@ -93,7 +92,6 @@ func (c *Client) listenWrite() { // Listen read request via chanel func (c *Client) listenRead() { - wslogger.Debugln("Listening read from client") for { select { diff --git a/websocket/message.go b/websocket/message.go index 67289c4c49..73b47456f6 100644 --- a/websocket/message.go +++ b/websocket/message.go @@ -5,7 +5,7 @@ import "github.com/ethereum/go-ethereum/ethutil" type Message struct { Call string `json:"call"` Args []interface{} `json:"args"` - Seed int `json:"seed"` + Id int `json:"_id"` Data interface{} `json:"data"` } diff --git a/websocket/server.go b/websocket/server.go index 5fd923a0c6..b0658b1b44 100644 --- a/websocket/server.go +++ b/websocket/server.go @@ -81,8 +81,6 @@ func (s *Server) MessageFunc(f MsgFunc) { // Listen and serve. // It serves client connection and broadcast request. func (s *Server) Listen() { - wslogger.Debugln("Listening server...") - // ws handler onConnected := func(ws *ws.Conn) { defer func() { diff --git a/whisper/envelope.go b/whisper/envelope.go index 066e20f6a3..9d28dfa6be 100644 --- a/whisper/envelope.go +++ b/whisper/envelope.go @@ -79,6 +79,7 @@ func (self *Envelope) Open(prv *ecdsa.PrivateKey) (msg *Message, err error) { if prv != nil { message.Payload, err = crypto.Decrypt(prv, payload) switch err { + case nil: // OK case ecies.ErrInvalidPublicKey: // Payload isn't encrypted message.Payload = payload return &message, err diff --git a/whisper/messages_test.go b/whisper/messages_test.go index cba103011d..93caa31b36 100644 --- a/whisper/messages_test.go +++ b/whisper/messages_test.go @@ -40,12 +40,11 @@ func TestMessageEncryptDecrypt(t *testing.T) { msg1, err := envelope.Open(prv2) if err != nil { - fmt.Println(err) + t.Error(err) t.FailNow() } if !bytes.Equal(msg1.Payload, data) { - fmt.Println("encryption error. data did not match") - t.FailNow() + t.Error("encryption error. data did not match") } } diff --git a/whisper/peer.go b/whisper/peer.go index d42b374b53..f82cc6e3e7 100644 --- a/whisper/peer.go +++ b/whisper/peer.go @@ -55,7 +55,7 @@ out: case <-relay.C: err := self.broadcast(self.host.envelopes()) if err != nil { - self.peer.Infoln(err) + self.peer.Infoln("broadcast err:", err) break out } diff --git a/whisper/whisper.go b/whisper/whisper.go index 9721ca9f9a..3ff4bac5ac 100644 --- a/whisper/whisper.go +++ b/whisper/whisper.go @@ -175,7 +175,7 @@ func (self *Whisper) add(envelope *Envelope) error { if !self.expiry[envelope.Expiry].Has(hash) { self.expiry[envelope.Expiry].Add(hash) - self.postEvent(envelope) + go self.postEvent(envelope) } return nil @@ -229,11 +229,11 @@ func (self *Whisper) envelopes() (envelopes []*Envelope) { func (self *Whisper) postEvent(envelope *Envelope) { for _, key := range self.keys { if message, err := envelope.Open(key); err == nil || (err != nil && err == ecies.ErrInvalidPublicKey) { - // Create a custom filter? self.filters.Notify(filter.Generic{ Str1: string(crypto.FromECDSA(key)), Str2: string(crypto.FromECDSAPub(message.Recover())), Data: bytesToMap(envelope.Topics), }, message) + break } else { wlogger.Infoln(err) } diff --git a/xeth/hexface.go b/xeth/hexface.go index 6c084f947c..c3d8cef864 100644 --- a/xeth/hexface.go +++ b/xeth/hexface.go @@ -138,10 +138,10 @@ type KeyVal struct { func (self *JSXEth) EachStorage(addr string) string { var values []KeyVal object := self.World().SafeGet(ethutil.Hex2Bytes(addr)) - object.EachStorage(func(name string, value *ethutil.Value) { - value.Decode() - values = append(values, KeyVal{ethutil.Bytes2Hex([]byte(name)), ethutil.Bytes2Hex(value.Bytes())}) - }) + it := object.Trie().Iterator() + for it.Next() { + values = append(values, KeyVal{ethutil.Bytes2Hex(it.Key), ethutil.Bytes2Hex(it.Value)}) + } valuesJson, err := json.Marshal(values) if err != nil { diff --git a/xeth/js_types.go b/xeth/js_types.go index 04018f6a5f..5fe5946b1c 100644 --- a/xeth/js_types.go +++ b/xeth/js_types.go @@ -1,6 +1,7 @@ package xeth import ( + "fmt" "strings" "github.com/ethereum/go-ethereum/core" @@ -38,25 +39,25 @@ func NewJSBlock(block *types.Block) *JSBlock { ptxs := make([]*JSTransaction, len(block.Transactions())) for i, tx := range block.Transactions() { - ptxs[i] = NewJSTx(tx, block.State()) + ptxs[i] = NewJSTx(tx) } txlist := ethutil.NewList(ptxs) - puncles := make([]*JSBlock, len(block.Uncles)) - for i, uncle := range block.Uncles { - puncles[i] = NewJSBlock(uncle) + puncles := make([]*JSBlock, len(block.Uncles())) + for i, uncle := range block.Uncles() { + puncles[i] = NewJSBlock(types.NewBlockWithHeader(uncle)) } ulist := ethutil.NewList(puncles) return &JSBlock{ ref: block, Size: block.Size().String(), - Number: int(block.Number.Uint64()), GasUsed: block.GasUsed.String(), - GasLimit: block.GasLimit.String(), Hash: ethutil.Bytes2Hex(block.Hash()), + Number: int(block.NumberU64()), GasUsed: block.GasUsed().String(), + GasLimit: block.GasLimit().String(), Hash: ethutil.Bytes2Hex(block.Hash()), Transactions: txlist, Uncles: ulist, - Time: block.Time, - Coinbase: ethutil.Bytes2Hex(block.Coinbase), - PrevHash: ethutil.Bytes2Hex(block.PrevHash), - Bloom: ethutil.Bytes2Hex(block.LogsBloom), + Time: block.Time(), + Coinbase: ethutil.Bytes2Hex(block.Coinbase()), + PrevHash: ethutil.Bytes2Hex(block.ParentHash()), + Bloom: ethutil.Bytes2Hex(block.Bloom()), Raw: block.String(), } } @@ -70,12 +71,12 @@ func (self *JSBlock) ToString() string { } func (self *JSBlock) GetTransaction(hash string) *JSTransaction { - tx := self.ref.GetTransaction(ethutil.Hex2Bytes(hash)) + tx := self.ref.Transaction(ethutil.Hex2Bytes(hash)) if tx == nil { return nil } - return NewJSTx(tx, self.ref.State()) + return NewJSTx(tx) } type JSTransaction struct { @@ -94,7 +95,7 @@ type JSTransaction struct { Confirmations int `json:"confirmations"` } -func NewJSTx(tx *types.Transaction, state *state.StateDB) *JSTransaction { +func NewJSTx(tx *types.Transaction) *JSTransaction { hash := ethutil.Bytes2Hex(tx.Hash()) receiver := ethutil.Bytes2Hex(tx.To()) if receiver == "0000000000000000000000000000000000000000" { @@ -154,36 +155,24 @@ func NewPReciept(contractCreation bool, creationAddress, hash, address []byte) * // Peer interface exposed to QML type JSPeer struct { - ref *p2p.Peer - // Inbound bool `json:"isInbound"` - // LastSend int64 `json:"lastSend"` - // LastPong int64 `json:"lastPong"` - // Ip string `json:"ip"` - // Port int `json:"port"` - // Version string `json:"version"` - // LastResponse string `json:"lastResponse"` - // Latency string `json:"latency"` - // Caps string `json:"caps"` + ref *p2p.Peer + Ip string `json:"ip"` + Version string `json:"version"` + Caps string `json:"caps"` } func NewJSPeer(peer *p2p.Peer) *JSPeer { + var caps []string + for _, cap := range peer.Caps() { + caps = append(caps, fmt.Sprintf("%s/%d", cap.Name, cap.Version)) + } - // var ip []string - // for _, i := range peer.Host() { - // ip = append(ip, strconv.Itoa(int(i))) - // } - // ipAddress := strings.Join(ip, ".") - - // var caps []string - // capsIt := peer.Caps().NewIterator() - // for capsIt.Next() { - // cap := capsIt.Value().Get(0).Str() - // ver := capsIt.Value().Get(1).Uint() - // caps = append(caps, fmt.Sprintf("%s/%d", cap, ver)) - // } - - return &JSPeer{ref: peer} - // return &JSPeer{ref: &peer, Inbound: peer.Inbound(), LastSend: peer.LastSend().Unix(), LastPong: peer.LastPong(), Version: peer.Version(), Ip: ipAddress, Port: int(peer.Port()), Latency: peer.PingTime(), Caps: "[" + strings.Join(caps, ", ") + "]"} + return &JSPeer{ + ref: peer, + Ip: fmt.Sprintf("%v", peer.RemoteAddr()), + Version: fmt.Sprintf("%v", peer.Identity()), + Caps: fmt.Sprintf("%v", caps), + } } type JSReceipt struct { diff --git a/xeth/vm_env.go b/xeth/vm_env.go index 7fb674a94b..1470b9eaa5 100644 --- a/xeth/vm_env.go +++ b/xeth/vm_env.go @@ -10,6 +10,7 @@ import ( ) type VMEnv struct { + chain *core.ChainManager state *state.StateDB block *types.Block value *big.Int @@ -18,7 +19,7 @@ type VMEnv struct { depth int } -func NewEnv(state *state.StateDB, block *types.Block, value *big.Int, sender []byte) *VMEnv { +func NewEnv(chain *core.ChainManager, state *state.StateDB, block *types.Block, value *big.Int, sender []byte) *VMEnv { return &VMEnv{ state: state, block: block, @@ -28,17 +29,23 @@ func NewEnv(state *state.StateDB, block *types.Block, value *big.Int, sender []b } func (self *VMEnv) Origin() []byte { return self.sender } -func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number } -func (self *VMEnv) PrevHash() []byte { return self.block.PrevHash } -func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase } -func (self *VMEnv) Time() int64 { return self.block.Time } -func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty } -func (self *VMEnv) BlockHash() []byte { return self.block.Hash() } +func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() } +func (self *VMEnv) PrevHash() []byte { return self.block.ParentHash() } +func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() } +func (self *VMEnv) Time() int64 { return self.block.Time() } +func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() } +func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() } func (self *VMEnv) Value() *big.Int { return self.value } func (self *VMEnv) State() *state.StateDB { return self.state } -func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit } func (self *VMEnv) Depth() int { return self.depth } func (self *VMEnv) SetDepth(i int) { self.depth = i } +func (self *VMEnv) GetHash(n uint64) []byte { + if block := self.chain.GetBlockByNumber(n); block != nil { + return block.Hash() + } + + return nil +} func (self *VMEnv) AddLog(log state.Log) { self.state.AddLog(log) } @@ -50,16 +57,16 @@ func (self *VMEnv) vm(addr, data []byte, gas, price, value *big.Int) *core.Execu return core.NewExecution(self, addr, data, gas, price, value) } -func (self *VMEnv) Call(me vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { +func (self *VMEnv) Call(me vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { exe := self.vm(addr, data, gas, price, value) return exe.Call(addr, me) } -func (self *VMEnv) CallCode(me vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { +func (self *VMEnv) CallCode(me vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { exe := self.vm(me.Address(), data, gas, price, value) return exe.Call(addr, me) } -func (self *VMEnv) Create(me vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ClosureRef) { +func (self *VMEnv) Create(me vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { exe := self.vm(addr, data, gas, price, value) return exe.Create(me) } diff --git a/xeth/world.go b/xeth/world.go index 008a084234..25c2f3eb8b 100644 --- a/xeth/world.go +++ b/xeth/world.go @@ -36,7 +36,7 @@ func (self *World) SafeGet(addr []byte) *Object { func (self *World) safeGet(addr []byte) *state.StateObject { object := self.State().GetStateObject(addr) if object == nil { - object = state.NewStateObject(addr) + object = state.NewStateObject(addr, self.pipe.obj.Db()) } return object diff --git a/xeth/pipe.go b/xeth/xeth.go similarity index 88% rename from xeth/pipe.go rename to xeth/xeth.go index 06820cc865..34d8ffd0ae 100644 --- a/xeth/pipe.go +++ b/xeth/xeth.go @@ -20,19 +20,19 @@ type VmVars struct { } type XEth struct { - obj core.EthManager - blockManager *core.BlockManager - chainManager *core.ChainManager - world *World + obj core.EthManager + blockProcessor *core.BlockProcessor + chainManager *core.ChainManager + world *World Vm VmVars } func New(obj core.EthManager) *XEth { pipe := &XEth{ - obj: obj, - blockManager: obj.BlockManager(), - chainManager: obj.ChainManager(), + obj: obj, + blockProcessor: obj.BlockProcessor(), + chainManager: obj.ChainManager(), } pipe.world = NewWorld(pipe) @@ -81,13 +81,13 @@ func (self *XEth) Execute(addr []byte, data []byte, value, gas, price *ethutil.V func (self *XEth) ExecuteObject(object *Object, data []byte, value, gas, price *ethutil.Value) ([]byte, error) { var ( - initiator = state.NewStateObject(self.obj.KeyManager().KeyPair().Address()) + initiator = state.NewStateObject(self.obj.KeyManager().KeyPair().Address(), self.obj.Db()) block = self.chainManager.CurrentBlock() ) self.Vm.State = self.World().State().Copy() - vmenv := NewEnv(self.Vm.State, block, value.BigInt(), initiator.Address()) + vmenv := NewEnv(self.chainManager, self.Vm.State, block, value.BigInt(), initiator.Address()) return vmenv.Call(initiator, object.Address(), data, gas.BigInt(), price.BigInt(), value.BigInt()) } @@ -139,9 +139,9 @@ func (self *XEth) Transact(key *crypto.KeyPair, to []byte, value, gas, price *et // Do some pre processing for our "pre" events and hooks block := self.chainManager.NewBlock(key.Address()) - coinbase := state.GetStateObject(key.Address()) - coinbase.SetGasPool(block.GasLimit) - self.blockManager.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true) + coinbase := state.GetOrNewStateObject(key.Address()) + coinbase.SetGasPool(block.GasLimit()) + self.blockProcessor.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true) err := self.obj.TxPool().Add(tx) if err != nil {