tendermint/block/tx.go

248 lines
6.6 KiB
Go
Raw Normal View History

2014-12-17 01:37:13 -08:00
package block
2014-06-05 02:34:45 -07:00
import (
"errors"
"io"
"github.com/tendermint/tendermint/account"
"github.com/tendermint/tendermint/binary"
2015-01-16 00:31:34 -08:00
. "github.com/tendermint/tendermint/common"
2014-06-05 02:34:45 -07:00
)
2014-12-23 01:35:54 -08:00
var (
ErrTxInvalidAddress = errors.New("Error invalid address")
ErrTxDuplicateAddress = errors.New("Error duplicate address")
ErrTxInvalidAmount = errors.New("Error invalid amount")
ErrTxInsufficientFunds = errors.New("Error insufficient funds")
ErrTxUnknownPubKey = errors.New("Error unknown pubkey")
ErrTxInvalidPubKey = errors.New("Error invalid pubkey")
2014-12-23 01:35:54 -08:00
ErrTxInvalidSignature = errors.New("Error invalid signature")
ErrTxInvalidSequence = errors.New("Error invalid sequence")
)
2014-06-05 02:34:45 -07:00
/*
Tx (Transaction) is an atomic operation on the ledger state.
2014-09-10 02:43:16 -07:00
Account Txs:
2014-12-23 01:35:54 -08:00
- SendTx Send coins to address
2015-03-18 01:27:16 -07:00
- CallTx Send a msg to a contract that runs in the vm
2014-09-10 02:43:16 -07:00
Validation Txs:
2014-12-23 01:35:54 -08:00
- BondTx New validator posts a bond
- UnbondTx Validator leaves
- DupeoutTx Validator dupes out (equivocates)
2014-06-05 02:34:45 -07:00
*/
type Tx interface {
WriteSignBytes(w io.Writer, n *int64, err *error)
2014-06-05 02:34:45 -07:00
}
2014-12-23 01:35:54 -08:00
// Types of Tx implementations
2014-06-05 02:34:45 -07:00
const (
2014-09-10 02:43:16 -07:00
// Account transactions
2014-10-07 23:11:04 -07:00
TxTypeSend = byte(0x01)
2015-03-18 01:27:16 -07:00
TxTypeCall = byte(0x02)
2014-09-10 02:43:16 -07:00
// Validation transactions
2014-10-07 23:11:04 -07:00
TxTypeBond = byte(0x11)
TxTypeUnbond = byte(0x12)
TxTypeRebond = byte(0x13)
TxTypeDupeout = byte(0x14)
2014-06-05 02:34:45 -07:00
)
2014-12-23 01:35:54 -08:00
// for binary.readReflect
var _ = binary.RegisterInterface(
struct{ Tx }{},
binary.ConcreteType{&SendTx{}},
2015-03-18 01:27:16 -07:00
binary.ConcreteType{&CallTx{}},
binary.ConcreteType{&BondTx{}},
binary.ConcreteType{&UnbondTx{}},
binary.ConcreteType{&RebondTx{}},
binary.ConcreteType{&DupeoutTx{}},
)
2014-09-10 02:43:16 -07:00
//-----------------------------------------------------------------------------
2014-06-05 02:34:45 -07:00
type TxInput struct {
Address []byte // Hash of the PubKey
Amount uint64 // Must not exceed account balance
Sequence uint // Must be 1 greater than the last committed TxInput
Signature account.Signature // Depends on the PubKey type and the whole Tx
PubKey account.PubKey // Must not be nil, may be PubKeyNil.
}
func (txIn *TxInput) ValidateBasic() error {
if len(txIn.Address) != 20 {
return ErrTxInvalidAddress
}
if txIn.Amount == 0 {
return ErrTxInvalidAmount
}
return nil
}
func (txIn *TxInput) WriteSignBytes(w io.Writer, n *int64, err *error) {
binary.WriteByteSlice(txIn.Address, w, n, err)
binary.WriteUint64(txIn.Amount, w, n, err)
binary.WriteUvarint(txIn.Sequence, w, n, err)
}
2015-01-16 00:31:34 -08:00
func (txIn *TxInput) String() string {
return Fmt("TxInput{%X,%v,%v,%v,%v}", txIn.Address, txIn.Amount, txIn.Sequence, txIn.Signature, txIn.PubKey)
}
//-----------------------------------------------------------------------------
type TxOutput struct {
Address []byte // Hash of the PubKey
Amount uint64 // The sum of all outputs must not exceed the inputs.
2014-06-05 02:34:45 -07:00
}
func (txOut *TxOutput) ValidateBasic() error {
if len(txOut.Address) != 20 {
return ErrTxInvalidAddress
}
if txOut.Amount == 0 {
return ErrTxInvalidAmount
}
return nil
2014-06-05 02:34:45 -07:00
}
func (txOut *TxOutput) WriteSignBytes(w io.Writer, n *int64, err *error) {
binary.WriteByteSlice(txOut.Address, w, n, err)
binary.WriteUint64(txOut.Amount, w, n, err)
}
2015-01-16 00:31:34 -08:00
func (txOut *TxOutput) String() string {
return Fmt("TxOutput{%X,%v}", txOut.Address, txOut.Amount)
}
2014-09-10 02:43:16 -07:00
//-----------------------------------------------------------------------------
2014-06-05 02:34:45 -07:00
type SendTx struct {
Inputs []*TxInput
Outputs []*TxOutput
2014-06-05 02:34:45 -07:00
}
func (tx *SendTx) TypeByte() byte { return TxTypeSend }
2014-09-10 02:43:16 -07:00
func (tx *SendTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
binary.WriteUvarint(uint(len(tx.Inputs)), w, n, err)
for _, in := range tx.Inputs {
in.WriteSignBytes(w, n, err)
}
binary.WriteUvarint(uint(len(tx.Outputs)), w, n, err)
for _, out := range tx.Outputs {
out.WriteSignBytes(w, n, err)
}
}
2015-01-16 00:31:34 -08:00
func (tx *SendTx) String() string {
return Fmt("SendTx{%v -> %v}", tx.Inputs, tx.Outputs)
}
2014-09-10 02:43:16 -07:00
//-----------------------------------------------------------------------------
2015-03-18 01:27:16 -07:00
type CallTx struct {
Input *TxInput
Address []byte
GasLimit uint64
FeeLimit uint64
Data []byte
}
func (tx *CallTx) TypeByte() byte { return TxTypeCall }
func (tx *CallTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
tx.Input.WriteSignBytes(w, n, err)
binary.WriteByteSlice(tx.Address, w, n, err)
binary.WriteUint64(tx.GasLimit, w, n, err)
binary.WriteUint64(tx.FeeLimit, w, n, err)
binary.WriteByteSlice(tx.Data, w, n, err)
}
func (tx *CallTx) String() string {
return Fmt("CallTx{%v -> %x: %x}", tx.Input, tx.Address, tx.Data)
}
//-----------------------------------------------------------------------------
2014-09-10 02:43:16 -07:00
type BondTx struct {
PubKey account.PubKeyEd25519
Inputs []*TxInput
UnbondTo []*TxOutput
2014-09-10 02:43:16 -07:00
}
func (tx *BondTx) TypeByte() byte { return TxTypeBond }
2014-09-10 02:43:16 -07:00
func (tx *BondTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
binary.WriteBinary(tx.PubKey, w, n, err)
binary.WriteUvarint(uint(len(tx.Inputs)), w, n, err)
for _, in := range tx.Inputs {
in.WriteSignBytes(w, n, err)
}
binary.WriteUvarint(uint(len(tx.UnbondTo)), w, n, err)
for _, out := range tx.UnbondTo {
out.WriteSignBytes(w, n, err)
}
}
2015-01-16 00:31:34 -08:00
func (tx *BondTx) String() string {
return Fmt("BondTx{%v: %v -> %v}", tx.PubKey, tx.Inputs, tx.UnbondTo)
}
2014-09-10 02:43:16 -07:00
//-----------------------------------------------------------------------------
type UnbondTx struct {
Address []byte
Height uint
Signature account.SignatureEd25519
2014-09-10 02:43:16 -07:00
}
func (tx *UnbondTx) TypeByte() byte { return TxTypeUnbond }
2014-09-10 02:43:16 -07:00
func (tx *UnbondTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
binary.WriteByteSlice(tx.Address, w, n, err)
binary.WriteUvarint(tx.Height, w, n, err)
}
2015-01-16 00:31:34 -08:00
func (tx *UnbondTx) String() string {
return Fmt("UnbondTx{%X,%v,%v}", tx.Address, tx.Height, tx.Signature)
}
2014-09-10 02:43:16 -07:00
//-----------------------------------------------------------------------------
type RebondTx struct {
Address []byte
Height uint
Signature account.SignatureEd25519
}
func (tx *RebondTx) TypeByte() byte { return TxTypeRebond }
func (tx *RebondTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
binary.WriteByteSlice(tx.Address, w, n, err)
binary.WriteUvarint(tx.Height, w, n, err)
}
2015-01-16 00:31:34 -08:00
func (tx *RebondTx) String() string {
return Fmt("RebondTx{%X,%v,%v}", tx.Address, tx.Height, tx.Signature)
}
//-----------------------------------------------------------------------------
2014-09-10 02:43:16 -07:00
type DupeoutTx struct {
Address []byte
VoteA Vote
VoteB Vote
2014-09-10 02:43:16 -07:00
}
func (tx *DupeoutTx) TypeByte() byte { return TxTypeDupeout }
func (tx *DupeoutTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
panic("DupeoutTx has no sign bytes")
}
2015-01-16 00:31:34 -08:00
func (tx *DupeoutTx) String() string {
return Fmt("DupeoutTx{%X,%v,%v}", tx.Address, tx.VoteA, tx.VoteB)
}