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.

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