Add refactored SendTx, chain filter, and new error codes
This commit is contained in:
parent
c130603d10
commit
2c9123224e
|
@ -7,8 +7,13 @@ package errors
|
||||||
import abci "github.com/tendermint/abci/types"
|
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)
|
||||||
|
}
|
||||||
|
|
21
txs/base.go
21
txs/base.go
|
@ -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}
|
||||||
|
}
|
||||||
|
|
|
@ -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}
|
||||||
|
}
|
Loading…
Reference in New Issue