mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-26 07:12:16 +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:
|
Account Txs:
|
||||||
- SendTx Send coins to address
|
- SendTx Send coins to address
|
||||||
|
- CallTx Send a msg to a contract that runs in the vm
|
||||||
|
|
||||||
Validation Txs:
|
Validation Txs:
|
||||||
- BondTx New validator posts a bond
|
- BondTx New validator posts a bond
|
||||||
@ -39,6 +40,7 @@ type Tx interface {
|
|||||||
const (
|
const (
|
||||||
// Account transactions
|
// Account transactions
|
||||||
TxTypeSend = byte(0x01)
|
TxTypeSend = byte(0x01)
|
||||||
|
TxTypeCall = byte(0x02)
|
||||||
|
|
||||||
// Validation transactions
|
// Validation transactions
|
||||||
TxTypeBond = byte(0x11)
|
TxTypeBond = byte(0x11)
|
||||||
@ -51,6 +53,7 @@ const (
|
|||||||
var _ = binary.RegisterInterface(
|
var _ = binary.RegisterInterface(
|
||||||
struct{ Tx }{},
|
struct{ Tx }{},
|
||||||
binary.ConcreteType{&SendTx{}},
|
binary.ConcreteType{&SendTx{}},
|
||||||
|
binary.ConcreteType{&CallTx{}},
|
||||||
binary.ConcreteType{&BondTx{}},
|
binary.ConcreteType{&BondTx{}},
|
||||||
binary.ConcreteType{&UnbondTx{}},
|
binary.ConcreteType{&UnbondTx{}},
|
||||||
binary.ConcreteType{&RebondTx{}},
|
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 {
|
type BondTx struct {
|
||||||
PubKey account.PubKeyEd25519
|
PubKey account.PubKeyEd25519
|
||||||
Inputs []*TxInput
|
Inputs []*TxInput
|
||||||
|
@ -128,16 +128,8 @@ func (s *State) GetOrMakeAccounts(ins []*blk.TxInput, outs []*blk.TxOutput) (map
|
|||||||
return nil, blk.ErrTxInvalidAddress
|
return nil, blk.ErrTxInvalidAddress
|
||||||
}
|
}
|
||||||
// PubKey should be present in either "account" or "in"
|
// PubKey should be present in either "account" or "in"
|
||||||
if _, isNil := acc.PubKey.(account.PubKeyNil); isNil {
|
if err := checkInputPubKey(acc, in); err != nil {
|
||||||
if _, isNil := in.PubKey.(account.PubKeyNil); isNil {
|
return nil, err
|
||||||
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{}
|
|
||||||
}
|
}
|
||||||
accounts[string(in.Address)] = acc
|
accounts[string(in.Address)] = acc
|
||||||
}
|
}
|
||||||
@ -161,6 +153,21 @@ func (s *State) GetOrMakeAccounts(ins []*blk.TxInput, outs []*blk.TxOutput) (map
|
|||||||
return accounts, nil
|
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) {
|
func (s *State) ValidateInputs(accounts map[string]*account.Account, signBytes []byte, ins []*blk.TxInput) (total uint64, err error) {
|
||||||
for _, in := range ins {
|
for _, in := range ins {
|
||||||
acc := accounts[string(in.Address)]
|
acc := accounts[string(in.Address)]
|
||||||
@ -261,6 +268,46 @@ func (s *State) ExecTx(tx_ blk.Tx) error {
|
|||||||
s.UpdateAccounts(accounts)
|
s.UpdateAccounts(accounts)
|
||||||
return nil
|
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:
|
case *blk.BondTx:
|
||||||
tx := tx_.(*blk.BondTx)
|
tx := tx_.(*blk.BondTx)
|
||||||
valInfo := s.GetValidatorInfo(tx.PubKey.Address())
|
valInfo := s.GetValidatorInfo(tx.PubKey.Address())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user