diff options
Diffstat (limited to 'xeth')
-rw-r--r-- | xeth/hexface.go | 93 | ||||
-rw-r--r-- | xeth/js_types.go | 87 | ||||
-rw-r--r-- | xeth/pipe.go | 141 | ||||
-rw-r--r-- | xeth/vm_env.go | 36 | ||||
-rw-r--r-- | xeth/world.go | 9 |
5 files changed, 187 insertions, 179 deletions
diff --git a/xeth/hexface.go b/xeth/hexface.go index 5bf9845d4..6c084f947 100644 --- a/xeth/hexface.go +++ b/xeth/hexface.go @@ -3,10 +3,9 @@ package xeth import ( "bytes" "encoding/json" - "sync/atomic" - "github.com/ethereum/go-ethereum/chain" - "github.com/ethereum/go-ethereum/chain/types" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/state" @@ -16,7 +15,7 @@ type JSXEth struct { *XEth } -func NewJSXEth(eth chain.EthManager) *JSXEth { +func NewJSXEth(eth core.EthManager) *JSXEth { return &JSXEth{New(eth)} } @@ -29,7 +28,7 @@ func (self *JSXEth) BlockByHash(strHash string) *JSBlock { func (self *JSXEth) BlockByNumber(num int32) *JSBlock { if num == -1 { - return NewJSBlock(self.obj.ChainManager().CurrentBlock) + return NewJSBlock(self.obj.ChainManager().CurrentBlock()) } return NewJSBlock(self.obj.ChainManager().GetBlockByNumber(uint64(num))) @@ -63,12 +62,8 @@ func (self *JSXEth) PeerCount() int { func (self *JSXEth) Peers() []JSPeer { var peers []JSPeer - for peer := self.obj.Peers().Front(); peer != nil; peer = peer.Next() { - p := peer.Value.(chain.Peer) - // we only want connected peers - if atomic.LoadInt32(p.Connected()) != 0 { - peers = append(peers, *NewJSPeer(p)) - } + for _, peer := range self.obj.Peers() { + peers = append(peers, *NewJSPeer(peer)) } return peers @@ -178,39 +173,13 @@ func (self *JSXEth) FromNumber(str string) string { return ethutil.BigD(ethutil.Hex2Bytes(str)).String() } -func (self *JSXEth) Transact(key, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (*JSReceipt, error) { - var hash []byte - var contractCreation bool - if len(toStr) == 0 { - contractCreation = true - } else { - // Check if an address is stored by this address - addr := self.World().Config().Get("NameReg").StorageString(toStr).Bytes() - if len(addr) > 0 { - hash = addr - } else { - hash = ethutil.Hex2Bytes(toStr) - } - } - - var keyPair *crypto.KeyPair - var err error - if ethutil.IsHex(key) { - keyPair, err = crypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(key[2:]))) - } else { - keyPair, err = crypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(key))) - } - - if err != nil { - return nil, err - } - +func (self *JSXEth) Transact(key, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) { var ( - value = ethutil.Big(valueStr) - gas = ethutil.Big(gasStr) - gasPrice = ethutil.Big(gasPriceStr) + to []byte + value = ethutil.NewValue(valueStr) + gas = ethutil.NewValue(gasStr) + gasPrice = ethutil.NewValue(gasPriceStr) data []byte - tx *types.Transaction ) if ethutil.IsHex(codeStr) { @@ -219,31 +188,43 @@ func (self *JSXEth) Transact(key, toStr, valueStr, gasStr, gasPriceStr, codeStr data = ethutil.Hex2Bytes(codeStr) } - if contractCreation { - tx = types.NewContractCreationTx(value, gas, gasPrice, data) + if ethutil.IsHex(toStr) { + to = ethutil.Hex2Bytes(toStr[2:]) } else { - tx = types.NewTransactionMessage(hash, value, gas, gasPrice, data) + to = ethutil.Hex2Bytes(toStr) } - acc := self.obj.BlockManager().TransState().GetOrNewStateObject(keyPair.Address()) - tx.Nonce = acc.Nonce - acc.Nonce += 1 - self.obj.BlockManager().TransState().UpdateStateObject(acc) + var keyPair *crypto.KeyPair + var err error + if ethutil.IsHex(key) { + keyPair, err = crypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(key[2:]))) + } else { + keyPair, err = crypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(key))) + } - tx.Sign(keyPair.PrivateKey) - self.obj.TxPool().QueueTransaction(tx) + if err != nil { + return "", err + } - if contractCreation { - pipelogger.Infof("Contract addr %x", tx.CreationAddress(self.World().State())) + tx, err := self.XEth.Transact(keyPair, to, value, gas, gasPrice, data) + if err != nil { + return "", err + } + if types.IsContractAddr(to) { + return ethutil.Bytes2Hex(core.AddressFromMessage(tx)), nil } - return NewJSReciept(contractCreation, tx.CreationAddress(self.World().State()), tx.Hash(), keyPair.Address()), nil + return ethutil.Bytes2Hex(tx.Hash()), nil } func (self *JSXEth) PushTx(txStr string) (*JSReceipt, error) { tx := types.NewTransactionFromBytes(ethutil.Hex2Bytes(txStr)) - self.obj.TxPool().QueueTransaction(tx) - return NewJSReciept(tx.CreatesContract(), tx.CreationAddress(self.World().State()), tx.Hash(), tx.Sender()), nil + err := self.obj.TxPool().Add(tx) + if err != nil { + return nil, err + } + + return NewJSReciept(core.MessageCreatesContract(tx), core.AddressFromMessage(tx), tx.Hash(), tx.From()), nil } func (self *JSXEth) CompileMutan(code string) string { diff --git a/xeth/js_types.go b/xeth/js_types.go index cba674416..04018f6a5 100644 --- a/xeth/js_types.go +++ b/xeth/js_types.go @@ -1,14 +1,13 @@ package xeth import ( - "fmt" - "strconv" "strings" - "github.com/ethereum/go-ethereum/chain" - "github.com/ethereum/go-ethereum/chain/types" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/state" ) @@ -95,23 +94,23 @@ type JSTransaction struct { Confirmations int `json:"confirmations"` } -func NewJSTx(tx *types.Transaction, state *state.State) *JSTransaction { +func NewJSTx(tx *types.Transaction, state *state.StateDB) *JSTransaction { hash := ethutil.Bytes2Hex(tx.Hash()) - receiver := ethutil.Bytes2Hex(tx.Recipient) + receiver := ethutil.Bytes2Hex(tx.To()) if receiver == "0000000000000000000000000000000000000000" { - receiver = ethutil.Bytes2Hex(tx.CreationAddress(state)) + receiver = ethutil.Bytes2Hex(core.AddressFromMessage(tx)) } - sender := ethutil.Bytes2Hex(tx.Sender()) - createsContract := tx.CreatesContract() + sender := ethutil.Bytes2Hex(tx.From()) + createsContract := core.MessageCreatesContract(tx) var data string - if tx.CreatesContract() { - data = strings.Join(chain.Disassemble(tx.Data), "\n") + if createsContract { + data = strings.Join(core.Disassemble(tx.Data()), "\n") } else { - data = ethutil.Bytes2Hex(tx.Data) + data = ethutil.Bytes2Hex(tx.Data()) } - return &JSTransaction{ref: tx, Hash: hash, Value: ethutil.CurrencyToString(tx.Value), Address: receiver, Contract: tx.CreatesContract(), Gas: tx.Gas.String(), GasPrice: tx.GasPrice.String(), Data: data, Sender: sender, CreatesContract: createsContract, RawData: ethutil.Bytes2Hex(tx.Data)} + return &JSTransaction{ref: tx, Hash: hash, Value: ethutil.CurrencyToString(tx.Value()), Address: receiver, Contract: createsContract, Gas: tx.Gas().String(), GasPrice: tx.GasPrice().String(), Data: data, Sender: sender, CreatesContract: createsContract, RawData: ethutil.Bytes2Hex(tx.Data())} } func (self *JSTransaction) ToString() string { @@ -155,38 +154,36 @@ func NewPReciept(contractCreation bool, creationAddress, hash, address []byte) * // Peer interface exposed to QML type JSPeer struct { - ref *chain.Peer - Inbound bool `json:"isInbound"` - LastSend int64 `json:"lastSend"` - LastPong int64 `json:"lastPong"` - Ip string `json:"ip"` - Port int `json:"port"` - Version string `json:"version"` - LastResponse string `json:"lastResponse"` - Latency string `json:"latency"` - Caps string `json:"caps"` -} - -func NewJSPeer(peer chain.Peer) *JSPeer { - if peer == nil { - return nil - } - - var ip []string - for _, i := range peer.Host() { - ip = append(ip, strconv.Itoa(int(i))) - } - ipAddress := strings.Join(ip, ".") - - var caps []string - capsIt := peer.Caps().NewIterator() - for capsIt.Next() { - cap := capsIt.Value().Get(0).Str() - ver := capsIt.Value().Get(1).Uint() - caps = append(caps, fmt.Sprintf("%s/%d", cap, ver)) - } - - return &JSPeer{ref: &peer, Inbound: peer.Inbound(), LastSend: peer.LastSend().Unix(), LastPong: peer.LastPong(), Version: peer.Version(), Ip: ipAddress, Port: int(peer.Port()), Latency: peer.PingTime(), Caps: "[" + strings.Join(caps, ", ") + "]"} + ref *p2p.Peer + // Inbound bool `json:"isInbound"` + // LastSend int64 `json:"lastSend"` + // LastPong int64 `json:"lastPong"` + // Ip string `json:"ip"` + // Port int `json:"port"` + // Version string `json:"version"` + // LastResponse string `json:"lastResponse"` + // Latency string `json:"latency"` + // Caps string `json:"caps"` +} + +func NewJSPeer(peer *p2p.Peer) *JSPeer { + + // var ip []string + // for _, i := range peer.Host() { + // ip = append(ip, strconv.Itoa(int(i))) + // } + // ipAddress := strings.Join(ip, ".") + + // var caps []string + // capsIt := peer.Caps().NewIterator() + // for capsIt.Next() { + // cap := capsIt.Value().Get(0).Str() + // ver := capsIt.Value().Get(1).Uint() + // caps = append(caps, fmt.Sprintf("%s/%d", cap, ver)) + // } + + return &JSPeer{ref: peer} + // return &JSPeer{ref: &peer, Inbound: peer.Inbound(), LastSend: peer.LastSend().Unix(), LastPong: peer.LastPong(), Version: peer.Version(), Ip: ipAddress, Port: int(peer.Port()), Latency: peer.PingTime(), Caps: "[" + strings.Join(caps, ", ") + "]"} } type JSReceipt struct { diff --git a/xeth/pipe.go b/xeth/pipe.go index 8130ab72e..06820cc86 100644 --- a/xeth/pipe.go +++ b/xeth/pipe.go @@ -5,44 +5,43 @@ package xeth */ import ( - "fmt" - "strings" - - "github.com/ethereum/go-ethereum/chain" - "github.com/ethereum/go-ethereum/chain/types" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/state" - "github.com/ethereum/go-ethereum/vm" ) var pipelogger = logger.NewLogger("XETH") type VmVars struct { - State *state.State + State *state.StateDB } type XEth struct { - obj chain.EthManager - blockManager *chain.BlockManager - blockChain *chain.ChainManager + obj core.EthManager + blockManager *core.BlockManager + chainManager *core.ChainManager world *World Vm VmVars } -func New(obj chain.EthManager) *XEth { +func New(obj core.EthManager) *XEth { pipe := &XEth{ obj: obj, blockManager: obj.BlockManager(), - blockChain: obj.ChainManager(), + chainManager: obj.ChainManager(), } pipe.world = NewWorld(pipe) return pipe } +/* + * State / Account accessors + */ func (self *XEth) Balance(addr []byte) *ethutil.Value { return ethutil.NewValue(self.World().safeGet(addr).Balance) } @@ -51,36 +50,19 @@ func (self *XEth) Nonce(addr []byte) uint64 { return self.World().safeGet(addr).Nonce } -func (self *XEth) Execute(addr []byte, data []byte, value, gas, price *ethutil.Value) ([]byte, error) { - return self.ExecuteObject(&Object{self.World().safeGet(addr)}, data, value, gas, price) -} - -func (self *XEth) ExecuteObject(object *Object, data []byte, value, gas, price *ethutil.Value) ([]byte, error) { - var ( - initiator = state.NewStateObject(self.obj.KeyManager().KeyPair().Address()) - block = self.blockChain.CurrentBlock - ) - - self.Vm.State = self.World().State().Copy() - - evm := vm.New(NewEnv(self.Vm.State, block, value.BigInt(), initiator.Address()), vm.Type(ethutil.Config.VmType)) - - msg := vm.NewExecution(evm, object.Address(), data, gas.BigInt(), price.BigInt(), value.BigInt()) - ret, err := msg.Exec(object.Address(), initiator) - - fmt.Println("returned from call", ret, err) - - return ret, err -} - func (self *XEth) Block(hash []byte) *types.Block { - return self.blockChain.GetBlock(hash) + return self.chainManager.GetBlock(hash) } func (self *XEth) Storage(addr, storageAddr []byte) *ethutil.Value { return self.World().safeGet(addr).GetStorage(ethutil.BigD(storageAddr)) } +func (self *XEth) Exists(addr []byte) bool { + return self.World().Get(addr) != nil +} + +// Converts the given private key to an address func (self *XEth) ToAddress(priv []byte) []byte { pair, err := crypto.NewKeyPairFromSec(priv) if err != nil { @@ -90,11 +72,29 @@ func (self *XEth) ToAddress(priv []byte) []byte { return pair.Address() } -func (self *XEth) Exists(addr []byte) bool { - return self.World().Get(addr) != nil +/* + * Execution helpers + */ +func (self *XEth) Execute(addr []byte, data []byte, value, gas, price *ethutil.Value) ([]byte, error) { + return self.ExecuteObject(&Object{self.World().safeGet(addr)}, data, value, gas, price) } -func (self *XEth) TransactString(key *crypto.KeyPair, rec string, value, gas, price *ethutil.Value, data []byte) ([]byte, error) { +func (self *XEth) ExecuteObject(object *Object, data []byte, value, gas, price *ethutil.Value) ([]byte, error) { + var ( + initiator = state.NewStateObject(self.obj.KeyManager().KeyPair().Address()) + block = self.chainManager.CurrentBlock() + ) + + self.Vm.State = self.World().State().Copy() + + vmenv := NewEnv(self.Vm.State, block, value.BigInt(), initiator.Address()) + return vmenv.Call(initiator, object.Address(), data, gas.BigInt(), price.BigInt(), value.BigInt()) +} + +/* + * Transactional methods + */ +func (self *XEth) TransactString(key *crypto.KeyPair, rec string, value, gas, price *ethutil.Value, data []byte) (*types.Transaction, error) { // Check if an address is stored by this address var hash []byte addr := self.World().Config().Get("NameReg").StorageString(rec).Bytes() @@ -109,57 +109,62 @@ func (self *XEth) TransactString(key *crypto.KeyPair, rec string, value, gas, pr return self.Transact(key, hash, value, gas, price, data) } -func (self *XEth) Transact(key *crypto.KeyPair, rec []byte, value, gas, price *ethutil.Value, data []byte) ([]byte, error) { +func (self *XEth) Transact(key *crypto.KeyPair, to []byte, value, gas, price *ethutil.Value, data []byte) (*types.Transaction, error) { var hash []byte var contractCreation bool - if rec == nil { + if types.IsContractAddr(to) { contractCreation = true + } else { + // Check if an address is stored by this address + addr := self.World().Config().Get("NameReg").Storage(to).Bytes() + if len(addr) > 0 { + hash = addr + } else { + hash = to + } } var tx *types.Transaction - // Compile and assemble the given data if contractCreation { - script, err := ethutil.Compile(string(data), false) - if err != nil { - return nil, err - } - - tx = types.NewContractCreationTx(value.BigInt(), gas.BigInt(), price.BigInt(), script) + tx = types.NewContractCreationTx(value.BigInt(), gas.BigInt(), price.BigInt(), data) } else { - data := ethutil.StringToByteFunc(string(data), func(s string) (ret []byte) { - slice := strings.Split(s, "\n") - for _, dataItem := range slice { - d := ethutil.FormatData(dataItem) - ret = append(ret, d...) - } - return - }) - tx = types.NewTransactionMessage(hash, value.BigInt(), gas.BigInt(), price.BigInt(), data) } - acc := self.blockManager.TransState().GetOrNewStateObject(key.Address()) - tx.Nonce = acc.Nonce - acc.Nonce += 1 - self.blockManager.TransState().UpdateStateObject(acc) + state := self.chainManager.TransState() + nonce := state.GetNonce(key.Address()) + tx.SetNonce(nonce) tx.Sign(key.PrivateKey) - self.obj.TxPool().QueueTransaction(tx) + + // Do some pre processing for our "pre" events and hooks + block := self.chainManager.NewBlock(key.Address()) + coinbase := state.GetStateObject(key.Address()) + coinbase.SetGasPool(block.GasLimit) + self.blockManager.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true) + + err := self.obj.TxPool().Add(tx) + if err != nil { + return nil, err + } + state.SetNonce(key.Address(), nonce+1) if contractCreation { - addr := tx.CreationAddress(self.World().State()) + addr := core.AddressFromMessage(tx) pipelogger.Infof("Contract addr %x\n", addr) - - return addr, nil } - return tx.Hash(), nil + return tx, nil } func (self *XEth) PushTx(tx *types.Transaction) ([]byte, error) { - self.obj.TxPool().QueueTransaction(tx) - if tx.Recipient == nil { - addr := tx.CreationAddress(self.World().State()) + err := self.obj.TxPool().Add(tx) + if err != nil { + return nil, err + } + + if tx.To() == nil { + addr := core.AddressFromMessage(tx) pipelogger.Infof("Contract addr %x\n", addr) return addr, nil } diff --git a/xeth/vm_env.go b/xeth/vm_env.go index 10575ad79..7fb674a94 100644 --- a/xeth/vm_env.go +++ b/xeth/vm_env.go @@ -2,19 +2,23 @@ package xeth import ( "math/big" - "github.com/ethereum/go-ethereum/chain/types" + + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/vm" ) type VMEnv struct { - state *state.State + state *state.StateDB block *types.Block value *big.Int sender []byte + + depth int } -func NewEnv(state *state.State, block *types.Block, value *big.Int, sender []byte) *VMEnv { +func NewEnv(state *state.StateDB, block *types.Block, value *big.Int, sender []byte) *VMEnv { return &VMEnv{ state: state, block: block, @@ -31,9 +35,31 @@ func (self *VMEnv) Time() int64 { return self.block.Time } func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty } func (self *VMEnv) BlockHash() []byte { return self.block.Hash() } func (self *VMEnv) Value() *big.Int { return self.value } -func (self *VMEnv) State() *state.State { 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) AddLog(*state.Log) {} +func (self *VMEnv) Depth() int { return self.depth } +func (self *VMEnv) SetDepth(i int) { self.depth = i } +func (self *VMEnv) AddLog(log state.Log) { + self.state.AddLog(log) +} func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error { return vm.Transfer(from, to, amount) } + +func (self *VMEnv) vm(addr, data []byte, gas, price, value *big.Int) *core.Execution { + return core.NewExecution(self, addr, data, gas, price, value) +} + +func (self *VMEnv) Call(me vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { + exe := self.vm(addr, data, gas, price, value) + return exe.Call(addr, me) +} +func (self *VMEnv) CallCode(me vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { + exe := self.vm(me.Address(), data, gas, price, value) + return exe.Call(addr, me) +} + +func (self *VMEnv) Create(me vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ClosureRef) { + exe := self.vm(addr, data, gas, price, value) + return exe.Create(me) +} diff --git a/xeth/world.go b/xeth/world.go index 6fb757d67..008a08423 100644 --- a/xeth/world.go +++ b/xeth/world.go @@ -1,8 +1,7 @@ package xeth import ( - "container/list" - + "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/state" ) @@ -22,8 +21,8 @@ func (self *XEth) World() *World { return self.world } -func (self *World) State() *state.State { - return self.pipe.blockManager.CurrentState() +func (self *World) State() *state.StateDB { + return self.pipe.chainManager.State() } func (self *World) Get(addr []byte) *Object { @@ -55,7 +54,7 @@ func (self *World) IsListening() bool { return self.pipe.obj.IsListening() } -func (self *World) Peers() *list.List { +func (self *World) Peers() []*p2p.Peer { return self.pipe.obj.Peers() } |