mirror of
https://github.com/fluencelabs/tendermint
synced 2025-05-29 22:21:21 +00:00
fix suicide
This commit is contained in:
parent
b9cbb0dac5
commit
586498331b
@ -5,11 +5,11 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
acm "github.com/tendermint/tendermint/account"
|
acm "github.com/tendermint/tendermint/account"
|
||||||
"github.com/tendermint/tendermint/wire"
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
dbm "github.com/tendermint/tendermint/db"
|
dbm "github.com/tendermint/tendermint/db"
|
||||||
"github.com/tendermint/tendermint/merkle"
|
"github.com/tendermint/tendermint/merkle"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
|
"github.com/tendermint/tendermint/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeStorage(db dbm.DB, root []byte) merkle.Tree {
|
func makeStorage(db dbm.DB, root []byte) merkle.Tree {
|
||||||
@ -177,7 +177,7 @@ func (cache *BlockCache) Sync() {
|
|||||||
addr, key := Tuple256Split(storageKey)
|
addr, key := Tuple256Split(storageKey)
|
||||||
if addr != curAddr || curAcc == nil {
|
if addr != curAddr || curAcc == nil {
|
||||||
acc, storage, removed, _ := cache.accounts[string(addr.Postfix(20))].unpack()
|
acc, storage, removed, _ := cache.accounts[string(addr.Postfix(20))].unpack()
|
||||||
if storage == nil {
|
if !removed && storage == nil {
|
||||||
storage = makeStorage(cache.db, acc.StorageRoot)
|
storage = makeStorage(cache.db, acc.StorageRoot)
|
||||||
}
|
}
|
||||||
curAddr = addr
|
curAddr = addr
|
||||||
@ -211,7 +211,7 @@ func (cache *BlockCache) Sync() {
|
|||||||
for _, addrStr := range addrStrs {
|
for _, addrStr := range addrStrs {
|
||||||
acc, storage, removed, dirty := cache.accounts[addrStr].unpack()
|
acc, storage, removed, dirty := cache.accounts[addrStr].unpack()
|
||||||
if removed {
|
if removed {
|
||||||
removed := cache.backend.RemoveAccount(acc.Address)
|
removed := cache.backend.RemoveAccount([]byte(addrStr))
|
||||||
if !removed {
|
if !removed {
|
||||||
PanicCrisis(Fmt("Could not remove account to be removed: %X", acc.Address))
|
PanicCrisis(Fmt("Could not remove account to be removed: %X", acc.Address))
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,18 @@
|
|||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/tendermint/tendermint/account"
|
|
||||||
_ "github.com/tendermint/tendermint/config/tendermint_test"
|
|
||||||
"github.com/tendermint/tendermint/types"
|
|
||||||
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/tendermint/tendermint/account"
|
||||||
|
_ "github.com/tendermint/tendermint/config/tendermint_test"
|
||||||
|
"github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func execTxWithState(state *State, tx types.Tx, runCall bool) error {
|
func execTxWithState(state *State, tx types.Tx, runCall bool) error {
|
||||||
cache := NewBlockCache(state)
|
cache := NewBlockCache(state)
|
||||||
err := ExecTx(cache, tx, runCall, nil)
|
if err := ExecTx(cache, tx, runCall, nil); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
cache.Sync()
|
cache.Sync()
|
||||||
@ -570,6 +569,60 @@ proof-of-work chain as proof of what happened while they were gone `
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSuicide(t *testing.T) {
|
||||||
|
|
||||||
|
state, privAccounts, _ := RandGenesisState(3, true, 1000, 1, true, 1000)
|
||||||
|
|
||||||
|
acc0 := state.GetAccount(privAccounts[0].PubKey.Address())
|
||||||
|
acc0PubKey := privAccounts[0].PubKey
|
||||||
|
acc1 := state.GetAccount(privAccounts[1].PubKey.Address())
|
||||||
|
acc2 := state.GetAccount(privAccounts[2].Address)
|
||||||
|
sendingAmount, refundedBalance, oldBalance := int64(1), acc1.Balance, acc2.Balance
|
||||||
|
|
||||||
|
newAcc1 := state.GetAccount(acc1.Address)
|
||||||
|
|
||||||
|
// store 0x1 at 0x1, push an address, then suicide :)
|
||||||
|
contractCode := []byte{0x60, 0x01, 0x60, 0x01, 0x55, 0x73}
|
||||||
|
contractCode = append(contractCode, acc2.Address...)
|
||||||
|
contractCode = append(contractCode, 0xff)
|
||||||
|
newAcc1.Code = contractCode
|
||||||
|
state.UpdateAccount(newAcc1)
|
||||||
|
|
||||||
|
// send call tx with no data, cause suicide
|
||||||
|
tx := types.NewCallTxWithNonce(acc0PubKey, acc1.Address, nil, sendingAmount, 1000, 0, acc0.Sequence+1)
|
||||||
|
tx.Input.Signature = privAccounts[0].Sign(state.ChainID, tx)
|
||||||
|
|
||||||
|
// we use cache instead of execTxWithState so we can run the tx twice
|
||||||
|
cache := NewBlockCache(state)
|
||||||
|
if err := ExecTx(cache, tx, true, nil); err != nil {
|
||||||
|
t.Errorf("Got error in executing call transaction, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we do it again, we won't get an error, but the suicide
|
||||||
|
// shouldn't happen twice and the caller should lose fee
|
||||||
|
tx.Input.Sequence += 1
|
||||||
|
tx.Input.Signature = privAccounts[0].Sign(state.ChainID, tx)
|
||||||
|
if err := ExecTx(cache, tx, true, nil); err != nil {
|
||||||
|
t.Errorf("Got error in executing call transaction, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// commit the block
|
||||||
|
cache.Sync()
|
||||||
|
|
||||||
|
// acc2 should receive the sent funds and the contracts balance
|
||||||
|
newAcc2 := state.GetAccount(acc2.Address)
|
||||||
|
newBalance := sendingAmount + refundedBalance + oldBalance
|
||||||
|
if newAcc2.Balance != newBalance {
|
||||||
|
t.Errorf("Unexpected newAcc2 balance. Expected %v, got %v",
|
||||||
|
newAcc2.Balance, newBalance)
|
||||||
|
}
|
||||||
|
newAcc1 = state.GetAccount(acc1.Address)
|
||||||
|
if newAcc1 != nil {
|
||||||
|
t.Errorf("Expected account to be removed")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestAddValidator(t *testing.T) {
|
func TestAddValidator(t *testing.T) {
|
||||||
|
|
||||||
// Generate a state, save & load it.
|
// Generate a state, save & load it.
|
||||||
|
9
vm/vm.go
9
vm/vm.go
@ -174,9 +174,6 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
|
|||||||
|
|
||||||
switch op {
|
switch op {
|
||||||
|
|
||||||
case STOP: // 0x00
|
|
||||||
return nil, nil
|
|
||||||
|
|
||||||
case ADD: // 0x01
|
case ADD: // 0x01
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
xb := new(big.Int).SetBytes(x[:])
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
@ -837,7 +834,8 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
|
|||||||
if useGasNegative(gas, GasGetAccount, &err) {
|
if useGasNegative(gas, GasGetAccount, &err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// TODO if the receiver is , then make it the fee.
|
// TODO if the receiver is , then make it the fee. (?)
|
||||||
|
// TODO: create account if doesn't exist (no reason not to)
|
||||||
receiver := vm.appState.GetAccount(addr)
|
receiver := vm.appState.GetAccount(addr)
|
||||||
if receiver == nil {
|
if receiver == nil {
|
||||||
return nil, firstErr(err, ErrUnknownAddress)
|
return nil, firstErr(err, ErrUnknownAddress)
|
||||||
@ -849,6 +847,9 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
|
|||||||
dbg.Printf(" => (%X) %v\n", addr[:4], balance)
|
dbg.Printf(" => (%X) %v\n", addr[:4], balance)
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
||||||
|
case STOP: // 0x00
|
||||||
|
return nil, nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dbg.Printf("(pc) %-3v Invalid opcode %X\n", pc, op)
|
dbg.Printf("(pc) %-3v Invalid opcode %X\n", pc, op)
|
||||||
return nil, fmt.Errorf("Invalid opcode %X", op)
|
return nil, fmt.Errorf("Invalid opcode %X", op)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user