diff --git a/ethpub/pub.go b/ethpub/pub.go deleted file mode 100644 index 64c08c2f1..000000000 --- a/ethpub/pub.go +++ /dev/null @@ -1,296 +0,0 @@ -package ethpub - -import ( - "bytes" - "encoding/json" - "math/big" - "strconv" - "strings" - "sync/atomic" - - "github.com/ethereum/eth-go/ethchain" - "github.com/ethereum/eth-go/ethcrypto" - "github.com/ethereum/eth-go/ethlog" - "github.com/ethereum/eth-go/ethpipe" - "github.com/ethereum/eth-go/ethstate" - "github.com/ethereum/eth-go/ethutil" -) - -var logger = ethlog.NewLogger("PUB") - -// TODO this has to move elsewhere -var cnfCtr = ethutil.Hex2Bytes("661005d2720d855f1d9976f88bb10c1a3398c77f") - -type helper struct { - sm *ethchain.StateManager -} - -func EthereumConfig(stateManager *ethchain.StateManager) helper { - return helper{stateManager} -} -func (self helper) obj() *ethstate.StateObject { - return self.sm.CurrentState().GetStateObject(cnfCtr) -} - -func (self helper) NameReg() *ethstate.StateObject { - if self.obj() != nil { - addr := self.obj().GetStorage(big.NewInt(0)) - if len(addr.Bytes()) > 0 { - return self.sm.CurrentState().GetStateObject(addr.Bytes()) - } - } - - return nil -} - -// TODO Re-write / refactor -type PEthereum struct { - manager ethchain.EthManager - stateManager *ethchain.StateManager - blockChain *ethchain.BlockChain - txPool *ethchain.TxPool - keyManager *ethcrypto.KeyManager -} - -func New(manager ethchain.EthManager) *PEthereum { - return &PEthereum{ - manager, - manager.StateManager(), - manager.BlockChain(), - manager.TxPool(), - manager.KeyManager(), - } -} - -func (self *PEthereum) LookupDomain(domain string) string { - pipe := ethpipe.New(self.manager) - world := pipe.World() - - if len(domain) > 32 { - domain = string(ethcrypto.Sha3Bin([]byte(domain))) - } - data := world.Config().Get("DnsReg").StorageString(domain).Bytes() - - // Left padded = A record, Right padded = CNAME - if data[0] == 0 { - data = bytes.TrimLeft(data, "\x00") - var ipSlice []string - for _, d := range data { - ipSlice = append(ipSlice, strconv.Itoa(int(d))) - } - - return strings.Join(ipSlice, ".") - } else { - data = bytes.TrimRight(data, "\x00") - - return string(data) - } -} - -func (lib *PEthereum) GetBlock(hexHash string) *PBlock { - hash := ethutil.Hex2Bytes(hexHash) - block := lib.blockChain.GetBlock(hash) - - return NewPBlock(block) -} - -func (lib *PEthereum) GetKey() *PKey { - return NewPKey(lib.keyManager.KeyPair()) -} - -func (lib *PEthereum) GetStateObject(address string) *PStateObject { - stateObject := lib.stateManager.CurrentState().GetStateObject(ethutil.Hex2Bytes(address)) - if stateObject != nil { - return NewPStateObject(stateObject) - } - - // See GetStorage for explanation on "nil" - return NewPStateObject(nil) -} - -func (lib *PEthereum) GetPeerCount() int { - return lib.manager.PeerCount() -} - -func (lib *PEthereum) GetPeers() []PPeer { - var peers []PPeer - for peer := lib.manager.Peers().Front(); peer != nil; peer = peer.Next() { - p := peer.Value.(ethchain.Peer) - // we only want connected peers - if atomic.LoadInt32(p.Connected()) != 0 { - peers = append(peers, *NewPPeer(p)) - } - } - - return peers -} - -func (lib *PEthereum) GetIsMining() bool { - return lib.manager.IsMining() -} - -func (lib *PEthereum) GetIsListening() bool { - return lib.manager.IsListening() -} - -func (lib *PEthereum) GetCoinBase() string { - return ethutil.Bytes2Hex(lib.keyManager.Address()) -} - -func (lib *PEthereum) GetTransactionsFor(address string, asJson bool) interface{} { - sBlk := lib.manager.BlockChain().LastBlockHash - blk := lib.manager.BlockChain().GetBlock(sBlk) - addr := []byte(ethutil.Hex2Bytes(address)) - - var txs []*PTx - - for ; blk != nil; blk = lib.manager.BlockChain().GetBlock(sBlk) { - sBlk = blk.PrevHash - - // Loop through all transactions to see if we missed any while being offline - for _, tx := range blk.Transactions() { - if bytes.Compare(tx.Sender(), addr) == 0 || bytes.Compare(tx.Recipient, addr) == 0 { - ptx := NewPTx(tx) - //TODO: somehow move this to NewPTx - ptx.Confirmations = int(lib.manager.BlockChain().LastBlockNumber - blk.BlockInfo().Number) - txs = append(txs, ptx) - } - } - } - if asJson { - txJson, err := json.Marshal(txs) - if err != nil { - return nil - } - return string(txJson) - } - return txs -} - -func (lib *PEthereum) GetStorage(address, storageAddress string) string { - return lib.GetStateObject(address).GetStorage(storageAddress) -} - -func (lib *PEthereum) GetTxCountAt(address string) int { - return lib.GetStateObject(address).Nonce() -} - -func (lib *PEthereum) IsContract(address string) bool { - return lib.GetStateObject(address).IsContract() -} - -func (lib *PEthereum) SecretToAddress(key string) string { - pair, err := ethcrypto.NewKeyPairFromSec(ethutil.Hex2Bytes(key)) - if err != nil { - return "" - } - - return ethutil.Bytes2Hex(pair.Address()) -} - -func FindAddressInNameReg(stateManager *ethchain.StateManager, name string) []byte { - nameReg := EthereumConfig(stateManager).NameReg() - if nameReg != nil { - addr := ethutil.RightPadBytes([]byte(name), 32) - - reg := nameReg.GetStorage(ethutil.BigD(addr)) - - return reg.Bytes() - } - - return nil -} - -func FindNameInNameReg(stateManager *ethchain.StateManager, addr []byte) string { - nameReg := EthereumConfig(stateManager).NameReg() - if nameReg != nil { - addr = ethutil.LeftPadBytes(addr, 32) - - reg := nameReg.GetStorage(ethutil.BigD(addr)) - - return strings.TrimRight(reg.Str(), "\x00") - } - - return "" -} - -func (lib *PEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) (*PReceipt, error) { - return lib.createTx(key, recipient, valueStr, gasStr, gasPriceStr, dataStr) -} - -func (lib *PEthereum) Create(key, valueStr, gasStr, gasPriceStr, script string) (*PReceipt, error) { - return lib.createTx(key, "", valueStr, gasStr, gasPriceStr, script) -} - -func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, scriptStr string) (*PReceipt, error) { - var hash []byte - var contractCreation bool - if len(recipient) == 0 { - contractCreation = true - } else { - // Check if an address is stored by this address - addr := FindAddressInNameReg(lib.stateManager, recipient) - if len(addr) > 0 { - hash = addr - } else { - hash = ethutil.Hex2Bytes(recipient) - } - } - - var keyPair *ethcrypto.KeyPair - var err error - if ethutil.IsHex(key) { - keyPair, err = ethcrypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(key[2:]))) - } else { - keyPair, err = ethcrypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(key))) - } - - if err != nil { - return nil, err - } - - value := ethutil.Big(valueStr) - gas := ethutil.Big(gasStr) - gasPrice := ethutil.Big(gasPriceStr) - var tx *ethchain.Transaction - // Compile and assemble the given data - if contractCreation { - var script []byte - var err error - if ethutil.IsHex(scriptStr) { - script = ethutil.Hex2Bytes(scriptStr[2:]) - } else { - script, err = ethutil.Compile(scriptStr, false) - if err != nil { - return nil, err - } - } - - tx = ethchain.NewContractCreationTx(value, gas, gasPrice, script) - } else { - data := ethutil.StringToByteFunc(scriptStr, func(s string) (ret []byte) { - slice := strings.Split(s, "\n") - for _, dataItem := range slice { - d := ethutil.FormatData(dataItem) - ret = append(ret, d...) - } - return - }) - - tx = ethchain.NewTransactionMessage(hash, value, gas, gasPrice, data) - } - - acc := lib.stateManager.TransState().GetOrNewStateObject(keyPair.Address()) - tx.Nonce = acc.Nonce - acc.Nonce += 1 - lib.stateManager.TransState().UpdateStateObject(acc) - - tx.Sign(keyPair.PrivateKey) - lib.txPool.QueueTransaction(tx) - - if contractCreation { - logger.Infof("Contract addr %x", tx.CreationAddress()) - } - - return NewPReciept(contractCreation, tx.CreationAddress(), tx.Hash(), keyPair.Address()), nil -} diff --git a/ethpub/types.go b/ethpub/types.go deleted file mode 100644 index 159f7d9a7..000000000 --- a/ethpub/types.go +++ /dev/null @@ -1,273 +0,0 @@ -package ethpub - -import ( - "encoding/json" - "fmt" - "strings" - - "github.com/ethereum/eth-go/ethchain" - "github.com/ethereum/eth-go/ethcrypto" - "github.com/ethereum/eth-go/ethstate" - "github.com/ethereum/eth-go/ethtrie" - "github.com/ethereum/eth-go/ethutil" -) - -// Peer interface exposed to QML - -type PPeer struct { - ref *ethchain.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"` -} - -func NewPPeer(peer ethchain.Peer) *PPeer { - if peer == nil { - return nil - } - - // TODO: There must be something build in to do this? - var ip []string - for _, i := range peer.Host() { - ip = append(ip, fmt.Sprintf("%d", i)) - } - ipAddress := strings.Join(ip, ".") - - return &PPeer{ref: &peer, Inbound: peer.Inbound(), LastSend: peer.LastSend().Unix(), LastPong: peer.LastPong(), Version: peer.Version(), Ip: ipAddress, Port: int(peer.Port()), Latency: peer.PingTime()} -} - -// Block interface exposed to QML -type PBlock struct { - ref *ethchain.Block - Number int `json:"number"` - Hash string `json:"hash"` - Transactions string `json:"transactions"` - Time int64 `json:"time"` - Coinbase string `json:"coinbase"` - Name string `json:"name"` - GasLimit string `json:"gasLimit"` - GasUsed string `json:"gasUsed"` -} - -// Creates a new QML Block from a chain block -func NewPBlock(block *ethchain.Block) *PBlock { - if block == nil { - return nil - } - - var ptxs []PTx - for _, tx := range block.Transactions() { - ptxs = append(ptxs, *NewPTx(tx)) - } - - txJson, err := json.Marshal(ptxs) - if err != nil { - return nil - } - - return &PBlock{ref: block, Number: int(block.Number.Uint64()), GasUsed: block.GasUsed.String(), GasLimit: block.GasLimit.String(), Hash: ethutil.Bytes2Hex(block.Hash()), Transactions: string(txJson), Time: block.Time, Coinbase: ethutil.Bytes2Hex(block.Coinbase)} -} - -func (self *PBlock) ToString() string { - if self.ref != nil { - return self.ref.String() - } - - return "" -} - -func (self *PBlock) GetTransaction(hash string) *PTx { - tx := self.ref.GetTransaction(ethutil.Hex2Bytes(hash)) - if tx == nil { - return nil - } - - return NewPTx(tx) -} - -type PTx struct { - ref *ethchain.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 NewPTx(tx *ethchain.Transaction) *PTx { - hash := ethutil.Bytes2Hex(tx.Hash()) - receiver := ethutil.Bytes2Hex(tx.Recipient) - if receiver == "0000000000000000000000000000000000000000" { - receiver = ethutil.Bytes2Hex(tx.CreationAddress()) - } - sender := ethutil.Bytes2Hex(tx.Sender()) - createsContract := tx.CreatesContract() - - var data string - if tx.CreatesContract() { - data = strings.Join(ethchain.Disassemble(tx.Data), "\n") - } else { - data = ethutil.Bytes2Hex(tx.Data) - } - - return &PTx{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)} -} - -func (self *PTx) ToString() string { - return self.ref.String() -} - -type PKey struct { - Address string `json:"address"` - PrivateKey string `json:"privateKey"` - PublicKey string `json:"publicKey"` -} - -func NewPKey(key *ethcrypto.KeyPair) *PKey { - return &PKey{ethutil.Bytes2Hex(key.Address()), ethutil.Bytes2Hex(key.PrivateKey), ethutil.Bytes2Hex(key.PublicKey)} -} - -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), - } -} - -type PStateObject struct { - object *ethstate.StateObject -} - -func NewPStateObject(object *ethstate.StateObject) *PStateObject { - return &PStateObject{object: object} -} - -func (c *PStateObject) GetStorage(address string) string { - // Because somehow, even if you return nil to QML it - // still has some magical object so we can't rely on - // undefined or null at the QML side - if c.object != nil { - val := c.object.GetStorage(ethutil.Big("0x" + address)) - - return val.BigInt().String() - } - - return "" -} - -func (c *PStateObject) Balance() string { - if c.object != nil { - return c.object.Balance.String() - } - - return "" -} - -func (c *PStateObject) Address() string { - if c.object != nil { - return ethutil.Bytes2Hex(c.object.Address()) - } - - return "" -} - -func (c *PStateObject) Nonce() int { - if c.object != nil { - return int(c.object.Nonce) - } - - return 0 -} - -func (c *PStateObject) Root() string { - if c.object != nil { - return ethutil.Bytes2Hex(ethutil.NewValue(c.object.State.Root()).Bytes()) - } - - return "" -} - -func (c *PStateObject) IsContract() bool { - if c.object != nil { - return len(c.object.Code) > 0 - } - - return false -} - -func (self *PStateObject) EachStorage(cb ethtrie.EachCallback) { - self.object.EachStorage(cb) -} - -type KeyVal struct { - Key string `json:"key"` - Value string `json:"value"` -} - -func (c *PStateObject) StateKeyVal(asJson bool) interface{} { - var values []KeyVal - if c.object != nil { - c.object.EachStorage(func(name string, value *ethutil.Value) { - value.Decode() - values = append(values, KeyVal{ethutil.Bytes2Hex([]byte(name)), ethutil.Bytes2Hex(value.Bytes())}) - }) - } - - if asJson { - valuesJson, err := json.Marshal(values) - if err != nil { - return nil - } - - return string(valuesJson) - } - - return values -} - -func (c *PStateObject) Script() string { - if c.object != nil { - return strings.Join(ethchain.Disassemble(c.object.Code), " ") - } - - return "" -} - -func (c *PStateObject) HexScript() string { - if c.object != nil { - return ethutil.Bytes2Hex(c.object.Code) - } - - return "" -} - -type PStorageState struct { - StateAddress string - Address string - Value string -} - -func NewPStorageState(storageObject *ethstate.StorageState) *PStorageState { - return &PStorageState{ethutil.Bytes2Hex(storageObject.StateAddress), ethutil.Bytes2Hex(storageObject.Address), storageObject.Value.String()} -} diff --git a/ethrpc/packages.go b/ethrpc/packages.go index d307d0314..bd7528415 100644 --- a/ethrpc/packages.go +++ b/ethrpc/packages.go @@ -6,12 +6,12 @@ import ( "math/big" "strings" - "github.com/ethereum/eth-go/ethpub" + "github.com/ethereum/eth-go/ethpipe" "github.com/ethereum/eth-go/ethutil" ) type EthereumApi struct { - ethp *ethpub.PEthereum + pipe *ethpipe.JSPipe } type JsonArgs interface { @@ -73,8 +73,8 @@ func (p *EthereumApi) GetBlock(args *GetBlockArgs, reply *string) error { if err != nil { return err } - // Do something - block := p.ethp.GetBlock(args.Hash) + + block := p.pipe.GetBlockByHash(args.Hash) *reply = NewSuccessRes(block) return nil } @@ -129,7 +129,7 @@ func (p *EthereumApi) Transact(args *NewTxArgs, reply *string) error { if err != nil { return err } - result, _ := p.ethp.Transact(p.ethp.GetKey().PrivateKey, args.Recipient, args.Value, args.Gas, args.GasPrice, args.Body) + result, _ := p.pipe.Transact(p.pipe.GetKey().PrivateKey, args.Recipient, args.Value, args.Gas, args.GasPrice, args.Body) *reply = NewSuccessRes(result) return nil } @@ -139,13 +139,14 @@ func (p *EthereumApi) Create(args *NewTxArgs, reply *string) error { if err != nil { return err } - result, _ := p.ethp.Create(p.ethp.GetKey().PrivateKey, args.Value, args.Gas, args.GasPrice, args.Body) + + result, _ := p.pipe.Transact(p.pipe.GetKey().PrivateKey, "", args.Value, args.Gas, args.GasPrice, args.Body) *reply = NewSuccessRes(result) return nil } func (p *EthereumApi) GetKey(args interface{}, reply *string) error { - *reply = NewSuccessRes(p.ethp.GetKey()) + *reply = NewSuccessRes(p.pipe.GetKey()) return nil } @@ -175,7 +176,8 @@ func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *string) error { if err != nil { return err } - state := p.ethp.GetStateObject(args.Address) + + state := p.pipe.World().SafeGet(ethutil.Hex2Bytes(args.Address)) var hx string if strings.Index(args.Key, "0x") == 0 { @@ -186,8 +188,8 @@ func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *string) error { hx = ethutil.Bytes2Hex(i.Bytes()) } logger.Debugf("GetStorageAt(%s, %s)\n", args.Address, hx) - value := state.GetStorage(hx) - *reply = NewSuccessRes(GetStorageAtRes{Address: args.Address, Key: args.Key, Value: value}) + value := state.Storage(ethutil.Hex2Bytes(hx)) + *reply = NewSuccessRes(GetStorageAtRes{Address: args.Address, Key: args.Key, Value: value.Str()}) return nil } @@ -210,7 +212,7 @@ type GetPeerCountRes struct { } func (p *EthereumApi) GetPeerCount(args *interface{}, reply *string) error { - *reply = NewSuccessRes(GetPeerCountRes{PeerCount: p.ethp.GetPeerCount()}) + *reply = NewSuccessRes(GetPeerCountRes{PeerCount: p.pipe.GetPeerCount()}) return nil } @@ -219,7 +221,7 @@ type GetListeningRes struct { } func (p *EthereumApi) GetIsListening(args *interface{}, reply *string) error { - *reply = NewSuccessRes(GetListeningRes{IsListening: p.ethp.GetIsListening()}) + *reply = NewSuccessRes(GetListeningRes{IsListening: p.pipe.GetIsListening()}) return nil } @@ -228,7 +230,7 @@ type GetCoinbaseRes struct { } func (p *EthereumApi) GetCoinbase(args *interface{}, reply *string) error { - *reply = NewSuccessRes(GetCoinbaseRes{Coinbase: p.ethp.GetCoinBase()}) + *reply = NewSuccessRes(GetCoinbaseRes{Coinbase: p.pipe.GetCoinBase()}) return nil } @@ -237,7 +239,7 @@ type GetMiningRes struct { } func (p *EthereumApi) GetIsMining(args *interface{}, reply *string) error { - *reply = NewSuccessRes(GetMiningRes{IsMining: p.ethp.GetIsMining()}) + *reply = NewSuccessRes(GetMiningRes{IsMining: p.pipe.GetIsMining()}) return nil } @@ -246,7 +248,7 @@ func (p *EthereumApi) GetTxCountAt(args *GetTxCountArgs, reply *string) error { if err != nil { return err } - state := p.ethp.GetTxCountAt(args.Address) + state := p.pipe.GetTxCountAt(args.Address) *reply = NewSuccessRes(GetTxCountRes{Nonce: state}) return nil } @@ -272,8 +274,8 @@ func (p *EthereumApi) GetBalanceAt(args *GetBalanceArgs, reply *string) error { if err != nil { return err } - state := p.ethp.GetStateObject(args.Address) - *reply = NewSuccessRes(BalanceRes{Balance: state.Balance(), Address: args.Address}) + state := p.pipe.World().SafeGet(ethutil.Hex2Bytes(args.Address)) + *reply = NewSuccessRes(BalanceRes{Balance: state.Balance.String(), Address: args.Address}) return nil } diff --git a/ethrpc/server.go b/ethrpc/server.go index d9d6f695b..4abe29aa9 100644 --- a/ethrpc/server.go +++ b/ethrpc/server.go @@ -2,11 +2,12 @@ package ethrpc import ( "fmt" - "github.com/ethereum/eth-go/ethlog" - "github.com/ethereum/eth-go/ethpub" "net" "net/rpc" "net/rpc/jsonrpc" + + "github.com/ethereum/eth-go/ethlog" + "github.com/ethereum/eth-go/ethpipe" ) var logger = ethlog.NewLogger("JSON") @@ -14,7 +15,7 @@ var logger = ethlog.NewLogger("JSON") type JsonRpcServer struct { quit chan bool listener net.Listener - ethp *ethpub.PEthereum + pipe *ethpipe.JSPipe } func (s *JsonRpcServer) exitHandler() { @@ -37,7 +38,7 @@ func (s *JsonRpcServer) Stop() { func (s *JsonRpcServer) Start() { logger.Infoln("Starting JSON-RPC server") go s.exitHandler() - rpc.Register(&EthereumApi{ethp: s.ethp}) + rpc.Register(&EthereumApi{pipe: s.pipe}) rpc.HandleHTTP() for { @@ -51,7 +52,7 @@ func (s *JsonRpcServer) Start() { } } -func NewJsonRpcServer(ethp *ethpub.PEthereum, port int) (*JsonRpcServer, error) { +func NewJsonRpcServer(pipe *ethpipe.JSPipe, port int) (*JsonRpcServer, error) { sport := fmt.Sprintf(":%d", port) l, err := net.Listen("tcp", sport) if err != nil { @@ -61,6 +62,6 @@ func NewJsonRpcServer(ethp *ethpub.PEthereum, port int) (*JsonRpcServer, error) return &JsonRpcServer{ listener: l, quit: make(chan bool), - ethp: ethp, + pipe: pipe, }, nil }