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.
 
 
 
 
 
 

210 lines
5.4 KiB

package block
import (
"errors"
"io"
"reflect"
. "github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/common"
)
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")
ErrTxRedeclaredPubKey = errors.New("Error redeclared pubkey")
ErrTxInvalidSignature = errors.New("Error invalid signature")
ErrTxInvalidSequence = errors.New("Error invalid sequence")
)
/*
Tx (Transaction) is an atomic operation on the ledger state.
Account Txs:
- SendTx Send coins to address
Validation Txs:
- BondTx New validator posts a bond
- UnbondTx Validator leaves
- DupeoutTx Validator dupes out (equivocates)
*/
type Tx interface {
WriteSignBytes(w io.Writer, n *int64, err *error)
}
// Types of Tx implementations
const (
// Account transactions
TxTypeSend = byte(0x01)
// Validation transactions
TxTypeBond = byte(0x11)
TxTypeUnbond = byte(0x12)
TxTypeRebond = byte(0x13)
TxTypeDupeout = byte(0x14)
)
//-------------------------------------
// for binary.readReflect
func TxDecoder(r Unreader, n *int64, err *error) interface{} {
switch t := PeekByte(r, n, err); t {
case TxTypeSend:
return ReadBinary(&SendTx{}, r, n, err)
case TxTypeBond:
return ReadBinary(&BondTx{}, r, n, err)
case TxTypeUnbond:
return ReadBinary(&UnbondTx{}, r, n, err)
case TxTypeRebond:
return ReadBinary(&RebondTx{}, r, n, err)
case TxTypeDupeout:
return ReadBinary(&DupeoutTx{}, r, n, err)
default:
*err = Errorf("Unknown Tx type %X", t)
return nil
}
}
var _ = RegisterType(&TypeInfo{
Type: reflect.TypeOf((*Tx)(nil)).Elem(),
Decoder: TxDecoder,
})
//-----------------------------------------------------------------------------
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 Signature // Depends on the PubKey type and the whole Tx
PubKey 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) {
WriteByteSlice(txIn.Address, w, n, err)
WriteUint64(txIn.Amount, w, n, err)
WriteUvarint(txIn.Sequence, w, n, err)
}
//-----------------------------------------------------------------------------
type TxOutput struct {
Address []byte // Hash of the PubKey
Amount uint64 // The sum of all outputs must not exceed the inputs.
}
func (txOut *TxOutput) ValidateBasic() error {
if len(txOut.Address) != 20 {
return ErrTxInvalidAddress
}
if txOut.Amount == 0 {
return ErrTxInvalidAmount
}
return nil
}
func (txOut *TxOutput) WriteSignBytes(w io.Writer, n *int64, err *error) {
WriteByteSlice(txOut.Address, w, n, err)
WriteUint64(txOut.Amount, w, n, err)
}
//-----------------------------------------------------------------------------
type SendTx struct {
Inputs []*TxInput
Outputs []*TxOutput
}
func (tx *SendTx) TypeByte() byte { return TxTypeSend }
func (tx *SendTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
WriteUvarint(uint(len(tx.Inputs)), w, n, err)
for _, in := range tx.Inputs {
in.WriteSignBytes(w, n, err)
}
WriteUvarint(uint(len(tx.Outputs)), w, n, err)
for _, out := range tx.Outputs {
out.WriteSignBytes(w, n, err)
}
}
//-----------------------------------------------------------------------------
type BondTx struct {
PubKey PubKeyEd25519
Inputs []*TxInput
UnbondTo []*TxOutput
}
func (tx *BondTx) TypeByte() byte { return TxTypeBond }
func (tx *BondTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
WriteBinary(tx.PubKey, w, n, err)
WriteUvarint(uint(len(tx.Inputs)), w, n, err)
for _, in := range tx.Inputs {
in.WriteSignBytes(w, n, err)
}
WriteUvarint(uint(len(tx.UnbondTo)), w, n, err)
for _, out := range tx.UnbondTo {
out.WriteSignBytes(w, n, err)
}
}
//-----------------------------------------------------------------------------
type UnbondTx struct {
Address []byte
Height uint
Signature SignatureEd25519
}
func (tx *UnbondTx) TypeByte() byte { return TxTypeUnbond }
func (tx *UnbondTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
WriteByteSlice(tx.Address, w, n, err)
WriteUvarint(tx.Height, w, n, err)
}
//-----------------------------------------------------------------------------
type RebondTx struct {
Address []byte
Height uint
Signature SignatureEd25519
}
func (tx *RebondTx) TypeByte() byte { return TxTypeRebond }
func (tx *RebondTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
WriteByteSlice(tx.Address, w, n, err)
WriteUvarint(tx.Height, w, n, err)
}
//-----------------------------------------------------------------------------
type DupeoutTx struct {
Address []byte
VoteA Vote
VoteB Vote
}
func (tx *DupeoutTx) TypeByte() byte { return TxTypeDupeout }
func (tx *DupeoutTx) WriteSignBytes(w io.Writer, n *int64, err *error) {
panic("DupeoutTx has no sign bytes")
}