You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
3.9 KiB

10 years ago
10 years ago
  1. package core
  2. import (
  3. "fmt"
  4. "github.com/tendermint/tendermint/account"
  5. . "github.com/tendermint/tendermint/common"
  6. ctypes "github.com/tendermint/tendermint/rpc/core/types"
  7. "github.com/tendermint/tendermint/state"
  8. "github.com/tendermint/tendermint/types"
  9. "github.com/tendermint/tendermint/vm"
  10. )
  11. func toVMAccount(acc *account.Account) *vm.Account {
  12. return &vm.Account{
  13. Address: LeftPadWord256(acc.Address),
  14. Balance: acc.Balance,
  15. Code: acc.Code, // This is crazy.
  16. Nonce: uint64(acc.Sequence),
  17. StorageRoot: LeftPadWord256(acc.StorageRoot),
  18. Other: acc.PubKey,
  19. }
  20. }
  21. //-----------------------------------------------------------------------------
  22. // Run a contract's code on an isolated and unpersisted state
  23. // Cannot be used to create new contracts
  24. func Call(address, data []byte) (*ctypes.ResponseCall, error) {
  25. st := consensusState.GetState() // performs a copy
  26. cache := state.NewBlockCache(st)
  27. outAcc := cache.GetAccount(address)
  28. if outAcc == nil {
  29. return nil, fmt.Errorf("Account %x does not exist", address)
  30. }
  31. callee := toVMAccount(outAcc)
  32. caller := &vm.Account{Address: Zero256}
  33. txCache := state.NewTxCache(cache)
  34. params := vm.Params{
  35. BlockHeight: uint64(st.LastBlockHeight),
  36. BlockHash: LeftPadWord256(st.LastBlockHash),
  37. BlockTime: st.LastBlockTime.Unix(),
  38. GasLimit: 10000000,
  39. }
  40. vmach := vm.NewVM(txCache, params, caller.Address, nil)
  41. gas := uint64(1000000000)
  42. ret, err := vmach.Call(caller, callee, callee.Code, data, 0, &gas)
  43. if err != nil {
  44. return nil, err
  45. }
  46. return &ctypes.ResponseCall{Return: ret}, nil
  47. }
  48. // Run the given code on an isolated and unpersisted state
  49. // Cannot be used to create new contracts
  50. func CallCode(code, data []byte) (*ctypes.ResponseCall, error) {
  51. st := consensusState.GetState() // performs a copy
  52. cache := mempoolReactor.Mempool.GetCache()
  53. callee := &vm.Account{Address: Zero256}
  54. caller := &vm.Account{Address: Zero256}
  55. txCache := state.NewTxCache(cache)
  56. params := vm.Params{
  57. BlockHeight: uint64(st.LastBlockHeight),
  58. BlockHash: LeftPadWord256(st.LastBlockHash),
  59. BlockTime: st.LastBlockTime.Unix(),
  60. GasLimit: 10000000,
  61. }
  62. vmach := vm.NewVM(txCache, params, caller.Address, nil)
  63. gas := uint64(1000000000)
  64. ret, err := vmach.Call(caller, callee, code, data, 0, &gas)
  65. if err != nil {
  66. return nil, err
  67. }
  68. return &ctypes.ResponseCall{Return: ret}, nil
  69. }
  70. //-----------------------------------------------------------------------------
  71. func SignTx(tx types.Tx, privAccounts []*account.PrivAccount) (types.Tx, error) {
  72. // more checks?
  73. for i, privAccount := range privAccounts {
  74. if privAccount == nil || privAccount.PrivKey == nil {
  75. return nil, fmt.Errorf("Invalid (empty) privAccount @%v", i)
  76. }
  77. }
  78. switch tx.(type) {
  79. case *types.SendTx:
  80. sendTx := tx.(*types.SendTx)
  81. for i, input := range sendTx.Inputs {
  82. input.PubKey = privAccounts[i].PubKey
  83. input.Signature = privAccounts[i].Sign(config.GetString("chain_id"), sendTx)
  84. }
  85. case *types.CallTx:
  86. callTx := tx.(*types.CallTx)
  87. callTx.Input.PubKey = privAccounts[0].PubKey
  88. callTx.Input.Signature = privAccounts[0].Sign(config.GetString("chain_id"), callTx)
  89. case *types.BondTx:
  90. bondTx := tx.(*types.BondTx)
  91. // the first privaccount corresponds to the BondTx pub key.
  92. // the rest to the inputs
  93. bondTx.Signature = privAccounts[0].Sign(config.GetString("chain_id"), bondTx).(account.SignatureEd25519)
  94. for i, input := range bondTx.Inputs {
  95. input.PubKey = privAccounts[i+1].PubKey
  96. input.Signature = privAccounts[i+1].Sign(config.GetString("chain_id"), bondTx)
  97. }
  98. case *types.UnbondTx:
  99. unbondTx := tx.(*types.UnbondTx)
  100. unbondTx.Signature = privAccounts[0].Sign(config.GetString("chain_id"), unbondTx).(account.SignatureEd25519)
  101. case *types.RebondTx:
  102. rebondTx := tx.(*types.RebondTx)
  103. rebondTx.Signature = privAccounts[0].Sign(config.GetString("chain_id"), rebondTx).(account.SignatureEd25519)
  104. }
  105. return tx, nil
  106. }