Add refactored SendTx, chain filter, and new error codes

This commit is contained in:
Ethan Frey 2017-05-29 14:15:42 +02:00
parent c130603d10
commit 2c9123224e
3 changed files with 166 additions and 3 deletions

View File

@ -9,6 +9,11 @@ import abci "github.com/tendermint/abci/types"
const ( const (
msgDecoding = "Error decoding input" msgDecoding = "Error decoding input"
msgUnauthorized = "Unauthorized" msgUnauthorized = "Unauthorized"
msgInvalidAddress = "Invalid Address"
msgInvalidCoins = "Invalid Coins"
msgInvalidSequence = "Invalid Sequence"
msgNoInputs = "No Input Coins"
msgNoOutputs = "No Output Coins"
) )
func DecodingError() TMError { func DecodingError() TMError {
@ -18,3 +23,23 @@ func DecodingError() TMError {
func Unauthorized() TMError { func Unauthorized() TMError {
return New(msgUnauthorized, abci.CodeType_Unauthorized) return New(msgUnauthorized, abci.CodeType_Unauthorized)
} }
func InvalidAddress() TMError {
return New(msgInvalidAddress, abci.CodeType_BaseInvalidInput)
}
func InvalidCoins() TMError {
return New(msgInvalidCoins, abci.CodeType_BaseInvalidInput)
}
func InvalidSequence() TMError {
return New(msgInvalidSequence, abci.CodeType_BaseInvalidInput)
}
func NoInputs() TMError {
return New(msgNoInputs, abci.CodeType_BaseInvalidInput)
}
func NoOutputs() TMError {
return New(msgNoOutputs, abci.CodeType_BaseInvalidOutput)
}

View File

@ -11,6 +11,7 @@ const (
ByteRaw = 0x1 ByteRaw = 0x1
ByteFees = 0x2 ByteFees = 0x2
ByteMulti = 0x3 ByteMulti = 0x3
ByteChain = 0x4
// for signatures // for signatures
ByteSig = 0x16 ByteSig = 0x16
@ -22,6 +23,7 @@ const (
TypeRaw = "raw" TypeRaw = "raw"
TypeFees = "fee" TypeFees = "fee"
TypeMulti = "multi" TypeMulti = "multi"
TypeChain = "chain"
// for signatures // for signatures
TypeSig = "sig" TypeSig = "sig"
@ -32,7 +34,8 @@ func init() {
basecoin.TxMapper. basecoin.TxMapper.
RegisterImplementation(Raw{}, TypeRaw, ByteRaw). RegisterImplementation(Raw{}, TypeRaw, ByteRaw).
RegisterImplementation(&Fee{}, TypeFees, ByteFees). RegisterImplementation(&Fee{}, TypeFees, ByteFees).
RegisterImplementation(&MultiTx{}, TypeMulti, ByteMulti) RegisterImplementation(&MultiTx{}, TypeMulti, ByteMulti).
RegisterImplementation(&Chain{}, TypeChain, ByteChain)
} }
// Raw just contains bytes that can be hex-ified // Raw just contains bytes that can be hex-ified
@ -78,3 +81,19 @@ func NewMultiTx(txs ...basecoin.Tx) *MultiTx {
func (mt *MultiTx) Wrap() basecoin.Tx { func (mt *MultiTx) Wrap() basecoin.Tx {
return basecoin.Tx{mt} return basecoin.Tx{mt}
} }
/*** Chain ****/
// Chain locks this tx to one chain, wrap with this before signing
type Chain struct {
Tx basecoin.Tx `json:"tx"`
ChainID string `json:"chain_id"`
}
func NewChain(tx basecoin.Tx, chainID string) *Chain {
return &Chain{Tx: tx, ChainID: chainID}
}
func (c *Chain) Wrap() basecoin.Tx {
return basecoin.Tx{c}
}

119
txs/send.go Normal file
View File

@ -0,0 +1,119 @@
package txs
import (
"fmt"
"github.com/tendermint/basecoin"
"github.com/tendermint/go-wire/data"
"github.com/tendermint/basecoin/errors"
"github.com/tendermint/basecoin/types"
)
//-----------------------------------------------------------------------------
type TxInput struct {
Address data.Bytes `json:"address"`
Coins types.Coins `json:"coins"`
Sequence int `json:"sequence"` // Nonce: Must be 1 greater than the last committed TxInput
}
func (txIn TxInput) ValidateBasic() error {
if len(txIn.Address) != 20 {
return errors.InvalidAddress()
}
if !txIn.Coins.IsValid() {
return errors.InvalidCoins()
}
if txIn.Coins.IsZero() {
return errors.InvalidCoins()
}
if txIn.Sequence <= 0 {
return errors.InvalidSequence()
}
return nil
}
func (txIn TxInput) String() string {
return fmt.Sprintf("TxInput{%v,%v,%v}", txIn.Address, txIn.Coins, txIn.Sequence)
}
func NewTxInput(addr []byte, coins types.Coins, sequence int) TxInput {
input := TxInput{
Address: addr,
Coins: coins,
Sequence: sequence,
}
return input
}
//-----------------------------------------------------------------------------
type TxOutput struct {
Address data.Bytes `json:"address"`
Coins types.Coins `json:"coins"`
}
func (txOut TxOutput) ValidateBasic() error {
if len(txOut.Address) != 20 {
return errors.InvalidAddress()
}
if !txOut.Coins.IsValid() {
return errors.InvalidCoins()
}
if txOut.Coins.IsZero() {
return errors.InvalidCoins()
}
return nil
}
func (txOut TxOutput) String() string {
return fmt.Sprintf("TxOutput{%X,%v}", txOut.Address, txOut.Coins)
}
func NewTxOutput(addr []byte, coins types.Coins) TxOutput {
output := TxOutput{
Address: addr,
Coins: coins,
}
return output
}
//-----------------------------------------------------------------------------
type SendTx struct {
Inputs []TxInput `json:"inputs"`
Outputs []TxOutput `json:"outputs"`
}
var _ basecoin.Tx = SendTx{}.Wrap()
func (tx SendTx) ValidateBasic() error {
// this just makes sure all the inputs and outputs are properly formatted,
// not that they actually have the money inside
if len(tx.Inputs) == 0 {
return errors.NoInputs()
}
if len(tx.Outputs) == 0 {
return errors.NoOutputs()
}
for _, in := range tx.Inputs {
if err := in.ValidateBasic(); err != nil {
return err
}
}
for _, out := range tx.Outputs {
if err := out.ValidateBasic(); err != nil {
return err
}
}
return nil
}
func (tx SendTx) String() string {
return fmt.Sprintf("SendTx{%v->%v}", tx.Inputs, tx.Outputs)
}
func (tx SendTx) Wrap() basecoin.Tx {
return basecoin.Tx{tx}
}