mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 14:52:17 +00:00
block/state: add CallTx type
This commit is contained in:
parent
3efd63e08d
commit
7a33aba6e5
27
block/tx.go
27
block/tx.go
@ -25,6 +25,7 @@ Tx (Transaction) is an atomic operation on the ledger state.
|
||||
|
||||
Account Txs:
|
||||
- SendTx Send coins to address
|
||||
- CallTx Send a msg to a contract that runs in the vm
|
||||
|
||||
Validation Txs:
|
||||
- BondTx New validator posts a bond
|
||||
@ -39,6 +40,7 @@ type Tx interface {
|
||||
const (
|
||||
// Account transactions
|
||||
TxTypeSend = byte(0x01)
|
||||
TxTypeCall = byte(0x02)
|
||||
|
||||
// Validation transactions
|
||||
TxTypeBond = byte(0x11)
|
||||
@ -51,6 +53,7 @@ const (
|
||||
var _ = binary.RegisterInterface(
|
||||
struct{ Tx }{},
|
||||
binary.ConcreteType{&SendTx{}},
|
||||
binary.ConcreteType{&CallTx{}},
|
||||
binary.ConcreteType{&BondTx{}},
|
||||
binary.ConcreteType{&UnbondTx{}},
|
||||
binary.ConcreteType{&RebondTx{}},
|
||||
@ -139,6 +142,30 @@ func (tx *SendTx) String() string {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type BondTx struct {
|
||||
PubKey account.PubKeyEd25519
|
||||
Inputs []*TxInput
|
||||
|
@ -128,16 +128,8 @@ func (s *State) GetOrMakeAccounts(ins []*blk.TxInput, outs []*blk.TxOutput) (map
|
||||
return nil, blk.ErrTxInvalidAddress
|
||||
}
|
||||
// PubKey should be present in either "account" or "in"
|
||||
if _, isNil := acc.PubKey.(account.PubKeyNil); isNil {
|
||||
if _, isNil := in.PubKey.(account.PubKeyNil); isNil {
|
||||
return nil, blk.ErrTxUnknownPubKey
|
||||
}
|
||||
if !bytes.Equal(in.PubKey.Address(), acc.Address) {
|
||||
return nil, blk.ErrTxInvalidPubKey
|
||||
}
|
||||
acc.PubKey = in.PubKey
|
||||
} else {
|
||||
in.PubKey = account.PubKeyNil{}
|
||||
if err := checkInputPubKey(acc, in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
accounts[string(in.Address)] = acc
|
||||
}
|
||||
@ -161,6 +153,21 @@ func (s *State) GetOrMakeAccounts(ins []*blk.TxInput, outs []*blk.TxOutput) (map
|
||||
return accounts, nil
|
||||
}
|
||||
|
||||
func checkInputPubKey(acc *account.Account, in *blk.TxInput) error {
|
||||
if _, isNil := acc.PubKey.(account.PubKeyNil); isNil {
|
||||
if _, isNil := in.PubKey.(account.PubKeyNil); isNil {
|
||||
return blk.ErrTxUnknownPubKey
|
||||
}
|
||||
if !bytes.Equal(in.PubKey.Address(), acc.Address) {
|
||||
return blk.ErrTxInvalidPubKey
|
||||
}
|
||||
acc.PubKey = in.PubKey
|
||||
} else {
|
||||
in.PubKey = account.PubKeyNil{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *State) ValidateInputs(accounts map[string]*account.Account, signBytes []byte, ins []*blk.TxInput) (total uint64, err error) {
|
||||
for _, in := range ins {
|
||||
acc := accounts[string(in.Address)]
|
||||
@ -261,6 +268,46 @@ func (s *State) ExecTx(tx_ blk.Tx) error {
|
||||
s.UpdateAccounts(accounts)
|
||||
return nil
|
||||
|
||||
case *blk.CallTx:
|
||||
tx := tx_.(*blk.CallTx)
|
||||
accounts := map[string]*account.Account{}
|
||||
inAcc := s.GetAccount(tx.Input.Address)
|
||||
if inAcc == nil {
|
||||
return blk.ErrTxInvalidAddress
|
||||
}
|
||||
// PubKey should be present in either "inAcc" or "tx.Input"
|
||||
if err := checkInputPubKey(inAcc, tx.Input); err != nil {
|
||||
return err
|
||||
}
|
||||
accounts[string(tx.Input.Address)] = inAcc
|
||||
signBytes := account.SignBytes(tx)
|
||||
inTotal, err := s.ValidateInputs(accounts, signBytes, []*blk.TxInput{tx.Input})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// validate output address
|
||||
if len(tx.Address) != 20 {
|
||||
return blk.ErrTxInvalidAddress
|
||||
}
|
||||
outAcc := s.GetAccount(tx.Address)
|
||||
if outAcc == nil {
|
||||
return blk.ErrTxInvalidAddress
|
||||
}
|
||||
accounts[string(tx.Address)] = outAcc
|
||||
|
||||
// TODO: fees
|
||||
// inTotal -= fees
|
||||
|
||||
// Good! Adjust accounts
|
||||
s.AdjustByInputs(accounts, []*blk.TxInput{tx.Input})
|
||||
outAcc.Balance += inTotal
|
||||
s.UpdateAccounts(accounts)
|
||||
|
||||
// TODO: Run the contract call!
|
||||
|
||||
return nil
|
||||
|
||||
case *blk.BondTx:
|
||||
tx := tx_.(*blk.BondTx)
|
||||
valInfo := s.GetValidatorInfo(tx.PubKey.Address())
|
||||
|
Loading…
x
Reference in New Issue
Block a user