forked from cerc-io/plugeth
Merge branch 'release/poc5-rc2'
This commit is contained in:
commit
3af35d922e
@ -21,9 +21,10 @@ func Disassemble(script []byte) (asm []string) {
|
|||||||
asm = append(asm, fmt.Sprintf("%v", op))
|
asm = append(asm, fmt.Sprintf("%v", op))
|
||||||
|
|
||||||
switch 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)
|
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)
|
val := ethutil.BigD(data)
|
||||||
|
|
||||||
var b []byte
|
var b []byte
|
||||||
@ -35,21 +36,7 @@ func Disassemble(script []byte) (asm []string) {
|
|||||||
|
|
||||||
asm = append(asm, fmt.Sprintf("0x%x", b))
|
asm = append(asm, fmt.Sprintf("0x%x", b))
|
||||||
|
|
||||||
pc.Add(pc, big.NewInt(31))
|
pc.Add(pc, big.NewInt(a-1))
|
||||||
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, ethutil.Big1)
|
pc.Add(pc, ethutil.Big1)
|
||||||
|
@ -11,7 +11,7 @@ type ClosureRef interface {
|
|||||||
ReturnGas(*big.Int, *big.Int, *State)
|
ReturnGas(*big.Int, *big.Int, *State)
|
||||||
Address() []byte
|
Address() []byte
|
||||||
GetMem(*big.Int) *ethutil.Value
|
GetMem(*big.Int) *ethutil.Value
|
||||||
SetMem(*big.Int, *ethutil.Value)
|
SetStore(*big.Int, *ethutil.Value)
|
||||||
N() *big.Int
|
N() *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,20 +24,18 @@ type Closure struct {
|
|||||||
|
|
||||||
Gas *big.Int
|
Gas *big.Int
|
||||||
Price *big.Int
|
Price *big.Int
|
||||||
Value *big.Int
|
|
||||||
|
|
||||||
Args []byte
|
Args []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new closure for the given data items
|
// 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}
|
c := &Closure{callee: callee, object: object, Script: script, State: state, Args: nil}
|
||||||
|
|
||||||
// In most cases gas, price and value are pointers to transaction objects
|
// In most cases gas, price and value are pointers to transaction objects
|
||||||
// and we don't want the transaction's values to change.
|
// and we don't want the transaction's values to change.
|
||||||
c.Gas = new(big.Int).Set(gas)
|
c.Gas = new(big.Int).Set(gas)
|
||||||
c.Price = new(big.Int).Set(price)
|
c.Price = new(big.Int).Set(price)
|
||||||
c.Value = new(big.Int).Set(val)
|
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
@ -66,8 +64,8 @@ func (c *Closure) Gets(x, y *big.Int) *ethutil.Value {
|
|||||||
return ethutil.NewValue(partial)
|
return ethutil.NewValue(partial)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Closure) SetMem(x *big.Int, val *ethutil.Value) {
|
func (c *Closure) SetStorage(x *big.Int, val *ethutil.Value) {
|
||||||
c.object.SetMem(x, val)
|
c.object.SetStorage(x, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Closure) Address() []byte {
|
func (c *Closure) Address() []byte {
|
||||||
|
@ -15,11 +15,13 @@ type State struct {
|
|||||||
trie *ethutil.Trie
|
trie *ethutil.Trie
|
||||||
// Nested states
|
// Nested states
|
||||||
states map[string]*State
|
states map[string]*State
|
||||||
|
|
||||||
|
manifest *Manifest
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new state from a given trie
|
// Create a new state from a given trie
|
||||||
func NewState(trie *ethutil.Trie) *State {
|
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
|
// Resets the trie and all siblings
|
||||||
@ -114,46 +116,6 @@ func (s *State) Copy() *State {
|
|||||||
return NewState(s.trie.Copy())
|
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
|
// Updates any given state object
|
||||||
func (s *State) UpdateStateObject(object *StateObject) {
|
func (s *State) UpdateStateObject(object *StateObject) {
|
||||||
addr := object.Address()
|
addr := object.Address()
|
||||||
@ -163,6 +125,7 @@ func (s *State) UpdateStateObject(object *StateObject) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.trie.Update(string(addr), string(object.RlpEncode()))
|
s.trie.Update(string(addr), string(object.RlpEncode()))
|
||||||
|
s.manifest.AddObjectChange(object)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) Put(key, object []byte) {
|
func (s *State) Put(key, object []byte) {
|
||||||
@ -172,3 +135,40 @@ func (s *State) Put(key, object []byte) {
|
|||||||
func (s *State) Root() interface{} {
|
func (s *State) Root() interface{} {
|
||||||
return s.trie.Root
|
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
|
||||||
|
}
|
||||||
|
@ -25,24 +25,16 @@ type EthManager interface {
|
|||||||
type StateManager struct {
|
type StateManager 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
|
||||||
bc *BlockChain
|
bc *BlockChain
|
||||||
// States for addresses. You can watch any address
|
|
||||||
// at any given time
|
|
||||||
stateObjectCache *StateObjectCache
|
|
||||||
|
|
||||||
// Stack for processing contracts
|
// Stack for processing contracts
|
||||||
stack *Stack
|
stack *Stack
|
||||||
// non-persistent key/value memory storage
|
// non-persistent key/value memory storage
|
||||||
mem map[string]*big.Int
|
mem map[string]*big.Int
|
||||||
|
// Proof of work used for validating
|
||||||
Pow PoW
|
Pow PoW
|
||||||
|
// The ethereum manager interface
|
||||||
Ethereum EthManager
|
Ethereum EthManager
|
||||||
|
|
||||||
SecondaryBlockProcessor BlockProcessor
|
|
||||||
|
|
||||||
// The managed states
|
// The managed states
|
||||||
// Processor state. Anything processed will be applied to this
|
// Processor state. Anything processed will be applied to this
|
||||||
// state
|
// state
|
||||||
@ -50,21 +42,28 @@ type StateManager struct {
|
|||||||
// Comparative state it used for comparing and validating end
|
// Comparative state it used for comparing and validating end
|
||||||
// results
|
// results
|
||||||
compState *State
|
compState *State
|
||||||
|
// Transiently state. The trans state isn't ever saved, validated and
|
||||||
manifest *Manifest
|
// 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 {
|
func NewStateManager(ethereum EthManager) *StateManager {
|
||||||
sm := &StateManager{
|
sm := &StateManager{
|
||||||
stack: NewStack(),
|
stack: NewStack(),
|
||||||
mem: make(map[string]*big.Int),
|
mem: make(map[string]*big.Int),
|
||||||
Pow: &EasyPow{},
|
Pow: &EasyPow{},
|
||||||
Ethereum: ethereum,
|
Ethereum: ethereum,
|
||||||
stateObjectCache: NewStateObjectCache(),
|
bc: ethereum.BlockChain(),
|
||||||
bc: ethereum.BlockChain(),
|
//manifest: NewManifest(),
|
||||||
manifest: NewManifest(),
|
|
||||||
}
|
}
|
||||||
sm.procState = ethereum.BlockChain().CurrentBlock.State()
|
sm.procState = ethereum.BlockChain().CurrentBlock.State()
|
||||||
|
sm.transState = sm.procState.Copy()
|
||||||
|
|
||||||
return sm
|
return sm
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,22 +71,8 @@ func (sm *StateManager) ProcState() *State {
|
|||||||
return sm.procState
|
return sm.procState
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watches any given address and puts it in the address state store
|
func (sm *StateManager) TransState() *State {
|
||||||
func (sm *StateManager) WatchAddr(addr []byte) *CachedStateObject {
|
return sm.transState
|
||||||
//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) BlockChain() *BlockChain {
|
func (sm *StateManager) BlockChain() *BlockChain {
|
||||||
@ -201,19 +186,13 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error {
|
|||||||
// Add the block to the chain
|
// Add the block to the chain
|
||||||
sm.bc.Add(block)
|
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())
|
ethutil.Config.Log.Infof("[STATE] Added block #%d (%x)\n", block.BlockInfo().Number, block.Hash())
|
||||||
if dontReact == false {
|
if dontReact == false {
|
||||||
sm.Ethereum.Reactor().Post("newBlock", block)
|
sm.Ethereum.Reactor().Post("newBlock", block)
|
||||||
|
|
||||||
sm.notifyChanges()
|
sm.notifyChanges()
|
||||||
|
|
||||||
sm.manifest.Reset()
|
sm.procState.manifest.Reset()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("total diff failed")
|
fmt.Println("total diff failed")
|
||||||
@ -323,7 +302,7 @@ func (sm *StateManager) EvalScript(script []byte, object *StateObject, tx *Trans
|
|||||||
return
|
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{
|
vm := NewVm(sm.procState, sm, RuntimeVars{
|
||||||
Origin: account.Address(),
|
Origin: account.Address(),
|
||||||
BlockNumber: block.BlockInfo().Number,
|
BlockNumber: block.BlockInfo().Number,
|
||||||
@ -331,59 +310,24 @@ func (sm *StateManager) EvalScript(script []byte, object *StateObject, tx *Trans
|
|||||||
Coinbase: block.Coinbase,
|
Coinbase: block.Coinbase,
|
||||||
Time: block.Time,
|
Time: block.Time,
|
||||||
Diff: block.Difficulty,
|
Diff: block.Difficulty,
|
||||||
|
Value: tx.Value,
|
||||||
//Price: tx.GasPrice,
|
//Price: tx.GasPrice,
|
||||||
})
|
})
|
||||||
closure.Call(vm, tx.Data, nil)
|
closure.Call(vm, tx.Data, nil)
|
||||||
|
|
||||||
// Update the account (refunds)
|
// Update the account (refunds)
|
||||||
sm.procState.UpdateStateObject(account)
|
sm.procState.UpdateStateObject(account)
|
||||||
sm.manifest.AddObjectChange(account)
|
|
||||||
|
|
||||||
sm.procState.UpdateStateObject(object)
|
sm.procState.UpdateStateObject(object)
|
||||||
sm.manifest.AddObjectChange(object)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *StateManager) notifyChanges() {
|
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)
|
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 {
|
for addr, value := range mappedObjects {
|
||||||
sm.Ethereum.Reactor().Post("storage:"+stateObjectAddr+":"+addr, &StorageState{[]byte(stateObjectAddr), []byte(addr), value})
|
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
|
|
||||||
}
|
|
||||||
|
@ -77,7 +77,7 @@ func (c *StateObject) SetAddr(addr []byte, value interface{}) {
|
|||||||
c.state.trie.Update(string(addr), string(ethutil.NewValue(value).Encode()))
|
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)
|
addr := ethutil.BigToBytes(num, 256)
|
||||||
c.SetAddr(addr, val)
|
c.SetAddr(addr, val)
|
||||||
}
|
}
|
||||||
@ -160,33 +160,8 @@ func (c *StateObject) RlpDecode(data []byte) {
|
|||||||
c.script = decoder.Get(3).Bytes()
|
c.script = decoder.Get(3).Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
// The cached state and state object cache are helpers which will give you somewhat
|
// Storage change object. Used by the manifest for notifying changes to
|
||||||
// control over the nonce. When creating new transactions you're interested in the 'next'
|
// the sub channels.
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
type StorageState struct {
|
type StorageState struct {
|
||||||
StateAddress []byte
|
StateAddress []byte
|
||||||
Address []byte
|
Address []byte
|
||||||
|
@ -148,8 +148,7 @@ func (pool *TxPool) ValidateTransaction(tx *Transaction) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the sender
|
// Get the sender
|
||||||
accountState := pool.Ethereum.StateManager().GetAddrState(tx.Sender())
|
sender := pool.Ethereum.StateManager().procState.GetAccount(tx.Sender())
|
||||||
sender := accountState.Object
|
|
||||||
|
|
||||||
totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(TxFee, TxFeeRat))
|
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
|
// Make sure there's enough in the sender's account. Having insufficient
|
||||||
|
@ -48,8 +48,6 @@ const (
|
|||||||
oGASLIMIT = 0x45
|
oGASLIMIT = 0x45
|
||||||
|
|
||||||
// 0x50 range - 'storage' and execution
|
// 0x50 range - 'storage' and execution
|
||||||
oPUSH = 0x50
|
|
||||||
oPUSH20 = 0x80
|
|
||||||
oPOP = 0x51
|
oPOP = 0x51
|
||||||
oDUP = 0x52
|
oDUP = 0x52
|
||||||
oSWAP = 0x53
|
oSWAP = 0x53
|
||||||
@ -63,14 +61,48 @@ const (
|
|||||||
oPC = 0x5b
|
oPC = 0x5b
|
||||||
oMSIZE = 0x5c
|
oMSIZE = 0x5c
|
||||||
|
|
||||||
// 0x60 range - closures
|
// 0x60 range
|
||||||
oCREATE = 0x60
|
oPUSH1 = 0x60
|
||||||
oCALL = 0x61
|
oPUSH2 = 0x61
|
||||||
oRETURN = 0x62
|
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
|
// 0x70 range - other
|
||||||
oLOG = 0x70 // XXX Unofficial
|
oLOG = 0xfe // XXX Unofficial
|
||||||
oSUICIDE = 0x7f
|
oSUICIDE = 0xff
|
||||||
)
|
)
|
||||||
|
|
||||||
// Since the opcodes aren't all in order we can't use a regular slice
|
// 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",
|
oGASLIMIT: "GASLIMIT",
|
||||||
|
|
||||||
// 0x50 range - 'storage' and execution
|
// 0x50 range - 'storage' and execution
|
||||||
oPUSH: "PUSH",
|
|
||||||
oPOP: "POP",
|
|
||||||
oDUP: "DUP",
|
oDUP: "DUP",
|
||||||
oSWAP: "SWAP",
|
oSWAP: "SWAP",
|
||||||
oMLOAD: "MLOAD",
|
oMLOAD: "MLOAD",
|
||||||
@ -133,7 +163,41 @@ var opCodeToString = map[OpCode]string{
|
|||||||
oPC: "PC",
|
oPC: "PC",
|
||||||
oMSIZE: "MSIZE",
|
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",
|
oCREATE: "CREATE",
|
||||||
oCALL: "CALL",
|
oCALL: "CALL",
|
||||||
oRETURN: "RETURN",
|
oRETURN: "RETURN",
|
||||||
@ -193,10 +257,6 @@ var OpCodes = map[string]byte{
|
|||||||
"GASLIMIT": 0x45,
|
"GASLIMIT": 0x45,
|
||||||
|
|
||||||
// 0x50 range - 'storage' and execution
|
// 0x50 range - 'storage' and execution
|
||||||
"PUSH": 0x50,
|
|
||||||
|
|
||||||
"PUSH20": 0x80,
|
|
||||||
|
|
||||||
"POP": 0x51,
|
"POP": 0x51,
|
||||||
"DUP": 0x52,
|
"DUP": 0x52,
|
||||||
"SWAP": 0x53,
|
"SWAP": 0x53,
|
||||||
@ -210,13 +270,47 @@ var OpCodes = map[string]byte{
|
|||||||
"PC": 0x5b,
|
"PC": 0x5b,
|
||||||
"MSIZE": 0x5c,
|
"MSIZE": 0x5c,
|
||||||
|
|
||||||
// 0x60 range - closures
|
// 0x70 range - 'push'
|
||||||
"CREATE": 0x60,
|
"PUSH1": 0x60,
|
||||||
"CALL": 0x61,
|
"PUSH2": 0x61,
|
||||||
"RETURN": 0x62,
|
"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
|
// 0x70 range - other
|
||||||
"LOG": 0x70,
|
"LOG": 0xfe,
|
||||||
"SUICIDE": 0x7f,
|
"SUICIDE": 0x7f,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ type RuntimeVars struct {
|
|||||||
Time int64
|
Time int64
|
||||||
Diff *big.Int
|
Diff *big.Int
|
||||||
TxData []string
|
TxData []string
|
||||||
|
Value *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVm(state *State, stateManager *StateManager, vars RuntimeVars) *Vm {
|
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 {
|
if ethutil.Config.Debug {
|
||||||
ethutil.Config.Log.Debugf("# op\n")
|
ethutil.Config.Log.Debugf("# op\n")
|
||||||
}
|
}
|
||||||
|
fmt.Println(closure.Script)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// The base for all big integer arithmetic
|
// 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)
|
val := closure.Get(pc)
|
||||||
// Get the opcode (it must be an opcode!)
|
// Get the opcode (it must be an opcode!)
|
||||||
op := OpCode(val.Uint())
|
op := OpCode(val.Uint())
|
||||||
/*
|
if ethutil.Config.Debug {
|
||||||
if ethutil.Config.Debug {
|
ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String())
|
||||||
ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String())
|
}
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
gas := new(big.Int)
|
gas := new(big.Int)
|
||||||
useGas := func(amount *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:
|
case oADDRESS:
|
||||||
stack.Push(ethutil.BigD(closure.Object().Address()))
|
stack.Push(ethutil.BigD(closure.Object().Address()))
|
||||||
case oBALANCE:
|
case oBALANCE:
|
||||||
stack.Push(closure.Value)
|
stack.Push(closure.object.Amount)
|
||||||
case oORIGIN:
|
case oORIGIN:
|
||||||
stack.Push(ethutil.BigD(vm.vars.Origin))
|
stack.Push(ethutil.BigD(vm.vars.Origin))
|
||||||
case oCALLER:
|
case oCALLER:
|
||||||
stack.Push(ethutil.BigD(closure.Callee().Address()))
|
stack.Push(ethutil.BigD(closure.Callee().Address()))
|
||||||
case oCALLVALUE:
|
case oCALLVALUE:
|
||||||
// FIXME: Original value of the call, not the current value
|
stack.Push(vm.vars.Value)
|
||||||
stack.Push(closure.Value)
|
|
||||||
case oCALLDATALOAD:
|
case oCALLDATALOAD:
|
||||||
require(1)
|
require(1)
|
||||||
offset := stack.Pop().Int64()
|
offset := stack.Pop().Int64()
|
||||||
@ -352,27 +351,17 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
|||||||
// TODO
|
// TODO
|
||||||
stack.Push(big.NewInt(0))
|
stack.Push(big.NewInt(0))
|
||||||
|
|
||||||
// 0x50 range
|
// 0x50 range
|
||||||
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:
|
||||||
|
a := big.NewInt(int64(op) - int64(oPUSH1) + 1)
|
||||||
pc.Add(pc, ethutil.Big1)
|
pc.Add(pc, ethutil.Big1)
|
||||||
data := closure.Gets(pc, big.NewInt(32))
|
data := closure.Gets(pc, a)
|
||||||
val := ethutil.BigD(data.Bytes())
|
val := ethutil.BigD(data.Bytes())
|
||||||
|
|
||||||
// Push value to stack
|
// Push value to stack
|
||||||
stack.Push(val)
|
stack.Push(val)
|
||||||
|
pc.Add(pc, a.Sub(a, big.NewInt(1)))
|
||||||
pc.Add(pc, big.NewInt(31))
|
|
||||||
step++
|
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:
|
case oPOP:
|
||||||
require(1)
|
require(1)
|
||||||
stack.Pop()
|
stack.Pop()
|
||||||
@ -406,21 +395,23 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
|||||||
case oSSTORE:
|
case oSSTORE:
|
||||||
require(2)
|
require(2)
|
||||||
val, loc := stack.Popn()
|
val, loc := stack.Popn()
|
||||||
closure.SetMem(loc, ethutil.NewValue(val))
|
closure.SetStorage(loc, ethutil.NewValue(val))
|
||||||
|
|
||||||
// Add the change to manifest
|
// 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:
|
case oJUMP:
|
||||||
require(1)
|
require(1)
|
||||||
pc = stack.Pop()
|
pc = stack.Pop()
|
||||||
// Reduce pc by one because of the increment that's at the end of this for loop
|
// 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:
|
case oJUMPI:
|
||||||
require(2)
|
require(2)
|
||||||
cond, pos := stack.Popn()
|
cond, pos := stack.Popn()
|
||||||
if cond.Cmp(ethutil.BigTrue) == 0 {
|
if cond.Cmp(ethutil.BigTrue) == 0 {
|
||||||
pc = pos
|
pc = pos
|
||||||
pc.Sub(pc, ethutil.Big1)
|
//pc.Sub(pc, ethutil.Big1)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
case oPC:
|
case oPC:
|
||||||
stack.Push(pc)
|
stack.Push(pc)
|
||||||
@ -449,8 +440,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
|||||||
contract.initScript,
|
contract.initScript,
|
||||||
vm.state,
|
vm.state,
|
||||||
gas,
|
gas,
|
||||||
closure.Price,
|
closure.Price)
|
||||||
value)
|
|
||||||
// Call the closure and set the return value as
|
// Call the closure and set the return value as
|
||||||
// main script.
|
// main script.
|
||||||
closure.Script, err = closure.Call(vm, nil, hook)
|
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
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the arguments from the memory
|
// Get the arguments from the memory
|
||||||
args := mem.Get(inOffset.Int64(), inSize.Int64())
|
args := mem.Get(inOffset.Int64(), inSize.Int64())
|
||||||
|
|
||||||
// Fetch the contract which will serve as the closure body
|
// Fetch the contract which will serve as the closure body
|
||||||
contract := vm.state.GetContract(addr.Bytes())
|
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)
|
gas = new(big.Int).Set(closure.Gas)
|
||||||
}
|
}
|
||||||
closure.Gas.Sub(closure.Gas, gas)
|
closure.Gas.Sub(closure.Gas, gas)
|
||||||
|
|
||||||
|
// Add the value to the state object
|
||||||
|
contract.AddAmount(value)
|
||||||
|
|
||||||
// Create a new callable closure
|
// 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)
|
// Executer the closure and get the return value (if any)
|
||||||
ret, err := closure.Call(vm, args, hook)
|
ret, err := closure.Call(vm, args, hook)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -500,10 +496,10 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
|||||||
//contract.State().Reset()
|
//contract.State().Reset()
|
||||||
} else {
|
} else {
|
||||||
stack.Push(ethutil.BigTrue)
|
stack.Push(ethutil.BigTrue)
|
||||||
// Notify of the changes
|
|
||||||
vm.stateManager.manifest.AddObjectChange(contract)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vm.state.SetStateObject(contract)
|
||||||
|
|
||||||
mem.Set(retOffset.Int64(), retSize.Int64(), ret)
|
mem.Set(retOffset.Int64(), retSize.Int64(), ret)
|
||||||
} else {
|
} else {
|
||||||
ethutil.Config.Log.Debugf("Contract %x not found\n", addr.Bytes())
|
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 := vm.state.GetAccount(stack.Pop().Bytes())
|
||||||
receiver.AddAmount(closure.object.Amount)
|
receiver.AddAmount(closure.object.Amount)
|
||||||
|
vm.state.SetStateObject(receiver)
|
||||||
vm.stateManager.manifest.AddObjectChange(receiver)
|
|
||||||
|
|
||||||
closure.object.state.Purge()
|
closure.object.state.Purge()
|
||||||
|
|
||||||
|
@ -11,71 +11,6 @@ import (
|
|||||||
"testing"
|
"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) {
|
func TestRun4(t *testing.T) {
|
||||||
ethutil.ReadConfig("")
|
ethutil.ReadConfig("")
|
||||||
|
|
||||||
@ -86,7 +21,7 @@ func TestRun4(t *testing.T) {
|
|||||||
int32 a = 10
|
int32 a = 10
|
||||||
int32 b = 20
|
int32 b = 20
|
||||||
if a > b {
|
if a > b {
|
||||||
int32 c = this.Caller()
|
int32 c = this.caller()
|
||||||
}
|
}
|
||||||
Exit()
|
Exit()
|
||||||
`), false)
|
`), false)
|
||||||
@ -98,21 +33,21 @@ func TestRun4(t *testing.T) {
|
|||||||
|
|
||||||
callerScript, err := mutan.Compile(strings.NewReader(`
|
callerScript, err := mutan.Compile(strings.NewReader(`
|
||||||
// Check if there's any cash in the initial store
|
// Check if there's any cash in the initial store
|
||||||
if store[1000] == 0 {
|
if this.store[1000] == 0 {
|
||||||
store[1000] = 10^20
|
this.store[1000] = 10^20
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
store[1001] = this.Value() * 20
|
this.store[1001] = this.value() * 20
|
||||||
store[this.Origin()] = store[this.Origin()] + 1000
|
this.store[this.origin()] = this.store[this.origin()] + 1000
|
||||||
|
|
||||||
if store[1001] > 20 {
|
if this.store[1001] > 20 {
|
||||||
store[1001] = 10^50
|
this.store[1001] = 10^50
|
||||||
}
|
}
|
||||||
|
|
||||||
int8 ret = 0
|
int8 ret = 0
|
||||||
int8 arg = 10
|
int8 arg = 10
|
||||||
Call(0xe6a12555fad1fb6eaaaed69001a87313d1fd7b54, 0, 100, arg, ret)
|
call(0xe6a12555fad1fb6eaaaed69001a87313d1fd7b54, 0, 100, arg, ret)
|
||||||
|
|
||||||
big t
|
big t
|
||||||
for int8 i = 0; i < 10; i++ {
|
for int8 i = 0; i < 10; i++ {
|
||||||
@ -142,7 +77,7 @@ func TestRun4(t *testing.T) {
|
|||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
fmt.Println("account.Amount =", account.Amount)
|
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{
|
vm := NewVm(state, nil, RuntimeVars{
|
||||||
Origin: account.Address(),
|
Origin: account.Address(),
|
||||||
|
88
ethereum.go
88
ethereum.go
@ -253,7 +253,7 @@ func (s *Ethereum) ReapDeadPeerHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start the ethereum
|
// Start the ethereum
|
||||||
func (s *Ethereum) Start() {
|
func (s *Ethereum) Start(seed bool) {
|
||||||
// Bind to addr and port
|
// Bind to addr and port
|
||||||
ln, err := net.Listen("tcp", ":"+s.Port)
|
ln, err := net.Listen("tcp", ":"+s.Port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -272,47 +272,51 @@ func (s *Ethereum) Start() {
|
|||||||
// Start the reaping processes
|
// Start the reaping processes
|
||||||
go s.ReapDeadPeerHandler()
|
go s.ReapDeadPeerHandler()
|
||||||
|
|
||||||
if ethutil.Config.Seed {
|
if seed {
|
||||||
ethutil.Config.Log.Debugln("Seeding")
|
s.Seed()
|
||||||
// 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))
|
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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,7 +343,9 @@ func (s *Ethereum) Stop() {
|
|||||||
|
|
||||||
close(s.quit)
|
close(s.quit)
|
||||||
|
|
||||||
s.RpcServer.Stop()
|
if s.RpcServer != nil {
|
||||||
|
s.RpcServer.Stop()
|
||||||
|
}
|
||||||
s.txPool.Stop()
|
s.txPool.Stop()
|
||||||
s.stateManager.Stop()
|
s.stateManager.Stop()
|
||||||
|
|
||||||
|
@ -92,7 +92,14 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, in
|
|||||||
hash = ethutil.FromHex(recipient)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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))
|
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
|
tx.Nonce = acc.Nonce
|
||||||
|
lib.stateManager.TransState().SetStateObject(acc)
|
||||||
|
|
||||||
tx.Sign(keyPair.PrivateKey)
|
tx.Sign(keyPair.PrivateKey)
|
||||||
lib.txPool.QueueTransaction(tx)
|
lib.txPool.QueueTransaction(tx)
|
||||||
|
|
||||||
|
@ -4,7 +4,8 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/ethereum/eth-go/ethpub"
|
"github.com/ethereum/eth-go/ethpub"
|
||||||
_ "log"
|
"github.com/ethereum/eth-go/ethutil"
|
||||||
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EthereumApi struct {
|
type EthereumApi struct {
|
||||||
@ -173,7 +174,10 @@ func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
state := p.ethp.GetStateObject(args.Address)
|
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})
|
*reply = NewSuccessRes(GetStorageAtRes{Address: args.Address, Key: args.Key, Value: value})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ func TestCommon(t *testing.T) {
|
|||||||
t.Error("Got", szabo)
|
t.Error("Got", szabo)
|
||||||
}
|
}
|
||||||
|
|
||||||
if vito != "10 Vito" {
|
if vito != "10 Vita" {
|
||||||
t.Error("Got", vito)
|
t.Error("Got", vito)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ type config struct {
|
|||||||
Ver string
|
Ver string
|
||||||
ClientString string
|
ClientString string
|
||||||
Pubkey []byte
|
Pubkey []byte
|
||||||
Seed bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var Config *config
|
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.Log = NewLogger(LogFile|LogStd, LogLevelDebug)
|
||||||
Config.SetClientString("/Ethereum(G)")
|
Config.SetClientString("/Ethereum(G)")
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package ethutil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"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) {
|
func TestEncode(t *testing.T) {
|
||||||
strRes := "\x83dog"
|
strRes := "\x83dog"
|
||||||
bytes := Encode("dog")
|
bytes := Encode("dog")
|
||||||
@ -131,7 +121,10 @@ func TestEncodeDecodeBytes(t *testing.T) {
|
|||||||
|
|
||||||
func TestEncodeZero(t *testing.T) {
|
func TestEncodeZero(t *testing.T) {
|
||||||
b := NewValue(0).Encode()
|
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) {
|
func BenchmarkEncodeDecode(b *testing.B) {
|
||||||
|
Loading…
Reference in New Issue
Block a user