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.

248 lines
6.7 KiB

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