mirror of
https://github.com/fluencelabs/tendermint
synced 2025-07-31 20:21:56 +00:00
Merge pull request #37 from tendermint/create_and_transact
state: fixes for creating a contract and msging it in the same block
This commit is contained in:
10
block/tx.go
10
block/tx.go
@@ -18,9 +18,17 @@ var (
|
||||
ErrTxUnknownPubKey = errors.New("Error unknown pubkey")
|
||||
ErrTxInvalidPubKey = errors.New("Error invalid pubkey")
|
||||
ErrTxInvalidSignature = errors.New("Error invalid signature")
|
||||
ErrTxInvalidSequence = errors.New("Error invalid sequence")
|
||||
)
|
||||
|
||||
type ErrTxInvalidSequence struct {
|
||||
Got uint64
|
||||
Expected uint64
|
||||
}
|
||||
|
||||
func (e ErrTxInvalidSequence) Error() string {
|
||||
return Fmt("Error invalid sequence. Got %d, expected %d", e.Got, e.Expected)
|
||||
}
|
||||
|
||||
/*
|
||||
Tx (Transaction) is an atomic operation on the ledger state.
|
||||
|
||||
|
@@ -196,7 +196,10 @@ func (s *State) ValidateInput(acc *account.Account, signBytes []byte, in *blk.Tx
|
||||
}
|
||||
// Check sequences
|
||||
if acc.Sequence+1 != in.Sequence {
|
||||
return blk.ErrTxInvalidSequence
|
||||
return blk.ErrTxInvalidSequence{
|
||||
Got: uint64(in.Sequence),
|
||||
Expected: uint64(acc.Sequence + 1),
|
||||
}
|
||||
}
|
||||
// Check amount
|
||||
if acc.Balance < in.Amount {
|
||||
@@ -308,13 +311,14 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
|
||||
log.Debug(Fmt("Destination address is not 20 bytes %X", tx.Address))
|
||||
return blk.ErrTxInvalidAddress
|
||||
}
|
||||
// this may be nil if we are still in mempool and contract was created in same block as this tx
|
||||
// but that's fine, because the account will be created properly when the create tx runs in the block
|
||||
// and then this won't return nil. otherwise, we take their fee
|
||||
outAcc = s.GetAccount(tx.Address)
|
||||
if outAcc == nil {
|
||||
log.Debug(Fmt("Cannot find destination address %X", tx.Address))
|
||||
return blk.ErrTxInvalidAddress
|
||||
}
|
||||
}
|
||||
|
||||
log.Debug(Fmt("Out account: %v", outAcc))
|
||||
|
||||
// Good!
|
||||
value := tx.Input.Amount - tx.Fee
|
||||
inAcc.Sequence += 1
|
||||
@@ -338,9 +342,18 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
|
||||
|
||||
// Maybe create a new callee account if
|
||||
// this transaction is creating a new contract.
|
||||
if outAcc != nil {
|
||||
if !createAccount {
|
||||
if outAcc == nil {
|
||||
// take fees (sorry pal)
|
||||
inAcc.Balance -= tx.Fee
|
||||
s.UpdateAccount(inAcc)
|
||||
log.Debug(Fmt("Cannot find destination address %X. Deducting fee from caller", tx.Address))
|
||||
return blk.ErrTxInvalidAddress
|
||||
|
||||
}
|
||||
callee = toVMAccount(outAcc)
|
||||
code = callee.Code
|
||||
log.Debug(Fmt("Calling contract %X with code %X", callee.Address.Address(), callee.Code))
|
||||
} else {
|
||||
callee, err = appState.CreateAccount(caller)
|
||||
if err != nil {
|
||||
@@ -350,6 +363,7 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
|
||||
log.Debug(Fmt("Created new account %X", callee.Address.Address()))
|
||||
code = tx.Data
|
||||
}
|
||||
log.Debug(Fmt("Code for this contract: %X", code))
|
||||
|
||||
appState.UpdateAccount(caller) // because we adjusted by input above, and bumped nonce maybe.
|
||||
appState.UpdateAccount(callee) // because we adjusted by input above.
|
||||
@@ -358,10 +372,12 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
|
||||
ret, err := vmach.Call(caller, callee, code, tx.Data, value, &gas)
|
||||
if err != nil {
|
||||
// Failure. Charge the gas fee. The 'value' was otherwise not transferred.
|
||||
log.Debug(Fmt("Error on execution: %v", err))
|
||||
inAcc.Balance -= tx.Fee
|
||||
s.UpdateAccount(inAcc)
|
||||
// Throw away 'appState' which holds incomplete updates.
|
||||
// Throw away 'appState' which holds incomplete updates (don't sync it).
|
||||
} else {
|
||||
log.Debug("Successful execution")
|
||||
// Success
|
||||
if createAccount {
|
||||
callee.Code = ret
|
||||
@@ -377,6 +393,9 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
|
||||
// So mempool will skip the actual .Call(),
|
||||
// and only deduct from the caller's balance.
|
||||
inAcc.Balance -= value
|
||||
if createAccount {
|
||||
inAcc.Sequence += 1
|
||||
}
|
||||
s.UpdateAccount(inAcc)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user