diff options
Diffstat (limited to 'xeth')
-rw-r--r-- | xeth/config.go | 35 | ||||
-rw-r--r-- | xeth/hexface.go | 255 | ||||
-rw-r--r-- | xeth/js_types.go | 236 | ||||
-rw-r--r-- | xeth/object.go | 26 | ||||
-rw-r--r-- | xeth/pipe.go | 181 | ||||
-rw-r--r-- | xeth/vm_env.go | 65 | ||||
-rw-r--r-- | xeth/world.go | 64 |
7 files changed, 862 insertions, 0 deletions
diff --git a/xeth/config.go b/xeth/config.go new file mode 100644 index 000000000..ad0660d75 --- /dev/null +++ b/xeth/config.go @@ -0,0 +1,35 @@ +package xeth + +import "github.com/ethereum/go-ethereum/ethutil" + +var cnfCtr = ethutil.Hex2Bytes("661005d2720d855f1d9976f88bb10c1a3398c77f") + +type Config struct { + pipe *XEth +} + +func (self *Config) Get(name string) *Object { + configCtrl := self.pipe.World().safeGet(cnfCtr) + var addr []byte + + switch name { + case "NameReg": + addr = []byte{0} + case "DnsReg": + objectAddr := configCtrl.GetStorage(ethutil.BigD([]byte{0})) + domainAddr := (&Object{self.pipe.World().safeGet(objectAddr.Bytes())}).StorageString("DnsReg").Bytes() + return &Object{self.pipe.World().safeGet(domainAddr)} + case "MergeMining": + addr = []byte{4} + default: + addr = ethutil.RightPadBytes([]byte(name), 32) + } + + objectAddr := configCtrl.GetStorage(ethutil.BigD(addr)) + + return &Object{self.pipe.World().safeGet(objectAddr.Bytes())} +} + +func (self *Config) Exist() bool { + return self.pipe.World().Get(cnfCtr) != nil +} diff --git a/xeth/hexface.go b/xeth/hexface.go new file mode 100644 index 000000000..bfd2dddd9 --- /dev/null +++ b/xeth/hexface.go @@ -0,0 +1,255 @@ +package xeth + +import ( + "bytes" + "encoding/json" + "sync/atomic" + + "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" +) + +type JSXEth struct { + *XEth +} + +func NewJSXEth(eth core.EthManager) *JSXEth { + return &JSXEth{New(eth)} +} + +func (self *JSXEth) BlockByHash(strHash string) *JSBlock { + hash := ethutil.Hex2Bytes(strHash) + block := self.obj.ChainManager().GetBlock(hash) + + return NewJSBlock(block) +} + +func (self *JSXEth) BlockByNumber(num int32) *JSBlock { + if num == -1 { + return NewJSBlock(self.obj.ChainManager().CurrentBlock()) + } + + return NewJSBlock(self.obj.ChainManager().GetBlockByNumber(uint64(num))) +} + +func (self *JSXEth) Block(v interface{}) *JSBlock { + if n, ok := v.(int32); ok { + return self.BlockByNumber(n) + } else if str, ok := v.(string); ok { + return self.BlockByHash(str) + } else if f, ok := v.(float64); ok { // Don't ask ... + return self.BlockByNumber(int32(f)) + } + + return nil +} + +func (self *JSXEth) Key() *JSKey { + return NewJSKey(self.obj.KeyManager().KeyPair()) +} + +func (self *JSXEth) StateObject(addr string) *JSObject { + object := &Object{self.World().safeGet(ethutil.Hex2Bytes(addr))} + + return NewJSObject(object) +} + +func (self *JSXEth) PeerCount() int { + return self.obj.PeerCount() +} + +func (self *JSXEth) Peers() []JSPeer { + var peers []JSPeer + for peer := self.obj.Peers().Front(); peer != nil; peer = peer.Next() { + p := peer.Value.(core.Peer) + // we only want connected peers + if atomic.LoadInt32(p.Connected()) != 0 { + peers = append(peers, *NewJSPeer(p)) + } + } + + return peers +} + +func (self *JSXEth) IsMining() bool { + return self.obj.IsMining() +} + +func (self *JSXEth) IsListening() bool { + return self.obj.IsListening() +} + +func (self *JSXEth) CoinBase() string { + return ethutil.Bytes2Hex(self.obj.KeyManager().Address()) +} + +func (self *JSXEth) NumberToHuman(balance string) string { + b := ethutil.Big(balance) + + return ethutil.CurrencyToString(b) +} + +func (self *JSXEth) StorageAt(addr, storageAddr string) string { + storage := self.World().SafeGet(ethutil.Hex2Bytes(addr)).Storage(ethutil.Hex2Bytes(storageAddr)) + + return ethutil.Bytes2Hex(storage.Bytes()) +} + +func (self *JSXEth) BalanceAt(addr string) string { + return self.World().SafeGet(ethutil.Hex2Bytes(addr)).Balance().String() +} + +func (self *JSXEth) TxCountAt(address string) int { + return int(self.World().SafeGet(ethutil.Hex2Bytes(address)).Nonce) +} + +func (self *JSXEth) CodeAt(address string) string { + return ethutil.Bytes2Hex(self.World().SafeGet(ethutil.Hex2Bytes(address)).Code) +} + +func (self *JSXEth) IsContract(address string) bool { + return len(self.World().SafeGet(ethutil.Hex2Bytes(address)).Code) > 0 +} + +func (self *JSXEth) SecretToAddress(key string) string { + pair, err := crypto.NewKeyPairFromSec(ethutil.Hex2Bytes(key)) + if err != nil { + return "" + } + + return ethutil.Bytes2Hex(pair.Address()) +} + +func (self *JSXEth) Execute(addr, value, gas, price, data string) (string, error) { + ret, err := self.ExecuteObject(&Object{ + self.World().safeGet(ethutil.Hex2Bytes(addr))}, + ethutil.Hex2Bytes(data), + ethutil.NewValue(value), + ethutil.NewValue(gas), + ethutil.NewValue(price), + ) + + return ethutil.Bytes2Hex(ret), err +} + +type KeyVal struct { + Key string `json:"key"` + Value string `json:"value"` +} + +func (self *JSXEth) EachStorage(addr string) string { + var values []KeyVal + object := self.World().SafeGet(ethutil.Hex2Bytes(addr)) + object.EachStorage(func(name string, value *ethutil.Value) { + value.Decode() + values = append(values, KeyVal{ethutil.Bytes2Hex([]byte(name)), ethutil.Bytes2Hex(value.Bytes())}) + }) + + valuesJson, err := json.Marshal(values) + if err != nil { + return "" + } + + return string(valuesJson) +} + +func (self *JSXEth) ToAscii(str string) string { + padded := ethutil.RightPadBytes([]byte(str), 32) + + return "0x" + ethutil.Bytes2Hex(padded) +} + +func (self *JSXEth) FromAscii(str string) string { + if ethutil.IsHex(str) { + str = str[2:] + } + + return string(bytes.Trim(ethutil.Hex2Bytes(str), "\x00")) +} + +func (self *JSXEth) FromNumber(str string) string { + if ethutil.IsHex(str) { + str = str[2:] + } + + return ethutil.BigD(ethutil.Hex2Bytes(str)).String() +} + +func (self *JSXEth) Transact(key, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) { + var ( + to []byte + value = ethutil.NewValue(valueStr) + gas = ethutil.NewValue(gasStr) + gasPrice = ethutil.NewValue(gasPriceStr) + data []byte + ) + + if ethutil.IsHex(codeStr) { + data = ethutil.Hex2Bytes(codeStr[2:]) + } else { + data = ethutil.Hex2Bytes(codeStr) + } + + if ethutil.IsHex(toStr) { + to = ethutil.Hex2Bytes(toStr[2:]) + } else { + to = 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 "", err + } + + 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 ethutil.Bytes2Hex(tx.Hash()), nil +} + +func (self *JSXEth) PushTx(txStr string) (*JSReceipt, error) { + tx := types.NewTransactionFromBytes(ethutil.Hex2Bytes(txStr)) + 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 { + data, err := self.XEth.CompileMutan(code) + if err != nil { + return err.Error() + } + + return ethutil.Bytes2Hex(data) +} + +func (self *JSXEth) FindInConfig(str string) string { + return ethutil.Bytes2Hex(self.World().Config().Get(str).Address()) +} + +func ToJSMessages(messages state.Messages) *ethutil.List { + var msgs []JSMessage + for _, m := range messages { + msgs = append(msgs, NewJSMessage(m)) + } + + return ethutil.NewList(msgs) +} diff --git a/xeth/js_types.go b/xeth/js_types.go new file mode 100644 index 000000000..62867d6a9 --- /dev/null +++ b/xeth/js_types.go @@ -0,0 +1,236 @@ +package xeth + +import ( + "fmt" + "strconv" + "strings" + + "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" +) + +// Block interface exposed to QML +type JSBlock struct { + //Transactions string `json:"transactions"` + ref *types.Block + Size string `json:"size"` + Number int `json:"number"` + Hash string `json:"hash"` + Transactions *ethutil.List `json:"transactions"` + Uncles *ethutil.List `json:"uncles"` + Time int64 `json:"time"` + Coinbase string `json:"coinbase"` + Name string `json:"name"` + GasLimit string `json:"gasLimit"` + GasUsed string `json:"gasUsed"` + PrevHash string `json:"prevHash"` + Bloom string `json:"bloom"` + Raw string `json:"raw"` +} + +// Creates a new QML Block from a chain block +func NewJSBlock(block *types.Block) *JSBlock { + if block == nil { + return &JSBlock{} + } + + ptxs := make([]*JSTransaction, len(block.Transactions())) + for i, tx := range block.Transactions() { + ptxs[i] = NewJSTx(tx, block.State()) + } + txlist := ethutil.NewList(ptxs) + + puncles := make([]*JSBlock, len(block.Uncles)) + for i, uncle := range block.Uncles { + puncles[i] = NewJSBlock(uncle) + } + ulist := ethutil.NewList(puncles) + + return &JSBlock{ + ref: block, Size: block.Size().String(), + Number: int(block.Number.Uint64()), GasUsed: block.GasUsed.String(), + GasLimit: block.GasLimit.String(), Hash: ethutil.Bytes2Hex(block.Hash()), + Transactions: txlist, Uncles: ulist, + Time: block.Time, + Coinbase: ethutil.Bytes2Hex(block.Coinbase), + PrevHash: ethutil.Bytes2Hex(block.PrevHash), + Bloom: ethutil.Bytes2Hex(block.LogsBloom), + Raw: block.String(), + } +} + +func (self *JSBlock) ToString() string { + if self.ref != nil { + return self.ref.String() + } + + return "" +} + +func (self *JSBlock) GetTransaction(hash string) *JSTransaction { + tx := self.ref.GetTransaction(ethutil.Hex2Bytes(hash)) + if tx == nil { + return nil + } + + return NewJSTx(tx, self.ref.State()) +} + +type JSTransaction struct { + ref *types.Transaction + + Value string `json:"value"` + Gas string `json:"gas"` + GasPrice string `json:"gasPrice"` + Hash string `json:"hash"` + Address string `json:"address"` + Sender string `json:"sender"` + RawData string `json:"rawData"` + Data string `json:"data"` + Contract bool `json:"isContract"` + CreatesContract bool `json:"createsContract"` + Confirmations int `json:"confirmations"` +} + +func NewJSTx(tx *types.Transaction, state *state.StateDB) *JSTransaction { + hash := ethutil.Bytes2Hex(tx.Hash()) + receiver := ethutil.Bytes2Hex(tx.To()) + if receiver == "0000000000000000000000000000000000000000" { + receiver = ethutil.Bytes2Hex(core.AddressFromMessage(tx)) + } + sender := ethutil.Bytes2Hex(tx.Sender()) + createsContract := core.MessageCreatesContract(tx) + + var data string + if createsContract { + data = strings.Join(core.Disassemble(tx.Data()), "\n") + } else { + data = 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 { + return self.ref.String() +} + +type JSKey struct { + Address string `json:"address"` + PrivateKey string `json:"privateKey"` + PublicKey string `json:"publicKey"` +} + +func NewJSKey(key *crypto.KeyPair) *JSKey { + return &JSKey{ethutil.Bytes2Hex(key.Address()), ethutil.Bytes2Hex(key.PrivateKey), ethutil.Bytes2Hex(key.PublicKey)} +} + +type JSObject struct { + *Object +} + +func NewJSObject(object *Object) *JSObject { + return &JSObject{object} +} + +type PReceipt struct { + CreatedContract bool `json:"createdContract"` + Address string `json:"address"` + Hash string `json:"hash"` + Sender string `json:"sender"` +} + +func NewPReciept(contractCreation bool, creationAddress, hash, address []byte) *PReceipt { + return &PReceipt{ + contractCreation, + ethutil.Bytes2Hex(creationAddress), + ethutil.Bytes2Hex(hash), + ethutil.Bytes2Hex(address), + } +} + +// Peer interface exposed to QML + +type JSPeer struct { + ref *core.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 core.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, ", ") + "]"} +} + +type JSReceipt struct { + CreatedContract bool `json:"createdContract"` + Address string `json:"address"` + Hash string `json:"hash"` + Sender string `json:"sender"` +} + +func NewJSReciept(contractCreation bool, creationAddress, hash, address []byte) *JSReceipt { + return &JSReceipt{ + contractCreation, + ethutil.Bytes2Hex(creationAddress), + ethutil.Bytes2Hex(hash), + ethutil.Bytes2Hex(address), + } +} + +type JSMessage struct { + To string `json:"to"` + From string `json:"from"` + Input string `json:"input"` + Output string `json:"output"` + Path int32 `json:"path"` + Origin string `json:"origin"` + Timestamp int32 `json:"timestamp"` + Coinbase string `json:"coinbase"` + Block string `json:"block"` + Number int32 `json:"number"` + Value string `json:"value"` +} + +func NewJSMessage(message *state.Message) JSMessage { + return JSMessage{ + To: ethutil.Bytes2Hex(message.To), + From: ethutil.Bytes2Hex(message.From), + Input: ethutil.Bytes2Hex(message.Input), + Output: ethutil.Bytes2Hex(message.Output), + Path: int32(message.Path), + Origin: ethutil.Bytes2Hex(message.Origin), + Timestamp: int32(message.Timestamp), + Coinbase: ethutil.Bytes2Hex(message.Origin), + Block: ethutil.Bytes2Hex(message.Block), + Number: int32(message.Number.Int64()), + Value: message.Value.String(), + } +} diff --git a/xeth/object.go b/xeth/object.go new file mode 100644 index 000000000..a4ac41e89 --- /dev/null +++ b/xeth/object.go @@ -0,0 +1,26 @@ +package xeth + +import ( + "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/state" +) + +type Object struct { + *state.StateObject +} + +func (self *Object) StorageString(str string) *ethutil.Value { + if ethutil.IsHex(str) { + return self.Storage(ethutil.Hex2Bytes(str[2:])) + } else { + return self.Storage(ethutil.RightPadBytes([]byte(str), 32)) + } +} + +func (self *Object) StorageValue(addr *ethutil.Value) *ethutil.Value { + return self.Storage(addr.Bytes()) +} + +func (self *Object) Storage(addr []byte) *ethutil.Value { + return self.StateObject.GetStorage(ethutil.BigD(addr)) +} diff --git a/xeth/pipe.go b/xeth/pipe.go new file mode 100644 index 000000000..06820cc86 --- /dev/null +++ b/xeth/pipe.go @@ -0,0 +1,181 @@ +package xeth + +/* + * eXtended ETHereum + */ + +import ( + "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" +) + +var pipelogger = logger.NewLogger("XETH") + +type VmVars struct { + State *state.StateDB +} + +type XEth struct { + obj core.EthManager + blockManager *core.BlockManager + chainManager *core.ChainManager + world *World + + Vm VmVars +} + +func New(obj core.EthManager) *XEth { + pipe := &XEth{ + obj: obj, + blockManager: obj.BlockManager(), + 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) +} + +func (self *XEth) Nonce(addr []byte) uint64 { + return self.World().safeGet(addr).Nonce +} + +func (self *XEth) Block(hash []byte) *types.Block { + 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 { + return nil + } + + return pair.Address() +} + +/* + * 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) 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() + if len(addr) > 0 { + hash = addr + } else if ethutil.IsHex(rec) { + hash = ethutil.Hex2Bytes(rec[2:]) + } else { + hash = ethutil.Hex2Bytes(rec) + } + + return self.Transact(key, hash, value, gas, price, data) +} + +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 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 + if contractCreation { + tx = types.NewContractCreationTx(value.BigInt(), gas.BigInt(), price.BigInt(), data) + } else { + tx = types.NewTransactionMessage(hash, value.BigInt(), gas.BigInt(), price.BigInt(), data) + } + + state := self.chainManager.TransState() + nonce := state.GetNonce(key.Address()) + + tx.SetNonce(nonce) + tx.Sign(key.PrivateKey) + + // 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 := core.AddressFromMessage(tx) + pipelogger.Infof("Contract addr %x\n", addr) + } + + return tx, nil +} + +func (self *XEth) PushTx(tx *types.Transaction) ([]byte, error) { + 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 + } + return tx.Hash(), nil +} + +func (self *XEth) CompileMutan(code string) ([]byte, error) { + data, err := ethutil.Compile(code, false) + if err != nil { + return nil, err + } + + return data, nil +} diff --git a/xeth/vm_env.go b/xeth/vm_env.go new file mode 100644 index 000000000..7fb674a94 --- /dev/null +++ b/xeth/vm_env.go @@ -0,0 +1,65 @@ +package xeth + +import ( + "math/big" + + "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.StateDB + block *types.Block + value *big.Int + sender []byte + + depth int +} + +func NewEnv(state *state.StateDB, block *types.Block, value *big.Int, sender []byte) *VMEnv { + return &VMEnv{ + state: state, + block: block, + value: value, + sender: sender, + } +} + +func (self *VMEnv) Origin() []byte { return self.sender } +func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number } +func (self *VMEnv) PrevHash() []byte { return self.block.PrevHash } +func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase } +func (self *VMEnv) 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.StateDB { return self.state } +func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit } +func (self *VMEnv) Depth() int { return self.depth } +func (self *VMEnv) 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 new file mode 100644 index 000000000..956ef1e15 --- /dev/null +++ b/xeth/world.go @@ -0,0 +1,64 @@ +package xeth + +import ( + "container/list" + + "github.com/ethereum/go-ethereum/state" +) + +type World struct { + pipe *XEth + cfg *Config +} + +func NewWorld(pipe *XEth) *World { + world := &World{pipe, nil} + world.cfg = &Config{pipe} + + return world +} + +func (self *XEth) World() *World { + return self.world +} + +func (self *World) State() *state.StateDB { + return self.pipe.chainManager.State() +} + +func (self *World) Get(addr []byte) *Object { + return &Object{self.State().GetStateObject(addr)} +} + +func (self *World) SafeGet(addr []byte) *Object { + return &Object{self.safeGet(addr)} +} + +func (self *World) safeGet(addr []byte) *state.StateObject { + object := self.State().GetStateObject(addr) + if object == nil { + object = state.NewStateObject(addr) + } + + return object +} + +func (self *World) Coinbase() *state.StateObject { + return nil +} + +func (self *World) IsMining() bool { + return self.pipe.obj.IsMining() +} + +func (self *World) IsListening() bool { + return self.pipe.obj.IsListening() +} + +func (self *World) Peers() *list.List { + return self.pipe.obj.Peers() +} + +func (self *World) Config() *Config { + return self.cfg +} |