github.com/karalabe/go-ethereum@v0.8.5/xeth/xeth.go (about) 1 package xeth 2 3 /* 4 * eXtended ETHereum 5 */ 6 7 import ( 8 "bytes" 9 "encoding/json" 10 "fmt" 11 12 "github.com/ethereum/go-ethereum/core" 13 "github.com/ethereum/go-ethereum/core/types" 14 "github.com/ethereum/go-ethereum/crypto" 15 "github.com/ethereum/go-ethereum/ethutil" 16 "github.com/ethereum/go-ethereum/event" 17 "github.com/ethereum/go-ethereum/logger" 18 "github.com/ethereum/go-ethereum/miner" 19 "github.com/ethereum/go-ethereum/p2p" 20 "github.com/ethereum/go-ethereum/whisper" 21 ) 22 23 var pipelogger = logger.NewLogger("XETH") 24 25 // to resolve the import cycle 26 type Backend interface { 27 BlockProcessor() *core.BlockProcessor 28 ChainManager() *core.ChainManager 29 TxPool() *core.TxPool 30 PeerCount() int 31 IsListening() bool 32 Peers() []*p2p.Peer 33 KeyManager() *crypto.KeyManager 34 Db() ethutil.Database 35 EventMux() *event.TypeMux 36 Whisper() *whisper.Whisper 37 Miner() *miner.Miner 38 } 39 40 type XEth struct { 41 eth Backend 42 blockProcessor *core.BlockProcessor 43 chainManager *core.ChainManager 44 state *State 45 whisper *Whisper 46 miner *miner.Miner 47 } 48 49 func New(eth Backend) *XEth { 50 xeth := &XEth{ 51 eth: eth, 52 blockProcessor: eth.BlockProcessor(), 53 chainManager: eth.ChainManager(), 54 whisper: NewWhisper(eth.Whisper()), 55 miner: eth.Miner(), 56 } 57 xeth.state = NewState(xeth) 58 59 return xeth 60 } 61 62 func (self *XEth) Backend() Backend { return self.eth } 63 func (self *XEth) State() *State { return self.state } 64 func (self *XEth) Whisper() *Whisper { return self.whisper } 65 func (self *XEth) Miner() *miner.Miner { return self.miner } 66 67 func (self *XEth) BlockByHash(strHash string) *Block { 68 hash := fromHex(strHash) 69 block := self.chainManager.GetBlock(hash) 70 71 return NewBlock(block) 72 } 73 74 func (self *XEth) BlockByNumber(num int32) *Block { 75 if num == -1 { 76 return NewBlock(self.chainManager.CurrentBlock()) 77 } 78 79 return NewBlock(self.chainManager.GetBlockByNumber(uint64(num))) 80 } 81 82 func (self *XEth) Block(v interface{}) *Block { 83 if n, ok := v.(int32); ok { 84 return self.BlockByNumber(n) 85 } else if str, ok := v.(string); ok { 86 return self.BlockByHash(str) 87 } else if f, ok := v.(float64); ok { // Don't ask ... 88 return self.BlockByNumber(int32(f)) 89 } 90 91 return nil 92 } 93 94 func (self *XEth) Accounts() []string { 95 return []string{toHex(self.eth.KeyManager().Address())} 96 } 97 98 func (self *XEth) PeerCount() int { 99 return self.eth.PeerCount() 100 } 101 102 func (self *XEth) IsMining() bool { 103 return self.miner.Mining() 104 } 105 106 func (self *XEth) SetMining(shouldmine bool) bool { 107 ismining := self.miner.Mining() 108 if shouldmine && !ismining { 109 self.miner.Start() 110 } 111 if ismining && !shouldmine { 112 self.miner.Stop() 113 } 114 return self.miner.Mining() 115 } 116 117 func (self *XEth) IsListening() bool { 118 return self.eth.IsListening() 119 } 120 121 func (self *XEth) Coinbase() string { 122 return toHex(self.eth.KeyManager().Address()) 123 } 124 125 func (self *XEth) NumberToHuman(balance string) string { 126 b := ethutil.Big(balance) 127 128 return ethutil.CurrencyToString(b) 129 } 130 131 func (self *XEth) StorageAt(addr, storageAddr string) string { 132 storage := self.State().SafeGet(addr).StorageString(storageAddr) 133 134 return toHex(storage.Bytes()) 135 } 136 137 func (self *XEth) BalanceAt(addr string) string { 138 return self.State().SafeGet(addr).Balance().String() 139 } 140 141 func (self *XEth) TxCountAt(address string) int { 142 return int(self.State().SafeGet(address).Nonce()) 143 } 144 145 func (self *XEth) CodeAt(address string) string { 146 return toHex(self.State().SafeGet(address).Code()) 147 } 148 149 func (self *XEth) IsContract(address string) bool { 150 return len(self.State().SafeGet(address).Code()) > 0 151 } 152 153 func (self *XEth) SecretToAddress(key string) string { 154 pair, err := crypto.NewKeyPairFromSec(fromHex(key)) 155 if err != nil { 156 return "" 157 } 158 159 return toHex(pair.Address()) 160 } 161 162 func (self *XEth) Execute(addr, value, gas, price, data string) (string, error) { 163 return "", nil 164 } 165 166 type KeyVal struct { 167 Key string `json:"key"` 168 Value string `json:"value"` 169 } 170 171 func (self *XEth) EachStorage(addr string) string { 172 var values []KeyVal 173 object := self.State().SafeGet(addr) 174 it := object.Trie().Iterator() 175 for it.Next() { 176 values = append(values, KeyVal{toHex(it.Key), toHex(it.Value)}) 177 } 178 179 valuesJson, err := json.Marshal(values) 180 if err != nil { 181 return "" 182 } 183 184 return string(valuesJson) 185 } 186 187 func (self *XEth) ToAscii(str string) string { 188 padded := ethutil.RightPadBytes([]byte(str), 32) 189 190 return "0x" + toHex(padded) 191 } 192 193 func (self *XEth) FromAscii(str string) string { 194 if ethutil.IsHex(str) { 195 str = str[2:] 196 } 197 198 return string(bytes.Trim(fromHex(str), "\x00")) 199 } 200 201 func (self *XEth) FromNumber(str string) string { 202 if ethutil.IsHex(str) { 203 str = str[2:] 204 } 205 206 return ethutil.BigD(fromHex(str)).String() 207 } 208 209 func (self *XEth) PushTx(encodedTx string) (string, error) { 210 tx := types.NewTransactionFromBytes(fromHex(encodedTx)) 211 err := self.eth.TxPool().Add(tx) 212 if err != nil { 213 return "", err 214 } 215 216 if tx.To() == nil { 217 addr := core.AddressFromMessage(tx) 218 return toHex(addr), nil 219 } 220 return toHex(tx.Hash()), nil 221 } 222 223 func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, error) { 224 if len(gasStr) == 0 { 225 gasStr = "100000" 226 } 227 if len(gasPriceStr) == 0 { 228 gasPriceStr = "1" 229 } 230 231 var ( 232 statedb = self.chainManager.TransState() 233 key = self.eth.KeyManager().KeyPair() 234 from = statedb.GetOrNewStateObject(key.Address()) 235 block = self.chainManager.CurrentBlock() 236 to = statedb.GetOrNewStateObject(fromHex(toStr)) 237 data = fromHex(dataStr) 238 gas = ethutil.Big(gasStr) 239 price = ethutil.Big(gasPriceStr) 240 value = ethutil.Big(valueStr) 241 ) 242 243 msg := types.NewTransactionMessage(fromHex(toStr), value, gas, price, data) 244 msg.Sign(key.PrivateKey) 245 vmenv := core.NewEnv(statedb, self.chainManager, msg, block) 246 247 res, err := vmenv.Call(from, to.Address(), data, gas, price, value) 248 if err != nil { 249 return "", err 250 } 251 252 return toHex(res), nil 253 } 254 255 func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) { 256 var ( 257 to []byte 258 value = ethutil.NewValue(valueStr) 259 gas = ethutil.NewValue(gasStr) 260 price = ethutil.NewValue(gasPriceStr) 261 data []byte 262 key = self.eth.KeyManager().KeyPair() 263 contractCreation bool 264 ) 265 266 data = fromHex(codeStr) 267 to = fromHex(toStr) 268 if len(to) == 0 { 269 contractCreation = true 270 } 271 272 var tx *types.Transaction 273 if contractCreation { 274 tx = types.NewContractCreationTx(value.BigInt(), gas.BigInt(), price.BigInt(), data) 275 } else { 276 tx = types.NewTransactionMessage(to, value.BigInt(), gas.BigInt(), price.BigInt(), data) 277 } 278 279 var err error 280 state := self.eth.ChainManager().TransState() 281 if balance := state.GetBalance(key.Address()); balance.Cmp(tx.Value()) < 0 { 282 return "", fmt.Errorf("insufficient balance. balance=%v tx=%v", balance, tx.Value()) 283 } 284 nonce := state.GetNonce(key.Address()) 285 286 tx.SetNonce(nonce) 287 tx.Sign(key.PrivateKey) 288 289 //fmt.Printf("create tx: %x %v\n", tx.Hash()[:4], tx.Nonce()) 290 291 // Do some pre processing for our "pre" events and hooks 292 block := self.chainManager.NewBlock(key.Address()) 293 coinbase := state.GetOrNewStateObject(key.Address()) 294 coinbase.SetGasPool(block.GasLimit()) 295 self.blockProcessor.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true) 296 297 err = self.eth.TxPool().Add(tx) 298 if err != nil { 299 return "", err 300 } 301 state.SetNonce(key.Address(), nonce+1) 302 303 if types.IsContractAddr(to) { 304 return toHex(core.AddressFromMessage(tx)), nil 305 } 306 307 return toHex(tx.Hash()), nil 308 }