pub.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. package ethpub
  2. import (
  3. "bytes"
  4. "encoding/hex"
  5. "encoding/json"
  6. "github.com/ethereum/eth-go/ethchain"
  7. "github.com/ethereum/eth-go/ethlog"
  8. "github.com/ethereum/eth-go/ethutil"
  9. "math/big"
  10. "strings"
  11. "sync/atomic"
  12. )
  13. var logger = ethlog.NewLogger("PUB")
  14. type PEthereum struct {
  15. manager ethchain.EthManager
  16. stateManager *ethchain.StateManager
  17. blockChain *ethchain.BlockChain
  18. txPool *ethchain.TxPool
  19. }
  20. func NewPEthereum(manager ethchain.EthManager) *PEthereum {
  21. return &PEthereum{
  22. manager,
  23. manager.StateManager(),
  24. manager.BlockChain(),
  25. manager.TxPool(),
  26. }
  27. }
  28. func (lib *PEthereum) GetBlock(hexHash string) *PBlock {
  29. hash := ethutil.FromHex(hexHash)
  30. block := lib.blockChain.GetBlock(hash)
  31. return NewPBlock(block)
  32. }
  33. func (lib *PEthereum) GetKey() *PKey {
  34. keyPair := ethutil.GetKeyRing().Get(0)
  35. return NewPKey(keyPair)
  36. }
  37. func (lib *PEthereum) GetStateObject(address string) *PStateObject {
  38. stateObject := lib.stateManager.CurrentState().GetStateObject(ethutil.FromHex(address))
  39. if stateObject != nil {
  40. return NewPStateObject(stateObject)
  41. }
  42. // See GetStorage for explanation on "nil"
  43. return NewPStateObject(nil)
  44. }
  45. func (lib *PEthereum) GetPeerCount() int {
  46. return lib.manager.PeerCount()
  47. }
  48. func (lib *PEthereum) GetPeers() []PPeer {
  49. var peers []PPeer
  50. for peer := lib.manager.Peers().Front(); peer != nil; peer = peer.Next() {
  51. p := peer.Value.(ethchain.Peer)
  52. // we only want connected peers
  53. if atomic.LoadInt32(p.Connected()) != 0 {
  54. peers = append(peers, *NewPPeer(p))
  55. }
  56. }
  57. return peers
  58. }
  59. func (lib *PEthereum) GetIsMining() bool {
  60. return lib.manager.IsMining()
  61. }
  62. func (lib *PEthereum) GetIsListening() bool {
  63. return lib.manager.IsListening()
  64. }
  65. func (lib *PEthereum) GetCoinBase() string {
  66. data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
  67. keyRing := ethutil.NewValueFromBytes(data)
  68. key := keyRing.Get(0).Bytes()
  69. return lib.SecretToAddress(hex.EncodeToString(key))
  70. }
  71. func (lib *PEthereum) GetTransactionsFor(address string, asJson bool) interface{} {
  72. sBlk := lib.manager.BlockChain().LastBlockHash
  73. blk := lib.manager.BlockChain().GetBlock(sBlk)
  74. addr := []byte(ethutil.FromHex(address))
  75. var txs []*PTx
  76. for ; blk != nil; blk = lib.manager.BlockChain().GetBlock(sBlk) {
  77. sBlk = blk.PrevHash
  78. // Loop through all transactions to see if we missed any while being offline
  79. for _, tx := range blk.Transactions() {
  80. if bytes.Compare(tx.Sender(), addr) == 0 || bytes.Compare(tx.Recipient, addr) == 0 {
  81. ptx := NewPTx(tx)
  82. //TODO: somehow move this to NewPTx
  83. ptx.Confirmations = int(lib.manager.BlockChain().LastBlockNumber - blk.BlockInfo().Number)
  84. txs = append(txs, ptx)
  85. }
  86. }
  87. }
  88. if asJson {
  89. txJson, err := json.Marshal(txs)
  90. if err != nil {
  91. return nil
  92. }
  93. return string(txJson)
  94. }
  95. return txs
  96. }
  97. func (lib *PEthereum) GetStorage(address, storageAddress string) string {
  98. return lib.GetStateObject(address).GetStorage(storageAddress)
  99. }
  100. func (lib *PEthereum) GetTxCountAt(address string) int {
  101. return lib.GetStateObject(address).Nonce()
  102. }
  103. func (lib *PEthereum) IsContract(address string) bool {
  104. return lib.GetStateObject(address).IsContract()
  105. }
  106. func (lib *PEthereum) SecretToAddress(key string) string {
  107. pair, err := ethutil.NewKeyPairFromSec(ethutil.FromHex(key))
  108. if err != nil {
  109. return ""
  110. }
  111. return ethutil.Hex(pair.Address())
  112. }
  113. func (lib *PEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) (*PReceipt, error) {
  114. return lib.createTx(key, recipient, valueStr, gasStr, gasPriceStr, dataStr)
  115. }
  116. func (lib *PEthereum) Create(key, valueStr, gasStr, gasPriceStr, script string) (*PReceipt, error) {
  117. return lib.createTx(key, "", valueStr, gasStr, gasPriceStr, script)
  118. }
  119. var namereg = ethutil.FromHex("bb5f186604d057c1c5240ca2ae0f6430138ac010")
  120. func GetAddressFromNameReg(stateManager *ethchain.StateManager, name string) []byte {
  121. recp := new(big.Int).SetBytes([]byte(name))
  122. object := stateManager.CurrentState().GetStateObject(namereg)
  123. if object != nil {
  124. reg := object.GetStorage(recp)
  125. return reg.Bytes()
  126. }
  127. return nil
  128. }
  129. func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, scriptStr string) (*PReceipt, error) {
  130. var hash []byte
  131. var contractCreation bool
  132. if len(recipient) == 0 {
  133. contractCreation = true
  134. } else {
  135. // Check if an address is stored by this address
  136. addr := GetAddressFromNameReg(lib.stateManager, recipient)
  137. if len(addr) > 0 {
  138. hash = addr
  139. } else {
  140. hash = ethutil.FromHex(recipient)
  141. }
  142. }
  143. var keyPair *ethutil.KeyPair
  144. var err error
  145. if key[0:2] == "0x" {
  146. keyPair, err = ethutil.NewKeyPairFromSec([]byte(ethutil.FromHex(key[2:])))
  147. } else {
  148. keyPair, err = ethutil.NewKeyPairFromSec([]byte(ethutil.FromHex(key)))
  149. }
  150. if err != nil {
  151. return nil, err
  152. }
  153. value := ethutil.Big(valueStr)
  154. gas := ethutil.Big(gasStr)
  155. gasPrice := ethutil.Big(gasPriceStr)
  156. var tx *ethchain.Transaction
  157. // Compile and assemble the given data
  158. if contractCreation {
  159. var script []byte
  160. var err error
  161. if ethutil.IsHex(scriptStr) {
  162. script = ethutil.FromHex(scriptStr)
  163. } else {
  164. script, err = ethutil.Compile(scriptStr)
  165. if err != nil {
  166. return nil, err
  167. }
  168. }
  169. tx = ethchain.NewContractCreationTx(value, gas, gasPrice, script)
  170. } else {
  171. data := ethutil.StringToByteFunc(scriptStr, func(s string) (ret []byte) {
  172. slice := strings.Split(s, "\n")
  173. for _, dataItem := range slice {
  174. d := ethutil.FormatData(dataItem)
  175. ret = append(ret, d...)
  176. }
  177. return
  178. })
  179. tx = ethchain.NewTransactionMessage(hash, value, gas, gasPrice, data)
  180. }
  181. acc := lib.stateManager.TransState().GetOrNewStateObject(keyPair.Address())
  182. tx.Nonce = acc.Nonce
  183. acc.Nonce += 1
  184. lib.stateManager.TransState().UpdateStateObject(acc)
  185. tx.Sign(keyPair.PrivateKey)
  186. lib.txPool.QueueTransaction(tx)
  187. if contractCreation {
  188. logger.Infof("Contract addr %x", tx.CreationAddress())
  189. }
  190. return NewPReciept(contractCreation, tx.CreationAddress(), tx.Hash(), keyPair.Address()), nil
  191. }