api.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. // Copyright 2015 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package ethreg
  17. import (
  18. "errors"
  19. "math/big"
  20. "github.com/ethereum/go-ethereum/accounts"
  21. "github.com/ethereum/go-ethereum/common"
  22. "github.com/ethereum/go-ethereum/common/compiler"
  23. "github.com/ethereum/go-ethereum/common/registrar"
  24. "github.com/ethereum/go-ethereum/core"
  25. "github.com/ethereum/go-ethereum/core/state"
  26. "github.com/ethereum/go-ethereum/core/types"
  27. "github.com/ethereum/go-ethereum/core/vm"
  28. "github.com/ethereum/go-ethereum/crypto"
  29. "github.com/ethereum/go-ethereum/ethdb"
  30. "github.com/ethereum/go-ethereum/logger"
  31. "github.com/ethereum/go-ethereum/logger/glog"
  32. )
  33. // registryAPIBackend is a backend for an Ethereum Registry.
  34. type registryAPIBackend struct {
  35. config *core.ChainConfig
  36. bc *core.BlockChain
  37. chainDb ethdb.Database
  38. txPool *core.TxPool
  39. am *accounts.Manager
  40. }
  41. // PrivateRegistarAPI offers various functions to access the Ethereum registry.
  42. type PrivateRegistarAPI struct {
  43. config *core.ChainConfig
  44. be *registryAPIBackend
  45. }
  46. // NewPrivateRegistarAPI creates a new PrivateRegistarAPI instance.
  47. func NewPrivateRegistarAPI(config *core.ChainConfig, bc *core.BlockChain, chainDb ethdb.Database, txPool *core.TxPool, am *accounts.Manager) *PrivateRegistarAPI {
  48. return &PrivateRegistarAPI{
  49. config: config,
  50. be: &registryAPIBackend{
  51. config: config,
  52. bc: bc,
  53. chainDb: chainDb,
  54. txPool: txPool,
  55. am: am,
  56. },
  57. }
  58. }
  59. // SetGlobalRegistrar allows clients to set the global registry for the node.
  60. // This method can be used to deploy a new registry. First zero out the current
  61. // address by calling the method with namereg = '0x0' and then call this method
  62. // again with '' as namereg. This will submit a transaction to the network which
  63. // will deploy a new registry on execution. The TX hash is returned. When called
  64. // with namereg '' and the current address is not zero the current global is
  65. // address is returned..
  66. func (api *PrivateRegistarAPI) SetGlobalRegistrar(namereg string, from common.Address) (string, error) {
  67. return registrar.New(api.be).SetGlobalRegistrar(namereg, from)
  68. }
  69. // SetHashReg queries the registry for a hash.
  70. func (api *PrivateRegistarAPI) SetHashReg(hashreg string, from common.Address) (string, error) {
  71. return registrar.New(api.be).SetHashReg(hashreg, from)
  72. }
  73. // SetUrlHint queries the registry for an url.
  74. func (api *PrivateRegistarAPI) SetUrlHint(hashreg string, from common.Address) (string, error) {
  75. return registrar.New(api.be).SetUrlHint(hashreg, from)
  76. }
  77. // SaveInfo stores contract information on the local file system.
  78. func (api *PrivateRegistarAPI) SaveInfo(info *compiler.ContractInfo, filename string) (contenthash common.Hash, err error) {
  79. return compiler.SaveInfo(info, filename)
  80. }
  81. // Register registers a new content hash in the registry.
  82. func (api *PrivateRegistarAPI) Register(sender common.Address, addr common.Address, contentHashHex string) (bool, error) {
  83. block := api.be.bc.CurrentBlock()
  84. state, err := state.New(block.Root(), api.be.chainDb)
  85. if err != nil {
  86. return false, err
  87. }
  88. codeb := state.GetCode(addr)
  89. codeHash := common.BytesToHash(crypto.Keccak256(codeb))
  90. contentHash := common.HexToHash(contentHashHex)
  91. _, err = registrar.New(api.be).SetHashToHash(sender, codeHash, contentHash)
  92. return err == nil, err
  93. }
  94. // RegisterUrl registers a new url in the registry.
  95. func (api *PrivateRegistarAPI) RegisterUrl(sender common.Address, contentHashHex string, url string) (bool, error) {
  96. _, err := registrar.New(api.be).SetUrlToHash(sender, common.HexToHash(contentHashHex), url)
  97. return err == nil, err
  98. }
  99. // callmsg is the message type used for call transations.
  100. type callmsg struct {
  101. from *state.StateObject
  102. to *common.Address
  103. gas, gasPrice *big.Int
  104. value *big.Int
  105. data []byte
  106. }
  107. // accessor boilerplate to implement core.Message
  108. func (m callmsg) From() (common.Address, error) {
  109. return m.from.Address(), nil
  110. }
  111. func (m callmsg) FromFrontier() (common.Address, error) {
  112. return m.from.Address(), nil
  113. }
  114. func (m callmsg) Nonce() uint64 {
  115. return m.from.Nonce()
  116. }
  117. func (m callmsg) To() *common.Address {
  118. return m.to
  119. }
  120. func (m callmsg) GasPrice() *big.Int {
  121. return m.gasPrice
  122. }
  123. func (m callmsg) Gas() *big.Int {
  124. return m.gas
  125. }
  126. func (m callmsg) Value() *big.Int {
  127. return m.value
  128. }
  129. func (m callmsg) Data() []byte {
  130. return m.data
  131. }
  132. // Call forms a transaction from the given arguments and tries to execute it on
  133. // a private VM with a copy of the state. Any changes are therefore only temporary
  134. // and not part of the actual state. This allows for local execution/queries.
  135. func (be *registryAPIBackend) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) {
  136. block := be.bc.CurrentBlock()
  137. statedb, err := state.New(block.Root(), be.chainDb)
  138. if err != nil {
  139. return "", "", err
  140. }
  141. var from *state.StateObject
  142. if len(fromStr) == 0 {
  143. accounts, err := be.am.Accounts()
  144. if err != nil || len(accounts) == 0 {
  145. from = statedb.GetOrNewStateObject(common.Address{})
  146. } else {
  147. from = statedb.GetOrNewStateObject(accounts[0].Address)
  148. }
  149. } else {
  150. from = statedb.GetOrNewStateObject(common.HexToAddress(fromStr))
  151. }
  152. from.SetBalance(common.MaxBig)
  153. msg := callmsg{
  154. from: from,
  155. gas: common.Big(gasStr),
  156. gasPrice: common.Big(gasPriceStr),
  157. value: common.Big(valueStr),
  158. data: common.FromHex(dataStr),
  159. }
  160. if len(toStr) > 0 {
  161. addr := common.HexToAddress(toStr)
  162. msg.to = &addr
  163. }
  164. if msg.gas.Cmp(big.NewInt(0)) == 0 {
  165. msg.gas = big.NewInt(50000000)
  166. }
  167. if msg.gasPrice.Cmp(big.NewInt(0)) == 0 {
  168. msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
  169. }
  170. header := be.bc.CurrentBlock().Header()
  171. vmenv := core.NewEnv(statedb, be.config, be.bc, msg, header, vm.Config{})
  172. gp := new(core.GasPool).AddGas(common.MaxBig)
  173. res, gas, err := core.ApplyMessage(vmenv, msg, gp)
  174. return common.ToHex(res), gas.String(), err
  175. }
  176. // StorageAt returns the data stores in the state for the given address and location.
  177. func (be *registryAPIBackend) StorageAt(addr string, storageAddr string) string {
  178. block := be.bc.CurrentBlock()
  179. state, err := state.New(block.Root(), be.chainDb)
  180. if err != nil {
  181. return ""
  182. }
  183. return state.GetState(common.HexToAddress(addr), common.HexToHash(storageAddr)).Hex()
  184. }
  185. // Transact forms a transaction from the given arguments and submits it to the
  186. // transactio pool for execution.
  187. func (be *registryAPIBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
  188. if len(toStr) > 0 && toStr != "0x" && !common.IsHexAddress(toStr) {
  189. return "", errors.New("invalid address")
  190. }
  191. var (
  192. from = common.HexToAddress(fromStr)
  193. to = common.HexToAddress(toStr)
  194. value = common.Big(valueStr)
  195. gas *big.Int
  196. price *big.Int
  197. data []byte
  198. contractCreation bool
  199. )
  200. if len(gasStr) == 0 {
  201. gas = big.NewInt(90000)
  202. } else {
  203. gas = common.Big(gasStr)
  204. }
  205. if len(gasPriceStr) == 0 {
  206. price = big.NewInt(10000000000000)
  207. } else {
  208. price = common.Big(gasPriceStr)
  209. }
  210. data = common.FromHex(codeStr)
  211. if len(toStr) == 0 {
  212. contractCreation = true
  213. }
  214. nonce := be.txPool.State().GetNonce(from)
  215. if len(nonceStr) != 0 {
  216. nonce = common.Big(nonceStr).Uint64()
  217. }
  218. var tx *types.Transaction
  219. if contractCreation {
  220. tx = types.NewContractCreation(nonce, value, gas, price, data)
  221. } else {
  222. tx = types.NewTransaction(nonce, to, value, gas, price, data)
  223. }
  224. acc := accounts.Account{from}
  225. signature, err := be.am.Sign(acc, tx.SigHash().Bytes())
  226. if err != nil {
  227. return "", err
  228. }
  229. signedTx, err := tx.WithSignature(signature)
  230. if err != nil {
  231. return "", err
  232. }
  233. be.txPool.SetLocal(signedTx)
  234. if err := be.txPool.Add(signedTx); err != nil {
  235. return "", nil
  236. }
  237. if contractCreation {
  238. addr := crypto.CreateAddress(from, nonce)
  239. glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signedTx.Hash().Hex(), addr.Hex())
  240. } else {
  241. glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signedTx.Hash().Hex(), tx.To().Hex())
  242. }
  243. return signedTx.Hash().Hex(), nil
  244. }