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.

115 lines
3.3 KiB

  1. package main
  2. import (
  3. "bufio"
  4. "bytes"
  5. "encoding/hex"
  6. "fmt"
  7. "os"
  8. "strconv"
  9. account_ "github.com/tendermint/tendermint/account"
  10. binary "github.com/tendermint/tendermint/binary"
  11. block_ "github.com/tendermint/tendermint/block"
  12. . "github.com/tendermint/tendermint/common"
  13. db_ "github.com/tendermint/tendermint/db"
  14. state_ "github.com/tendermint/tendermint/state"
  15. )
  16. func getString(prompt string) string {
  17. reader := bufio.NewReader(os.Stdin)
  18. fmt.Print(prompt)
  19. input, _ := reader.ReadString('\n')
  20. return input[:len(input)-1]
  21. }
  22. func getByteSliceFromHex(prompt string) []byte {
  23. input := getString(prompt)
  24. bytes, err := hex.DecodeString(input)
  25. if err != nil {
  26. Exit(Fmt("Not in hex format: %v\nError: %v\n", input, err))
  27. }
  28. return bytes
  29. }
  30. func getUint64(prompt string) uint64 {
  31. input := getString(prompt)
  32. i, err := strconv.Atoi(input)
  33. if err != nil {
  34. Exit(Fmt("Not a valid uint64 amount: %v\nError: %v\n", input, err))
  35. }
  36. return uint64(i)
  37. }
  38. func gen_tx() {
  39. // Get State, which may be nil.
  40. stateDB := db_.GetDB("state")
  41. state := state_.LoadState(stateDB)
  42. // Get source pubkey
  43. srcPubKeyBytes := getByteSliceFromHex("Enter source pubkey: ")
  44. r, n, err := bytes.NewReader(srcPubKeyBytes), new(int64), new(error)
  45. srcPubKey := binary.ReadBinary(struct{ account_.PubKey }{}, r, n, err).(struct{ account_.PubKey }).PubKey
  46. if *err != nil {
  47. Exit(Fmt("Invalid PubKey. Error: %v", err))
  48. }
  49. // Get the state of the account.
  50. var srcAccount *account_.Account
  51. var srcAccountAddress = srcPubKey.Address()
  52. var srcAccountBalanceStr = "unknown"
  53. var srcAccountSequenceStr = "unknown"
  54. srcAddress := srcPubKey.Address()
  55. if state != nil {
  56. srcAccount = state.GetAccount(srcAddress)
  57. srcAccountBalanceStr = Fmt("%v", srcAccount.Balance)
  58. srcAccountSequenceStr = Fmt("%v", srcAccount.Sequence+1)
  59. }
  60. // Get the amount to send from src account
  61. srcSendAmount := getUint64(Fmt("Enter amount to send from %X (total: %v): ", srcAccountAddress, srcAccountBalanceStr))
  62. // Get the next sequence of src account
  63. srcSendSequence := uint(getUint64(Fmt("Enter next sequence for %X (guess: %v): ", srcAccountAddress, srcAccountSequenceStr)))
  64. // Get dest address
  65. dstAddress := getByteSliceFromHex("Enter destination address: ")
  66. // Get the amount to send to dst account
  67. dstSendAmount := getUint64(Fmt("Enter amount to send to %X: ", dstAddress))
  68. // Construct SendTx
  69. tx := &block_.SendTx{
  70. Inputs: []*block_.TxInput{
  71. &block_.TxInput{
  72. Address: srcAddress,
  73. Amount: srcSendAmount,
  74. Sequence: srcSendSequence,
  75. Signature: account_.SignatureEd25519{},
  76. PubKey: srcPubKey,
  77. },
  78. },
  79. Outputs: []*block_.TxOutput{
  80. &block_.TxOutput{
  81. Address: dstAddress,
  82. Amount: dstSendAmount,
  83. },
  84. },
  85. }
  86. // Show the intermediate form.
  87. fmt.Printf("Generated tx: %X\n", binary.BinaryBytes(tx))
  88. // Get source privkey (for signing)
  89. srcPrivKeyBytes := getByteSliceFromHex("Enter source privkey (for signing): ")
  90. r, n, err = bytes.NewReader(srcPrivKeyBytes), new(int64), new(error)
  91. srcPrivKey := binary.ReadBinary(struct{ account_.PrivKey }{}, r, n, err).(struct{ account_.PrivKey }).PrivKey
  92. if *err != nil {
  93. Exit(Fmt("Invalid PrivKey. Error: %v", err))
  94. }
  95. // Sign
  96. tx.Inputs[0].Signature = srcPrivKey.Sign(account_.SignBytes(tx))
  97. fmt.Printf("Signed tx: %X\n", binary.BinaryBytes(tx))
  98. }