aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-05-10 08:04:06 +0800
committerobscuren <geffobscura@gmail.com>2014-05-10 08:04:06 +0800
commit3af35d922e5751dcf265d31abf293b759e570fec (patch)
tree5dbfdb50177d9c7ededabb240f7e792d1174505b
parent2096b3a9edb3289a8f30da81704181dec7b39917 (diff)
parentdbf8645aafb19837d01b939ba9b1d3e1a2fffbf9 (diff)
downloadgo-tangerine-3af35d922e5751dcf265d31abf293b759e570fec.tar
go-tangerine-3af35d922e5751dcf265d31abf293b759e570fec.tar.gz
go-tangerine-3af35d922e5751dcf265d31abf293b759e570fec.tar.bz2
go-tangerine-3af35d922e5751dcf265d31abf293b759e570fec.tar.lz
go-tangerine-3af35d922e5751dcf265d31abf293b759e570fec.tar.xz
go-tangerine-3af35d922e5751dcf265d31abf293b759e570fec.tar.zst
go-tangerine-3af35d922e5751dcf265d31abf293b759e570fec.zip
Merge branch 'release/poc5-rc2'
-rw-r--r--ethchain/asm.go21
-rw-r--r--ethchain/closure.go10
-rw-r--r--ethchain/state.go82
-rw-r--r--ethchain/state_manager.go106
-rw-r--r--ethchain/state_object.go31
-rw-r--r--ethchain/transaction_pool.go3
-rw-r--r--ethchain/types.go134
-rw-r--r--ethchain/vm.go63
-rw-r--r--ethchain/vm_test.go83
-rw-r--r--ethereum.go86
-rw-r--r--ethpub/pub.go14
-rw-r--r--ethrpc/packages.go8
-rw-r--r--ethutil/common_test.go2
-rw-r--r--ethutil/config.go3
-rw-r--r--ethutil/rlp_test.go15
15 files changed, 300 insertions, 361 deletions
diff --git a/ethchain/asm.go b/ethchain/asm.go
index 3194549ba..492be0999 100644
--- a/ethchain/asm.go
+++ b/ethchain/asm.go
@@ -21,9 +21,10 @@ func Disassemble(script []byte) (asm []string) {
asm = append(asm, fmt.Sprintf("%v", op))
switch op {
- case oPUSH: // Push PC+1 on to the stack
+ case oPUSH1, oPUSH2, oPUSH3, oPUSH4, oPUSH5, oPUSH6, oPUSH7, oPUSH8, oPUSH9, oPUSH10, oPUSH11, oPUSH12, oPUSH13, oPUSH14, oPUSH15, oPUSH16, oPUSH17, oPUSH18, oPUSH19, oPUSH20, oPUSH21, oPUSH22, oPUSH23, oPUSH24, oPUSH25, oPUSH26, oPUSH27, oPUSH28, oPUSH29, oPUSH30, oPUSH31, oPUSH32:
pc.Add(pc, ethutil.Big1)
- data := script[pc.Int64() : pc.Int64()+32]
+ a := int64(op) - int64(oPUSH1) + 1
+ data := script[pc.Int64() : pc.Int64()+a]
val := ethutil.BigD(data)
var b []byte
@@ -35,21 +36,7 @@ func Disassemble(script []byte) (asm []string) {
asm = append(asm, fmt.Sprintf("0x%x", b))
- pc.Add(pc, big.NewInt(31))
- case oPUSH20:
- pc.Add(pc, ethutil.Big1)
- data := script[pc.Int64() : pc.Int64()+20]
- val := ethutil.BigD(data)
- var b []byte
- if val.Int64() == 0 {
- b = []byte{0}
- } else {
- b = val.Bytes()
- }
-
- asm = append(asm, fmt.Sprintf("0x%x", b))
-
- pc.Add(pc, big.NewInt(19))
+ pc.Add(pc, big.NewInt(a-1))
}
pc.Add(pc, ethutil.Big1)
diff --git a/ethchain/closure.go b/ethchain/closure.go
index 7e911ad99..59194e4e8 100644
--- a/ethchain/closure.go
+++ b/ethchain/closure.go
@@ -11,7 +11,7 @@ type ClosureRef interface {
ReturnGas(*big.Int, *big.Int, *State)
Address() []byte
GetMem(*big.Int) *ethutil.Value
- SetMem(*big.Int, *ethutil.Value)
+ SetStore(*big.Int, *ethutil.Value)
N() *big.Int
}
@@ -24,20 +24,18 @@ type Closure struct {
Gas *big.Int
Price *big.Int
- Value *big.Int
Args []byte
}
// Create a new closure for the given data items
-func NewClosure(callee, object *StateObject, script []byte, state *State, gas, price, val *big.Int) *Closure {
+func NewClosure(callee, object *StateObject, script []byte, state *State, gas, price *big.Int) *Closure {
c := &Closure{callee: callee, object: object, Script: script, State: state, Args: nil}
// In most cases gas, price and value are pointers to transaction objects
// and we don't want the transaction's values to change.
c.Gas = new(big.Int).Set(gas)
c.Price = new(big.Int).Set(price)
- c.Value = new(big.Int).Set(val)
return c
}
@@ -66,8 +64,8 @@ func (c *Closure) Gets(x, y *big.Int) *ethutil.Value {
return ethutil.NewValue(partial)
}
-func (c *Closure) SetMem(x *big.Int, val *ethutil.Value) {
- c.object.SetMem(x, val)
+func (c *Closure) SetStorage(x *big.Int, val *ethutil.Value) {
+ c.object.SetStorage(x, val)
}
func (c *Closure) Address() []byte {
diff --git a/ethchain/state.go b/ethchain/state.go
index 1b5655d4c..d02584d67 100644
--- a/ethchain/state.go
+++ b/ethchain/state.go
@@ -15,11 +15,13 @@ type State struct {
trie *ethutil.Trie
// Nested states
states map[string]*State
+
+ manifest *Manifest
}
// Create a new state from a given trie
func NewState(trie *ethutil.Trie) *State {
- return &State{trie: trie, states: make(map[string]*State)}
+ return &State{trie: trie, states: make(map[string]*State), manifest: NewManifest()}
}
// Resets the trie and all siblings
@@ -114,46 +116,6 @@ func (s *State) Copy() *State {
return NewState(s.trie.Copy())
}
-type ObjType byte
-
-const (
- NilTy ObjType = iota
- AccountTy
- ContractTy
-
- UnknownTy
-)
-
-/*
-// Returns the object stored at key and the type stored at key
-// Returns nil if nothing is stored
-func (s *State) GetStateObject(key []byte) (*ethutil.Value, ObjType) {
- // Fetch data from the trie
- data := s.trie.Get(string(key))
- // Returns the nil type, indicating nothing could be retrieved.
- // Anything using this function should check for this ret val
- if data == "" {
- return nil, NilTy
- }
-
- var typ ObjType
- val := ethutil.NewValueFromBytes([]byte(data))
- // Check the length of the retrieved value.
- // Len 2 = Account
- // Len 3 = Contract
- // Other = invalid for now. If other types emerge, add them here
- if val.Len() == 2 {
- typ = AccountTy
- } else if val.Len() == 3 {
- typ = ContractTy
- } else {
- typ = UnknownTy
- }
-
- return val, typ
-}
-*/
-
// Updates any given state object
func (s *State) UpdateStateObject(object *StateObject) {
addr := object.Address()
@@ -163,6 +125,7 @@ func (s *State) UpdateStateObject(object *StateObject) {
}
s.trie.Update(string(addr), string(object.RlpEncode()))
+ s.manifest.AddObjectChange(object)
}
func (s *State) Put(key, object []byte) {
@@ -172,3 +135,40 @@ func (s *State) Put(key, object []byte) {
func (s *State) Root() interface{} {
return s.trie.Root
}
+
+// Object manifest
+//
+// The object manifest is used to keep changes to the state so we can keep track of the changes
+// that occurred during a state transitioning phase.
+type Manifest struct {
+ // XXX These will be handy in the future. Not important for now.
+ objectAddresses map[string]bool
+ storageAddresses map[string]map[string]bool
+
+ objectChanges map[string]*StateObject
+ storageChanges map[string]map[string]*big.Int
+}
+
+func NewManifest() *Manifest {
+ m := &Manifest{objectAddresses: make(map[string]bool), storageAddresses: make(map[string]map[string]bool)}
+ m.Reset()
+
+ return m
+}
+
+func (m *Manifest) Reset() {
+ m.objectChanges = make(map[string]*StateObject)
+ m.storageChanges = make(map[string]map[string]*big.Int)
+}
+
+func (m *Manifest) AddObjectChange(stateObject *StateObject) {
+ m.objectChanges[string(stateObject.Address())] = stateObject
+}
+
+func (m *Manifest) AddStorageChange(stateObject *StateObject, storageAddr []byte, storage *big.Int) {
+ if m.storageChanges[string(stateObject.Address())] == nil {
+ m.storageChanges[string(stateObject.Address())] = make(map[string]*big.Int)
+ }
+
+ m.storageChanges[string(stateObject.Address())][string(storageAddr)] = storage
+}
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index 501ec102b..dd21a31b1 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -25,24 +25,16 @@ type EthManager interface {
type StateManager struct {
// Mutex for locking the block processor. Blocks can only be handled one at a time
mutex sync.Mutex
-
// Canonical block chain
bc *BlockChain
- // States for addresses. You can watch any address
- // at any given time
- stateObjectCache *StateObjectCache
-
// Stack for processing contracts
stack *Stack
// non-persistent key/value memory storage
mem map[string]*big.Int
-
+ // Proof of work used for validating
Pow PoW
-
+ // The ethereum manager interface
Ethereum EthManager
-
- SecondaryBlockProcessor BlockProcessor
-
// The managed states
// Processor state. Anything processed will be applied to this
// state
@@ -50,21 +42,28 @@ type StateManager struct {
// Comparative state it used for comparing and validating end
// results
compState *State
-
- manifest *Manifest
+ // Transiently state. The trans state isn't ever saved, validated and
+ // it could be used for setting account nonces without effecting
+ // the main states.
+ transState *State
+ // Manifest for keeping changes regarding state objects. See `notify`
+ // XXX Should we move the manifest to the State object. Benefit:
+ // * All states can keep their own local changes
+ //manifest *Manifest
}
func NewStateManager(ethereum EthManager) *StateManager {
sm := &StateManager{
- stack: NewStack(),
- mem: make(map[string]*big.Int),
- Pow: &EasyPow{},
- Ethereum: ethereum,
- stateObjectCache: NewStateObjectCache(),
- bc: ethereum.BlockChain(),
- manifest: NewManifest(),
+ stack: NewStack(),
+ mem: make(map[string]*big.Int),
+ Pow: &EasyPow{},
+ Ethereum: ethereum,
+ bc: ethereum.BlockChain(),
+ //manifest: NewManifest(),
}
sm.procState = ethereum.BlockChain().CurrentBlock.State()
+ sm.transState = sm.procState.Copy()
+
return sm
}
@@ -72,22 +71,8 @@ func (sm *StateManager) ProcState() *State {
return sm.procState
}
-// Watches any given address and puts it in the address state store
-func (sm *StateManager) WatchAddr(addr []byte) *CachedStateObject {
- //XXX account := sm.bc.CurrentBlock.state.GetAccount(addr)
- account := sm.procState.GetAccount(addr)
-
- return sm.stateObjectCache.Add(addr, account)
-}
-
-func (sm *StateManager) GetAddrState(addr []byte) *CachedStateObject {
- account := sm.stateObjectCache.Get(addr)
- if account == nil {
- a := sm.procState.GetAccount(addr)
- account = &CachedStateObject{Nonce: a.Nonce, Object: a}
- }
-
- return account
+func (sm *StateManager) TransState() *State {
+ return sm.transState
}
func (sm *StateManager) BlockChain() *BlockChain {
@@ -201,19 +186,13 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error {
// Add the block to the chain
sm.bc.Add(block)
- // If there's a block processor present, pass in the block for further
- // processing
- if sm.SecondaryBlockProcessor != nil {
- sm.SecondaryBlockProcessor.ProcessBlock(block)
- }
-
ethutil.Config.Log.Infof("[STATE] Added block #%d (%x)\n", block.BlockInfo().Number, block.Hash())
if dontReact == false {
sm.Ethereum.Reactor().Post("newBlock", block)
sm.notifyChanges()
- sm.manifest.Reset()
+ sm.procState.manifest.Reset()
}
} else {
fmt.Println("total diff failed")
@@ -323,7 +302,7 @@ func (sm *StateManager) EvalScript(script []byte, object *StateObject, tx *Trans
return
}
- closure := NewClosure(account, object, script, sm.procState, tx.Gas, tx.GasPrice, tx.Value)
+ closure := NewClosure(account, object, script, sm.procState, tx.Gas, tx.GasPrice)
vm := NewVm(sm.procState, sm, RuntimeVars{
Origin: account.Address(),
BlockNumber: block.BlockInfo().Number,
@@ -331,59 +310,24 @@ func (sm *StateManager) EvalScript(script []byte, object *StateObject, tx *Trans
Coinbase: block.Coinbase,
Time: block.Time,
Diff: block.Difficulty,
+ Value: tx.Value,
//Price: tx.GasPrice,
})
closure.Call(vm, tx.Data, nil)
// Update the account (refunds)
sm.procState.UpdateStateObject(account)
- sm.manifest.AddObjectChange(account)
-
sm.procState.UpdateStateObject(object)
- sm.manifest.AddObjectChange(object)
}
func (sm *StateManager) notifyChanges() {
- for addr, stateObject := range sm.manifest.objectChanges {
+ for addr, stateObject := range sm.procState.manifest.objectChanges {
sm.Ethereum.Reactor().Post("object:"+addr, stateObject)
}
- for stateObjectAddr, mappedObjects := range sm.manifest.storageChanges {
+ for stateObjectAddr, mappedObjects := range sm.procState.manifest.storageChanges {
for addr, value := range mappedObjects {
sm.Ethereum.Reactor().Post("storage:"+stateObjectAddr+":"+addr, &StorageState{[]byte(stateObjectAddr), []byte(addr), value})
}
}
}
-
-type Manifest struct {
- // XXX These will be handy in the future. Not important for now.
- objectAddresses map[string]bool
- storageAddresses map[string]map[string]bool
-
- objectChanges map[string]*StateObject
- storageChanges map[string]map[string]*big.Int
-}
-
-func NewManifest() *Manifest {
- m := &Manifest{objectAddresses: make(map[string]bool), storageAddresses: make(map[string]map[string]bool)}
- m.Reset()
-
- return m
-}
-
-func (m *Manifest) Reset() {
- m.objectChanges = make(map[string]*StateObject)
- m.storageChanges = make(map[string]map[string]*big.Int)
-}
-
-func (m *Manifest) AddObjectChange(stateObject *StateObject) {
- m.objectChanges[string(stateObject.Address())] = stateObject
-}
-
-func (m *Manifest) AddStorageChange(stateObject *StateObject, storageAddr []byte, storage *big.Int) {
- if m.storageChanges[string(stateObject.Address())] == nil {
- m.storageChanges[string(stateObject.Address())] = make(map[string]*big.Int)
- }
-
- m.storageChanges[string(stateObject.Address())][string(storageAddr)] = storage
-}
diff --git a/ethchain/state_object.go b/ethchain/state_object.go
index 617646077..7a11a1152 100644
--- a/ethchain/state_object.go
+++ b/ethchain/state_object.go
@@ -77,7 +77,7 @@ func (c *StateObject) SetAddr(addr []byte, value interface{}) {
c.state.trie.Update(string(addr), string(ethutil.NewValue(value).Encode()))
}
-func (c *StateObject) SetMem(num *big.Int, val *ethutil.Value) {
+func (c *StateObject) SetStorage(num *big.Int, val *ethutil.Value) {
addr := ethutil.BigToBytes(num, 256)
c.SetAddr(addr, val)
}
@@ -160,33 +160,8 @@ func (c *StateObject) RlpDecode(data []byte) {
c.script = decoder.Get(3).Bytes()
}
-// The cached state and state object cache are helpers which will give you somewhat
-// control over the nonce. When creating new transactions you're interested in the 'next'
-// nonce rather than the current nonce. This to avoid creating invalid-nonce transactions.
-type StateObjectCache struct {
- cachedObjects map[string]*CachedStateObject
-}
-
-func NewStateObjectCache() *StateObjectCache {
- return &StateObjectCache{cachedObjects: make(map[string]*CachedStateObject)}
-}
-
-func (s *StateObjectCache) Add(addr []byte, object *StateObject) *CachedStateObject {
- state := &CachedStateObject{Nonce: object.Nonce, Object: object}
- s.cachedObjects[string(addr)] = state
-
- return state
-}
-
-func (s *StateObjectCache) Get(addr []byte) *CachedStateObject {
- return s.cachedObjects[string(addr)]
-}
-
-type CachedStateObject struct {
- Nonce uint64
- Object *StateObject
-}
-
+// Storage change object. Used by the manifest for notifying changes to
+// the sub channels.
type StorageState struct {
StateAddress []byte
Address []byte
diff --git a/ethchain/transaction_pool.go b/ethchain/transaction_pool.go
index 72836d6cb..56deae0c6 100644
--- a/ethchain/transaction_pool.go
+++ b/ethchain/transaction_pool.go
@@ -148,8 +148,7 @@ func (pool *TxPool) ValidateTransaction(tx *Transaction) error {
}
// Get the sender
- accountState := pool.Ethereum.StateManager().GetAddrState(tx.Sender())
- sender := accountState.Object
+ sender := pool.Ethereum.StateManager().procState.GetAccount(tx.Sender())
totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(TxFee, TxFeeRat))
// Make sure there's enough in the sender's account. Having insufficient
diff --git a/ethchain/types.go b/ethchain/types.go
index 827d4f27f..9964bbe3b 100644
--- a/ethchain/types.go
+++ b/ethchain/types.go
@@ -48,8 +48,6 @@ const (
oGASLIMIT = 0x45
// 0x50 range - 'storage' and execution
- oPUSH = 0x50
- oPUSH20 = 0x80
oPOP = 0x51
oDUP = 0x52
oSWAP = 0x53
@@ -63,14 +61,48 @@ const (
oPC = 0x5b
oMSIZE = 0x5c
- // 0x60 range - closures
- oCREATE = 0x60
- oCALL = 0x61
- oRETURN = 0x62
+ // 0x60 range
+ oPUSH1 = 0x60
+ oPUSH2 = 0x61
+ oPUSH3 = 0x62
+ oPUSH4 = 0x63
+ oPUSH5 = 0x64
+ oPUSH6 = 0x65
+ oPUSH7 = 0x66
+ oPUSH8 = 0x67
+ oPUSH9 = 0x68
+ oPUSH10 = 0x69
+ oPUSH11 = 0x6a
+ oPUSH12 = 0x6b
+ oPUSH13 = 0x6c
+ oPUSH14 = 0x6d
+ oPUSH15 = 0x6e
+ oPUSH16 = 0x6f
+ oPUSH17 = 0x70
+ oPUSH18 = 0x71
+ oPUSH19 = 0x72
+ oPUSH20 = 0x73
+ oPUSH21 = 0x74
+ oPUSH22 = 0x75
+ oPUSH23 = 0x76
+ oPUSH24 = 0x77
+ oPUSH25 = 0x78
+ oPUSH26 = 0x79
+ oPUSH27 = 0x7a
+ oPUSH28 = 0x7b
+ oPUSH29 = 0x7c
+ oPUSH30 = 0x7d
+ oPUSH31 = 0x7e
+ oPUSH32 = 0x7f
+
+ // 0xf0 range - closures
+ oCREATE = 0xf0
+ oCALL = 0xf1
+ oRETURN = 0xf2
// 0x70 range - other
- oLOG = 0x70 // XXX Unofficial
- oSUICIDE = 0x7f
+ oLOG = 0xfe // XXX Unofficial
+ oSUICIDE = 0xff
)
// Since the opcodes aren't all in order we can't use a regular slice
@@ -119,8 +151,6 @@ var opCodeToString = map[OpCode]string{
oGASLIMIT: "GASLIMIT",
// 0x50 range - 'storage' and execution
- oPUSH: "PUSH",
- oPOP: "POP",
oDUP: "DUP",
oSWAP: "SWAP",
oMLOAD: "MLOAD",
@@ -133,7 +163,41 @@ var opCodeToString = map[OpCode]string{
oPC: "PC",
oMSIZE: "MSIZE",
- // 0x60 range - closures
+ // 0x60 range - push
+ oPUSH1: "PUSH1",
+ oPUSH2: "PUSH2",
+ oPUSH3: "PUSH3",
+ oPUSH4: "PUSH4",
+ oPUSH5: "PUSH5",
+ oPUSH6: "PUSH6",
+ oPUSH7: "PUSH7",
+ oPUSH8: "PUSH8",
+ oPUSH9: "PUSH9",
+ oPUSH10: "PUSH10",
+ oPUSH11: "PUSH11",
+ oPUSH12: "PUSH12",
+ oPUSH13: "PUSH13",
+ oPUSH14: "PUSH14",
+ oPUSH15: "PUSH15",
+ oPUSH16: "PUSH16",
+ oPUSH17: "PUSH17",
+ oPUSH18: "PUSH18",
+ oPUSH19: "PUSH19",
+ oPUSH20: "PUSH20",
+ oPUSH21: "PUSH21",
+ oPUSH22: "PUSH22",
+ oPUSH23: "PUSH23",
+ oPUSH24: "PUSH24",
+ oPUSH25: "PUSH25",
+ oPUSH26: "PUSH26",
+ oPUSH27: "PUSH27",
+ oPUSH28: "PUSH28",
+ oPUSH29: "PUSH29",
+ oPUSH30: "PUSH30",
+ oPUSH31: "PUSH31",
+ oPUSH32: "PUSH32",
+
+ // 0xf0 range
oCREATE: "CREATE",
oCALL: "CALL",
oRETURN: "RETURN",
@@ -193,10 +257,6 @@ var OpCodes = map[string]byte{
"GASLIMIT": 0x45,
// 0x50 range - 'storage' and execution
- "PUSH": 0x50,
-
- "PUSH20": 0x80,
-
"POP": 0x51,
"DUP": 0x52,
"SWAP": 0x53,
@@ -210,13 +270,47 @@ var OpCodes = map[string]byte{
"PC": 0x5b,
"MSIZE": 0x5c,
- // 0x60 range - closures
- "CREATE": 0x60,
- "CALL": 0x61,
- "RETURN": 0x62,
+ // 0x70 range - 'push'
+ "PUSH1": 0x60,
+ "PUSH2": 0x61,
+ "PUSH3": 0x62,
+ "PUSH4": 0x63,
+ "PUSH5": 0x64,
+ "PUSH6": 0x65,
+ "PUSH7": 0x66,
+ "PUSH8": 0x67,
+ "PUSH9": 0x68,
+ "PUSH10": 0x69,
+ "PUSH11": 0x6a,
+ "PUSH12": 0x6b,
+ "PUSH13": 0x6c,
+ "PUSH14": 0x6d,
+ "PUSH15": 0x6e,
+ "PUSH16": 0x6f,
+ "PUSH17": 0x70,
+ "PUSH18": 0x71,
+ "PUSH19": 0x72,
+ "PUSH20": 0x73,
+ "PUSH21": 0x74,
+ "PUSH22": 0x75,
+ "PUSH23": 0x76,
+ "PUSH24": 0x77,
+ "PUSH25": 0x78,
+ "PUSH26": 0x70,
+ "PUSH27": 0x7a,
+ "PUSH28": 0x7b,
+ "PUSH29": 0x7c,
+ "PUSH30": 0x7d,
+ "PUSH31": 0x7e,
+ "PUSH32": 0x7f,
+
+ // 0xf0 range - closures
+ "CREATE": 0xf0,
+ "CALL": 0xf1,
+ "RETURN": 0xf2,
// 0x70 range - other
- "LOG": 0x70,
+ "LOG": 0xfe,
"SUICIDE": 0x7f,
}
diff --git a/ethchain/vm.go b/ethchain/vm.go
index 3a3b3447a..584c66611 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -53,6 +53,7 @@ type RuntimeVars struct {
Time int64
Diff *big.Int
TxData []string
+ Value *big.Int
}
func NewVm(state *State, stateManager *StateManager, vars RuntimeVars) *Vm {
@@ -94,6 +95,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
if ethutil.Config.Debug {
ethutil.Config.Log.Debugf("# op\n")
}
+ fmt.Println(closure.Script)
for {
// The base for all big integer arithmetic
@@ -104,11 +106,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
val := closure.Get(pc)
// Get the opcode (it must be an opcode!)
op := OpCode(val.Uint())
- /*
- if ethutil.Config.Debug {
- ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String())
- }
- */
+ if ethutil.Config.Debug {
+ ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String())
+ }
gas := new(big.Int)
useGas := func(amount *big.Int) {
@@ -318,14 +318,13 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case oADDRESS:
stack.Push(ethutil.BigD(closure.Object().Address()))
case oBALANCE:
- stack.Push(closure.Value)
+ stack.Push(closure.object.Amount)
case oORIGIN:
stack.Push(ethutil.BigD(vm.vars.Origin))
case oCALLER:
stack.Push(ethutil.BigD(closure.Callee().Address()))
case oCALLVALUE:
- // FIXME: Original value of the call, not the current value
- stack.Push(closure.Value)
+ stack.Push(vm.vars.Value)
case oCALLDATALOAD:
require(1)
offset := stack.Pop().Int64()
@@ -352,27 +351,17 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// TODO
stack.Push(big.NewInt(0))
- // 0x50 range
- case oPUSH: // Push PC+1 on to the stack
+ // 0x50 range
+ case oPUSH1, oPUSH2, oPUSH3, oPUSH4, oPUSH5, oPUSH6, oPUSH7, oPUSH8, oPUSH9, oPUSH10, oPUSH11, oPUSH12, oPUSH13, oPUSH14, oPUSH15, oPUSH16, oPUSH17, oPUSH18, oPUSH19, oPUSH20, oPUSH21, oPUSH22, oPUSH23, oPUSH24, oPUSH25, oPUSH26, oPUSH27, oPUSH28, oPUSH29, oPUSH30, oPUSH31, oPUSH32:
+ a := big.NewInt(int64(op) - int64(oPUSH1) + 1)
pc.Add(pc, ethutil.Big1)
- data := closure.Gets(pc, big.NewInt(32))
+ data := closure.Gets(pc, a)
val := ethutil.BigD(data.Bytes())
-
// Push value to stack
stack.Push(val)
-
- pc.Add(pc, big.NewInt(31))
+ pc.Add(pc, a.Sub(a, big.NewInt(1)))
step++
- case oPUSH20:
- pc.Add(pc, ethutil.Big1)
- data := closure.Gets(pc, big.NewInt(20))
- val := ethutil.BigD(data.Bytes())
-
- // Push value to stack
- stack.Push(val)
- pc.Add(pc, big.NewInt(19))
- step++
case oPOP:
require(1)
stack.Pop()
@@ -406,21 +395,23 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case oSSTORE:
require(2)
val, loc := stack.Popn()
- closure.SetMem(loc, ethutil.NewValue(val))
+ closure.SetStorage(loc, ethutil.NewValue(val))
// Add the change to manifest
- vm.stateManager.manifest.AddStorageChange(closure.Object(), loc.Bytes(), val)
+ vm.state.manifest.AddStorageChange(closure.Object(), loc.Bytes(), val)
case oJUMP:
require(1)
pc = stack.Pop()
// Reduce pc by one because of the increment that's at the end of this for loop
- pc.Sub(pc, ethutil.Big1)
+ //pc.Sub(pc, ethutil.Big1)
+ continue
case oJUMPI:
require(2)
cond, pos := stack.Popn()
if cond.Cmp(ethutil.BigTrue) == 0 {
pc = pos
- pc.Sub(pc, ethutil.Big1)
+ //pc.Sub(pc, ethutil.Big1)
+ continue
}
case oPC:
stack.Push(pc)
@@ -449,8 +440,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
contract.initScript,
vm.state,
gas,
- closure.Price,
- value)
+ closure.Price)
// Call the closure and set the return value as
// main script.
closure.Script, err = closure.Call(vm, nil, hook)
@@ -477,8 +467,10 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
break
}
+
// Get the arguments from the memory
args := mem.Get(inOffset.Int64(), inSize.Int64())
+
// Fetch the contract which will serve as the closure body
contract := vm.state.GetContract(addr.Bytes())
@@ -490,8 +482,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
gas = new(big.Int).Set(closure.Gas)
}
closure.Gas.Sub(closure.Gas, gas)
+
+ // Add the value to the state object
+ contract.AddAmount(value)
+
// Create a new callable closure
- closure := NewClosure(closure.Object(), contract, contract.script, vm.state, gas, closure.Price, value)
+ closure := NewClosure(closure.Object(), contract, contract.script, vm.state, gas, closure.Price)
// Executer the closure and get the return value (if any)
ret, err := closure.Call(vm, args, hook)
if err != nil {
@@ -500,10 +496,10 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
//contract.State().Reset()
} else {
stack.Push(ethutil.BigTrue)
- // Notify of the changes
- vm.stateManager.manifest.AddObjectChange(contract)
}
+ vm.state.SetStateObject(contract)
+
mem.Set(retOffset.Int64(), retSize.Int64(), ret)
} else {
ethutil.Config.Log.Debugf("Contract %x not found\n", addr.Bytes())
@@ -520,8 +516,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
receiver := vm.state.GetAccount(stack.Pop().Bytes())
receiver.AddAmount(closure.object.Amount)
-
- vm.stateManager.manifest.AddObjectChange(receiver)
+ vm.state.SetStateObject(receiver)
closure.object.state.Purge()
diff --git a/ethchain/vm_test.go b/ethchain/vm_test.go
index 35a7b2e3f..b919b496f 100644
--- a/ethchain/vm_test.go
+++ b/ethchain/vm_test.go
@@ -11,71 +11,6 @@ import (
"testing"
)
-/*
-func TestRun3(t *testing.T) {
- ethutil.ReadConfig("")
-
- db, _ := ethdb.NewMemDatabase()
- state := NewState(ethutil.NewTrie(db, ""))
-
- script := Compile([]string{
- "PUSH", "300",
- "PUSH", "0",
- "MSTORE",
-
- "PUSH", "32",
- "CALLDATA",
-
- "PUSH", "64",
- "PUSH", "0",
- "RETURN",
- })
- tx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), script)
- addr := tx.Hash()[12:]
- contract := MakeContract(tx, state)
- state.UpdateContract(contract)
-
- callerScript := ethutil.Assemble(
- "PUSH", 1337, // Argument
- "PUSH", 65, // argument mem offset
- "MSTORE",
- "PUSH", 64, // ret size
- "PUSH", 0, // ret offset
-
- "PUSH", 32, // arg size
- "PUSH", 65, // arg offset
- "PUSH", 1000, /// Gas
- "PUSH", 0, /// value
- "PUSH", addr, // Sender
- "CALL",
- "PUSH", 64,
- "PUSH", 0,
- "RETURN",
- )
- callerTx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), callerScript)
-
- // Contract addr as test address
- account := NewAccount(ContractAddr, big.NewInt(10000000))
- callerClosure := NewClosure(account, MakeContract(callerTx, state), state, big.NewInt(1000000000), new(big.Int))
-
- vm := NewVm(state, RuntimeVars{
- origin: account.Address(),
- blockNumber: 1,
- prevHash: ethutil.FromHex("5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"),
- coinbase: ethutil.FromHex("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"),
- time: 1,
- diff: big.NewInt(256),
- // XXX Tx data? Could be just an argument to the closure instead
- txData: nil,
- })
- ret := callerClosure.Call(vm, nil)
-
- exp := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 57}
- if bytes.Compare(ret, exp) != 0 {
- t.Errorf("expected return value to be %v, got %v", exp, ret)
- }
-}*/
-
func TestRun4(t *testing.T) {
ethutil.ReadConfig("")
@@ -86,7 +21,7 @@ func TestRun4(t *testing.T) {
int32 a = 10
int32 b = 20
if a > b {
- int32 c = this.Caller()
+ int32 c = this.caller()
}
Exit()
`), false)
@@ -98,21 +33,21 @@ func TestRun4(t *testing.T) {
callerScript, err := mutan.Compile(strings.NewReader(`
// Check if there's any cash in the initial store
- if store[1000] == 0 {
- store[1000] = 10^20
+ if this.store[1000] == 0 {
+ this.store[1000] = 10^20
}
- store[1001] = this.Value() * 20
- store[this.Origin()] = store[this.Origin()] + 1000
+ this.store[1001] = this.value() * 20
+ this.store[this.origin()] = this.store[this.origin()] + 1000
- if store[1001] > 20 {
- store[1001] = 10^50
+ if this.store[1001] > 20 {
+ this.store[1001] = 10^50
}
int8 ret = 0
int8 arg = 10
- Call(0xe6a12555fad1fb6eaaaed69001a87313d1fd7b54, 0, 100, arg, ret)
+ call(0xe6a12555fad1fb6eaaaed69001a87313d1fd7b54, 0, 100, arg, ret)
big t
for int8 i = 0; i < 10; i++ {
@@ -142,7 +77,7 @@ func TestRun4(t *testing.T) {
fmt.Println(err)
}
fmt.Println("account.Amount =", account.Amount)
- callerClosure := NewClosure(account, c, c.script, state, gas, gasPrice, big.NewInt(0))
+ callerClosure := NewClosure(account, c, c.script, state, gas, gasPrice)
vm := NewVm(state, nil, RuntimeVars{
Origin: account.Address(),
diff --git a/ethereum.go b/ethereum.go
index 707938639..e3140b5ce 100644
--- a/ethereum.go
+++ b/ethereum.go
@@ -253,7 +253,7 @@ func (s *Ethereum) ReapDeadPeerHandler() {
}
// Start the ethereum
-func (s *Ethereum) Start() {
+func (s *Ethereum) Start(seed bool) {
// Bind to addr and port
ln, err := net.Listen("tcp", ":"+s.Port)
if err != nil {
@@ -272,47 +272,51 @@ func (s *Ethereum) Start() {
// Start the reaping processes
go s.ReapDeadPeerHandler()
- if ethutil.Config.Seed {
- ethutil.Config.Log.Debugln("Seeding")
- // DNS Bootstrapping
- _, nodes, err := net.LookupSRV("eth", "tcp", "ethereum.org")
- if err == nil {
- peers := []string{}
- // Iterate SRV nodes
- for _, n := range nodes {
- target := n.Target
- port := strconv.Itoa(int(n.Port))
- // Resolve target to ip (Go returns list, so may resolve to multiple ips?)
- addr, err := net.LookupHost(target)
- if err == nil {
- for _, a := range addr {
- // Build string out of SRV port and Resolved IP
- peer := net.JoinHostPort(a, port)
- log.Println("Found DNS Bootstrap Peer:", peer)
- peers = append(peers, peer)
- }
- } else {
- log.Println("Couldn't resolve :", target)
+ if seed {
+ s.Seed()
+ }
+}
+
+func (s *Ethereum) Seed() {
+ ethutil.Config.Log.Debugln("Seeding")
+ // DNS Bootstrapping
+ _, nodes, err := net.LookupSRV("eth", "tcp", "ethereum.org")
+ if err == nil {
+ peers := []string{}
+ // Iterate SRV nodes
+ for _, n := range nodes {
+ target := n.Target
+ port := strconv.Itoa(int(n.Port))
+ // Resolve target to ip (Go returns list, so may resolve to multiple ips?)
+ addr, err := net.LookupHost(target)
+ if err == nil {
+ for _, a := range addr {
+ // Build string out of SRV port and Resolved IP
+ peer := net.JoinHostPort(a, port)
+ log.Println("Found DNS Bootstrap Peer:", peer)
+ peers = append(peers, peer)
}
+ } else {
+ log.Println("Couldn't resolve :", target)
}
- // Connect to Peer list
- s.ProcessPeerList(peers)
- } else {
- // Fallback to servers.poc3.txt
- resp, err := http.Get("http://www.ethereum.org/servers.poc3.txt")
- if err != nil {
- log.Println("Fetching seed failed:", err)
- return
- }
- defer resp.Body.Close()
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- log.Println("Reading seed failed:", err)
- return
- }
-
- s.ConnectToPeer(string(body))
}
+ // Connect to Peer list
+ s.ProcessPeerList(peers)
+ } else {
+ // Fallback to servers.poc3.txt
+ resp, err := http.Get("http://www.ethereum.org/servers.poc3.txt")
+ if err != nil {
+ log.Println("Fetching seed failed:", err)
+ return
+ }
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ log.Println("Reading seed failed:", err)
+ return
+ }
+
+ s.ConnectToPeer(string(body))
}
}
@@ -339,7 +343,9 @@ func (s *Ethereum) Stop() {
close(s.quit)
- s.RpcServer.Stop()
+ if s.RpcServer != nil {
+ s.RpcServer.Stop()
+ }
s.txPool.Stop()
s.stateManager.Stop()
diff --git a/ethpub/pub.go b/ethpub/pub.go
index 5e7792a9f..f7e641b35 100644
--- a/ethpub/pub.go
+++ b/ethpub/pub.go
@@ -92,7 +92,14 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, in
hash = ethutil.FromHex(recipient)
}
- keyPair, err := ethchain.NewKeyPairFromSec([]byte(ethutil.FromHex(key)))
+ var keyPair *ethchain.KeyPair
+ var err error
+ if key[0:2] == "0x" {
+ keyPair, err = ethchain.NewKeyPairFromSec([]byte(ethutil.FromHex(key[0:2])))
+ } else {
+ keyPair, err = ethchain.NewKeyPairFromSec([]byte(ethutil.FromHex(key)))
+ }
+
if err != nil {
return nil, err
}
@@ -132,8 +139,11 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, in
tx = ethchain.NewTransactionMessage(hash, value, gas, gasPrice, ethutil.FromHex(initStr))
}
- acc := lib.stateManager.GetAddrState(keyPair.Address())
+ acc := lib.stateManager.TransState().GetStateObject(keyPair.Address())
+ //acc := lib.stateManager.GetAddrState(keyPair.Address())
tx.Nonce = acc.Nonce
+ lib.stateManager.TransState().SetStateObject(acc)
+
tx.Sign(keyPair.PrivateKey)
lib.txPool.QueueTransaction(tx)
diff --git a/ethrpc/packages.go b/ethrpc/packages.go
index b989a65cb..4ec2b4602 100644
--- a/ethrpc/packages.go
+++ b/ethrpc/packages.go
@@ -4,7 +4,8 @@ import (
"encoding/json"
"errors"
"github.com/ethereum/eth-go/ethpub"
- _ "log"
+ "github.com/ethereum/eth-go/ethutil"
+ "math/big"
)
type EthereumApi struct {
@@ -173,7 +174,10 @@ func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *string) error {
return err
}
state := p.ethp.GetStateObject(args.Address)
- value := state.GetStorage(args.Key)
+ // Convert the incoming string (which is a bigint) into hex
+ i, _ := new(big.Int).SetString(args.Key, 10)
+ hx := ethutil.Hex(i.Bytes())
+ value := state.GetStorage(hx)
*reply = NewSuccessRes(GetStorageAtRes{Address: args.Address, Key: args.Key, Value: value})
return nil
}
diff --git a/ethutil/common_test.go b/ethutil/common_test.go
index b5c733ff3..8031f08ab 100644
--- a/ethutil/common_test.go
+++ b/ethutil/common_test.go
@@ -26,7 +26,7 @@ func TestCommon(t *testing.T) {
t.Error("Got", szabo)
}
- if vito != "10 Vito" {
+ if vito != "10 Vita" {
t.Error("Got", vito)
}
diff --git a/ethutil/config.go b/ethutil/config.go
index 382396ceb..5e36b06d2 100644
--- a/ethutil/config.go
+++ b/ethutil/config.go
@@ -27,7 +27,6 @@ type config struct {
Ver string
ClientString string
Pubkey []byte
- Seed bool
}
var Config *config
@@ -51,7 +50,7 @@ func ReadConfig(base string) *config {
}
}
- Config = &config{ExecPath: path, Debug: true, Ver: "0.5 RC1"}
+ Config = &config{ExecPath: path, Debug: true, Ver: "0.5.0 RC2"}
Config.Log = NewLogger(LogFile|LogStd, LogLevelDebug)
Config.SetClientString("/Ethereum(G)")
}
diff --git a/ethutil/rlp_test.go b/ethutil/rlp_test.go
index 9e8127aab..095c01ecc 100644
--- a/ethutil/rlp_test.go
+++ b/ethutil/rlp_test.go
@@ -2,7 +2,6 @@ package ethutil
import (
"bytes"
- "fmt"
"math/big"
"reflect"
"testing"
@@ -56,15 +55,6 @@ func TestValue(t *testing.T) {
}
}
-func TestEncodeDecodeMaran(t *testing.T) {
- b := NewValue([]interface{}{"dog", 15, []interface{}{"cat", "cat", []interface{}{}}, 1024, "tachikoma"})
- a := b.Encode()
- fmt.Println("voor maran", a)
- f, i := Decode(a, 0)
- fmt.Println("voor maran 2", f)
- fmt.Println(i)
-}
-
func TestEncode(t *testing.T) {
strRes := "\x83dog"
bytes := Encode("dog")
@@ -131,7 +121,10 @@ func TestEncodeDecodeBytes(t *testing.T) {
func TestEncodeZero(t *testing.T) {
b := NewValue(0).Encode()
- fmt.Println(b)
+ exp := []byte{0xc0}
+ if bytes.Compare(b, exp) == 0 {
+ t.Error("Expected", exp, "got", b)
+ }
}
func BenchmarkEncodeDecode(b *testing.B) {