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.

116 lines
3.9 KiB

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