Merge remote-tracking branch 'upstream/poc8' into kademlia

This commit is contained in:
zelig 2015-01-05 16:10:56 +00:00
commit 6dd253f564
342 changed files with 17150 additions and 5180 deletions

View file

@ -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="

View file

@ -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

View file

@ -9,10 +9,11 @@ Ethereum
[![Build [![Build
Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20master%20branch)](http://build.ethdev.com:8010/builders/Linux%20Go%20master%20branch/builds/-1) master [![Build Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20master%20branch)](http://build.ethdev.com:8010/builders/Linux%20Go%20master%20branch/builds/-1) master [![Build
Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](http://build.ethdev.com:8010/builders/Linux%20Go%20develop%20branch/builds/-1) develop Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](http://build.ethdev.com:8010/builders/Linux%20Go%20develop%20branch/builds/-1) develop
[![Coverage Status](https://coveralls.io/repos/ethereum/go-ethereum/badge.png?branch=tests)](https://coveralls.io/r/ethereum/go-ethereum?branch=tests) tests
Ethereum Go Client © 2014 Jeffrey Wilcke. 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.

Binary file not shown.

Binary file not shown.

BIN
_data/invalid1 Executable file

Binary file not shown.

BIN
_data/valid1 Executable file

Binary file not shown.

BIN
_data/valid2 Executable file

Binary file not shown.

BIN
_data/valid3 Executable file

Binary file not shown.

BIN
_data/valid4 Executable file

Binary file not shown.

View file

@ -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")

View file

@ -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(&eth.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()
} }

View file

@ -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
View file

@ -0,0 +1,5 @@
{
"directory": "example/js/",
"cwd": "./",
"analytics": false
}

12
cmd/ethtest/.editorconfig Normal file
View 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
View 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
View 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
View 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
View 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

View file

@ -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))

View file

@ -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)
} }

View file

@ -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) {

View file

@ -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"})
*/
} }
} }

View file

@ -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))
} }

View file

@ -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
}
}
} }

View file

@ -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)
} }

View file

@ -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())

View file

@ -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")

View file

@ -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))
}
*/

View file

@ -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)
} }

View file

@ -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(&eth.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()

View file

@ -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)
} }

View file

@ -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) }
*/

View file

@ -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 {}
} }

View file

@ -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
}

View file

@ -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)
} }

View file

@ -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()
} }

View file

@ -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()

View file

@ -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)
}

View file

@ -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")
}
} }

View file

@ -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
} }

View file

@ -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
} }

View file

@ -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
}

View file

@ -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 {

View file

@ -1 +0,0 @@
package core

View file

@ -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 {

View file

@ -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() {

View 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())
}
}

View file

@ -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
View file

@ -0,0 +1 @@
package types

View file

@ -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()
} }

View file

@ -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
} }

View file

@ -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)
} }

View file

@ -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())
}
} }
} }

View file

@ -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
View 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
}
*/

View file

@ -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()

View file

@ -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)
}

View file

@ -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

View file

@ -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

View file

@ -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
View 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
}

View file

@ -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)

View file

@ -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
View 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
}

View file

@ -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
} }

View file

@ -1,4 +1,4 @@
package core package dagger
import ( import (
"hash" "hash"

View file

@ -1,4 +1,4 @@
package core package dagger
import ( import (
"math/big" "math/big"

View file

@ -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())
} }

File diff suppressed because it is too large Load diff

View file

@ -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
} }

View file

@ -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 {

View file

@ -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+" "))
} }

View file

@ -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)
}

View file

@ -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()

View file

@ -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)
}
} }

View file

@ -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

View file

@ -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)

View file

@ -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) {

View file

@ -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
} }
} }
} }

View file

@ -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",

View file

@ -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",

View file

@ -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"
}
} }
} }

View file

@ -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"],

View 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" : {
}
}
}
}
}

View 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" : {
}
}
}
}
}

View 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" : {
}
}
}
}
}

View 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" : {
}
}
}
}
}

View 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" : {
}
}
}
}
}

View 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" : {
}
}
}
}
}

View 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" : {
}
}
}
}
}

View 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" : {
}
}
}
}
}

View 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" : {
}
}
}
}
}

View 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" : {
}
}
}
}
}

View 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" : {
}
}
}
}
}

View 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" : {
}
}
}
}
}

View 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" : {
}
}
}
}
}

View 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" : {
}
}
}
}
}

View 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" : {
}
}
}
}
}

View 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