api.go 8.8 KB

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