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.

263 lines
7.0 KiB

  1. package types
  2. import (
  3. "errors"
  4. "io"
  5. "github.com/tendermint/tendermint/account"
  6. "github.com/tendermint/tendermint/binary"
  7. . "github.com/tendermint/tendermint/common"
  8. )
  9. var (
  10. ErrTxInvalidAddress = errors.New("Error invalid address")
  11. ErrTxDuplicateAddress = errors.New("Error duplicate address")
  12. ErrTxInvalidAmount = errors.New("Error invalid amount")
  13. ErrTxInsufficientFunds = errors.New("Error insufficient funds")
  14. ErrTxInsufficientGasPrice = errors.New("Error insufficient gas price")
  15. ErrTxUnknownPubKey = errors.New("Error unknown pubkey")
  16. ErrTxInvalidPubKey = errors.New("Error invalid pubkey")
  17. ErrTxInvalidSignature = errors.New("Error invalid signature")
  18. )
  19. type ErrTxInvalidSequence struct {
  20. Got uint64
  21. Expected uint64
  22. }
  23. func (e ErrTxInvalidSequence) Error() string {
  24. return Fmt("Error invalid sequence. Got %d, expected %d", e.Got, e.Expected)
  25. }
  26. /*
  27. Tx (Transaction) is an atomic operation on the ledger state.
  28. Account Txs:
  29. - SendTx Send coins to address
  30. - CallTx Send a msg to a contract that runs in the vm
  31. Validation Txs:
  32. - BondTx New validator posts a bond
  33. - UnbondTx Validator leaves
  34. - DupeoutTx Validator dupes out (equivocates)
  35. */
  36. type Tx interface {
  37. WriteSignBytes(w io.Writer, n *int64, err *error)
  38. }
  39. // Types of Tx implementations
  40. const (
  41. // Account transactions
  42. TxTypeSend = byte(0x01)
  43. TxTypeCall = byte(0x02)
  44. // Validation transactions
  45. TxTypeBond = byte(0x11)
  46. TxTypeUnbond = byte(0x12)
  47. TxTypeRebond = byte(0x13)
  48. TxTypeDupeout = byte(0x14)
  49. )
  50. // for binary.readReflect
  51. var _ = binary.RegisterInterface(
  52. struct{ Tx }{},
  53. binary.ConcreteType{&SendTx{}},
  54. binary.ConcreteType{&CallTx{}},
  55. binary.ConcreteType{&BondTx{}},
  56. binary.ConcreteType{&UnbondTx{}},
  57. binary.ConcreteType{&RebondTx{}},
  58. binary.ConcreteType{&DupeoutTx{}},
  59. )
  60. //-----------------------------------------------------------------------------
  61. type TxInput struct {
  62. Address []byte // Hash of the PubKey
  63. Amount uint64 // Must not exceed account balance
  64. Sequence uint // Must be 1 greater than the last committed TxInput
  65. Signature account.Signature // Depends on the PubKey type and the whole Tx
  66. PubKey account.PubKey // Must not be nil, may be nil
  67. }
  68. func (txIn *TxInput) ValidateBasic() error {
  69. if len(txIn.Address) != 20 {
  70. return ErrTxInvalidAddress
  71. }
  72. if txIn.Amount == 0 {
  73. return ErrTxInvalidAmount
  74. }
  75. return nil
  76. }
  77. func (txIn *TxInput) WriteSignBytes(w io.Writer, n *int64, err *error) {
  78. binary.WriteByteSlice(txIn.Address, w, n, err)
  79. binary.WriteUint64(txIn.Amount, w, n, err)
  80. binary.WriteUvarint(txIn.Sequence, w, n, err)
  81. }
  82. func (txIn *TxInput) String() string {
  83. return Fmt("TxInput{%X,%v,%v,%v,%v}", txIn.Address, txIn.Amount, txIn.Sequence, txIn.Signature, txIn.PubKey)
  84. }
  85. //-----------------------------------------------------------------------------
  86. type TxOutput struct {
  87. Address []byte // Hash of the PubKey
  88. Amount uint64 // The sum of all outputs must not exceed the inputs.
  89. }
  90. func (txOut *TxOutput) ValidateBasic() error {
  91. if len(txOut.Address) != 20 {
  92. return ErrTxInvalidAddress
  93. }
  94. if txOut.Amount == 0 {
  95. return ErrTxInvalidAmount
  96. }
  97. return nil
  98. }
  99. func (txOut *TxOutput) WriteSignBytes(w io.Writer, n *int64, err *error) {
  100. binary.WriteByteSlice(txOut.Address, w, n, err)
  101. binary.WriteUint64(txOut.Amount, w, n, err)
  102. }
  103. func (txOut *TxOutput) String() string {
  104. return Fmt("TxOutput{%X,%v}", txOut.Address, txOut.Amount)
  105. }
  106. //-----------------------------------------------------------------------------
  107. type SendTx struct {
  108. Inputs []*TxInput
  109. Outputs []*TxOutput
  110. }
  111. func (tx *SendTx) TypeByte() byte { return TxTypeSend }
  112. func (tx *SendTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
  113. binary.WriteUvarint(uint(len(tx.Inputs)), w, n, err)
  114. for _, in := range tx.Inputs {
  115. in.WriteSignBytes(w, n, err)
  116. }
  117. binary.WriteUvarint(uint(len(tx.Outputs)), w, n, err)
  118. for _, out := range tx.Outputs {
  119. out.WriteSignBytes(w, n, err)
  120. }
  121. }
  122. func (tx *SendTx) String() string {
  123. return Fmt("SendTx{%v -> %v}", tx.Inputs, tx.Outputs)
  124. }
  125. //-----------------------------------------------------------------------------
  126. type CallTx struct {
  127. Input *TxInput
  128. Address []byte
  129. GasLimit uint64
  130. Fee uint64
  131. Data []byte
  132. }
  133. func (tx *CallTx) TypeByte() byte { return TxTypeCall }
  134. func (tx *CallTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
  135. tx.Input.WriteSignBytes(w, n, err)
  136. binary.WriteByteSlice(tx.Address, w, n, err)
  137. binary.WriteUint64(tx.GasLimit, w, n, err)
  138. binary.WriteUint64(tx.Fee, w, n, err)
  139. binary.WriteByteSlice(tx.Data, w, n, err)
  140. }
  141. func (tx *CallTx) String() string {
  142. return Fmt("CallTx{%v -> %x: %x}", tx.Input, tx.Address, tx.Data)
  143. }
  144. //-----------------------------------------------------------------------------
  145. type BondTx struct {
  146. PubKey account.PubKeyEd25519
  147. Inputs []*TxInput
  148. UnbondTo []*TxOutput
  149. }
  150. func (tx *BondTx) TypeByte() byte { return TxTypeBond }
  151. func (tx *BondTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
  152. binary.WriteBinary(tx.PubKey, w, n, err)
  153. binary.WriteUvarint(uint(len(tx.Inputs)), w, n, err)
  154. for _, in := range tx.Inputs {
  155. in.WriteSignBytes(w, n, err)
  156. }
  157. binary.WriteUvarint(uint(len(tx.UnbondTo)), w, n, err)
  158. for _, out := range tx.UnbondTo {
  159. out.WriteSignBytes(w, n, err)
  160. }
  161. }
  162. func (tx *BondTx) String() string {
  163. return Fmt("BondTx{%v: %v -> %v}", tx.PubKey, tx.Inputs, tx.UnbondTo)
  164. }
  165. //-----------------------------------------------------------------------------
  166. type UnbondTx struct {
  167. Address []byte
  168. Height uint
  169. Signature account.SignatureEd25519
  170. }
  171. func (tx *UnbondTx) TypeByte() byte { return TxTypeUnbond }
  172. func (tx *UnbondTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
  173. binary.WriteByteSlice(tx.Address, w, n, err)
  174. binary.WriteUvarint(tx.Height, w, n, err)
  175. }
  176. func (tx *UnbondTx) String() string {
  177. return Fmt("UnbondTx{%X,%v,%v}", tx.Address, tx.Height, tx.Signature)
  178. }
  179. //-----------------------------------------------------------------------------
  180. type RebondTx struct {
  181. Address []byte
  182. Height uint
  183. Signature account.SignatureEd25519
  184. }
  185. func (tx *RebondTx) TypeByte() byte { return TxTypeRebond }
  186. func (tx *RebondTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
  187. binary.WriteByteSlice(tx.Address, w, n, err)
  188. binary.WriteUvarint(tx.Height, w, n, err)
  189. }
  190. func (tx *RebondTx) String() string {
  191. return Fmt("RebondTx{%X,%v,%v}", tx.Address, tx.Height, tx.Signature)
  192. }
  193. //-----------------------------------------------------------------------------
  194. type DupeoutTx struct {
  195. Address []byte
  196. VoteA Vote
  197. VoteB Vote
  198. }
  199. func (tx *DupeoutTx) TypeByte() byte { return TxTypeDupeout }
  200. func (tx *DupeoutTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
  201. panic("DupeoutTx has no sign bytes")
  202. }
  203. func (tx *DupeoutTx) String() string {
  204. return Fmt("DupeoutTx{%X,%v,%v}", tx.Address, tx.VoteA, tx.VoteB)
  205. }
  206. //-----------------------------------------------------------------------------
  207. func TxId(tx Tx) []byte {
  208. signBytes := account.SignBytes(tx)
  209. return binary.BinaryRipemd160(signBytes)
  210. }