mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-22 04:36:42 +00:00
Merge remote-tracking branch 'upstream/poc8' into kademlia
This commit is contained in:
commit
6dd253f564
342 changed files with 17150 additions and 5180 deletions
10
.travis.yml
10
.travis.yml
|
|
@ -1,6 +1,6 @@
|
||||||
language: go
|
language: go
|
||||||
go:
|
go:
|
||||||
- 1.3
|
- tip
|
||||||
before_install:
|
before_install:
|
||||||
- sudo add-apt-repository ppa:ubuntu-sdk-team/ppa -y
|
- sudo add-apt-repository ppa:ubuntu-sdk-team/ppa -y
|
||||||
- sudo apt-get update -qq
|
- sudo apt-get update -qq
|
||||||
|
|
@ -8,10 +8,10 @@ before_install:
|
||||||
install:
|
install:
|
||||||
- go get code.google.com/p/go.tools/cmd/goimports
|
- go get code.google.com/p/go.tools/cmd/goimports
|
||||||
- go get github.com/golang/lint/golint
|
- go get github.com/golang/lint/golint
|
||||||
# - go get code.google.com/p/go.tools/cmd/vet
|
# - go get golang.org/x/tools/cmd/vet
|
||||||
- go get code.google.com/p/go.tools/cmd/cover
|
- 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
|
- 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:
|
before_script:
|
||||||
- gofmt -l -w .
|
- gofmt -l -w .
|
||||||
- goimports -l -w .
|
- goimports -l -w .
|
||||||
|
|
@ -19,7 +19,7 @@ before_script:
|
||||||
# - go vet ./...
|
# - go vet ./...
|
||||||
# - go test -race ./...
|
# - go test -race ./...
|
||||||
script:
|
script:
|
||||||
- ./gocoverage.sh && goveralls -coverprofile=profile.cov -service=travis-ci -repotoken $COVERALLS_TOKEN
|
- ./gocoverage.sh
|
||||||
env:
|
env:
|
||||||
- secure: "U2U1AmkU4NJBgKR/uUAebQY87cNL0+1JHjnLOmmXwxYYyj5ralWb1aSuSH3qSXiT93qLBmtaUkuv9fberHVqrbAeVlztVdUsKAq7JMQH+M99iFkC9UiRMqHmtjWJ0ok4COD1sRYixxi21wb/JrMe3M1iL4QJVS61iltjHhVdM64="
|
- secure: "U2U1AmkU4NJBgKR/uUAebQY87cNL0+1JHjnLOmmXwxYYyj5ralWb1aSuSH3qSXiT93qLBmtaUkuv9fberHVqrbAeVlztVdUsKAq7JMQH+M99iFkC9UiRMqHmtjWJ0ok4COD1sRYixxi21wb/JrMe3M1iL4QJVS61iltjHhVdM64="
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,14 +25,14 @@ RUN apt-get install -y qtbase5-private-dev qtdeclarative5-private-dev libqt5open
|
||||||
## Fetch and install serpent-go
|
## Fetch and install serpent-go
|
||||||
RUN go get -v -d github.com/ethereum/serpent-go
|
RUN go get -v -d github.com/ethereum/serpent-go
|
||||||
WORKDIR $GOPATH/src/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 git submodule update --init
|
||||||
RUN go install -v
|
RUN go install -v
|
||||||
|
|
||||||
# Fetch and install go-ethereum
|
# Fetch and install go-ethereum
|
||||||
RUN go get -v -d github.com/ethereum/go-ethereum/...
|
RUN go get -v -d github.com/ethereum/go-ethereum/...
|
||||||
WORKDIR $GOPATH/src/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 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
|
RUN go install -v ./cmd/ethereum
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,11 @@ Ethereum
|
||||||
[](http://build.ethdev.com:8010/builders/Linux%20Go%20master%20branch/builds/-1) master [](http://build.ethdev.com:8010/builders/Linux%20Go%20master%20branch/builds/-1) master [](http://build.ethdev.com:8010/builders/Linux%20Go%20develop%20branch/builds/-1) develop
|
Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](http://build.ethdev.com:8010/builders/Linux%20Go%20develop%20branch/builds/-1) develop
|
||||||
|
[](https://coveralls.io/r/ethereum/go-ethereum?branch=tests) tests
|
||||||
|
|
||||||
Ethereum Go Client © 2014 Jeffrey Wilcke.
|
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.
|
Ethereum is currently in its testing phase.
|
||||||
|
|
||||||
|
|
|
||||||
BIN
_data/chain1
BIN
_data/chain1
Binary file not shown.
BIN
_data/chain2
BIN
_data/chain2
Binary file not shown.
BIN
_data/invalid1
Executable file
BIN
_data/invalid1
Executable file
Binary file not shown.
BIN
_data/valid1
Executable file
BIN
_data/valid1
Executable file
Binary file not shown.
BIN
_data/valid2
Executable file
BIN
_data/valid2
Executable file
Binary file not shown.
BIN
_data/valid3
Executable file
BIN
_data/valid3
Executable file
Binary file not shown.
BIN
_data/valid4
Executable file
BIN
_data/valid4
Executable file
Binary file not shown.
|
|
@ -58,6 +58,7 @@ var (
|
||||||
DumpHash string
|
DumpHash string
|
||||||
DumpNumber int
|
DumpNumber int
|
||||||
VmType int
|
VmType int
|
||||||
|
ImportChain string
|
||||||
)
|
)
|
||||||
|
|
||||||
// flags specific to cli client
|
// flags specific to cli client
|
||||||
|
|
@ -87,7 +88,7 @@ func Init() {
|
||||||
flag.StringVar(&OutboundPort, "port", "30303", "listening port")
|
flag.StringVar(&OutboundPort, "port", "30303", "listening port")
|
||||||
flag.StringVar(&NatType, "nat", "", "NAT support (UPNP|PMP) (none)")
|
flag.StringVar(&NatType, "nat", "", "NAT support (UPNP|PMP) (none)")
|
||||||
flag.StringVar(&PMPGateway, "pmp", "", "Gateway IP for PMP")
|
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.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
|
||||||
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
|
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
|
||||||
flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server")
|
flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server")
|
||||||
|
|
@ -104,6 +105,7 @@ func Init() {
|
||||||
flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0")
|
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.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.BoolVar(&ShowGenesis, "genesis", false, "Dump the genesis block")
|
||||||
|
flag.StringVar(&ImportChain, "chain", "", "Imports fiven chain")
|
||||||
|
|
||||||
flag.BoolVar(&Dump, "dump", false, "output the ethereum state in JSON format. Sub args [number, hash]")
|
flag.BoolVar(&Dump, "dump", false, "output the ethereum state in JSON format. Sub args [number, hash]")
|
||||||
flag.StringVar(&DumpHash, "hash", "", "specify arg in hex")
|
flag.StringVar(&DumpHash, "hash", "", "specify arg in hex")
|
||||||
|
|
|
||||||
|
|
@ -21,16 +21,18 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ClientIdentifier = "Ethereum(G)"
|
ClientIdentifier = "Ethereum(G)"
|
||||||
Version = "0.7.9"
|
Version = "0.8.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
var clilogger = logger.NewLogger("CLI")
|
var clilogger = logger.NewLogger("CLI")
|
||||||
|
|
@ -38,40 +40,35 @@ var clilogger = logger.NewLogger("CLI")
|
||||||
func main() {
|
func main() {
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
logger.Flush()
|
||||||
|
}()
|
||||||
|
|
||||||
utils.HandleInterrupt()
|
utils.HandleInterrupt()
|
||||||
|
|
||||||
// precedence: code-internal flag default < config file < environment variables < command line
|
// precedence: code-internal flag default < config file < environment variables < command line
|
||||||
Init() // parsing command line
|
Init() // parsing command line
|
||||||
|
|
||||||
// If the difftool option is selected ignore all other log output
|
|
||||||
if DiffTool || Dump {
|
|
||||||
LogLevel = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
|
utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
|
||||||
ethutil.Config.Diff = DiffTool
|
|
||||||
ethutil.Config.DiffType = DiffType
|
|
||||||
|
|
||||||
utils.InitDataDir(Datadir)
|
ethereum, err := eth.New(ð.Config{
|
||||||
|
Name: ClientIdentifier,
|
||||||
utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile)
|
Version: Version,
|
||||||
|
KeyStore: KeyStore,
|
||||||
db := utils.NewDatabase()
|
DataDir: Datadir,
|
||||||
err := utils.DBSanityCheck(db)
|
LogFile: LogFile,
|
||||||
|
LogLevel: LogLevel,
|
||||||
|
Identifier: Identifier,
|
||||||
|
MaxPeers: MaxPeer,
|
||||||
|
Port: OutboundPort,
|
||||||
|
NATType: PMPGateway,
|
||||||
|
PMPGateway: PMPGateway,
|
||||||
|
KeyRing: KeyRing,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
clilogger.Fatalln(err)
|
||||||
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
|
||||||
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 Dump {
|
if Dump {
|
||||||
var block *types.Block
|
var block *types.Block
|
||||||
|
|
@ -93,25 +90,28 @@ func main() {
|
||||||
os.Exit(1)
|
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
|
// Leave the Println. This needs clean output for piping
|
||||||
fmt.Printf("%s\n", block.State().Dump())
|
fmt.Printf("%s\n", block.State().Dump())
|
||||||
|
|
||||||
fmt.Println(block)
|
fmt.Println(block)
|
||||||
|
|
||||||
os.Exit(0)
|
return
|
||||||
}
|
|
||||||
|
|
||||||
if ShowGenesis {
|
|
||||||
utils.ShowGenesis(ethereum)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if StartMining {
|
if StartMining {
|
||||||
utils.StartMining(ethereum)
|
utils.StartMining(ethereum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
// better reworked as cases
|
// better reworked as cases
|
||||||
if StartJsConsole {
|
if StartJsConsole {
|
||||||
InitJsConsole(ethereum)
|
InitJsConsole(ethereum)
|
||||||
|
|
@ -131,5 +131,4 @@ func main() {
|
||||||
|
|
||||||
// this blocks the thread
|
// this blocks the thread
|
||||||
ethereum.WaitForShutdown()
|
ethereum.WaitForShutdown()
|
||||||
logger.Flush()
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,11 +86,6 @@ func (self *JSRepl) Stop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *JSRepl) parseInput(code string) {
|
func (self *JSRepl) parseInput(code string) {
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
fmt.Println("[native] error", r)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
value, err := self.re.Run(code)
|
value, err := self.re.Run(code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
5
cmd/ethtest/.bowerrc
Normal file
5
cmd/ethtest/.bowerrc
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"directory": "example/js/",
|
||||||
|
"cwd": "./",
|
||||||
|
"analytics": false
|
||||||
|
}
|
||||||
12
cmd/ethtest/.editorconfig
Normal file
12
cmd/ethtest/.editorconfig
Normal file
|
|
@ -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
|
||||||
18
cmd/ethtest/.gitignore
vendored
Normal file
18
cmd/ethtest/.gitignore
vendored
Normal file
|
|
@ -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
|
||||||
50
cmd/ethtest/.jshintrc
Normal file
50
cmd/ethtest/.jshintrc
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
9
cmd/ethtest/.npmignore
Normal file
9
cmd/ethtest/.npmignore
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
example/js
|
||||||
|
node_modules
|
||||||
|
test
|
||||||
|
.gitignore
|
||||||
|
.editorconfig
|
||||||
|
.travis.yml
|
||||||
|
.npmignore
|
||||||
|
component.json
|
||||||
|
testling.html
|
||||||
11
cmd/ethtest/.travis.yml
Normal file
11
cmd/ethtest/.travis.yml
Normal file
|
|
@ -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
|
||||||
|
|
@ -95,11 +95,16 @@ func RunVmTest(js string) (failed int) {
|
||||||
failed = 1
|
failed = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
gexp := ethutil.Big(test.Gas)
|
||||||
if gexp.Cmp(gas) != 0 {
|
if gexp.Cmp(gas) != 0 {
|
||||||
log.Printf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas)
|
log.Printf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas)
|
||||||
failed = 1
|
failed = 1
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for addr, account := range test.Post {
|
for addr, account := range test.Post {
|
||||||
obj := state.GetStateObject(helper.FromHex(addr))
|
obj := state.GetStateObject(helper.FromHex(addr))
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,8 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
|
"github.com/ethereum/go-ethereum/ptrie"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
"github.com/ethereum/go-ethereum/state"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
|
||||||
"github.com/ethereum/go-ethereum/vm"
|
"github.com/ethereum/go-ethereum/vm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -65,7 +65,7 @@ func main() {
|
||||||
ethutil.ReadConfig("/tmp/evmtest", "/tmp/evm", "")
|
ethutil.ReadConfig("/tmp/evmtest", "/tmp/evm", "")
|
||||||
|
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db, _ := ethdb.NewMemDatabase()
|
||||||
statedb := state.New(trie.New(db, ""))
|
statedb := state.New(ptrie.New(nil, db))
|
||||||
sender := statedb.NewStateObject([]byte("sender"))
|
sender := statedb.NewStateObject([]byte("sender"))
|
||||||
receiver := statedb.NewStateObject([]byte("receiver"))
|
receiver := statedb.NewStateObject([]byte("receiver"))
|
||||||
//receiver.SetCode([]byte(*code))
|
//receiver.SetCode([]byte(*code))
|
||||||
|
|
@ -141,24 +141,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 {
|
func (self *VMEnv) vm(addr, data []byte, gas, price, value *big.Int) *core.Execution {
|
||||||
evm := vm.New(self, vm.DebugVmTy)
|
return core.NewExecution(self, addr, data, gas, price, value)
|
||||||
|
|
||||||
return core.NewExecution(evm, 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)
|
exe := self.vm(addr, data, gas, price, value)
|
||||||
ret, err := exe.Call(addr, caller)
|
ret, err := exe.Call(addr, caller)
|
||||||
self.Gas = exe.Gas
|
self.Gas = exe.Gas
|
||||||
|
|
||||||
return ret, err
|
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)
|
exe := self.vm(caller.Address(), data, gas, price, value)
|
||||||
return exe.Call(addr, caller)
|
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)
|
exe := self.vm(addr, data, gas, price, value)
|
||||||
return exe.Create(caller)
|
return exe.Create(caller)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,11 @@ Rectangle {
|
||||||
onMessages: {
|
onMessages: {
|
||||||
// Bit of a cheat to get proper JSON
|
// Bit of a cheat to get proper JSON
|
||||||
var m = JSON.parse(JSON.parse(JSON.stringify(messages)))
|
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("shhChanged", id, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|
@ -327,6 +331,33 @@ Rectangle {
|
||||||
require(1);
|
require(1);
|
||||||
eth.uninstallFilter(data.args[0])
|
eth.uninstallFilter(data.args[0])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case "shhNewFilter":
|
||||||
|
require(1);
|
||||||
|
var id = shh.watch(data.args[0], window);
|
||||||
|
postData(data._id, id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "newIdentity":
|
||||||
|
postData(data._id, shh.newIdentity())
|
||||||
|
break
|
||||||
|
|
||||||
|
case "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;
|
||||||
|
|
||||||
|
console.log(JSON.stringify(params))
|
||||||
|
shh.post(params.payload, params.to, params.from, params.topics, params.priority, params.ttl);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.log(data.call + ": " + e)
|
console.log(data.call + ": " + e)
|
||||||
|
|
@ -348,8 +379,8 @@ Rectangle {
|
||||||
function postData(seed, data) {
|
function postData(seed, data) {
|
||||||
webview.experimental.postMessage(JSON.stringify({data: data, _id: seed}))
|
webview.experimental.postMessage(JSON.stringify({data: data, _id: seed}))
|
||||||
}
|
}
|
||||||
function postEvent(event, data) {
|
function postEvent(event, id, data) {
|
||||||
webview.experimental.postMessage(JSON.stringify({data: data, _event: event}))
|
webview.experimental.postMessage(JSON.stringify({data: data, _id: id, _event: event}))
|
||||||
}
|
}
|
||||||
|
|
||||||
function onWatchedCb(data, id) {
|
function onWatchedCb(data, id) {
|
||||||
|
|
@ -45,7 +45,7 @@ ApplicationWindow {
|
||||||
// Takes care of loading all default plugins
|
// Takes care of loading all default plugins
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
var wallet = addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "ethereum", active: true});
|
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;
|
root.browser = browser;
|
||||||
addPlugin("./views/miner.qml", {noAdd: true, close: false, section: "ethereum", active: true});
|
addPlugin("./views/miner.qml", {noAdd: true, close: false, section: "ethereum", active: true});
|
||||||
|
|
||||||
|
|
@ -787,8 +787,8 @@ ApplicationWindow {
|
||||||
title: "About"
|
title: "About"
|
||||||
minimumWidth: 350
|
minimumWidth: 350
|
||||||
maximumWidth: 350
|
maximumWidth: 350
|
||||||
maximumHeight: 200
|
maximumHeight: 280
|
||||||
minimumHeight: 200
|
minimumHeight: 280
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: aboutIcon
|
id: aboutIcon
|
||||||
|
|
@ -798,7 +798,7 @@ ApplicationWindow {
|
||||||
smooth: true
|
smooth: true
|
||||||
source: "../facet.png"
|
source: "../facet.png"
|
||||||
x: 10
|
x: 10
|
||||||
y: 10
|
y: 30
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
|
@ -807,7 +807,7 @@ ApplicationWindow {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 30
|
anchors.topMargin: 30
|
||||||
font.pointSize: 12
|
font.pointSize: 12
|
||||||
text: "<h2>Mist (0.6.5)</h2><h4>Amalthea</h4><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br><h3>Building</h3>Maran Hidskes"
|
text: "<h2>Mist (0.7.10)</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br>Felix Lange<br>Taylor Gerring<br>Daniel Nagy<br><h3>UX</h3>Alex van de Sande<br>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -866,12 +866,14 @@ ApplicationWindow {
|
||||||
model: ListModel { id: pastPeers }
|
model: ListModel { id: pastPeers }
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
/*
|
||||||
var ips = eth.pastPeers()
|
var ips = eth.pastPeers()
|
||||||
for(var i = 0; i < ips.length; i++) {
|
for(var i = 0; i < ips.length; i++) {
|
||||||
pastPeers.append({text: ips.get(i)})
|
pastPeers.append({text: ips.get(i)})
|
||||||
}
|
}
|
||||||
|
|
||||||
pastPeers.insert(0, {text: "poc-7.ethdev.com:30303"})
|
pastPeers.insert(0, {text: "poc-7.ethdev.com:30303"})
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setBalance() {
|
function setBalance() {
|
||||||
balance.text = "<b>Balance</b>: " + eth.numberToHuman(eth.balanceAt(eth.key().address))
|
//balance.text = "<b>Balance</b>: " + eth.numberToHuman(eth.balanceAt(eth.key().address))
|
||||||
if(menuItem)
|
if(menuItem)
|
||||||
menuItem.secondaryTitle = eth.numberToHuman(eth.balanceAt(eth.key().address))
|
menuItem.secondaryTitle = eth.numberToHuman(eth.balanceAt(eth.key().address))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import Ethereum 1.0
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
property var title: "Whisper"
|
property var title: "Whisper Traffic"
|
||||||
property var iconSource: "../facet.png"
|
property var iconSource: "../facet.png"
|
||||||
property var menuItem
|
property var menuItem
|
||||||
|
|
||||||
|
|
@ -21,10 +21,22 @@ Rectangle {
|
||||||
identity = shh.newIdentity()
|
identity = shh.newIdentity()
|
||||||
console.log("New identity:", identity)
|
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 {
|
RowLayout {
|
||||||
|
id: input
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: 20
|
||||||
|
top: parent.top
|
||||||
|
topMargin: 20
|
||||||
|
}
|
||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: to
|
id: to
|
||||||
placeholderText: "To"
|
placeholderText: "To"
|
||||||
|
|
@ -40,8 +52,25 @@ Rectangle {
|
||||||
Button {
|
Button {
|
||||||
text: "Send"
|
text: "Send"
|
||||||
onClicked: {
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ func (gui *Gui) GetCustomIdentifier() string {
|
||||||
// functions that allow Gui to implement interface guilogger.LogSystem
|
// functions that allow Gui to implement interface guilogger.LogSystem
|
||||||
func (gui *Gui) SetLogLevel(level logger.LogLevel) {
|
func (gui *Gui) SetLogLevel(level logger.LogLevel) {
|
||||||
gui.logLevel = level
|
gui.logLevel = level
|
||||||
gui.stdLog.SetLogLevel(level)
|
gui.eth.Logger().SetLogLevel(level)
|
||||||
gui.config.Save("loglevel", level)
|
gui.config.Save("loglevel", level)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
|
||||||
|
|
||||||
block := self.lib.eth.ChainManager().CurrentBlock()
|
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))
|
self.Logf("callsize %d", len(script))
|
||||||
go func() {
|
go func() {
|
||||||
|
|
@ -309,9 +309,11 @@ func (d *Debugger) halting(pc int, op vm.OpCode, mem *vm.Memory, stack *vm.Stack
|
||||||
d.win.Root().Call("setStack", val.String())
|
d.win.Root().Call("setStack", val.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
stateObject.EachStorage(func(key string, node *ethutil.Value) {
|
it := stateObject.Trie().Iterator()
|
||||||
d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", key), fmt.Sprintf("% x", node.Str())})
|
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))
|
stackFrameAt := new(big.Int).SetBytes(mem.Get(0, 32))
|
||||||
psize := mem.Len() - int(new(big.Int).SetBytes(mem.Get(0, 32)).Uint64())
|
psize := mem.Len() - int(new(big.Int).SetBytes(mem.Get(0, 32)).Uint64())
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ func Init() {
|
||||||
flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file (db)")
|
flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file (db)")
|
||||||
flag.StringVar(&OutboundPort, "port", "30303", "listening port")
|
flag.StringVar(&OutboundPort, "port", "30303", "listening port")
|
||||||
flag.BoolVar(&UseUPnP, "upnp", true, "enable UPnP support")
|
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.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
|
||||||
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
|
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
|
||||||
flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server")
|
flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server")
|
||||||
|
|
|
||||||
101
cmd/mist/gui.go
101
cmd/mist/gui.go
|
|
@ -43,38 +43,6 @@ import (
|
||||||
"gopkg.in/qml.v1"
|
"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")
|
var guilogger = logger.NewLogger("GUI")
|
||||||
|
|
||||||
type Gui struct {
|
type Gui struct {
|
||||||
|
|
@ -105,7 +73,6 @@ type Gui struct {
|
||||||
plugins map[string]plugin
|
plugins map[string]plugin
|
||||||
|
|
||||||
miner *miner.Miner
|
miner *miner.Miner
|
||||||
stdLog logger.LogSystem
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create GUI, but doesn't start it
|
// Create GUI, but doesn't start it
|
||||||
|
|
@ -145,7 +112,7 @@ func (gui *Gui) Start(assetPath string) {
|
||||||
// Expose the eth library and the ui library to QML
|
// Expose the eth library and the ui library to QML
|
||||||
context.SetVar("gui", gui)
|
context.SetVar("gui", gui)
|
||||||
context.SetVar("eth", gui.uiLib)
|
context.SetVar("eth", gui.uiLib)
|
||||||
context.SetVar("shh", gui.whisper)
|
//context.SetVar("shh", gui.whisper)
|
||||||
|
|
||||||
// Load the main QML interface
|
// Load the main QML interface
|
||||||
data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
|
data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
|
||||||
|
|
@ -253,7 +220,7 @@ func (gui *Gui) setInitialChain(ancientBlocks bool) {
|
||||||
sBlk := gui.eth.ChainManager().LastBlockHash()
|
sBlk := gui.eth.ChainManager().LastBlockHash()
|
||||||
blk := gui.eth.ChainManager().GetBlock(sBlk)
|
blk := gui.eth.ChainManager().GetBlock(sBlk)
|
||||||
for ; blk != nil; 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)
|
gui.processBlock(blk, true)
|
||||||
}
|
}
|
||||||
|
|
@ -263,35 +230,33 @@ func (gui *Gui) loadAddressBook() {
|
||||||
view := gui.getObjectByName("infoView")
|
view := gui.getObjectByName("infoView")
|
||||||
nameReg := gui.pipe.World().Config().Get("NameReg")
|
nameReg := gui.pipe.World().Config().Get("NameReg")
|
||||||
if nameReg != nil {
|
if nameReg != nil {
|
||||||
nameReg.EachStorage(func(name string, value *ethutil.Value) {
|
it := nameReg.Trie().Iterator()
|
||||||
if name[0] != 0 {
|
for it.Next() {
|
||||||
value.Decode()
|
if it.Key[0] != 0 {
|
||||||
|
view.Call("addAddress", struct{ Name, Address string }{string(it.Key), ethutil.Bytes2Hex(it.Value)})
|
||||||
view.Call("addAddress", struct{ Name, Address string }{name, ethutil.Bytes2Hex(value.Bytes())})
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Gui) loadMergedMiningOptions() {
|
func (self *Gui) loadMergedMiningOptions() {
|
||||||
view := self.getObjectByName("mergedMiningModel")
|
view := self.getObjectByName("mergedMiningModel")
|
||||||
|
|
||||||
nameReg := self.pipe.World().Config().Get("MergeMining")
|
mergeMining := self.pipe.World().Config().Get("MergeMining")
|
||||||
if nameReg != nil {
|
if mergeMining != nil {
|
||||||
i := 0
|
i := 0
|
||||||
nameReg.EachStorage(func(name string, value *ethutil.Value) {
|
it := mergeMining.Trie().Iterator()
|
||||||
if name[0] != 0 {
|
for it.Next() {
|
||||||
value.Decode()
|
|
||||||
|
|
||||||
view.Call("addMergedMiningOption", struct {
|
view.Call("addMergedMiningOption", struct {
|
||||||
Checked bool
|
Checked bool
|
||||||
Name, Address string
|
Name, Address string
|
||||||
Id, ItemId int
|
Id, ItemId int
|
||||||
}{false, name, ethutil.Bytes2Hex(value.Bytes()), 0, i})
|
}{false, string(it.Key), ethutil.Bytes2Hex(it.Value), 0, i})
|
||||||
|
|
||||||
i++
|
i++
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -354,7 +319,7 @@ func (gui *Gui) readPreviousTransactions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) processBlock(block *types.Block, initial bool) {
|
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.pipe.World().Config().Get("NameReg").Storage(block.Coinbase()).Str(), "\x00")
|
||||||
b := xeth.NewJSBlock(block)
|
b := xeth.NewJSBlock(block)
|
||||||
b.Name = name
|
b.Name = name
|
||||||
|
|
||||||
|
|
@ -432,7 +397,7 @@ func (gui *Gui) update() {
|
||||||
switch ev := ev.(type) {
|
switch ev := ev.(type) {
|
||||||
case core.NewBlockEvent:
|
case core.NewBlockEvent:
|
||||||
gui.processBlock(ev.Block, false)
|
gui.processBlock(ev.Block, false)
|
||||||
if bytes.Compare(ev.Block.Coinbase, gui.address()) == 0 {
|
if bytes.Compare(ev.Block.Coinbase(), gui.address()) == 0 {
|
||||||
gui.setWalletValue(gui.eth.ChainManager().State().GetBalance(gui.address()), nil)
|
gui.setWalletValue(gui.eth.ChainManager().State().GetBalance(gui.address()), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -470,7 +435,7 @@ func (gui *Gui) update() {
|
||||||
case <-peerUpdateTicker.C:
|
case <-peerUpdateTicker.C:
|
||||||
gui.setPeerInfo()
|
gui.setPeerInfo()
|
||||||
case <-generalUpdateTicker.C:
|
case <-generalUpdateTicker.C:
|
||||||
statusText := "#" + gui.eth.ChainManager().CurrentBlock().Number.String()
|
statusText := "#" + gui.eth.ChainManager().CurrentBlock().Number().String()
|
||||||
lastBlockLabel.Set("text", statusText)
|
lastBlockLabel.Set("text", statusText)
|
||||||
miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.miner.GetPow().GetHashrate(), 10)+"Khash")
|
miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.miner.GetPow().GetHashrate(), 10)+"Khash")
|
||||||
|
|
||||||
|
|
@ -535,3 +500,35 @@ func (gui *Gui) privateKey() string {
|
||||||
func (gui *Gui) address() []byte {
|
func (gui *Gui) address() []byte {
|
||||||
return gui.eth.KeyManager().Address()
|
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))
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ func (app *HtmlApplication) Window() *qml.Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *HtmlApplication) NewBlock(block *types.Block) {
|
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)
|
app.webView.Call("onNewBlockCb", b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,15 +26,17 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"gopkg.in/qml.v1"
|
"gopkg.in/qml.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ClientIdentifier = "Mist"
|
ClientIdentifier = "Mist"
|
||||||
Version = "0.7.9"
|
Version = "0.8.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ethereum *eth.Ethereum
|
var ethereum *eth.Ethereum
|
||||||
|
var mainlogger = logger.NewLogger("MAIN")
|
||||||
|
|
||||||
func run() error {
|
func run() error {
|
||||||
// precedence: code-internal flag default < config file < environment variables < command line
|
// precedence: code-internal flag default < config file < environment variables < command line
|
||||||
|
|
@ -43,27 +45,24 @@ func run() error {
|
||||||
tstart := time.Now()
|
tstart := time.Now()
|
||||||
config := utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
|
config := utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
|
||||||
|
|
||||||
utils.InitDataDir(Datadir)
|
ethereum, err := eth.New(ð.Config{
|
||||||
|
Name: ClientIdentifier,
|
||||||
stdLog := utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile)
|
Version: Version,
|
||||||
|
KeyStore: KeyStore,
|
||||||
db := utils.NewDatabase()
|
DataDir: Datadir,
|
||||||
err := utils.DBSanityCheck(db)
|
LogFile: LogFile,
|
||||||
|
LogLevel: LogLevel,
|
||||||
|
Identifier: Identifier,
|
||||||
|
MaxPeers: MaxPeer,
|
||||||
|
Port: OutboundPort,
|
||||||
|
NATType: PMPGateway,
|
||||||
|
PMPGateway: PMPGateway,
|
||||||
|
KeyRing: KeyRing,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrorWindow(err)
|
mainlogger.Fatalln(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)
|
|
||||||
}
|
}
|
||||||
|
utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
|
||||||
|
|
||||||
if StartRpc {
|
if StartRpc {
|
||||||
utils.StartRpc(ethereum, RpcPort)
|
utils.StartRpc(ethereum, RpcPort)
|
||||||
|
|
@ -73,8 +72,7 @@ func run() error {
|
||||||
utils.StartWebSockets(ethereum)
|
utils.StartWebSockets(ethereum)
|
||||||
}
|
}
|
||||||
|
|
||||||
gui := NewWindow(ethereum, config, clientIdentity, KeyRing, LogLevel)
|
gui := NewWindow(ethereum, config, ethereum.ClientIdentity().(*p2p.SimpleClientIdentity), KeyRing, LogLevel)
|
||||||
gui.stdLog = stdLog
|
|
||||||
|
|
||||||
utils.RegisterInterrupt(func(os.Signal) {
|
utils.RegisterInterrupt(func(os.Signal) {
|
||||||
gui.Stop()
|
gui.Stop()
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ func (app *QmlApplication) NewWatcher(quitChan chan bool) {
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
func (app *QmlApplication) NewBlock(block *types.Block) {
|
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)
|
app.win.Call("onNewBlockCb", pblock)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,83 @@ func (self *UiLib) StartDebugger() {
|
||||||
dbWindow.Show()
|
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) 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) {
|
func (self *UiLib) NewFilter(object map[string]interface{}) (id int) {
|
||||||
filter := qt.NewFilterFromMap(object, self.eth)
|
filter := qt.NewFilterFromMap(object, self.eth)
|
||||||
filter.MessageCallback = func(messages state.Messages) {
|
filter.MessageCallback = func(messages state.Messages) {
|
||||||
|
|
@ -312,80 +389,3 @@ func mapToTxParams(object map[string]interface{}) map[string]string {
|
||||||
|
|
||||||
return conv
|
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) }
|
|
||||||
*/
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ func main() {
|
||||||
marshaled := elliptic.Marshal(crypto.S256(), key.PublicKey.X, key.PublicKey.Y)
|
marshaled := elliptic.Marshal(crypto.S256(), key.PublicKey.X, key.PublicKey.Y)
|
||||||
|
|
||||||
srv := p2p.Server{
|
srv := p2p.Server{
|
||||||
MaxPeers: 10,
|
MaxPeers: 100,
|
||||||
Identity: p2p.NewSimpleClientIdentity("Ethereum(G)", "0.1", "Peer Server Two", string(marshaled)),
|
Identity: p2p.NewSimpleClientIdentity("Ethereum(G)", "0.1", "Peer Server Two", string(marshaled)),
|
||||||
ListenAddr: ":30301",
|
ListenAddr: ":30301",
|
||||||
NAT: p2p.UPNP(),
|
NAT: p2p.UPNP(),
|
||||||
|
|
@ -29,12 +29,12 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add seed peers
|
// add seed peers
|
||||||
seed, err := net.ResolveTCPAddr("tcp", "poc-7.ethdev.com:30300")
|
seed, err := net.ResolveTCPAddr("tcp", "poc-8.ethdev.com:30303")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("couldn't resolve:", err)
|
fmt.Println("couldn't resolve:", err)
|
||||||
os.Exit(1)
|
} else {
|
||||||
}
|
|
||||||
srv.SuggestPeer(seed.IP, seed.Port, nil)
|
srv.SuggestPeer(seed.IP, seed.Port, nil)
|
||||||
|
}
|
||||||
|
|
||||||
select {}
|
select {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
131
cmd/utils/cmd.go
131
cmd/utils/cmd.go
|
|
@ -2,9 +2,6 @@ package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path"
|
"path"
|
||||||
|
|
@ -13,13 +10,13 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"bitbucket.org/kardianos/osext"
|
"bitbucket.org/kardianos/osext"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/miner"
|
"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/rpc"
|
||||||
"github.com/ethereum/go-ethereum/xeth"
|
"github.com/ethereum/go-ethereum/xeth"
|
||||||
)
|
)
|
||||||
|
|
@ -50,15 +47,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 {
|
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)
|
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("error opening log file '%s': %v", filename, err))
|
panic(fmt.Sprintf("error opening log file '%s': %v", filename, err))
|
||||||
|
|
@ -74,23 +64,13 @@ func confirm(message string) bool {
|
||||||
if r == "n" || r == "y" {
|
if r == "n" || r == "y" {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Yes or no?", r)
|
fmt.Printf("Yes or no? (%s)", r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r == "y"
|
return r == "y"
|
||||||
}
|
}
|
||||||
|
|
||||||
func DBSanityCheck(db ethutil.Database) error {
|
func initDataDir(Datadir string) {
|
||||||
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) {
|
|
||||||
_, err := os.Stat(Datadir)
|
_, err := os.Stat(Datadir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
|
|
@ -100,26 +80,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 {
|
func InitConfig(vmType int, ConfigFile string, Datadir string, EnvPrefix string) *ethutil.ConfigManager {
|
||||||
InitDataDir(Datadir)
|
initDataDir(Datadir)
|
||||||
cfg := ethutil.ReadConfig(ConfigFile, Datadir, EnvPrefix)
|
cfg := ethutil.ReadConfig(ConfigFile, Datadir, EnvPrefix)
|
||||||
cfg.VmType = vmType
|
cfg.VmType = vmType
|
||||||
|
|
||||||
|
|
@ -136,43 +98,6 @@ func exit(err error) {
|
||||||
os.Exit(status)
|
os.Exit(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDatabase() ethutil.Database {
|
|
||||||
db, err := ethdb.NewLDBDatabase("database")
|
|
||||||
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) {
|
func StartEthereum(ethereum *eth.Ethereum, UseSeed bool) {
|
||||||
clilogger.Infof("Starting %s", ethereum.ClientIdentity())
|
clilogger.Infof("Starting %s", ethereum.ClientIdentity())
|
||||||
ethereum.Start(UseSeed)
|
ethereum.Start(UseSeed)
|
||||||
|
|
@ -182,24 +107,6 @@ func StartEthereum(ethereum *eth.Ethereum, UseSeed bool) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
func DefaultAssetPath() string {
|
||||||
var assetPath string
|
var assetPath string
|
||||||
// If the current working directory is the go-ethereum dir
|
// If the current working directory is the go-ethereum dir
|
||||||
|
|
@ -325,9 +232,9 @@ func BlockDo(ethereum *eth.Ethereum, hash []byte) error {
|
||||||
return fmt.Errorf("unknown block %x", hash)
|
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)
|
_, err := ethereum.BlockProcessor().TransitionState(parent.State(), parent, block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -335,3 +242,25 @@ func BlockDo(ethereum *eth.Ethereum, hash []byte) error {
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type VMEnv struct {
|
type VMEnv struct {
|
||||||
|
chain *core.ChainManager
|
||||||
state *state.StateDB
|
state *state.StateDB
|
||||||
block *types.Block
|
block *types.Block
|
||||||
|
|
||||||
|
|
@ -20,8 +21,9 @@ type VMEnv struct {
|
||||||
Gas *big.Int
|
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{
|
return &VMEnv{
|
||||||
|
chain: chain,
|
||||||
state: state,
|
state: state,
|
||||||
block: block,
|
block: block,
|
||||||
transactor: transactor,
|
transactor: transactor,
|
||||||
|
|
@ -30,17 +32,23 @@ func NewEnv(state *state.StateDB, block *types.Block, transactor []byte, value *
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *VMEnv) Origin() []byte { return self.transactor }
|
func (self *VMEnv) Origin() []byte { return self.transactor }
|
||||||
func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number }
|
func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() }
|
||||||
func (self *VMEnv) PrevHash() []byte { return self.block.PrevHash }
|
func (self *VMEnv) PrevHash() []byte { return self.block.ParentHash() }
|
||||||
func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase }
|
func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() }
|
||||||
func (self *VMEnv) Time() int64 { return self.block.Time }
|
func (self *VMEnv) Time() int64 { return self.block.Time() }
|
||||||
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty }
|
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() }
|
||||||
func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
|
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() }
|
||||||
func (self *VMEnv) Value() *big.Int { return self.value }
|
func (self *VMEnv) Value() *big.Int { return self.value }
|
||||||
func (self *VMEnv) State() *state.StateDB { return self.state }
|
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) Depth() int { return self.depth }
|
||||||
func (self *VMEnv) SetDepth(i int) { self.depth = i }
|
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) {
|
func (self *VMEnv) AddLog(log state.Log) {
|
||||||
self.state.AddLog(log)
|
self.state.AddLog(log)
|
||||||
}
|
}
|
||||||
|
|
@ -52,19 +60,19 @@ func (self *VMEnv) vm(addr, data []byte, gas, price, value *big.Int) *core.Execu
|
||||||
return core.NewExecution(self, 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)
|
exe := self.vm(addr, data, gas, price, value)
|
||||||
ret, err := exe.Call(addr, caller)
|
ret, err := exe.Call(addr, caller)
|
||||||
self.Gas = exe.Gas
|
self.Gas = exe.Gas
|
||||||
|
|
||||||
return ret, err
|
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)
|
exe := self.vm(caller.Address(), data, gas, price, value)
|
||||||
return exe.Call(addr, caller)
|
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)
|
exe := self.vm(addr, data, gas, price, value)
|
||||||
return exe.Create(caller)
|
return exe.Create(caller)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,13 @@ package utils
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/websocket"
|
"github.com/ethereum/go-ethereum/websocket"
|
||||||
"github.com/ethereum/go-ethereum/xeth"
|
"github.com/ethereum/go-ethereum/xeth"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var wslogger = logger.NewLogger("WS")
|
||||||
|
|
||||||
func args(v ...interface{}) []interface{} {
|
func args(v ...interface{}) []interface{} {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
@ -106,6 +109,8 @@ func (self *WebSocketServer) Serv() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartWebSockets(eth *eth.Ethereum) {
|
func StartWebSockets(eth *eth.Ethereum) {
|
||||||
|
wslogger.Infoln("Starting WebSockets")
|
||||||
|
|
||||||
sock := NewWebSocketServer(eth)
|
sock := NewWebSocketServer(eth)
|
||||||
go sock.Serv()
|
go sock.Serv()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
|
@ -17,24 +16,13 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/pow"
|
"github.com/ethereum/go-ethereum/pow"
|
||||||
"github.com/ethereum/go-ethereum/pow/ezp"
|
"github.com/ethereum/go-ethereum/pow/ezp"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
"github.com/ethereum/go-ethereum/state"
|
||||||
|
"gopkg.in/fatih/set.v0"
|
||||||
)
|
)
|
||||||
|
|
||||||
var statelogger = logger.NewLogger("BLOCK")
|
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 {
|
type EthManager interface {
|
||||||
BlockManager() *BlockManager
|
BlockProcessor() *BlockProcessor
|
||||||
ChainManager() *ChainManager
|
ChainManager() *ChainManager
|
||||||
TxPool() *TxPool
|
TxPool() *TxPool
|
||||||
PeerCount() int
|
PeerCount() int
|
||||||
|
|
@ -47,7 +35,7 @@ type EthManager interface {
|
||||||
EventMux() *event.TypeMux
|
EventMux() *event.TypeMux
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlockManager struct {
|
type BlockProcessor struct {
|
||||||
// Mutex for locking the block processor. Blocks can only be handled one at a time
|
// Mutex for locking the block processor. Blocks can only be handled one at a time
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
// Canonical block chain
|
// Canonical block chain
|
||||||
|
|
@ -69,8 +57,8 @@ type BlockManager struct {
|
||||||
eventMux *event.TypeMux
|
eventMux *event.TypeMux
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBlockManager(txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockManager {
|
func NewBlockProcessor(txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
|
||||||
sm := &BlockManager{
|
sm := &BlockProcessor{
|
||||||
mem: make(map[string]*big.Int),
|
mem: make(map[string]*big.Int),
|
||||||
Pow: ezp.New(),
|
Pow: ezp.New(),
|
||||||
bc: chainManager,
|
bc: chainManager,
|
||||||
|
|
@ -81,11 +69,11 @@ func NewBlockManager(txpool *TxPool, chainManager *ChainManager, eventMux *event
|
||||||
return sm
|
return sm
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *BlockManager) TransitionState(statedb *state.StateDB, parent, block *types.Block) (receipts types.Receipts, err error) {
|
func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block) (receipts types.Receipts, err error) {
|
||||||
coinbase := statedb.GetOrNewStateObject(block.Coinbase)
|
coinbase := statedb.GetOrNewStateObject(block.Header().Coinbase)
|
||||||
coinbase.SetGasPool(block.CalcGasLimit(parent))
|
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)
|
receipts, _, _, _, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -94,7 +82,7 @@ func (sm *BlockManager) TransitionState(statedb *state.StateDB, parent, block *t
|
||||||
return receipts, nil
|
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 (
|
var (
|
||||||
receipts types.Receipts
|
receipts types.Receipts
|
||||||
handled, unhandled types.Transactions
|
handled, unhandled types.Transactions
|
||||||
|
|
@ -112,7 +100,7 @@ done:
|
||||||
txGas := new(big.Int).Set(tx.Gas())
|
txGas := new(big.Int).Set(tx.Gas())
|
||||||
|
|
||||||
cb := state.GetStateObject(coinbase.Address())
|
cb := state.GetStateObject(coinbase.Address())
|
||||||
st := NewStateTransition(cb, tx, state, block)
|
st := NewStateTransition(NewEnv(state, self.bc, tx, block), tx, cb)
|
||||||
_, err = st.TransitionState()
|
_, err = st.TransitionState()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch {
|
switch {
|
||||||
|
|
@ -127,7 +115,6 @@ done:
|
||||||
statelogger.Infoln(err)
|
statelogger.Infoln(err)
|
||||||
erroneous = append(erroneous, tx)
|
erroneous = append(erroneous, tx)
|
||||||
err = nil
|
err = nil
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,6 +128,7 @@ done:
|
||||||
receipt := types.NewReceipt(state.Root(), cumulative)
|
receipt := types.NewReceipt(state.Root(), cumulative)
|
||||||
receipt.SetLogs(state.Logs())
|
receipt.SetLogs(state.Logs())
|
||||||
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
||||||
|
chainlogger.Debugln(receipt)
|
||||||
|
|
||||||
// Notify all subscribers
|
// Notify all subscribers
|
||||||
if !transientProcess {
|
if !transientProcess {
|
||||||
|
|
@ -156,38 +144,33 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
block.Reward = cumulativeSum
|
block.Reward = cumulativeSum
|
||||||
block.GasUsed = totalUsedGas
|
block.Header().GasUsed = totalUsedGas
|
||||||
|
|
||||||
return receipts, handled, unhandled, erroneous, err
|
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
|
// Processing a blocks may never happen simultaneously
|
||||||
sm.mutex.Lock()
|
sm.mutex.Lock()
|
||||||
defer sm.mutex.Unlock()
|
defer sm.mutex.Unlock()
|
||||||
|
|
||||||
if sm.bc.HasBlock(block.Hash()) {
|
header := block.Header()
|
||||||
return nil, nil, &KnownBlockError{block.Number, block.Hash()}
|
if sm.bc.HasBlock(header.Hash()) {
|
||||||
|
return nil, nil, &KnownBlockError{header.Number, header.Hash()}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !sm.bc.HasBlock(block.PrevHash) {
|
if !sm.bc.HasBlock(header.ParentHash) {
|
||||||
return nil, nil, ParentError(block.PrevHash)
|
return nil, nil, ParentError(header.ParentHash)
|
||||||
}
|
}
|
||||||
parent := sm.bc.GetBlock(block.PrevHash)
|
parent := sm.bc.GetBlock(header.ParentHash)
|
||||||
|
|
||||||
return sm.ProcessWithParent(block, parent)
|
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
|
sm.lastAttemptedBlock = block
|
||||||
|
|
||||||
state := parent.State().Copy()
|
state := state.New(parent.Trie().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()
|
|
||||||
|
|
||||||
// Block validation
|
// Block validation
|
||||||
if err = sm.ValidateBlock(block, parent); err != nil {
|
if err = sm.ValidateBlock(block, parent); err != nil {
|
||||||
|
|
@ -199,21 +182,24 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header := block.Header()
|
||||||
|
|
||||||
rbloom := types.CreateBloom(receipts)
|
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)
|
err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
txSha := types.DeriveSha(block.Transactions())
|
txSha := types.DeriveSha(block.Transactions())
|
||||||
if bytes.Compare(txSha, block.TxSha) != 0 {
|
if bytes.Compare(txSha, header.TxHash) != 0 {
|
||||||
err = fmt.Errorf("validating transaction root. received=%x got=%x", block.TxSha, txSha)
|
err = fmt.Errorf("validating transaction root. received=%x got=%x", header.TxHash, txSha)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
receiptSha := types.DeriveSha(receipts)
|
receiptSha := types.DeriveSha(receipts)
|
||||||
if bytes.Compare(receiptSha, block.ReceiptSha) != 0 {
|
if bytes.Compare(receiptSha, header.ReceiptHash) != 0 {
|
||||||
err = fmt.Errorf("validating receipt root. received=%x got=%x", block.ReceiptSha, receiptSha)
|
fmt.Println("receipts", receipts)
|
||||||
|
err = fmt.Errorf("validating receipt root. received=%x got=%x", header.ReceiptHash, receiptSha)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,8 +209,8 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I
|
||||||
|
|
||||||
state.Update(ethutil.Big0)
|
state.Update(ethutil.Big0)
|
||||||
|
|
||||||
if !block.State().Cmp(state) {
|
if !bytes.Equal(header.Root, state.Root()) {
|
||||||
err = fmt.Errorf("invalid merkle root. received=%x got=%x", block.Root(), state.Root())
|
err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -233,10 +219,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
|
// Sync the current block's state to the database and cancelling out the deferred Undo
|
||||||
state.Sync()
|
state.Sync()
|
||||||
|
|
||||||
|
state.Manifest().SetHash(block.Hash())
|
||||||
|
|
||||||
messages := state.Manifest().Messages
|
messages := state.Manifest().Messages
|
||||||
state.Manifest().Reset()
|
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())
|
sm.txpool.RemoveSet(block.Transactions())
|
||||||
|
|
||||||
|
|
@ -246,16 +234,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)
|
uncleDiff := new(big.Int)
|
||||||
for _, uncle := range block.Uncles {
|
for _, uncle := range block.Uncles() {
|
||||||
uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty)
|
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(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty
|
||||||
td := new(big.Int)
|
td := new(big.Int)
|
||||||
td = td.Add(sm.bc.Td(), uncleDiff)
|
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
|
// The new TD will only be accepted if the new difficulty is
|
||||||
// is greater than the previous.
|
// is greater than the previous.
|
||||||
|
|
@ -269,15 +257,15 @@ func (sm *BlockManager) CalculateTD(block *types.Block) (*big.Int, bool) {
|
||||||
// Validates the current block. Returns an error if the block was invalid,
|
// Validates the current block. Returns an error if the block was invalid,
|
||||||
// an uncle or anything that isn't on the current block chain.
|
// an uncle or anything that isn't on the current block chain.
|
||||||
// Validation validates easy over difficult (dagger takes longer time = difficult)
|
// Validation validates easy over difficult (dagger takes longer time = difficult)
|
||||||
func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error {
|
func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error {
|
||||||
expd := CalcDifficulty(block, parent)
|
expd := CalcDifficulty(block, parent)
|
||||||
if expd.Cmp(block.Difficulty) < 0 {
|
if expd.Cmp(block.Header().Difficulty) < 0 {
|
||||||
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd)
|
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd)
|
||||||
}
|
}
|
||||||
|
|
||||||
diff := block.Time - parent.Time
|
diff := block.Header().Time - parent.Header().Time
|
||||||
if diff < 0 {
|
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
|
/* XXX
|
||||||
|
|
@ -289,33 +277,37 @@ func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error {
|
||||||
|
|
||||||
// Verify the nonce of the block. Return an error if it's not valid
|
// 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*/) {
|
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
|
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)
|
reward := new(big.Int).Set(BlockReward)
|
||||||
|
|
||||||
knownUncles := ethutil.Set(parent.Uncles)
|
knownUncles := set.New()
|
||||||
nonces := ethutil.NewSet(block.Nonce)
|
for _, uncle := range parent.Uncles() {
|
||||||
for _, uncle := range block.Uncles {
|
knownUncles.Add(string(uncle.Hash()))
|
||||||
|
}
|
||||||
|
|
||||||
|
nonces := ethutil.NewSet(block.Header().Nonce)
|
||||||
|
for _, uncle := range block.Uncles() {
|
||||||
if nonces.Include(uncle.Nonce) {
|
if nonces.Include(uncle.Nonce) {
|
||||||
// Error not unique
|
// Error not unique
|
||||||
return UncleError("Uncle not unique")
|
return UncleError("Uncle not unique")
|
||||||
}
|
}
|
||||||
|
|
||||||
uncleParent := sm.bc.GetBlock(uncle.PrevHash)
|
uncleParent := sm.bc.GetBlock(uncle.ParentHash)
|
||||||
if uncleParent == nil {
|
if uncleParent == nil {
|
||||||
return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.PrevHash[0:4]))
|
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 {
|
if uncleParent.Header().Number.Cmp(new(big.Int).Sub(parent.Header().Number, big.NewInt(6))) < 0 {
|
||||||
return UncleError("Uncle too old")
|
return UncleError("Uncle too old")
|
||||||
}
|
}
|
||||||
|
|
||||||
if knownUncles.Include(uncle.Hash()) {
|
if knownUncles.Has(string(uncle.Hash())) {
|
||||||
return UncleError("Uncle in chain")
|
return UncleError("Uncle in chain")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -331,31 +323,31 @@ func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the account associated with the coinbase
|
// 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
|
// Reward amount of ether to the coinbase address
|
||||||
account.AddAmount(reward)
|
account.AddAmount(reward)
|
||||||
|
|
||||||
statedb.Manifest().AddMessage(&state.Message{
|
statedb.Manifest().AddMessage(&state.Message{
|
||||||
To: block.Coinbase,
|
To: block.Header().Coinbase,
|
||||||
Input: nil,
|
Input: nil,
|
||||||
Origin: nil,
|
Origin: nil,
|
||||||
Block: block.Hash(), Timestamp: block.Time, Coinbase: block.Coinbase, Number: block.Number,
|
Timestamp: int64(block.Header().Time), Coinbase: block.Header().Coinbase, Number: block.Header().Number,
|
||||||
Value: new(big.Int).Add(reward, block.Reward),
|
Value: new(big.Int).Add(reward, block.Reward),
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *BlockManager) GetMessages(block *types.Block) (messages []*state.Message, err error) {
|
func (sm *BlockProcessor) GetMessages(block *types.Block) (messages []*state.Message, err error) {
|
||||||
if !sm.bc.HasBlock(block.PrevHash) {
|
if !sm.bc.HasBlock(block.Header().ParentHash) {
|
||||||
return nil, ParentError(block.PrevHash)
|
return nil, ParentError(block.Header().ParentHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
sm.lastAttemptedBlock = block
|
sm.lastAttemptedBlock = block
|
||||||
|
|
||||||
var (
|
var (
|
||||||
parent = sm.bc.GetBlock(block.PrevHash)
|
parent = sm.bc.GetBlock(block.Header().ParentHash)
|
||||||
state = parent.State().Copy()
|
state = state.New(parent.Trie().Copy())
|
||||||
)
|
)
|
||||||
|
|
||||||
defer state.Reset()
|
defer state.Reset()
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -9,42 +10,49 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
"github.com/ethereum/go-ethereum/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
var chainlogger = logger.NewLogger("CHAIN")
|
var chainlogger = logger.NewLogger("CHAIN")
|
||||||
|
|
||||||
func AddTestNetFunds(block *types.Block) {
|
type StateQuery interface {
|
||||||
for _, addr := range []string{
|
GetAccount(addr []byte) *state.StateObject
|
||||||
"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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CalcDifficulty(block, parent *types.Block) *big.Int {
|
func CalcDifficulty(block, parent *types.Block) *big.Int {
|
||||||
diff := new(big.Int)
|
diff := new(big.Int)
|
||||||
|
|
||||||
adjust := new(big.Int).Rsh(parent.Difficulty, 10)
|
bh, ph := block.Header(), parent.Header()
|
||||||
if block.Time >= parent.Time+5 {
|
adjust := new(big.Int).Rsh(ph.Difficulty, 10)
|
||||||
diff.Sub(parent.Difficulty, adjust)
|
if bh.Time >= ph.Time+5 {
|
||||||
|
diff.Sub(ph.Difficulty, adjust)
|
||||||
} else {
|
} else {
|
||||||
diff.Add(parent.Difficulty, adjust)
|
diff.Add(ph.Difficulty, adjust)
|
||||||
}
|
}
|
||||||
|
|
||||||
return diff
|
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 {
|
type ChainManager struct {
|
||||||
//eth EthManager
|
//eth EthManager
|
||||||
processor types.BlockProcessor
|
processor types.BlockProcessor
|
||||||
|
|
@ -90,7 +98,7 @@ func (self *ChainManager) CurrentBlock() *types.Block {
|
||||||
|
|
||||||
func NewChainManager(mux *event.TypeMux) *ChainManager {
|
func NewChainManager(mux *event.TypeMux) *ChainManager {
|
||||||
bc := &ChainManager{}
|
bc := &ChainManager{}
|
||||||
bc.genesisBlock = types.NewBlockFromBytes(ethutil.Encode(Genesis))
|
bc.genesisBlock = GenesisBlock()
|
||||||
bc.eventMux = mux
|
bc.eventMux = mux
|
||||||
|
|
||||||
bc.setLastBlock()
|
bc.setLastBlock()
|
||||||
|
|
@ -112,7 +120,7 @@ func (self *ChainManager) SetProcessor(proc types.BlockProcessor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ChainManager) State() *state.StateDB {
|
func (self *ChainManager) State() *state.StateDB {
|
||||||
return self.CurrentBlock().State()
|
return state.New(self.CurrentBlock().Trie())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ChainManager) TransState() *state.StateDB {
|
func (self *ChainManager) TransState() *state.StateDB {
|
||||||
|
|
@ -122,13 +130,11 @@ func (self *ChainManager) TransState() *state.StateDB {
|
||||||
func (bc *ChainManager) setLastBlock() {
|
func (bc *ChainManager) setLastBlock() {
|
||||||
data, _ := ethutil.Config.Db.Get([]byte("LastBlock"))
|
data, _ := ethutil.Config.Db.Get([]byte("LastBlock"))
|
||||||
if len(data) != 0 {
|
if len(data) != 0 {
|
||||||
// Prep genesis
|
var block types.Block
|
||||||
AddTestNetFunds(bc.genesisBlock)
|
rlp.Decode(bytes.NewReader(data), &block)
|
||||||
|
bc.currentBlock = &block
|
||||||
block := types.NewBlockFromBytes(data)
|
|
||||||
bc.currentBlock = block
|
|
||||||
bc.lastBlockHash = block.Hash()
|
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)
|
// Set the last know difficulty (might be 0x0 as initial value, Genesis)
|
||||||
bc.td = ethutil.BigD(ethutil.Config.Db.LastKnownTD())
|
bc.td = ethutil.BigD(ethutil.Config.Db.LastKnownTD())
|
||||||
|
|
@ -144,27 +150,28 @@ func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block {
|
||||||
bc.mu.RLock()
|
bc.mu.RLock()
|
||||||
defer bc.mu.RUnlock()
|
defer bc.mu.RUnlock()
|
||||||
|
|
||||||
var root interface{}
|
var root []byte
|
||||||
hash := ZeroHash256
|
parentHash := ZeroHash256
|
||||||
|
|
||||||
if bc.CurrentBlock != nil {
|
if bc.CurrentBlock != nil {
|
||||||
root = bc.currentBlock.Root()
|
root = bc.currentBlock.Header().Root
|
||||||
hash = bc.lastBlockHash
|
parentHash = bc.lastBlockHash
|
||||||
}
|
}
|
||||||
|
|
||||||
block := types.CreateBlock(
|
block := types.NewBlock(
|
||||||
root,
|
parentHash,
|
||||||
hash,
|
|
||||||
coinbase,
|
coinbase,
|
||||||
|
root,
|
||||||
ethutil.BigPow(2, 32),
|
ethutil.BigPow(2, 32),
|
||||||
nil,
|
nil,
|
||||||
"")
|
"")
|
||||||
|
|
||||||
parent := bc.currentBlock
|
parent := bc.currentBlock
|
||||||
if parent != nil {
|
if parent != nil {
|
||||||
block.Difficulty = CalcDifficulty(block, parent)
|
header := block.Header()
|
||||||
block.Number = new(big.Int).Add(bc.currentBlock.Number, ethutil.Big1)
|
header.Difficulty = CalcDifficulty(block, parent)
|
||||||
block.GasLimit = block.CalcGasLimit(bc.currentBlock)
|
header.Number = new(big.Int).Add(parent.Header().Number, ethutil.Big1)
|
||||||
|
header.GasLimit = CalcGasLimit(parent, block)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,36 +182,34 @@ func (bc *ChainManager) Reset() {
|
||||||
bc.mu.Lock()
|
bc.mu.Lock()
|
||||||
defer bc.mu.Unlock()
|
defer bc.mu.Unlock()
|
||||||
|
|
||||||
AddTestNetFunds(bc.genesisBlock)
|
for block := bc.currentBlock; block != nil; block = bc.GetBlock(block.Header().ParentHash) {
|
||||||
|
ethutil.Config.Db.Delete(block.Hash())
|
||||||
|
}
|
||||||
|
|
||||||
bc.genesisBlock.Trie().Sync()
|
|
||||||
// Prepare the genesis block
|
// Prepare the genesis block
|
||||||
bc.write(bc.genesisBlock)
|
bc.write(bc.genesisBlock)
|
||||||
bc.insert(bc.genesisBlock)
|
bc.insert(bc.genesisBlock)
|
||||||
bc.currentBlock = bc.genesisBlock
|
bc.currentBlock = bc.genesisBlock
|
||||||
|
|
||||||
bc.setTotalDifficulty(ethutil.Big("0"))
|
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 {
|
func (self *ChainManager) Export() []byte {
|
||||||
self.mu.RLock()
|
self.mu.RLock()
|
||||||
defer self.mu.RUnlock()
|
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)
|
blocks := make([]*types.Block, int(self.currentBlock.NumberU64())+1)
|
||||||
for block := self.currentBlock; block != nil; block = self.GetBlock(block.PrevHash) {
|
for block := self.currentBlock; block != nil; block = self.GetBlock(block.Header().ParentHash) {
|
||||||
blocks[block.Number.Int64()] = block
|
blocks[block.NumberU64()] = block
|
||||||
}
|
}
|
||||||
|
|
||||||
return ethutil.Encode(blocks)
|
return ethutil.Encode(blocks)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *ChainManager) insert(block *types.Block) {
|
func (bc *ChainManager) insert(block *types.Block) {
|
||||||
encodedBlock := block.RlpEncode()
|
encodedBlock := ethutil.Encode(block)
|
||||||
ethutil.Config.Db.Put([]byte("LastBlock"), encodedBlock)
|
ethutil.Config.Db.Put([]byte("LastBlock"), encodedBlock)
|
||||||
bc.currentBlock = block
|
bc.currentBlock = block
|
||||||
bc.lastBlockHash = block.Hash()
|
bc.lastBlockHash = block.Hash()
|
||||||
|
|
@ -213,7 +218,7 @@ func (bc *ChainManager) insert(block *types.Block) {
|
||||||
func (bc *ChainManager) write(block *types.Block) {
|
func (bc *ChainManager) write(block *types.Block) {
|
||||||
bc.writeBlockInfo(block)
|
bc.writeBlockInfo(block)
|
||||||
|
|
||||||
encodedBlock := block.RlpEncode()
|
encodedBlock := ethutil.Encode(block)
|
||||||
ethutil.Config.Db.Put(block.Hash(), encodedBlock)
|
ethutil.Config.Db.Put(block.Hash(), encodedBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,11 +243,11 @@ func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain
|
||||||
for i := uint64(0); i < max; i++ {
|
for i := uint64(0); i < max; i++ {
|
||||||
chain = append(chain, block.Hash())
|
chain = append(chain, block.Hash())
|
||||||
|
|
||||||
if block.Number.Cmp(ethutil.Big0) <= 0 {
|
if block.Header().Number.Cmp(ethutil.Big0) <= 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
block = self.GetBlock(block.PrevHash)
|
block = self.GetBlock(block.Header().ParentHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
@ -253,23 +258,28 @@ func (self *ChainManager) GetBlock(hash []byte) *types.Block {
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return nil
|
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) GetBlockByNumber(num uint64) *types.Block {
|
func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block {
|
||||||
self.mu.RLock()
|
self.mu.RLock()
|
||||||
defer self.mu.RUnlock()
|
defer self.mu.RUnlock()
|
||||||
|
|
||||||
block := self.currentBlock
|
var block *types.Block
|
||||||
for ; block != nil; block = self.GetBlock(block.PrevHash) {
|
|
||||||
if block.Number.Uint64() == num {
|
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
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if block != nil && block.Number.Uint64() == 0 && num != 0 {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return block
|
return block
|
||||||
|
|
@ -281,40 +291,28 @@ func (bc *ChainManager) setTotalDifficulty(td *big.Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ChainManager) CalcTotalDiff(block *types.Block) (*big.Int, error) {
|
func (self *ChainManager) CalcTotalDiff(block *types.Block) (*big.Int, error) {
|
||||||
parent := self.GetBlock(block.PrevHash)
|
parent := self.GetBlock(block.Header().ParentHash)
|
||||||
if parent == nil {
|
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)
|
uncleDiff := new(big.Int)
|
||||||
for _, uncle := range block.Uncles {
|
for _, uncle := range block.Uncles() {
|
||||||
uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty)
|
uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty)
|
||||||
}
|
}
|
||||||
|
|
||||||
td := new(big.Int)
|
td := new(big.Int)
|
||||||
td = td.Add(parentTd, uncleDiff)
|
td = td.Add(parentTd, uncleDiff)
|
||||||
td = td.Add(td, block.Difficulty)
|
td = td.Add(td, block.Header().Difficulty)
|
||||||
|
|
||||||
return td, nil
|
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
|
// Unexported method for writing extra non-essential block info to the db
|
||||||
func (bc *ChainManager) writeBlockInfo(block *types.Block) {
|
func (bc *ChainManager) writeBlockInfo(block *types.Block) {
|
||||||
bc.lastBlockNumber++
|
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() {
|
func (bc *ChainManager) Stop() {
|
||||||
|
|
@ -331,24 +329,26 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
|
||||||
continue
|
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(block)
|
||||||
chainlogger.Infoln(err)
|
chainlogger.Infoln(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
block.Td = td
|
||||||
|
|
||||||
self.mu.Lock()
|
self.mu.Lock()
|
||||||
{
|
{
|
||||||
|
|
||||||
self.write(block)
|
self.write(block)
|
||||||
|
cblock := self.currentBlock
|
||||||
if td.Cmp(self.td) > 0 {
|
if td.Cmp(self.td) > 0 {
|
||||||
if block.Number.Cmp(new(big.Int).Add(self.currentBlock.Number, ethutil.Big1)) < 0 {
|
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.Number, block.Hash()[:4], self.currentBlock.Number, self.currentBlock.Hash()[:4])
|
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.setTotalDifficulty(td)
|
||||||
self.insert(block)
|
self.insert(block)
|
||||||
self.transState = self.currentBlock.State().Copy()
|
self.transState = state.New(cblock.Trie().Copy())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -360,3 +360,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Satisfy state query interface
|
||||||
|
func (self *ChainManager) GetAccount(addr []byte) *state.StateObject {
|
||||||
|
return self.State().GetAccount(addr)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,27 +2,26 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"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() {
|
func init() {
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
//Logger = logpkg.NewStdLogSystem(os.Stdout, log.LstdFlags, logpkg.InfoLevel)
|
|
||||||
//logpkg.AddLogSystem(Logger)
|
|
||||||
|
|
||||||
ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH")
|
ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH")
|
||||||
|
}
|
||||||
|
|
||||||
|
func reset() {
|
||||||
db, err := ethdb.NewMemDatabase()
|
db, err := ethdb.NewMemDatabase()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Could not create mem-db, failing")
|
panic("Could not create mem-db, failing")
|
||||||
|
|
@ -30,20 +29,19 @@ func init() {
|
||||||
ethutil.Config.Db = db
|
ethutil.Config.Db = db
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadChain(fn string, t *testing.T) types.Blocks {
|
func loadChain(fn string, t *testing.T) (types.Blocks, error) {
|
||||||
c1, err := ethutil.ReadAllFile(path.Join("..", "_data", fn))
|
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 {
|
if err != nil {
|
||||||
fmt.Println(err)
|
return nil, err
|
||||||
t.FailNow()
|
|
||||||
}
|
}
|
||||||
value := ethutil.NewValueFromBytes([]byte(c1))
|
defer fh.Close()
|
||||||
blocks := make(types.Blocks, value.Len())
|
|
||||||
it := value.NewIterator()
|
var chain types.Blocks
|
||||||
for it.Next() {
|
if err := rlp.Decode(fh, &chain); err != nil {
|
||||||
blocks[it.Idx()] = types.NewBlockFromRlpValue(it.Value())
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return blocks
|
return chain, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *testing.T) {
|
func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *testing.T) {
|
||||||
|
|
@ -56,11 +54,23 @@ func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChainInsertions(t *testing.T) {
|
func TestChainInsertions(t *testing.T) {
|
||||||
chain1 := loadChain("chain1", t)
|
reset()
|
||||||
chain2 := loadChain("chain2", t)
|
|
||||||
|
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
|
var eventMux event.TypeMux
|
||||||
chainMan := NewChainManager(&eventMux)
|
chainMan := NewChainManager(&eventMux)
|
||||||
txPool := NewTxPool(chainMan, nil, &eventMux)
|
txPool := NewTxPool(&eventMux)
|
||||||
blockMan := NewBlockManager(txPool, chainMan, &eventMux)
|
blockMan := NewBlockManager(txPool, chainMan, &eventMux)
|
||||||
chainMan.SetProcessor(blockMan)
|
chainMan.SetProcessor(blockMan)
|
||||||
|
|
||||||
|
|
@ -73,5 +83,56 @@ func TestChainInsertions(t *testing.T) {
|
||||||
for i := 0; i < max; i++ {
|
for i := 0; i < max; i++ {
|
||||||
<-done
|
<-done
|
||||||
}
|
}
|
||||||
fmt.Println(chainMan.CurrentBlock())
|
|
||||||
|
if reflect.DeepEqual(chain2[len(chain2)-1], chainMan.CurrentBlock()) {
|
||||||
|
t.Error("chain2 is canonical and shouldn't be")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(chain1[len(chain1)-1], chainMan.CurrentBlock()) {
|
||||||
|
t.Error("chain1 isn't canonical and should be")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChainMultipleInsertions(t *testing.T) {
|
||||||
|
reset()
|
||||||
|
|
||||||
|
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(&eventMux)
|
||||||
|
txPool := NewTxPool(&eventMux)
|
||||||
|
blockMan := NewBlockManager(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 !reflect.DeepEqual(chains[longest][len(chains[longest])-1], chainMan.CurrentBlock()) {
|
||||||
|
t.Error("Invalid canonical chain")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,41 +3,39 @@ package core
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/state"
|
"github.com/ethereum/go-ethereum/state"
|
||||||
"github.com/ethereum/go-ethereum/vm"
|
"github.com/ethereum/go-ethereum/vm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Execution struct {
|
type Execution struct {
|
||||||
vm vm.VirtualMachine
|
env vm.Environment
|
||||||
address, input []byte
|
address, input []byte
|
||||||
Gas, price, value *big.Int
|
Gas, price, value *big.Int
|
||||||
object *state.StateObject
|
|
||||||
SkipTransfer bool
|
SkipTransfer bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewExecution(env vm.Environment, address, input []byte, gas, gasPrice, value *big.Int) *Execution {
|
func NewExecution(env vm.Environment, address, input []byte, gas, gasPrice, value *big.Int) *Execution {
|
||||||
evm := vm.New(env, vm.DebugVmTy)
|
return &Execution{env: env, address: address, input: input, Gas: gas, price: gasPrice, value: value}
|
||||||
|
|
||||||
return &Execution{vm: evm, address: address, input: input, Gas: gas, price: gasPrice, value: value}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Execution) Addr() []byte {
|
func (self *Execution) Addr() []byte {
|
||||||
return self.address
|
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
|
// Retrieve the executing code
|
||||||
code := self.vm.Env().State().GetCode(codeAddr)
|
code := self.env.State().GetCode(codeAddr)
|
||||||
|
|
||||||
return self.exec(code, codeAddr, caller)
|
return self.exec(code, codeAddr, caller)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Execution) exec(code, contextAddr []byte, caller vm.ClosureRef) (ret []byte, err error) {
|
func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret []byte, err error) {
|
||||||
env := self.vm.Env()
|
env := self.env
|
||||||
chainlogger.Debugf("pre state %x\n", env.State().Root())
|
evm := vm.New(env, vm.DebugVmTy)
|
||||||
|
|
||||||
if self.vm.Env().Depth() == vm.MaxCallDepth {
|
if env.Depth() == vm.MaxCallDepth {
|
||||||
// Consume all gas (by not returning it) and return a depth error
|
// Consume all gas (by not returning it) and return a depth error
|
||||||
return nil, vm.DepthError{}
|
return nil, vm.DepthError{}
|
||||||
}
|
}
|
||||||
|
|
@ -55,22 +53,19 @@ func (self *Execution) exec(code, contextAddr []byte, caller vm.ClosureRef) (ret
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshot := env.State().Copy()
|
snapshot := env.State().Copy()
|
||||||
defer func() {
|
start := time.Now()
|
||||||
if /*vm.IsDepthErr(err) ||*/ vm.IsOOGErr(err) {
|
ret, err = evm.Run(to, caller, code, self.value, self.Gas, self.price, self.input)
|
||||||
|
if err != nil {
|
||||||
env.State().Set(snapshot)
|
env.State().Set(snapshot)
|
||||||
}
|
}
|
||||||
chainlogger.Debugf("post state %x\n", env.State().Root())
|
chainlogger.Debugf("vm took %v\n", time.Since(start))
|
||||||
}()
|
|
||||||
|
|
||||||
self.object = to
|
|
||||||
ret, err = self.vm.Run(to, caller, code, self.value, self.Gas, self.price, self.input)
|
|
||||||
|
|
||||||
return
|
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)
|
ret, err = self.exec(self.input, nil, caller)
|
||||||
account = self.vm.Env().State().GetStateObject(self.address)
|
account = self.env.State().GetStateObject(self.address)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,13 +76,14 @@ func (self *Filter) SetSkip(skip int) {
|
||||||
|
|
||||||
// Run filters messages with the current parameters set
|
// Run filters messages with the current parameters set
|
||||||
func (self *Filter) Find() []*state.Message {
|
func (self *Filter) Find() []*state.Message {
|
||||||
|
earliestBlock := self.eth.ChainManager().CurrentBlock()
|
||||||
var earliestBlockNo uint64 = uint64(self.earliest)
|
var earliestBlockNo uint64 = uint64(self.earliest)
|
||||||
if self.earliest == -1 {
|
if self.earliest == -1 {
|
||||||
earliestBlockNo = self.eth.ChainManager().CurrentBlock().Number.Uint64()
|
earliestBlockNo = earliestBlock.NumberU64()
|
||||||
}
|
}
|
||||||
var latestBlockNo uint64 = uint64(self.latest)
|
var latestBlockNo uint64 = uint64(self.latest)
|
||||||
if self.latest == -1 {
|
if self.latest == -1 {
|
||||||
latestBlockNo = self.eth.ChainManager().CurrentBlock().Number.Uint64()
|
latestBlockNo = earliestBlock.NumberU64()
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -93,7 +94,7 @@ func (self *Filter) Find() []*state.Message {
|
||||||
for i := 0; !quit && block != nil; i++ {
|
for i := 0; !quit && block != nil; i++ {
|
||||||
// Quit on latest
|
// Quit on latest
|
||||||
switch {
|
switch {
|
||||||
case block.Number.Uint64() == earliestBlockNo, block.Number.Uint64() == 0:
|
case block.NumberU64() == earliestBlockNo, block.NumberU64() == 0:
|
||||||
quit = true
|
quit = true
|
||||||
case self.max <= len(messages):
|
case self.max <= len(messages):
|
||||||
break
|
break
|
||||||
|
|
@ -103,7 +104,7 @@ func (self *Filter) Find() []*state.Message {
|
||||||
// current parameters
|
// current parameters
|
||||||
if self.bloomFilter(block) {
|
if self.bloomFilter(block) {
|
||||||
// Get the messages of the block
|
// Get the messages of the block
|
||||||
msgs, err := self.eth.BlockManager().GetMessages(block)
|
msgs, err := self.eth.BlockProcessor().GetMessages(block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
chainlogger.Warnln("err: filter get messages ", err)
|
chainlogger.Warnln("err: filter get messages ", err)
|
||||||
|
|
||||||
|
|
@ -113,7 +114,7 @@ func (self *Filter) Find() []*state.Message {
|
||||||
messages = append(messages, self.FilterMessages(msgs)...)
|
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)))
|
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
|
var fromIncluded, toIncluded bool
|
||||||
if len(self.from) > 0 {
|
if len(self.from) > 0 {
|
||||||
for _, from := range self.from {
|
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
|
fromIncluded = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -187,7 +188,7 @@ func (self *Filter) bloomFilter(block *types.Block) bool {
|
||||||
|
|
||||||
if len(self.to) > 0 {
|
if len(self.to) > 0 {
|
||||||
for _, to := range self.to {
|
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
|
toIncluded = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,10 @@ package core
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
|
"github.com/ethereum/go-ethereum/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -17,36 +19,35 @@ var ZeroHash512 = make([]byte, 64)
|
||||||
var EmptyShaList = crypto.Sha3(ethutil.Encode([]interface{}{}))
|
var EmptyShaList = crypto.Sha3(ethutil.Encode([]interface{}{}))
|
||||||
var EmptyListRoot = crypto.Sha3(ethutil.Encode(""))
|
var EmptyListRoot = crypto.Sha3(ethutil.Encode(""))
|
||||||
|
|
||||||
var GenesisHeader = []interface{}{
|
func GenesisBlock() *types.Block {
|
||||||
// Previous hash (none)
|
genesis := types.NewBlock(ZeroHash256, ZeroHash160, nil, big.NewInt(131072), crypto.Sha3(big.NewInt(42).Bytes()), "")
|
||||||
ZeroHash256,
|
genesis.Header().Number = ethutil.Big0
|
||||||
// Empty uncles
|
genesis.Header().GasLimit = big.NewInt(1000000)
|
||||||
EmptyShaList,
|
genesis.Header().GasUsed = ethutil.Big0
|
||||||
// Coinbase
|
genesis.Header().Time = 0
|
||||||
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()),
|
|
||||||
}
|
|
||||||
|
|
||||||
var Genesis = []interface{}{GenesisHeader, []interface{}{}, []interface{}{}}
|
genesis.SetUncles([]*types.Header{})
|
||||||
|
genesis.SetTransactions(types.Transactions{})
|
||||||
|
genesis.SetReceipts(types.Receipts{})
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/wire"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Implement our EthTest Manager
|
// Implement our EthTest Manager
|
||||||
|
|
@ -54,11 +54,11 @@ func (tm *TestManager) TxPool() *TxPool {
|
||||||
func (tm *TestManager) EventMux() *event.TypeMux {
|
func (tm *TestManager) EventMux() *event.TypeMux {
|
||||||
return tm.eventMux
|
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")
|
fmt.Println("Broadcast not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tm *TestManager) ClientIdentity() wire.ClientIdentity {
|
func (tm *TestManager) ClientIdentity() p2p.ClientIdentity {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (tm *TestManager) KeyManager() *crypto.KeyManager {
|
func (tm *TestManager) KeyManager() *crypto.KeyManager {
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
package core
|
|
||||||
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
"github.com/ethereum/go-ethereum/state"
|
||||||
|
|
@ -28,18 +27,17 @@ import (
|
||||||
* 6) Derive new state root
|
* 6) Derive new state root
|
||||||
*/
|
*/
|
||||||
type StateTransition struct {
|
type StateTransition struct {
|
||||||
coinbase, receiver []byte
|
coinbase []byte
|
||||||
msg Message
|
msg Message
|
||||||
gas, gasPrice *big.Int
|
gas, gasPrice *big.Int
|
||||||
initialGas *big.Int
|
initialGas *big.Int
|
||||||
value *big.Int
|
value *big.Int
|
||||||
data []byte
|
data []byte
|
||||||
state *state.StateDB
|
state *state.StateDB
|
||||||
block *types.Block
|
|
||||||
|
|
||||||
cb, rec, sen *state.StateObject
|
cb, rec, sen *state.StateObject
|
||||||
|
|
||||||
Env vm.Environment
|
env vm.Environment
|
||||||
}
|
}
|
||||||
|
|
||||||
type Message interface {
|
type Message interface {
|
||||||
|
|
@ -69,16 +67,19 @@ func MessageGasValue(msg Message) *big.Int {
|
||||||
return new(big.Int).Mul(msg.Gas(), msg.GasPrice())
|
return new(big.Int).Mul(msg.Gas(), msg.GasPrice())
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStateTransition(coinbase *state.StateObject, msg Message, state *state.StateDB, block *types.Block) *StateTransition {
|
func NewStateTransition(env vm.Environment, msg Message, coinbase *state.StateObject) *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}
|
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateTransition) VmEnv() vm.Environment {
|
|
||||||
if self.Env == nil {
|
|
||||||
self.Env = NewEnv(self.state, self.msg, self.block)
|
|
||||||
}
|
|
||||||
|
|
||||||
return self.Env
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateTransition) Coinbase() *state.StateObject {
|
func (self *StateTransition) Coinbase() *state.StateObject {
|
||||||
|
|
@ -112,7 +113,7 @@ func (self *StateTransition) BuyGas() error {
|
||||||
|
|
||||||
sender := self.From()
|
sender := self.From()
|
||||||
if sender.Balance().Cmp(MessageGasValue(self.msg)) < 0 {
|
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()
|
coinbase := self.Coinbase()
|
||||||
|
|
@ -183,18 +184,25 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
vmenv := self.VmEnv()
|
vmenv := self.env
|
||||||
var ref vm.ClosureRef
|
var ref vm.ContextRef
|
||||||
if MessageCreatesContract(msg) {
|
if MessageCreatesContract(msg) {
|
||||||
self.rec = MakeContract(msg, self.state)
|
contract := MakeContract(msg, self.state)
|
||||||
|
ret, err, ref = vmenv.Create(sender, contract.Address(), self.msg.Data(), self.gas, self.gasPrice, self.value)
|
||||||
ret, err, ref = vmenv.Create(sender, self.rec.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)
|
ref.SetCode(ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ret, err = vmenv.Call(self.From(), self.To().Address(), self.msg.Data(), self.gas, self.gasPrice, self.value)
|
ret, err = vmenv.Call(self.From(), self.To().Address(), self.msg.Data(), self.gas, self.gasPrice, self.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
statelogger.Debugln(err)
|
self.UseGas(self.gas)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
@ -211,20 +219,19 @@ func MakeContract(msg Message, state *state.StateDB) *state.StateObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateTransition) RefundGas() {
|
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, sender := self.Coinbase(), self.From()
|
||||||
coinbase.RefundGas(coinbaseSub, self.msg.GasPrice())
|
|
||||||
|
|
||||||
// Return remaining gas
|
// Return remaining gas
|
||||||
remaining := new(big.Int).Mul(self.gas, self.msg.GasPrice())
|
remaining := new(big.Int).Mul(self.gas, self.msg.GasPrice())
|
||||||
sender.AddAmount(remaining)
|
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 {
|
func (self *StateTransition) GasUsed() *big.Int {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,13 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"container/list"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
"gopkg.in/fatih/set.v0"
|
||||||
)
|
)
|
||||||
|
|
||||||
var txplogger = logger.NewLogger("TXP")
|
var txplogger = logger.NewLogger("TXP")
|
||||||
|
|
@ -26,101 +23,66 @@ const (
|
||||||
minGasPrice = 1000000
|
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 {
|
type TxProcessor interface {
|
||||||
ProcessTransaction(tx *types.Transaction)
|
ProcessTransaction(tx *types.Transaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The tx pool a thread safe transaction pool handler. In order to
|
// 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
|
// guarantee a non blocking pool we use a queue channel which can be
|
||||||
// independently read without needing access to the actual pool. If the
|
// independently read without needing access to the actual pool.
|
||||||
// pool is being drained or synced for whatever reason the transactions
|
|
||||||
// will simple queue up and handled when the mutex is freed.
|
|
||||||
type TxPool struct {
|
type TxPool struct {
|
||||||
// The mutex for accessing the Tx pool.
|
|
||||||
mutex sync.Mutex
|
|
||||||
// Queueing channel for reading and writing incoming
|
// Queueing channel for reading and writing incoming
|
||||||
// transactions to
|
// transactions to
|
||||||
queueChan chan *types.Transaction
|
queueChan chan *types.Transaction
|
||||||
// Quiting channel
|
// Quiting channel
|
||||||
quit chan bool
|
quit chan bool
|
||||||
// The actual pool
|
// The actual pool
|
||||||
pool *list.List
|
//pool *list.List
|
||||||
|
pool *set.Set
|
||||||
|
|
||||||
SecondaryProcessor TxProcessor
|
SecondaryProcessor TxProcessor
|
||||||
|
|
||||||
subscribers []chan TxMsg
|
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{
|
return &TxPool{
|
||||||
pool: list.New(),
|
pool: set.New(),
|
||||||
queueChan: make(chan *types.Transaction, txPoolQueueSize),
|
queueChan: make(chan *types.Transaction, txPoolQueueSize),
|
||||||
quit: make(chan bool),
|
quit: make(chan bool),
|
||||||
chainManager: chainManager,
|
|
||||||
eventMux: eventMux,
|
eventMux: eventMux,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blocking function. Don't use directly. Use QueueTransaction instead
|
|
||||||
func (pool *TxPool) addTransaction(tx *types.Transaction) {
|
func (pool *TxPool) addTransaction(tx *types.Transaction) {
|
||||||
pool.mutex.Lock()
|
pool.pool.Add(tx)
|
||||||
defer pool.mutex.Unlock()
|
|
||||||
|
|
||||||
pool.pool.PushBack(tx)
|
|
||||||
|
|
||||||
// Broadcast the transaction to the rest of the peers
|
// Broadcast the transaction to the rest of the peers
|
||||||
pool.eventMux.Post(TxPreEvent{tx})
|
pool.eventMux.Post(TxPreEvent{tx})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error {
|
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 {
|
if len(tx.To()) != 0 && len(tx.To()) != 20 {
|
||||||
return fmt.Errorf("Invalid recipient. len = %d", len(tx.To()))
|
return fmt.Errorf("Invalid recipient. len = %d", len(tx.To()))
|
||||||
}
|
}
|
||||||
|
|
||||||
v, _, _ := tx.Curve()
|
v, _, _ := tx.Curve()
|
||||||
if v > 28 || v < 27 {
|
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
|
// Get the sender
|
||||||
senderAddr := tx.From()
|
senderAddr := tx.From()
|
||||||
if senderAddr == nil {
|
if senderAddr == nil {
|
||||||
return fmt.Errorf("invalid sender")
|
return fmt.Errorf("invalid sender")
|
||||||
}
|
}
|
||||||
sender := pool.chainManager.State().GetAccount(senderAddr)
|
sender := pool.stateQuery.GetAccount(senderAddr)
|
||||||
|
|
||||||
totAmount := new(big.Int).Set(tx.Value())
|
totAmount := new(big.Int).Set(tx.Value())
|
||||||
// Make sure there's enough in the sender's account. Having insufficient
|
// Make sure there's enough in the sender's account. Having insufficient
|
||||||
|
|
@ -128,20 +90,14 @@ func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error {
|
||||||
if sender.Balance().Cmp(totAmount) < 0 {
|
if sender.Balance().Cmp(totAmount) < 0 {
|
||||||
return fmt.Errorf("Insufficient amount in sender's (%x) account", tx.From())
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TxPool) Add(tx *types.Transaction) error {
|
func (self *TxPool) Add(tx *types.Transaction) error {
|
||||||
hash := tx.Hash()
|
hash := tx.Hash()
|
||||||
foundTx := FindTx(self.pool, func(tx *types.Transaction, e *list.Element) bool {
|
if self.pool.Has(tx) {
|
||||||
return bytes.Compare(tx.Hash(), hash) == 0
|
|
||||||
})
|
|
||||||
|
|
||||||
if foundTx != nil {
|
|
||||||
return fmt.Errorf("Known transaction (%x)", hash[0:4])
|
return fmt.Errorf("Known transaction (%x)", hash[0:4])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,7 +108,14 @@ func (self *TxPool) Add(tx *types.Transaction) error {
|
||||||
|
|
||||||
self.addTransaction(tx)
|
self.addTransaction(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
|
// Notify the subscribers
|
||||||
go self.eventMux.Post(TxPreEvent{tx})
|
go self.eventMux.Post(TxPreEvent{tx})
|
||||||
|
|
@ -161,7 +124,7 @@ func (self *TxPool) Add(tx *types.Transaction) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TxPool) Size() int {
|
func (self *TxPool) Size() int {
|
||||||
return self.pool.Len()
|
return self.pool.Size()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TxPool) AddTransactions(txs []*types.Transaction) {
|
func (self *TxPool) AddTransactions(txs []*types.Transaction) {
|
||||||
|
|
@ -175,63 +138,47 @@ func (self *TxPool) AddTransactions(txs []*types.Transaction) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pool *TxPool) GetTransactions() []*types.Transaction {
|
func (pool *TxPool) GetTransactions() []*types.Transaction {
|
||||||
pool.mutex.Lock()
|
txList := make([]*types.Transaction, pool.Size())
|
||||||
defer pool.mutex.Unlock()
|
|
||||||
|
|
||||||
txList := make([]*types.Transaction, pool.pool.Len())
|
|
||||||
i := 0
|
i := 0
|
||||||
for e := pool.pool.Front(); e != nil; e = e.Next() {
|
pool.pool.Each(func(v interface{}) bool {
|
||||||
tx := e.Value.(*types.Transaction)
|
txList[i] = v.(*types.Transaction)
|
||||||
|
|
||||||
txList[i] = tx
|
|
||||||
|
|
||||||
i++
|
i++
|
||||||
}
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
return txList
|
return txList
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pool *TxPool) RemoveInvalid(state *state.StateDB) {
|
func (pool *TxPool) RemoveInvalid(query StateQuery) {
|
||||||
pool.mutex.Lock()
|
var removedTxs types.Transactions
|
||||||
defer pool.mutex.Unlock()
|
pool.pool.Each(func(v interface{}) bool {
|
||||||
|
tx := v.(*types.Transaction)
|
||||||
for e := pool.pool.Front(); e != nil; e = e.Next() {
|
sender := query.GetAccount(tx.From())
|
||||||
tx := e.Value.(*types.Transaction)
|
|
||||||
sender := state.GetAccount(tx.From())
|
|
||||||
err := pool.ValidateTransaction(tx)
|
err := pool.ValidateTransaction(tx)
|
||||||
if err != nil || sender.Nonce >= tx.Nonce() {
|
if err != nil || sender.Nonce >= tx.Nonce() {
|
||||||
pool.pool.Remove(e)
|
removedTxs = append(removedTxs, tx)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
pool.RemoveSet(removedTxs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TxPool) RemoveSet(txs types.Transactions) {
|
func (self *TxPool) RemoveSet(txs types.Transactions) {
|
||||||
self.mutex.Lock()
|
|
||||||
defer self.mutex.Unlock()
|
|
||||||
|
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
EachTx(self.pool, func(t *types.Transaction, element *list.Element) bool {
|
self.pool.Remove(tx)
|
||||||
if t == tx {
|
|
||||||
self.pool.Remove(element)
|
|
||||||
return true // To stop the loop
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pool *TxPool) Flush() []*types.Transaction {
|
func (pool *TxPool) Flush() []*types.Transaction {
|
||||||
txList := pool.GetTransactions()
|
txList := pool.GetTransactions()
|
||||||
|
pool.pool.Clear()
|
||||||
// Recreate a new list all together
|
|
||||||
// XXX Is this the fastest way?
|
|
||||||
pool.pool = list.New()
|
|
||||||
|
|
||||||
return txList
|
return txList
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pool *TxPool) Start() {
|
func (pool *TxPool) Start() {
|
||||||
//go pool.queueHandler()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pool *TxPool) Stop() {
|
func (pool *TxPool) Stop() {
|
||||||
|
|
|
||||||
81
core/transaction_pool_test.go
Normal file
81
core/transaction_pool_test.go
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
"github.com/ethereum/go-ethereum/state"
|
||||||
|
)
|
||||||
|
|
||||||
|
// State query interface
|
||||||
|
type stateQuery struct{}
|
||||||
|
|
||||||
|
func (self stateQuery) GetAccount(addr []byte) *state.StateObject {
|
||||||
|
return state.NewStateObject(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
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.pool.Add(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.pool.Add(tx1)
|
||||||
|
pool.RemoveInvalid(stateQuery{})
|
||||||
|
if pool.Size() > 0 {
|
||||||
|
t.Error("expected pool size to be 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
tx1.SetNonce(1)
|
||||||
|
tx1.SignECDSA(key)
|
||||||
|
pool.pool.Add(tx1)
|
||||||
|
pool.RemoveInvalid(stateQuery{})
|
||||||
|
if pool.Size() != 1 {
|
||||||
|
t.Error("expected pool size to be 1, is", pool.Size())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,41 +9,240 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
|
"github.com/ethereum/go-ethereum/ptrie"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
"github.com/ethereum/go-ethereum/state"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type BlockInfo struct {
|
type Header struct {
|
||||||
Number uint64
|
// Hash to the previous block
|
||||||
Hash []byte
|
ParentHash ethutil.Bytes
|
||||||
Parent []byte
|
// Uncles of this block
|
||||||
TD *big.Int
|
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) {
|
func (self *Header) rlpData(withNonce bool) []interface{} {
|
||||||
decoder := ethutil.NewValueFromBytes(data)
|
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 {
|
||||||
bi.Number = decoder.Get(0).Uint()
|
fields = append(fields, self.Nonce)
|
||||||
bi.Hash = decoder.Get(1).Bytes()
|
|
||||||
bi.Parent = decoder.Get(2).Bytes()
|
|
||||||
bi.TD = decoder.Get(3).BigInt()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bi *BlockInfo) RlpEncode() []byte {
|
return fields
|
||||||
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 {
|
||||||
|
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 {
|
||||||
|
if _, err := s.List(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var header Header
|
||||||
|
if err := s.Decode(&header); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var transactions []*Transaction
|
||||||
|
if err := s.Decode(&transactions); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var uncleHeaders []*Header
|
||||||
|
if err := s.Decode(&uncleHeaders); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tdBytes []byte
|
||||||
|
if err := s.Decode(&tdBytes); err != nil {
|
||||||
|
// If this block comes from the network that's fine. If loaded from disk it should be there
|
||||||
|
// Blocks don't store their Td when propagated over the network
|
||||||
|
} else {
|
||||||
|
self.Td = ethutil.BigD(tdBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.ListEnd(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
self.header = &header
|
||||||
|
self.uncles = uncleHeaders
|
||||||
|
self.transactions = transactions
|
||||||
|
|
||||||
|
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) ParentHash() []byte { return self.header.ParentHash }
|
||||||
|
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) Hash() []byte { return self.header.Hash() }
|
||||||
|
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) Size() ethutil.StorageSize { return ethutil.StorageSize(len(ethutil.Encode(self))) }
|
||||||
|
func (self *Block) SetRoot(root []byte) { self.header.Root = root }
|
||||||
|
|
||||||
|
// Implement block.Pow
|
||||||
|
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 crypto.Sha3(ethutil.Encode(self.header.rlpData(false)))
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
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
|
type BlockBy func(b1, b2 *Block) bool
|
||||||
|
|
||||||
func (self BlockBy) Sort(blocks Blocks) {
|
func (self BlockBy) Sort(blocks Blocks) {
|
||||||
|
|
@ -65,352 +264,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 (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 }
|
func Number(b1, b2 *Block) bool { return b1.Header().Number.Cmp(b2.Header().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 }
|
|
||||||
|
|
|
||||||
1
core/types/block_test.go
Normal file
1
core/types/block_test.go
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
package types
|
||||||
|
|
@ -2,7 +2,7 @@ package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/ptrie"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DerivableList interface {
|
type DerivableList interface {
|
||||||
|
|
@ -11,10 +11,10 @@ type DerivableList interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeriveSha(list DerivableList) []byte {
|
func DeriveSha(list DerivableList) []byte {
|
||||||
trie := trie.New(ethutil.Config.Db, "")
|
trie := ptrie.New(nil, ethutil.Config.Db)
|
||||||
for i := 0; i < list.Len(); i++ {
|
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()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/ecdsa"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/obscuren/secp256k1-go"
|
"github.com/obscuren/secp256k1-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -14,22 +17,22 @@ func IsContractAddr(addr []byte) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Transaction struct {
|
type Transaction struct {
|
||||||
nonce uint64
|
AccountNonce uint64
|
||||||
recipient []byte
|
Price *big.Int
|
||||||
value *big.Int
|
GasLimit *big.Int
|
||||||
gas *big.Int
|
Recipient []byte
|
||||||
gasPrice *big.Int
|
Amount *big.Int
|
||||||
data []byte
|
Payload []byte
|
||||||
v byte
|
V uint64
|
||||||
r, s []byte
|
R, S []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContractCreationTx(value, gas, gasPrice *big.Int, script []byte) *Transaction {
|
func NewContractCreationTx(Amount, gasAmount, price *big.Int, data []byte) *Transaction {
|
||||||
return &Transaction{recipient: nil, value: value, gas: gas, gasPrice: gasPrice, data: script}
|
return NewTransactionMessage(nil, Amount, gasAmount, price, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTransactionMessage(to []byte, value, gas, gasPrice *big.Int, data []byte) *Transaction {
|
func NewTransactionMessage(to []byte, Amount, gasAmount, price *big.Int, data []byte) *Transaction {
|
||||||
return &Transaction{recipient: to, value: value, gasPrice: gasPrice, gas: gas, data: data}
|
return &Transaction{Recipient: to, Amount: Amount, Price: price, GasLimit: gasAmount, Payload: data}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTransactionFromBytes(data []byte) *Transaction {
|
func NewTransactionFromBytes(data []byte) *Transaction {
|
||||||
|
|
@ -39,7 +42,7 @@ func NewTransactionFromBytes(data []byte) *Transaction {
|
||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTransactionFromValue(val *ethutil.Value) *Transaction {
|
func NewTransactionFromAmount(val *ethutil.Value) *Transaction {
|
||||||
tx := &Transaction{}
|
tx := &Transaction{}
|
||||||
tx.RlpValueDecode(val)
|
tx.RlpValueDecode(val)
|
||||||
|
|
||||||
|
|
@ -47,33 +50,33 @@ func NewTransactionFromValue(val *ethutil.Value) *Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) Hash() []byte {
|
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 {
|
func (self *Transaction) Data() []byte {
|
||||||
return self.data
|
return self.Payload
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Transaction) Gas() *big.Int {
|
func (self *Transaction) Gas() *big.Int {
|
||||||
return self.gas
|
return self.GasLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Transaction) GasPrice() *big.Int {
|
func (self *Transaction) GasPrice() *big.Int {
|
||||||
return self.gasPrice
|
return self.Price
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Transaction) Value() *big.Int {
|
func (self *Transaction) Value() *big.Int {
|
||||||
return self.value
|
return self.Amount
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Transaction) Nonce() uint64 {
|
func (self *Transaction) Nonce() uint64 {
|
||||||
return self.nonce
|
return self.AccountNonce
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Transaction) SetNonce(nonce uint64) {
|
func (self *Transaction) SetNonce(AccountNonce uint64) {
|
||||||
self.nonce = nonce
|
self.AccountNonce = AccountNonce
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Transaction) From() []byte {
|
func (self *Transaction) From() []byte {
|
||||||
|
|
@ -81,13 +84,13 @@ func (self *Transaction) From() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Transaction) To() []byte {
|
func (self *Transaction) To() []byte {
|
||||||
return self.recipient
|
return self.Recipient
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) Curve() (v byte, r []byte, s []byte) {
|
func (tx *Transaction) Curve() (v byte, r []byte, s []byte) {
|
||||||
v = tx.v
|
v = byte(tx.V)
|
||||||
r = ethutil.LeftPadBytes(tx.r, 32)
|
r = ethutil.LeftPadBytes(tx.R, 32)
|
||||||
s = ethutil.LeftPadBytes(tx.s, 32)
|
s = ethutil.LeftPadBytes(tx.S, 32)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -108,8 +111,8 @@ func (tx *Transaction) PublicKey() []byte {
|
||||||
sig := append(r, s...)
|
sig := append(r, s...)
|
||||||
sig = append(sig, v-27)
|
sig = append(sig, v-27)
|
||||||
|
|
||||||
pubkey := crypto.Ecrecover(append(hash, sig...))
|
//pubkey := crypto.Ecrecover(append(hash, sig...))
|
||||||
//pubkey, _ := secp256k1.RecoverPubkey(hash, sig)
|
pubkey, _ := secp256k1.RecoverPubkey(hash, sig)
|
||||||
|
|
||||||
return pubkey
|
return pubkey
|
||||||
}
|
}
|
||||||
|
|
@ -130,44 +133,41 @@ func (tx *Transaction) Sign(privk []byte) error {
|
||||||
|
|
||||||
sig := tx.Signature(privk)
|
sig := tx.Signature(privk)
|
||||||
|
|
||||||
tx.r = sig[:32]
|
tx.R = sig[:32]
|
||||||
tx.s = sig[32:64]
|
tx.S = sig[32:64]
|
||||||
tx.v = sig[64] + 27
|
tx.V = uint64(sig[64] + 27)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) RlpData() interface{} {
|
func (tx *Transaction) SignECDSA(key *ecdsa.PrivateKey) error {
|
||||||
data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.recipient, tx.Value, tx.Data}
|
return tx.Sign(crypto.FromECDSA(key))
|
||||||
|
|
||||||
// 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) RlpValue() *ethutil.Value {
|
func (tx *Transaction) RlpData() interface{} {
|
||||||
return ethutil.NewValue(tx.RlpData())
|
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 {
|
func (tx *Transaction) RlpEncode() []byte {
|
||||||
return tx.RlpValue().Encode()
|
return ethutil.Encode(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) RlpDecode(data []byte) {
|
func (tx *Transaction) RlpDecode(data []byte) {
|
||||||
tx.RlpValueDecode(ethutil.NewValueFromBytes(data))
|
rlp.Decode(bytes.NewReader(data), tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
|
func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
|
||||||
tx.nonce = decoder.Get(0).Uint()
|
tx.AccountNonce = decoder.Get(0).Uint()
|
||||||
tx.gasPrice = decoder.Get(1).BigInt()
|
tx.Price = decoder.Get(1).BigInt()
|
||||||
tx.gas = decoder.Get(2).BigInt()
|
tx.GasLimit = decoder.Get(2).BigInt()
|
||||||
tx.recipient = decoder.Get(3).Bytes()
|
tx.Recipient = decoder.Get(3).Bytes()
|
||||||
tx.value = decoder.Get(4).BigInt()
|
tx.Amount = decoder.Get(4).BigInt()
|
||||||
tx.data = decoder.Get(5).Bytes()
|
tx.Payload = decoder.Get(5).Bytes()
|
||||||
tx.v = byte(decoder.Get(6).Uint())
|
tx.V = decoder.Get(6).Uint()
|
||||||
|
tx.R = decoder.Get(7).Bytes()
|
||||||
tx.r = decoder.Get(7).Bytes()
|
tx.S = decoder.Get(8).Bytes()
|
||||||
tx.s = decoder.Get(8).Bytes()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) String() string {
|
func (tx *Transaction) String() string {
|
||||||
|
|
@ -178,25 +178,28 @@ func (tx *Transaction) String() string {
|
||||||
To: %x
|
To: %x
|
||||||
Nonce: %v
|
Nonce: %v
|
||||||
GasPrice: %v
|
GasPrice: %v
|
||||||
Gas: %v
|
GasLimit %v
|
||||||
Value: %v
|
Value: %v
|
||||||
Data: 0x%x
|
Data: 0x%x
|
||||||
V: 0x%x
|
V: 0x%x
|
||||||
R: 0x%x
|
R: 0x%x
|
||||||
S: 0x%x
|
S: 0x%x
|
||||||
|
Hex: %x
|
||||||
`,
|
`,
|
||||||
tx.Hash(),
|
tx.Hash(),
|
||||||
len(tx.recipient) == 0,
|
len(tx.Recipient) == 0,
|
||||||
tx.From(),
|
tx.From(),
|
||||||
tx.recipient,
|
tx.To(),
|
||||||
tx.nonce,
|
tx.AccountNonce,
|
||||||
tx.gasPrice,
|
tx.Price,
|
||||||
tx.gas,
|
tx.GasLimit,
|
||||||
tx.Value,
|
tx.Amount,
|
||||||
tx.Data,
|
tx.Payload,
|
||||||
tx.v,
|
tx.V,
|
||||||
tx.r,
|
tx.R,
|
||||||
tx.s)
|
tx.S,
|
||||||
|
ethutil.Encode(tx),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transaction slice type for basic sorting
|
// 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 }
|
type TxByNonce struct{ Transactions }
|
||||||
|
|
||||||
func (s TxByNonce) Less(i, j int) bool {
|
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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,12 @@ type VMEnv struct {
|
||||||
block *types.Block
|
block *types.Block
|
||||||
msg Message
|
msg Message
|
||||||
depth int
|
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{
|
return &VMEnv{
|
||||||
|
chain: chain,
|
||||||
state: state,
|
state: state,
|
||||||
block: block,
|
block: block,
|
||||||
msg: msg,
|
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) Origin() []byte { return self.msg.From() }
|
||||||
func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number }
|
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) Coinbase() []byte { return self.block.Coinbase }
|
func (self *VMEnv) Time() int64 { return self.block.Time() }
|
||||||
func (self *VMEnv) Time() int64 { return self.block.Time }
|
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() }
|
||||||
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty }
|
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() }
|
||||||
func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
|
|
||||||
func (self *VMEnv) Value() *big.Int { return self.msg.Value() }
|
func (self *VMEnv) Value() *big.Int { return self.msg.Value() }
|
||||||
func (self *VMEnv) State() *state.StateDB { return self.state }
|
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) Depth() int { return self.depth }
|
||||||
func (self *VMEnv) SetDepth(i int) { self.depth = i }
|
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) {
|
func (self *VMEnv) AddLog(log state.Log) {
|
||||||
self.state.AddLog(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)
|
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)
|
exe := self.vm(addr, data, gas, price, value)
|
||||||
return exe.Call(addr, me)
|
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)
|
exe := self.vm(me.Address(), data, gas, price, value)
|
||||||
return exe.Call(addr, me)
|
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)
|
exe := self.vm(addr, data, gas, price, value)
|
||||||
return exe.Create(me)
|
return exe.Create(me)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
106
eth/backend.go
106
eth/backend.go
|
|
@ -1,11 +1,13 @@
|
||||||
package eth
|
package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
ethlogger "github.com/ethereum/go-ethereum/logger"
|
ethlogger "github.com/ethereum/go-ethereum/logger"
|
||||||
|
|
@ -19,6 +21,24 @@ const (
|
||||||
seedNodeAddress = "poc-7.ethdev.com:30300"
|
seedNodeAddress = "poc-7.ethdev.com:30300"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
KeyManager *crypto.KeyManager
|
||||||
|
}
|
||||||
|
|
||||||
var logger = ethlogger.NewLogger("SERV")
|
var logger = ethlogger.NewLogger("SERV")
|
||||||
|
|
||||||
type Ethereum struct {
|
type Ethereum struct {
|
||||||
|
|
@ -32,13 +52,13 @@ type Ethereum struct {
|
||||||
|
|
||||||
//*** SERVICES ***
|
//*** SERVICES ***
|
||||||
// State manager for processing new blocks and managing the over all states
|
// State manager for processing new blocks and managing the over all states
|
||||||
blockManager *core.BlockManager
|
blockProcessor *core.BlockProcessor
|
||||||
txPool *core.TxPool
|
txPool *core.TxPool
|
||||||
chainManager *core.ChainManager
|
chainManager *core.ChainManager
|
||||||
blockPool *BlockPool
|
blockPool *BlockPool
|
||||||
whisper *whisper.Whisper
|
whisper *whisper.Whisper
|
||||||
|
|
||||||
server *p2p.Server
|
net *p2p.Server
|
||||||
eventMux *event.TypeMux
|
eventMux *event.TypeMux
|
||||||
txSub event.Subscription
|
txSub event.Subscription
|
||||||
blockSub event.Subscription
|
blockSub event.Subscription
|
||||||
|
|
@ -47,6 +67,7 @@ type Ethereum struct {
|
||||||
keyManager *crypto.KeyManager
|
keyManager *crypto.KeyManager
|
||||||
|
|
||||||
clientIdentity p2p.ClientIdentity
|
clientIdentity p2p.ClientIdentity
|
||||||
|
logger ethlogger.LogSystem
|
||||||
|
|
||||||
synclock sync.Mutex
|
synclock sync.Mutex
|
||||||
syncGroup sync.WaitGroup
|
syncGroup sync.WaitGroup
|
||||||
|
|
@ -54,7 +75,36 @@ type Ethereum struct {
|
||||||
Mining bool
|
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("database")
|
||||||
|
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)
|
saveProtocolVersion(db)
|
||||||
ethutil.Config.Db = db
|
ethutil.Config.Db = db
|
||||||
|
|
@ -64,15 +114,16 @@ func New(db ethutil.Database, identity p2p.ClientIdentity, keyManager *crypto.Ke
|
||||||
quit: make(chan bool),
|
quit: make(chan bool),
|
||||||
db: db,
|
db: db,
|
||||||
keyManager: keyManager,
|
keyManager: keyManager,
|
||||||
clientIdentity: identity,
|
clientIdentity: clientId,
|
||||||
blacklist: p2p.NewBlacklist(),
|
blacklist: p2p.NewBlacklist(),
|
||||||
eventMux: &event.TypeMux{},
|
eventMux: &event.TypeMux{},
|
||||||
|
logger: logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
eth.chainManager = core.NewChainManager(eth.EventMux())
|
eth.chainManager = core.NewChainManager(eth.EventMux())
|
||||||
eth.txPool = core.NewTxPool(eth.chainManager, eth.EventMux())
|
eth.txPool = core.NewTxPool(eth.EventMux())
|
||||||
eth.blockManager = core.NewBlockManager(eth.txPool, eth.chainManager, eth.EventMux())
|
eth.blockProcessor = core.NewBlockProcessor(eth.txPool, eth.chainManager, eth.EventMux())
|
||||||
eth.chainManager.SetProcessor(eth.blockManager)
|
eth.chainManager.SetProcessor(eth.blockProcessor)
|
||||||
eth.whisper = whisper.New()
|
eth.whisper = whisper.New()
|
||||||
|
|
||||||
hasBlock := eth.chainManager.HasBlock
|
hasBlock := eth.chainManager.HasBlock
|
||||||
|
|
@ -85,17 +136,20 @@ func New(db ethutil.Database, identity p2p.ClientIdentity, keyManager *crypto.Ke
|
||||||
ethProto := EthProtocol(eth.txPool, eth.chainManager, eth.blockPool)
|
ethProto := EthProtocol(eth.txPool, eth.chainManager, eth.blockPool)
|
||||||
protocols := []p2p.Protocol{ethProto, eth.whisper.Protocol()}
|
protocols := []p2p.Protocol{ethProto, eth.whisper.Protocol()}
|
||||||
|
|
||||||
server := &p2p.Server{
|
nat, err := p2p.ParseNAT(config.NATType, config.PMPGateway)
|
||||||
Identity: identity,
|
if err != nil {
|
||||||
MaxPeers: maxPeers,
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
eth.net = &p2p.Server{
|
||||||
|
Identity: clientId,
|
||||||
|
MaxPeers: config.MaxPeers,
|
||||||
Protocols: protocols,
|
Protocols: protocols,
|
||||||
ListenAddr: ":" + port,
|
ListenAddr: ":" + config.Port,
|
||||||
Blacklist: eth.blacklist,
|
Blacklist: eth.blacklist,
|
||||||
NAT: nat,
|
NAT: nat,
|
||||||
}
|
}
|
||||||
|
|
||||||
eth.server = server
|
|
||||||
|
|
||||||
return eth, nil
|
return eth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,6 +157,10 @@ func (s *Ethereum) KeyManager() *crypto.KeyManager {
|
||||||
return s.keyManager
|
return s.keyManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Ethereum) Logger() ethlogger.LogSystem {
|
||||||
|
return s.logger
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Ethereum) ClientIdentity() p2p.ClientIdentity {
|
func (s *Ethereum) ClientIdentity() p2p.ClientIdentity {
|
||||||
return s.clientIdentity
|
return s.clientIdentity
|
||||||
}
|
}
|
||||||
|
|
@ -111,8 +169,8 @@ func (s *Ethereum) ChainManager() *core.ChainManager {
|
||||||
return s.chainManager
|
return s.chainManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Ethereum) BlockManager() *core.BlockManager {
|
func (s *Ethereum) BlockProcessor() *core.BlockProcessor {
|
||||||
return s.blockManager
|
return s.blockProcessor
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Ethereum) TxPool() *core.TxPool {
|
func (s *Ethereum) TxPool() *core.TxPool {
|
||||||
|
|
@ -144,20 +202,20 @@ func (s *Ethereum) IsListening() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Ethereum) PeerCount() int {
|
func (s *Ethereum) PeerCount() int {
|
||||||
return s.server.PeerCount()
|
return s.net.PeerCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Ethereum) Peers() []*p2p.Peer {
|
func (s *Ethereum) Peers() []*p2p.Peer {
|
||||||
return s.server.Peers()
|
return s.net.Peers()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Ethereum) MaxPeers() int {
|
func (s *Ethereum) MaxPeers() int {
|
||||||
return s.server.MaxPeers
|
return s.net.MaxPeers
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the ethereum
|
// Start the ethereum
|
||||||
func (s *Ethereum) Start(seed bool) error {
|
func (s *Ethereum) Start(seed bool) error {
|
||||||
err := s.server.Start()
|
err := s.net.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -191,7 +249,7 @@ func (self *Ethereum) SuggestPeer(addr string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
self.server.SuggestPeer(netaddr.IP, netaddr.Port, nil)
|
self.net.SuggestPeer(netaddr.IP, netaddr.Port, nil)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -227,15 +285,17 @@ func (self *Ethereum) txBroadcastLoop() {
|
||||||
// automatically stops if unsubscribe
|
// automatically stops if unsubscribe
|
||||||
for obj := range self.txSub.Chan() {
|
for obj := range self.txSub.Chan() {
|
||||||
event := obj.(core.TxPreEvent)
|
event := obj.(core.TxPreEvent)
|
||||||
self.server.Broadcast("eth", TxMsg, []interface{}{event.Tx.RlpData()})
|
self.net.Broadcast("eth", TxMsg, []interface{}{event.Tx.RlpData()})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Ethereum) blockBroadcastLoop() {
|
func (self *Ethereum) blockBroadcastLoop() {
|
||||||
// automatically stops if unsubscribe
|
// automatically stops if unsubscribe
|
||||||
for obj := range self.txSub.Chan() {
|
for obj := range self.txSub.Chan() {
|
||||||
event := obj.(core.NewMinedBlockEvent)
|
switch ev := obj.(type) {
|
||||||
self.server.Broadcast("eth", NewBlockMsg, event.Block.Value().Val)
|
case core.NewMinedBlockEvent:
|
||||||
|
self.net.Broadcast("eth", NewBlockMsg, ev.Block.RlpData())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ProtocolVersion = 49
|
ProtocolVersion = 51
|
||||||
NetworkId = 0
|
NetworkId = 0
|
||||||
ProtocolLength = uint64(8)
|
ProtocolLength = uint64(8)
|
||||||
ProtocolMaxMsgSize = 10 * 1024 * 1024
|
ProtocolMaxMsgSize = 10 * 1024 * 1024
|
||||||
|
|
@ -172,7 +172,7 @@ func (self *ethProtocol) handle() error {
|
||||||
}
|
}
|
||||||
block := self.chainManager.GetBlock(hash)
|
block := self.chainManager.GetBlock(hash)
|
||||||
if block != nil {
|
if block != nil {
|
||||||
blocks = append(blocks, block.Value().Raw())
|
blocks = append(blocks, block.RlpData())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self.rw.EncodeMsg(BlocksMsg, blocks...)
|
return self.rw.EncodeMsg(BlocksMsg, blocks...)
|
||||||
|
|
|
||||||
80
eth/wallet.go
Normal file
80
eth/wallet.go
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
package eth
|
||||||
|
|
||||||
|
/*
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Account struct {
|
||||||
|
w *Wallet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Account) Transact(to *Account, value, gas, price *big.Int, data []byte) error {
|
||||||
|
return self.w.transact(self, to, value, gas, price, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Account) Address() []byte {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Account) PrivateKey() *ecdsa.PrivateKey {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Wallet struct{}
|
||||||
|
|
||||||
|
func NewWallet() *Wallet {
|
||||||
|
return &Wallet{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Wallet) GetAccount(i int) *Account {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Wallet) transact(from, to *Account, value, gas, price *big.Int, data []byte) error {
|
||||||
|
if from.PrivateKey() == nil {
|
||||||
|
return errors.New("accounts is not owned (no private key available)")
|
||||||
|
}
|
||||||
|
|
||||||
|
var createsContract bool
|
||||||
|
if to == nil {
|
||||||
|
createsContract = true
|
||||||
|
}
|
||||||
|
|
||||||
|
var msg *types.Transaction
|
||||||
|
if contractCreation {
|
||||||
|
msg = types.NewContractCreationTx(value, gas, price, data)
|
||||||
|
} else {
|
||||||
|
msg = types.NewTransactionMessage(to.Address(), value, gas, price, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
state := self.chainManager.TransState()
|
||||||
|
nonce := state.GetNonce(key.Address())
|
||||||
|
|
||||||
|
msg.SetNonce(nonce)
|
||||||
|
msg.SignECDSA(from.PriateKey())
|
||||||
|
|
||||||
|
// Do some pre processing for our "pre" events and hooks
|
||||||
|
block := self.chainManager.NewBlock(from.Address())
|
||||||
|
coinbase := state.GetOrNewStateObject(from.Address())
|
||||||
|
coinbase.SetGasPool(block.GasLimit())
|
||||||
|
self.blockManager.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true)
|
||||||
|
|
||||||
|
err := self.obj.TxPool().Add(tx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
state.SetNonce(key.Address(), nonce+1)
|
||||||
|
|
||||||
|
if contractCreation {
|
||||||
|
addr := core.AddressFromMessage(tx)
|
||||||
|
pipelogger.Infof("Contract addr %x\n", addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx, nil
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
@ -71,6 +71,10 @@ func (self *LDBDatabase) NewIterator() iterator.Iterator {
|
||||||
return self.db.NewIterator(nil, nil)
|
return self.db.NewIterator(nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *LDBDatabase) Write(batch *leveldb.Batch) error {
|
||||||
|
return self.db.Write(batch, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (self *LDBDatabase) Close() {
|
func (self *LDBDatabase) Close() {
|
||||||
// Close the leveldb database
|
// Close the leveldb database
|
||||||
self.db.Close()
|
self.db.Close()
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -58,3 +59,10 @@ func WriteFile(filePath string, content []byte) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AbsolutePath(Datadir string, filename string) string {
|
||||||
|
if path.IsAbs(filename) {
|
||||||
|
return filename
|
||||||
|
}
|
||||||
|
return path.Join(Datadir, filename)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,10 @@ for dir in $(find . -maxdepth 10 -not -path './.git*' -not -path '*/_*' -type d)
|
||||||
do
|
do
|
||||||
if ls $dir/*.go &> /dev/null; then
|
if ls $dir/*.go &> /dev/null; then
|
||||||
# echo $dir
|
# echo $dir
|
||||||
|
if [[ $dir != "./tests/vm" ]]
|
||||||
|
then
|
||||||
go test -covermode=count -coverprofile=$dir/profile.tmp $dir
|
go test -covermode=count -coverprofile=$dir/profile.tmp $dir
|
||||||
|
fi
|
||||||
if [ -f $dir/profile.tmp ]
|
if [ -f $dir/profile.tmp ]
|
||||||
then
|
then
|
||||||
cat $dir/profile.tmp | tail -n +2 >> profile.cov
|
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,
|
# To submit the test coverage result to coveralls.io,
|
||||||
# use goveralls (https://github.com/mattn/goveralls)
|
# use goveralls (https://github.com/mattn/goveralls)
|
||||||
# goveralls -coverprofile=profile.cov -service=travis-ci
|
goveralls -coverprofile=profile.cov -service=travis-ci -repotoken $COVERALLS_TOKEN
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -18,11 +18,11 @@ type JSStateObject struct {
|
||||||
|
|
||||||
func (self *JSStateObject) EachStorage(call otto.FunctionCall) otto.Value {
|
func (self *JSStateObject) EachStorage(call otto.FunctionCall) otto.Value {
|
||||||
cb := call.Argument(0)
|
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()
|
return otto.UndefinedValue()
|
||||||
}
|
}
|
||||||
|
|
@ -72,15 +72,21 @@ type JSEthereum struct {
|
||||||
ethereum *eth.Ethereum
|
ethereum *eth.Ethereum
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *JSEthereum) GetBlock(hash string) otto.Value {
|
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 self.toVal(&JSBlock{self.JSXEth.BlockByHash(hash), self})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *JSEthereum) GetPeers() otto.Value {
|
return otto.UndefinedValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *JSEthereum) Peers() otto.Value {
|
||||||
return self.toVal(self.JSXEth.Peers())
|
return self.toVal(self.JSXEth.Peers())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *JSEthereum) GetKey() otto.Value {
|
func (self *JSEthereum) Key() otto.Value {
|
||||||
return self.toVal(self.JSXEth.Key())
|
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})
|
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 {
|
func (self *JSEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) otto.Value {
|
||||||
r, err := self.JSXEth.Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr)
|
r, err := self.JSXEth.Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -103,18 +105,6 @@ func (self *JSEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr,
|
||||||
return self.toVal(r)
|
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 {
|
func (self *JSEthereum) toVal(v interface{}) otto.Value {
|
||||||
result, err := self.vm.ToValue(v)
|
result, err := self.vm.ToValue(v)
|
||||||
|
|
||||||
|
|
|
||||||
33
logger/log.go
Normal file
33
logger/log.go
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -56,7 +56,7 @@ type Miner struct {
|
||||||
eth *eth.Ethereum
|
eth *eth.Ethereum
|
||||||
events event.Subscription
|
events event.Subscription
|
||||||
|
|
||||||
uncles types.Blocks
|
uncles []*types.Header
|
||||||
localTxs map[int]*LocalTx
|
localTxs map[int]*LocalTx
|
||||||
localTxId int
|
localTxId int
|
||||||
|
|
||||||
|
|
@ -174,7 +174,7 @@ func (self *Miner) reset() {
|
||||||
|
|
||||||
func (self *Miner) mine() {
|
func (self *Miner) mine() {
|
||||||
var (
|
var (
|
||||||
blockManager = self.eth.BlockManager()
|
blockProcessor = self.eth.BlockProcessor()
|
||||||
chainMan = self.eth.ChainManager()
|
chainMan = self.eth.ChainManager()
|
||||||
block = chainMan.NewBlock(self.Coinbase)
|
block = chainMan.NewBlock(self.Coinbase)
|
||||||
)
|
)
|
||||||
|
|
@ -184,15 +184,17 @@ func (self *Miner) mine() {
|
||||||
block.SetUncles(self.uncles)
|
block.SetUncles(self.uncles)
|
||||||
}
|
}
|
||||||
|
|
||||||
parent := chainMan.GetBlock(block.PrevHash)
|
parent := chainMan.GetBlock(block.ParentHash())
|
||||||
coinbase := block.State().GetOrNewStateObject(block.Coinbase)
|
coinbase := block.State().GetOrNewStateObject(block.Coinbase())
|
||||||
coinbase.SetGasPool(block.CalcGasLimit(parent))
|
coinbase.SetGasPool(core.CalcGasLimit(parent, block))
|
||||||
|
|
||||||
transactions := self.finiliseTxs()
|
transactions := self.finiliseTxs()
|
||||||
|
|
||||||
|
state := block.State()
|
||||||
|
|
||||||
// Accumulate all valid transactions and apply them to the new state
|
// Accumulate all valid transactions and apply them to the new state
|
||||||
// Error may be ignored. It's not important during mining
|
// 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 {
|
if err != nil {
|
||||||
minerlogger.Debugln(err)
|
minerlogger.Debugln(err)
|
||||||
}
|
}
|
||||||
|
|
@ -202,16 +204,17 @@ func (self *Miner) mine() {
|
||||||
block.SetReceipts(receipts)
|
block.SetReceipts(receipts)
|
||||||
|
|
||||||
// Accumulate the rewards included for this block
|
// 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))
|
minerlogger.Infof("Mining on block. Includes %v transactions", len(transactions))
|
||||||
|
|
||||||
// Find a valid nonce
|
// Find a valid nonce
|
||||||
nonce := self.pow.Search(block, self.powQuitCh)
|
nonce := self.pow.Search(block, self.powQuitCh)
|
||||||
if nonce != nil {
|
if nonce != nil {
|
||||||
block.Nonce = nonce
|
block.Header().Nonce = nonce
|
||||||
err := chainMan.InsertChain(types.Blocks{block})
|
err := chainMan.InsertChain(types.Blocks{block})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
minerlogger.Infoln(err)
|
minerlogger.Infoln(err)
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,10 @@ type SimpleClientIdentity struct {
|
||||||
customIdentifier string
|
customIdentifier string
|
||||||
os string
|
os string
|
||||||
implementation 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{
|
clientIdentity := &SimpleClientIdentity{
|
||||||
clientIdentifier: clientIdentifier,
|
clientIdentifier: clientIdentifier,
|
||||||
version: version,
|
version: version,
|
||||||
|
|
|
||||||
23
p2p/nat.go
Normal file
23
p2p/nat.go
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@ package pow
|
||||||
import "math/big"
|
import "math/big"
|
||||||
|
|
||||||
type Block interface {
|
type Block interface {
|
||||||
Diff() *big.Int
|
Difficulty() *big.Int
|
||||||
HashNoNonce() []byte
|
HashNoNonce() []byte
|
||||||
N() []byte
|
N() []byte
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package core
|
package dagger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"hash"
|
"hash"
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package core
|
package dagger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
@ -35,7 +35,7 @@ func (pow *EasyPow) Turbo(on bool) {
|
||||||
func (pow *EasyPow) Search(block pow.Block, stop <-chan struct{}) []byte {
|
func (pow *EasyPow) Search(block pow.Block, stop <-chan struct{}) []byte {
|
||||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
hash := block.HashNoNonce()
|
hash := block.HashNoNonce()
|
||||||
diff := block.Diff()
|
diff := block.Difficulty()
|
||||||
i := int64(0)
|
i := int64(0)
|
||||||
start := time.Now().UnixNano()
|
start := time.Now().UnixNano()
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
|
|
@ -89,5 +89,5 @@ func verify(hash []byte, diff *big.Int, nonce []byte) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Verify(block pow.Block) bool {
|
func Verify(block pow.Block) bool {
|
||||||
return verify(block.HashNoNonce(), block.Diff(), block.N())
|
return verify(block.HashNoNonce(), block.Difficulty(), block.N())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
3038
profile.cov
3038
profile.cov
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,7 @@
|
||||||
package ptrie
|
package ptrie
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
type FullNode struct {
|
type FullNode struct {
|
||||||
trie *Trie
|
trie *Trie
|
||||||
nodes [17]Node
|
nodes [17]Node
|
||||||
|
|
@ -21,8 +23,10 @@ func (self *FullNode) Branches() []Node {
|
||||||
func (self *FullNode) Copy() Node {
|
func (self *FullNode) Copy() Node {
|
||||||
nnode := NewFullNode(self.trie)
|
nnode := NewFullNode(self.trie)
|
||||||
for i, node := range self.nodes {
|
for i, node := range self.nodes {
|
||||||
|
if node != nil {
|
||||||
nnode.nodes[i] = node
|
nnode.nodes[i] = node
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nnode
|
return nnode
|
||||||
}
|
}
|
||||||
|
|
@ -56,6 +60,10 @@ func (self *FullNode) RlpData() interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FullNode) set(k byte, value Node) {
|
func (self *FullNode) set(k byte, value Node) {
|
||||||
|
if _, ok := value.(*ValueNode); ok && k != 16 {
|
||||||
|
fmt.Println(value, k)
|
||||||
|
}
|
||||||
|
|
||||||
self.nodes[int(k)] = value
|
self.nodes[int(k)] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ type Iterator struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIterator(trie *Trie) *Iterator {
|
func NewIterator(trie *Trie) *Iterator {
|
||||||
return &Iterator{trie: trie, Key: []byte{0}}
|
return &Iterator{trie: trie, Key: make([]byte, 32)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Iterator) Next() bool {
|
func (self *Iterator) Next() bool {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ type Node interface {
|
||||||
func (self *ValueNode) String() string { return self.fstring("") }
|
func (self *ValueNode) String() string { return self.fstring("") }
|
||||||
func (self *FullNode) String() string { return self.fstring("") }
|
func (self *FullNode) String() string { return self.fstring("") }
|
||||||
func (self *ShortNode) 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) }
|
func (self *HashNode) fstring(ind string) string { return fmt.Sprintf("%x ", self.key) }
|
||||||
|
|
||||||
// Full node
|
// Full node
|
||||||
|
|
@ -36,5 +36,5 @@ func (self *FullNode) fstring(ind string) string {
|
||||||
|
|
||||||
// Short node
|
// Short node
|
||||||
func (self *ShortNode) fstring(ind string) string {
|
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+" "))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ func ParanoiaCheck(t1 *Trie, backend Backend) (bool, *Trie) {
|
||||||
t2.Update(it.Key, it.Value)
|
t2.Update(it.Key, it.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytes.Compare(t2.Hash(), t1.Hash()) == 0, t2
|
return bytes.Equal(t2.Hash(), t1.Hash()), t2
|
||||||
}
|
}
|
||||||
|
|
||||||
type Trie struct {
|
type Trie struct {
|
||||||
|
|
@ -49,14 +49,17 @@ func (self *Trie) Iterator() *Iterator {
|
||||||
return NewIterator(self)
|
return NewIterator(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Trie) Copy() *Trie {
|
||||||
|
return New(self.roothash, self.cache.backend)
|
||||||
|
}
|
||||||
|
|
||||||
// Legacy support
|
// Legacy support
|
||||||
func (self *Trie) Root() []byte { return self.Hash() }
|
func (self *Trie) Root() []byte { return self.Hash() }
|
||||||
func (self *Trie) Hash() []byte {
|
func (self *Trie) Hash() []byte {
|
||||||
var hash []byte
|
var hash []byte
|
||||||
if self.root != nil {
|
if self.root != nil {
|
||||||
//hash = self.root.Hash().([]byte)
|
|
||||||
t := self.root.Hash()
|
t := self.root.Hash()
|
||||||
if byts, ok := t.([]byte); ok {
|
if byts, ok := t.([]byte); ok && len(byts) > 0 {
|
||||||
hash = byts
|
hash = byts
|
||||||
} else {
|
} else {
|
||||||
hash = crypto.Sha3(ethutil.Encode(self.root.RlpData()))
|
hash = crypto.Sha3(ethutil.Encode(self.root.RlpData()))
|
||||||
|
|
@ -73,6 +76,9 @@ func (self *Trie) Hash() []byte {
|
||||||
return hash
|
return hash
|
||||||
}
|
}
|
||||||
func (self *Trie) Commit() {
|
func (self *Trie) Commit() {
|
||||||
|
self.mu.Lock()
|
||||||
|
defer self.mu.Unlock()
|
||||||
|
|
||||||
// Hash first
|
// Hash first
|
||||||
self.Hash()
|
self.Hash()
|
||||||
|
|
||||||
|
|
@ -81,10 +87,15 @@ func (self *Trie) Commit() {
|
||||||
|
|
||||||
// Reset should only be called if the trie has been hashed
|
// Reset should only be called if the trie has been hashed
|
||||||
func (self *Trie) Reset() {
|
func (self *Trie) Reset() {
|
||||||
|
self.mu.Lock()
|
||||||
|
defer self.mu.Unlock()
|
||||||
|
|
||||||
self.cache.Reset()
|
self.cache.Reset()
|
||||||
|
|
||||||
|
if self.revisions.Len() > 0 {
|
||||||
revision := self.revisions.Remove(self.revisions.Back()).([]byte)
|
revision := self.revisions.Remove(self.revisions.Back()).([]byte)
|
||||||
self.roothash = revision
|
self.roothash = revision
|
||||||
|
}
|
||||||
value := ethutil.NewValueFromBytes(self.cache.Get(self.roothash))
|
value := ethutil.NewValueFromBytes(self.cache.Get(self.roothash))
|
||||||
self.root = self.mknode(value)
|
self.root = self.mknode(value)
|
||||||
}
|
}
|
||||||
|
|
@ -173,7 +184,7 @@ func (self *Trie) insert(node Node, key []byte, value Node) Node {
|
||||||
return cpy
|
return cpy
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("Invalid node")
|
panic(fmt.Sprintf("%T: invalid node: %v", node, node))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,7 +215,7 @@ func (self *Trie) get(node Node, key []byte) Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Trie) delete(node Node, key []byte) Node {
|
func (self *Trie) delete(node Node, key []byte) Node {
|
||||||
if len(key) == 0 {
|
if len(key) == 0 && node == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,7 +234,9 @@ func (self *Trie) delete(node Node, key []byte) Node {
|
||||||
nkey := append(k, child.Key()...)
|
nkey := append(k, child.Key()...)
|
||||||
n = NewShortNode(self, nkey, child.Value())
|
n = NewShortNode(self, nkey, child.Value())
|
||||||
case *FullNode:
|
case *FullNode:
|
||||||
n = NewShortNode(self, node.key, child)
|
sn := NewShortNode(self, node.Key(), child)
|
||||||
|
sn.key = node.key
|
||||||
|
n = sn
|
||||||
}
|
}
|
||||||
|
|
||||||
return n
|
return n
|
||||||
|
|
@ -264,9 +277,10 @@ func (self *Trie) delete(node Node, key []byte) Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
return nnode
|
return nnode
|
||||||
|
case nil:
|
||||||
|
return nil
|
||||||
default:
|
default:
|
||||||
panic("Invalid node")
|
panic(fmt.Sprintf("%T: invalid node: %v (%v)", node, node, key))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,8 +288,13 @@ func (self *Trie) delete(node Node, key []byte) Node {
|
||||||
func (self *Trie) mknode(value *ethutil.Value) Node {
|
func (self *Trie) mknode(value *ethutil.Value) Node {
|
||||||
l := value.Len()
|
l := value.Len()
|
||||||
switch l {
|
switch l {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
case 2:
|
case 2:
|
||||||
|
// A value node may consists of 2 bytes.
|
||||||
|
if value.Get(0).Len() != 0 {
|
||||||
return NewShortNode(self, trie.CompactDecode(string(value.Get(0).Bytes())), self.mknode(value.Get(1)))
|
return NewShortNode(self, trie.CompactDecode(string(value.Get(0).Bytes())), self.mknode(value.Get(1)))
|
||||||
|
}
|
||||||
case 17:
|
case 17:
|
||||||
fnode := NewFullNode(self)
|
fnode := NewFullNode(self)
|
||||||
for i := 0; i < l; i++ {
|
for i := 0; i < l; i++ {
|
||||||
|
|
@ -284,9 +303,9 @@ func (self *Trie) mknode(value *ethutil.Value) Node {
|
||||||
return fnode
|
return fnode
|
||||||
case 32:
|
case 32:
|
||||||
return &HashNode{value.Bytes()}
|
return &HashNode{value.Bytes()}
|
||||||
default:
|
|
||||||
return &ValueNode{self, value.Bytes()}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return &ValueNode{self, value.Bytes()}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Trie) trans(node Node) Node {
|
func (self *Trie) trans(node Node) Node {
|
||||||
|
|
@ -310,3 +329,7 @@ func (self *Trie) store(node Node) interface{} {
|
||||||
|
|
||||||
return node.RlpData()
|
return node.RlpData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Trie) PrintRoot() {
|
||||||
|
fmt.Println(self.root)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ func TestReplication(t *testing.T) {
|
||||||
|
|
||||||
trie2 := New(trie.roothash, trie.cache.backend)
|
trie2 := New(trie.roothash, trie.cache.backend)
|
||||||
if string(trie2.GetString("horse")) != "stallion" {
|
if string(trie2.GetString("horse")) != "stallion" {
|
||||||
t.Error("expected to have harse => stallion")
|
t.Error("expected to have horse => stallion")
|
||||||
}
|
}
|
||||||
|
|
||||||
hash := trie2.Hash()
|
hash := trie2.Hash()
|
||||||
|
|
|
||||||
|
|
@ -22,22 +22,23 @@ type World struct {
|
||||||
|
|
||||||
func (self *StateDB) Dump() []byte {
|
func (self *StateDB) Dump() []byte {
|
||||||
world := World{
|
world := World{
|
||||||
Root: ethutil.Bytes2Hex(self.Trie.GetRoot()),
|
Root: ethutil.Bytes2Hex(self.trie.Root()),
|
||||||
Accounts: make(map[string]Account),
|
Accounts: make(map[string]Account),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.Trie.NewIterator().Each(func(key string, value *ethutil.Value) {
|
it := self.trie.Iterator()
|
||||||
stateObject := NewStateObjectFromBytes([]byte(key), value.Bytes())
|
for it.Next() {
|
||||||
|
stateObject := NewStateObjectFromBytes(it.Key, it.Value)
|
||||||
|
|
||||||
account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.Nonce, Root: ethutil.Bytes2Hex(stateObject.Root()), CodeHash: ethutil.Bytes2Hex(stateObject.codeHash)}
|
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)
|
account.Storage = make(map[string]string)
|
||||||
|
|
||||||
stateObject.EachStorage(func(key string, value *ethutil.Value) {
|
storageIt := stateObject.State.trie.Iterator()
|
||||||
value.Decode()
|
for storageIt.Next() {
|
||||||
account.Storage[ethutil.Bytes2Hex([]byte(key))] = ethutil.Bytes2Hex(value.Bytes())
|
account.Storage[ethutil.Bytes2Hex(it.Key)] = ethutil.Bytes2Hex(it.Value)
|
||||||
})
|
}
|
||||||
world.Accounts[ethutil.Bytes2Hex([]byte(key))] = account
|
world.Accounts[ethutil.Bytes2Hex(it.Key)] = account
|
||||||
})
|
}
|
||||||
|
|
||||||
json, err := json.MarshalIndent(world, "", " ")
|
json, err := json.MarshalIndent(world, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -50,7 +51,8 @@ func (self *StateDB) Dump() []byte {
|
||||||
// Debug stuff
|
// Debug stuff
|
||||||
func (self *StateObject) CreateOutputForDiff() {
|
func (self *StateObject) CreateOutputForDiff() {
|
||||||
fmt.Printf("%x %x %x %x\n", self.Address(), self.State.Root(), self.balance.Bytes(), self.Nonce)
|
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) {
|
it := self.State.trie.Iterator()
|
||||||
fmt.Printf("%x %x\n", addr, value.Bytes())
|
for it.Next() {
|
||||||
})
|
fmt.Printf("%x %x\n", it.Key, it.Value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,12 @@ func (self *Manifest) AddMessage(msg *Message) *Message {
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Manifest) SetHash(hash []byte) {
|
||||||
|
for _, message := range self.Messages {
|
||||||
|
message.Block = hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Messages []*Message
|
type Messages []*Message
|
||||||
type Message struct {
|
type Message struct {
|
||||||
To, From []byte
|
To, From []byte
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/ptrie"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Code []byte
|
type Code []byte
|
||||||
|
|
@ -62,7 +62,7 @@ func NewStateObject(addr []byte) *StateObject {
|
||||||
address := ethutil.Address(addr)
|
address := ethutil.Address(addr)
|
||||||
|
|
||||||
object := &StateObject{address: address, balance: new(big.Int), gasPool: new(big.Int)}
|
object := &StateObject{address: address, balance: new(big.Int), gasPool: new(big.Int)}
|
||||||
object.State = New(trie.New(ethutil.Config.Db, ""))
|
object.State = New(ptrie.New(nil, ethutil.Config.Db)) //New(trie.New(ethutil.Config.Db, ""))
|
||||||
object.storage = make(Storage)
|
object.storage = make(Storage)
|
||||||
object.gasPool = new(big.Int)
|
object.gasPool = new(big.Int)
|
||||||
|
|
||||||
|
|
@ -72,7 +72,7 @@ func NewStateObject(addr []byte) *StateObject {
|
||||||
func NewContract(address []byte, balance *big.Int, root []byte) *StateObject {
|
func NewContract(address []byte, balance *big.Int, root []byte) *StateObject {
|
||||||
contract := NewStateObject(address)
|
contract := NewStateObject(address)
|
||||||
contract.balance = balance
|
contract.balance = balance
|
||||||
contract.State = New(trie.New(ethutil.Config.Db, string(root)))
|
contract.State = New(ptrie.New(nil, ethutil.Config.Db)) //New(trie.New(ethutil.Config.Db, string(root)))
|
||||||
|
|
||||||
return contract
|
return contract
|
||||||
}
|
}
|
||||||
|
|
@ -89,12 +89,12 @@ func (self *StateObject) MarkForDeletion() {
|
||||||
statelogger.DebugDetailf("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.balance)
|
statelogger.DebugDetailf("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.balance)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *StateObject) GetAddr(addr []byte) *ethutil.Value {
|
func (c *StateObject) getAddr(addr []byte) *ethutil.Value {
|
||||||
return ethutil.NewValueFromBytes([]byte(c.State.Trie.Get(string(addr))))
|
return ethutil.NewValueFromBytes([]byte(c.State.trie.Get(addr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *StateObject) SetAddr(addr []byte, value interface{}) {
|
func (c *StateObject) setAddr(addr []byte, value interface{}) {
|
||||||
c.State.Trie.Update(string(addr), string(ethutil.NewValue(value).Encode()))
|
c.State.trie.Update(addr, ethutil.Encode(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateObject) GetStorage(key *big.Int) *ethutil.Value {
|
func (self *StateObject) GetStorage(key *big.Int) *ethutil.Value {
|
||||||
|
|
@ -113,7 +113,7 @@ func (self *StateObject) GetState(k []byte) *ethutil.Value {
|
||||||
|
|
||||||
value := self.storage[string(key)]
|
value := self.storage[string(key)]
|
||||||
if value == nil {
|
if value == nil {
|
||||||
value = self.GetAddr(key)
|
value = self.getAddr(key)
|
||||||
|
|
||||||
if !value.IsNil() {
|
if !value.IsNil() {
|
||||||
self.storage[string(key)] = value
|
self.storage[string(key)] = value
|
||||||
|
|
@ -128,6 +128,7 @@ func (self *StateObject) SetState(k []byte, value *ethutil.Value) {
|
||||||
self.storage[string(key)] = value.Copy()
|
self.storage[string(key)] = value.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// Iterate over each storage address and yield callback
|
// Iterate over each storage address and yield callback
|
||||||
func (self *StateObject) EachStorage(cb trie.EachCallback) {
|
func (self *StateObject) EachStorage(cb trie.EachCallback) {
|
||||||
// First loop over the uncommit/cached values in storage
|
// First loop over the uncommit/cached values in storage
|
||||||
|
|
@ -145,23 +146,26 @@ func (self *StateObject) EachStorage(cb trie.EachCallback) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func (self *StateObject) Sync() {
|
func (self *StateObject) Sync() {
|
||||||
for key, value := range self.storage {
|
for key, value := range self.storage {
|
||||||
if value.Len() == 0 {
|
if value.Len() == 0 {
|
||||||
self.State.Trie.Delete(string(key))
|
self.State.trie.Delete([]byte(key))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
self.SetAddr([]byte(key), value)
|
self.setAddr([]byte(key), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
valid, t2 := trie.ParanoiaCheck(self.State.Trie)
|
/*
|
||||||
|
valid, t2 := ptrie.ParanoiaCheck(self.State.trie, ethutil.Config.Db)
|
||||||
if !valid {
|
if !valid {
|
||||||
statelogger.Infof("Warn: PARANOIA: Different state storage root during copy %x vs %x\n", self.State.Root(), t2.GetRoot())
|
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 {
|
func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value {
|
||||||
|
|
@ -276,8 +280,12 @@ func (c *StateObject) Init() Code {
|
||||||
return c.InitCode
|
return c.InitCode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *StateObject) Trie() *ptrie.Trie {
|
||||||
|
return self.State.trie
|
||||||
|
}
|
||||||
|
|
||||||
func (self *StateObject) Root() []byte {
|
func (self *StateObject) Root() []byte {
|
||||||
return self.State.Trie.GetRoot()
|
return self.Trie().Root()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateObject) SetCode(code []byte) {
|
func (self *StateObject) SetCode(code []byte) {
|
||||||
|
|
@ -302,7 +310,7 @@ func (c *StateObject) RlpDecode(data []byte) {
|
||||||
|
|
||||||
c.Nonce = decoder.Get(0).Uint()
|
c.Nonce = decoder.Get(0).Uint()
|
||||||
c.balance = decoder.Get(1).BigInt()
|
c.balance = decoder.Get(1).BigInt()
|
||||||
c.State = New(trie.New(ethutil.Config.Db, decoder.Get(2).Interface()))
|
c.State = New(ptrie.New(decoder.Get(2).Bytes(), ethutil.Config.Db)) //New(trie.New(ethutil.Config.Db, decoder.Get(2).Interface()))
|
||||||
c.storage = make(map[string]*ethutil.Value)
|
c.storage = make(map[string]*ethutil.Value)
|
||||||
c.gasPool = new(big.Int)
|
c.gasPool = new(big.Int)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/ptrie"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StateSuite struct {
|
type StateSuite struct {
|
||||||
|
|
@ -18,9 +18,8 @@ var _ = checker.Suite(&StateSuite{})
|
||||||
|
|
||||||
func (s *StateSuite) TestDump(c *checker.C) {
|
func (s *StateSuite) TestDump(c *checker.C) {
|
||||||
key := []byte{0x01}
|
key := []byte{0x01}
|
||||||
value := "foo"
|
value := []byte("foo")
|
||||||
node := []interface{}{key, value}
|
s.state.trie.Update(key, value)
|
||||||
s.state.Trie.Put(node)
|
|
||||||
dump := s.state.Dump()
|
dump := s.state.Dump()
|
||||||
c.Assert(dump, checker.NotNil)
|
c.Assert(dump, checker.NotNil)
|
||||||
}
|
}
|
||||||
|
|
@ -29,7 +28,7 @@ func (s *StateSuite) SetUpTest(c *checker.C) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db, _ := ethdb.NewMemDatabase()
|
||||||
ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "")
|
ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "")
|
||||||
ethutil.Config.Db = db
|
ethutil.Config.Db = db
|
||||||
s.state = New(trie.New(db, ""))
|
s.state = New(ptrie.New(nil, db))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateSuite) TestSnapshot(c *checker.C) {
|
func (s *StateSuite) TestSnapshot(c *checker.C) {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/ptrie"
|
||||||
)
|
)
|
||||||
|
|
||||||
var statelogger = logger.NewLogger("STATE")
|
var statelogger = logger.NewLogger("STATE")
|
||||||
|
|
@ -16,8 +17,8 @@ var statelogger = logger.NewLogger("STATE")
|
||||||
// * Contracts
|
// * Contracts
|
||||||
// * Accounts
|
// * Accounts
|
||||||
type StateDB struct {
|
type StateDB struct {
|
||||||
// The trie for this structure
|
//Trie *trie.Trie
|
||||||
Trie *trie.Trie
|
trie *ptrie.Trie
|
||||||
|
|
||||||
stateObjects map[string]*StateObject
|
stateObjects map[string]*StateObject
|
||||||
|
|
||||||
|
|
@ -29,8 +30,8 @@ type StateDB struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new state from a given trie
|
// Create a new state from a given trie
|
||||||
func New(trie *trie.Trie) *StateDB {
|
func New(trie *ptrie.Trie) *StateDB {
|
||||||
return &StateDB{Trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest(), refund: make(map[string]*big.Int)}
|
return &StateDB{trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest(), refund: make(map[string]*big.Int)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateDB) EmptyLogs() {
|
func (self *StateDB) EmptyLogs() {
|
||||||
|
|
@ -94,6 +95,13 @@ func (self *StateDB) GetCode(addr []byte) []byte {
|
||||||
return nil
|
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 {
|
func (self *StateDB) GetState(a, b []byte) []byte {
|
||||||
stateObject := self.GetStateObject(a)
|
stateObject := self.GetStateObject(a)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
|
|
@ -133,12 +141,12 @@ func (self *StateDB) UpdateStateObject(stateObject *StateObject) {
|
||||||
ethutil.Config.Db.Put(stateObject.CodeHash(), stateObject.Code)
|
ethutil.Config.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
|
// Delete the given state object and delete it from the state trie
|
||||||
func (self *StateDB) DeleteStateObject(stateObject *StateObject) {
|
func (self *StateDB) DeleteStateObject(stateObject *StateObject) {
|
||||||
self.Trie.Delete(string(stateObject.Address()))
|
self.trie.Delete(stateObject.Address())
|
||||||
|
|
||||||
delete(self.stateObjects, string(stateObject.Address()))
|
delete(self.stateObjects, string(stateObject.Address()))
|
||||||
}
|
}
|
||||||
|
|
@ -152,7 +160,7 @@ func (self *StateDB) GetStateObject(addr []byte) *StateObject {
|
||||||
return stateObject
|
return stateObject
|
||||||
}
|
}
|
||||||
|
|
||||||
data := self.Trie.Get(string(addr))
|
data := self.trie.Get(addr)
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -199,12 +207,12 @@ func (self *StateDB) GetAccount(addr []byte) *StateObject {
|
||||||
//
|
//
|
||||||
|
|
||||||
func (s *StateDB) Cmp(other *StateDB) bool {
|
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 {
|
func (self *StateDB) Copy() *StateDB {
|
||||||
if self.Trie != nil {
|
if self.trie != nil {
|
||||||
state := New(self.Trie.Copy())
|
state := New(self.trie.Copy())
|
||||||
for k, stateObject := range self.stateObjects {
|
for k, stateObject := range self.stateObjects {
|
||||||
state.stateObjects[k] = stateObject.Copy()
|
state.stateObjects[k] = stateObject.Copy()
|
||||||
}
|
}
|
||||||
|
|
@ -228,19 +236,19 @@ func (self *StateDB) Set(state *StateDB) {
|
||||||
panic("Tried setting 'state' to nil through 'Set'")
|
panic("Tried setting 'state' to nil through 'Set'")
|
||||||
}
|
}
|
||||||
|
|
||||||
self.Trie = state.Trie
|
self.trie = state.trie
|
||||||
self.stateObjects = state.stateObjects
|
self.stateObjects = state.stateObjects
|
||||||
self.refund = state.refund
|
self.refund = state.refund
|
||||||
self.logs = state.logs
|
self.logs = state.logs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateDB) Root() []byte {
|
func (s *StateDB) Root() []byte {
|
||||||
return s.Trie.GetRoot()
|
return s.trie.Root()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resets the trie and all siblings
|
// Resets the trie and all siblings
|
||||||
func (s *StateDB) Reset() {
|
func (s *StateDB) Reset() {
|
||||||
s.Trie.Undo()
|
s.trie.Reset()
|
||||||
|
|
||||||
// Reset all nested states
|
// Reset all nested states
|
||||||
for _, stateObject := range s.stateObjects {
|
for _, stateObject := range s.stateObjects {
|
||||||
|
|
@ -265,7 +273,7 @@ func (s *StateDB) Sync() {
|
||||||
stateObject.State.Sync()
|
stateObject.State.Sync()
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Trie.Sync()
|
s.trie.Commit()
|
||||||
|
|
||||||
s.Empty()
|
s.Empty()
|
||||||
}
|
}
|
||||||
|
|
@ -297,11 +305,11 @@ func (self *StateDB) Update(gasUsed *big.Int) {
|
||||||
|
|
||||||
// FIXME trie delete is broken
|
// FIXME trie delete is broken
|
||||||
if deleted {
|
if deleted {
|
||||||
valid, t2 := trie.ParanoiaCheck(self.Trie)
|
valid, t2 := ptrie.ParanoiaCheck(self.trie, ethutil.Config.Db)
|
||||||
if !valid {
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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" : {
|
"CallRecursiveContract" : {
|
||||||
"env" : {
|
"env" : {
|
||||||
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
|
@ -244,251 +596,6 @@
|
||||||
"value" : "1"
|
"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" : {
|
"CallTheContractToCreateEmptyContract" : {
|
||||||
"env" : {
|
"env" : {
|
||||||
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
|
@ -651,6 +758,60 @@
|
||||||
"value" : "1"
|
"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" : {
|
"TransactionContractCreation" : {
|
||||||
"env" : {
|
"env" : {
|
||||||
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
|
|
||||||
|
|
@ -552,14 +552,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
|
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
|
||||||
"balance" : "261077",
|
"balance" : "261097",
|
||||||
"code" : "0x",
|
"code" : "0x",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
"balance" : "999999999999638923",
|
"balance" : "999999999999638903",
|
||||||
"code" : "0x",
|
"code" : "0x",
|
||||||
"nonce" : "1",
|
"nonce" : "1",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
|
|
@ -584,7 +584,7 @@
|
||||||
},
|
},
|
||||||
"transaction" : {
|
"transaction" : {
|
||||||
"data" : "",
|
"data" : "",
|
||||||
"gasLimit" : "365223",
|
"gasLimit" : "365243",
|
||||||
"gasPrice" : "1",
|
"gasPrice" : "1",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
|
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
|
||||||
|
|
@ -610,19 +610,19 @@
|
||||||
"code" : "0x600160005401600055600060006000600060003060e05a03f1600155",
|
"code" : "0x600160005401600055600060006000600060003060e05a03f1600155",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
"0x" : "0x03ff",
|
"0x" : "0x0400",
|
||||||
"0x01" : "0x01"
|
"0x01" : "0x01"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
|
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
|
||||||
"balance" : "261078",
|
"balance" : "260996",
|
||||||
"code" : "0x",
|
"code" : "0x",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
"balance" : "999999999999638922",
|
"balance" : "999999999999639004",
|
||||||
"code" : "0x",
|
"code" : "0x",
|
||||||
"nonce" : "1",
|
"nonce" : "1",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
|
|
@ -647,7 +647,7 @@
|
||||||
},
|
},
|
||||||
"transaction" : {
|
"transaction" : {
|
||||||
"data" : "",
|
"data" : "",
|
||||||
"gasLimit" : "365224",
|
"gasLimit" : "365244",
|
||||||
"gasPrice" : "1",
|
"gasPrice" : "1",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
|
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
|
||||||
|
|
@ -4166,11 +4166,10 @@
|
||||||
"code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000604060406000601773945304eb96065b2a98b57a48a06ae28d285a71b56103e8f1600055",
|
"code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000604060406000601773945304eb96065b2a98b57a48a06ae28d285a71b56103e8f1600055",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
"0x" : "0x01"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
|
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
|
||||||
"balance" : "1165",
|
"balance" : "1636",
|
||||||
"code" : "0x",
|
"code" : "0x",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
|
|
@ -4181,11 +4180,10 @@
|
||||||
"code" : "0x60003554156009570060203560003555",
|
"code" : "0x60003554156009570060203560003555",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" : "0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
"balance" : "999999999999898835",
|
"balance" : "999999999999898364",
|
||||||
"code" : "0x",
|
"code" : "0x",
|
||||||
"nonce" : "1",
|
"nonce" : "1",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
|
|
@ -4243,11 +4241,10 @@
|
||||||
"code" : "0x7feeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000620f120660406000601773945304eb96065b2a98b57a48a06ae28d285a71b56101f4f1600055",
|
"code" : "0x7feeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000620f120660406000601773945304eb96065b2a98b57a48a06ae28d285a71b56101f4f1600055",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
"0x" : "0x01"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
|
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
|
||||||
"balance" : "1165",
|
"balance" : "1136",
|
||||||
"code" : "0x",
|
"code" : "0x",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
|
|
@ -4258,11 +4255,10 @@
|
||||||
"code" : "0x60003554156009570060203560003555",
|
"code" : "0x60003554156009570060203560003555",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
"0xeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00" : "0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
"balance" : "999999999999898835",
|
"balance" : "999999999999898864",
|
||||||
"code" : "0x",
|
"code" : "0x",
|
||||||
"nonce" : "1",
|
"nonce" : "1",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
|
|
@ -4320,11 +4316,10 @@
|
||||||
"code" : "0x7feeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa602052600060406000620f1206601773945304eb96065b2a98b57a48a06ae28d285a71b56101f4f1600055",
|
"code" : "0x7feeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa602052600060406000620f1206601773945304eb96065b2a98b57a48a06ae28d285a71b56101f4f1600055",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
"0x" : "0x01"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
|
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
|
||||||
"balance" : "965",
|
"balance" : "1136",
|
||||||
"code" : "0x",
|
"code" : "0x",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
|
|
@ -4338,7 +4333,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
"balance" : "999999999999899035",
|
"balance" : "999999999999898864",
|
||||||
"code" : "0x",
|
"code" : "0x",
|
||||||
"nonce" : "1",
|
"nonce" : "1",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
|
|
@ -4848,18 +4843,17 @@
|
||||||
"code" : "0x60003554156009570060203560003555",
|
"code" : "0x60003554156009570060203560003555",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa" : "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
|
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
|
||||||
"balance" : "1149",
|
"balance" : "1000000",
|
||||||
"code" : "0x",
|
"code" : "0x",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
"balance" : "999999999999898851",
|
"balance" : "999999999998900000",
|
||||||
"code" : "0x",
|
"code" : "0x",
|
||||||
"nonce" : "1",
|
"nonce" : "1",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
|
|
@ -4892,6 +4886,68 @@
|
||||||
"value" : "100000"
|
"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" : {
|
"callcodeToNameRegistrator0" : {
|
||||||
"env" : {
|
"env" : {
|
||||||
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
|
@ -4910,12 +4966,10 @@
|
||||||
"code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000604060406000601773945304eb96065b2a98b57a48a06ae28d285a71b56103e8f2600055",
|
"code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000604060406000601773945304eb96065b2a98b57a48a06ae28d285a71b56103e8f2600055",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
"0x" : "0x01",
|
|
||||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" : "0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
|
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
|
||||||
"balance" : "1165",
|
"balance" : "1636",
|
||||||
"code" : "0x",
|
"code" : "0x",
|
||||||
"nonce" : "0",
|
"nonce" : "0",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
|
|
@ -4929,7 +4983,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
"balance" : "999999999999898835",
|
"balance" : "999999999999898364",
|
||||||
"code" : "0x",
|
"code" : "0x",
|
||||||
"nonce" : "1",
|
"nonce" : "1",
|
||||||
"storage" : {
|
"storage" : {
|
||||||
|
|
@ -5046,6 +5100,68 @@
|
||||||
"value" : "100000"
|
"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" : {
|
"callstatelessToReturn1" : {
|
||||||
"env" : {
|
"env" : {
|
||||||
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
|
@ -5367,6 +5483,68 @@
|
||||||
"value" : "100000"
|
"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" : {
|
"return0" : {
|
||||||
"env" : {
|
"env" : {
|
||||||
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
|
|
||||||
|
|
@ -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" : {
|
"EmptyTransaction" : {
|
||||||
"env" : {
|
"env" : {
|
||||||
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
|
@ -273,5 +425,59 @@
|
||||||
"to" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
"to" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||||
"value" : "502"
|
"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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -12,6 +12,61 @@
|
||||||
],
|
],
|
||||||
"root": "0x5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84"
|
"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": {
|
"jeff": {
|
||||||
"in": [
|
"in": [
|
||||||
["0x0000000000000000000000000000000000000000000000000000000000000045", "0x22b224a1420a802ab51d326e29fa98e34c4f24ea"],
|
["0x0000000000000000000000000000000000000000000000000000000000000045", "0x22b224a1420a802ab51d326e29fa98e34c4f24ea"],
|
||||||
|
|
|
||||||
46
tests/files/VMTests/RandomTests/201412231524.json
Normal file
46
tests/files/VMTests/RandomTests/201412231524.json
Normal file
|
|
@ -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" : "0x63705a0b6b69a11044518876953776",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9998",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x63705a0b6b69a11044518876953776",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x63705a0b6b69a11044518876953776",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231526.json
Normal file
46
tests/files/VMTests/RandomTests/201412231526.json
Normal file
|
|
@ -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" : "0x5b6ca284a383618e389e20848652",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9998",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x5b6ca284a383618e389e20848652",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x5b6ca284a383618e389e20848652",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231529.json
Normal file
46
tests/files/VMTests/RandomTests/201412231529.json
Normal file
|
|
@ -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" : "0x6a5a558f440b6d7530533a356b7589",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9998",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x6a5a558f440b6d7530533a356b7589",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x6a5a558f440b6d7530533a356b7589",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231535.json
Normal file
46
tests/files/VMTests/RandomTests/201412231535.json
Normal file
|
|
@ -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" : "0x68931051429d9b75069160636bff",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9997",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x68931051429d9b75069160636bff",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x68931051429d9b75069160636bff",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231543.json
Normal file
46
tests/files/VMTests/RandomTests/201412231543.json
Normal file
|
|
@ -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" : "0x5a385968087df24038513535",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9996",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x5a385968087df24038513535",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x5a385968087df24038513535",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231544.json
Normal file
46
tests/files/VMTests/RandomTests/201412231544.json
Normal file
|
|
@ -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" : "0x3463823507",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9998",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x3463823507",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x3463823507",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231545.json
Normal file
46
tests/files/VMTests/RandomTests/201412231545.json
Normal file
|
|
@ -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" : "0x66a3535b8b8af38a658b3b",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9998",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x66a3535b8b8af38a658b3b",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x66a3535b8b8af38a658b3b",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231546.json
Normal file
46
tests/files/VMTests/RandomTests/201412231546.json
Normal file
|
|
@ -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" : "0x63794554ff426ef0a18a8a9c6e137a8c",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9997",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x63794554ff426ef0a18a8a9c6e137a8c",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x63794554ff426ef0a18a8a9c6e137a8c",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231549.json
Normal file
46
tests/files/VMTests/RandomTests/201412231549.json
Normal file
|
|
@ -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" : "0x66509a88803091046789893377",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9998",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x66509a88803091046789893377",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x66509a88803091046789893377",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231551.json
Normal file
46
tests/files/VMTests/RandomTests/201412231551.json
Normal file
|
|
@ -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" : "0x426a507bf0a09c7b6a381314",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9998",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x426a507bf0a09c7b6a381314",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x426a507bf0a09c7b6a381314",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231552.json
Normal file
46
tests/files/VMTests/RandomTests/201412231552.json
Normal file
|
|
@ -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" : "0x306383a29e826a05865054039f36",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9997",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x306383a29e826a05865054039f36",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x306383a29e826a05865054039f36",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231553.json
Normal file
46
tests/files/VMTests/RandomTests/201412231553.json
Normal file
|
|
@ -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" : "0x66691196a4a00209506d8290855570",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9997",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x66691196a4a00209506d8290855570",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x66691196a4a00209506d8290855570",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231556.json
Normal file
46
tests/files/VMTests/RandomTests/201412231556.json
Normal file
|
|
@ -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" : "0x645b7753a4806e848481311373338b66",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9998",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x645b7753a4806e848481311373338b66",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x645b7753a4806e848481311373338b66",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231557.json
Normal file
46
tests/files/VMTests/RandomTests/201412231557.json
Normal file
|
|
@ -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" : "0x386609796d5a7b53",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9998",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x386609796d5a7b53",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x386609796d5a7b53",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231558.json
Normal file
46
tests/files/VMTests/RandomTests/201412231558.json
Normal file
|
|
@ -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" : "0x67767162694473797350685804",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9997",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x67767162694473797350685804",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x67767162694473797350685804",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/files/VMTests/RandomTests/201412231559.json
Normal file
46
tests/files/VMTests/RandomTests/201412231559.json
Normal file
|
|
@ -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" : "0x33666b7c09ff376d",
|
||||||
|
"data" : "0x",
|
||||||
|
"gas" : "10000",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000"
|
||||||
|
},
|
||||||
|
"gas" : "9998",
|
||||||
|
"logs" : [
|
||||||
|
],
|
||||||
|
"out" : "0x",
|
||||||
|
"post" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x33666b7c09ff376d",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"code" : "0x33666b7c09ff376d",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue