mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-23 17:51:39 +00:00
Fixed issues from review with Ethan
This commit is contained in:
@ -120,11 +120,14 @@ func (t *IAVLTree) Save() []byte {
|
|||||||
return t.root.save(t)
|
return t.root.save(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sets the root node by reading from db.
|
||||||
|
// If the hash is empty, then sets root to nil.
|
||||||
func (t *IAVLTree) Load(hash []byte) {
|
func (t *IAVLTree) Load(hash []byte) {
|
||||||
if len(hash) == 0 {
|
if len(hash) == 0 {
|
||||||
panic("IAVLTree.Load() hash was nil")
|
t.root = nil
|
||||||
}
|
} else {
|
||||||
t.root = t.ndb.GetNode(t, hash)
|
t.root = t.ndb.GetNode(t, hash)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *IAVLTree) Get(key interface{}) (index uint64, value interface{}) {
|
func (t *IAVLTree) Get(key interface{}) (index uint64, value interface{}) {
|
||||||
|
@ -320,7 +320,7 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
|
|||||||
err error = nil
|
err error = nil
|
||||||
caller *vm.Account = toVMAccount(inAcc)
|
caller *vm.Account = toVMAccount(inAcc)
|
||||||
callee *vm.Account = nil
|
callee *vm.Account = nil
|
||||||
appState = NewVMAppState(s)
|
appState = NewVMAppState(s) // TODO: confusing.
|
||||||
params = vm.Params{
|
params = vm.Params{
|
||||||
BlockHeight: uint64(s.LastBlockHeight),
|
BlockHeight: uint64(s.LastBlockHeight),
|
||||||
BlockHash: vm.BytesToWord(s.LastBlockHash),
|
BlockHash: vm.BytesToWord(s.LastBlockHash),
|
||||||
@ -340,11 +340,12 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appState.AddAccount(caller) // because we adjusted by input above, and bumped nonce maybe.
|
appState.UpdateAccount(caller) // because we adjusted by input above, and bumped nonce maybe.
|
||||||
appState.AddAccount(callee) // because we adjusted by input above.
|
appState.UpdateAccount(callee) // because we adjusted by input above.
|
||||||
vmach := vm.NewVM(appState, params, caller.Address)
|
vmach := vm.NewVM(appState, params, caller.Address)
|
||||||
ret, err_ := vmach.Call(caller, callee, outAcc.Code, tx.Data, value, &gas)
|
// NOTE: Call() transfers the value from caller to callee iff call succeeds.
|
||||||
if err_ != nil {
|
ret, err := vmach.Call(caller, callee, outAcc.Code, tx.Data, value, &gas)
|
||||||
|
if err != nil {
|
||||||
// Failure. Charge the gas fee. The 'value' was otherwise not transferred.
|
// Failure. Charge the gas fee. The 'value' was otherwise not transferred.
|
||||||
inAcc.Balance -= tx.Fee
|
inAcc.Balance -= tx.Fee
|
||||||
s.UpdateAccount(inAcc)
|
s.UpdateAccount(inAcc)
|
||||||
@ -357,7 +358,7 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
|
|||||||
appState.Sync()
|
appState.Sync()
|
||||||
}
|
}
|
||||||
// Create a receipt from the ret and whether errored.
|
// Create a receipt from the ret and whether errored.
|
||||||
log.Info("VM call complete", "caller", caller, "callee", callee, "return", ret, "err", err_)
|
log.Info("VM call complete", "caller", caller, "callee", callee, "return", ret, "err", err)
|
||||||
} else {
|
} else {
|
||||||
// The mempool does not call txs until
|
// The mempool does not call txs until
|
||||||
// the proposer determines the order of txs.
|
// the proposer determines the order of txs.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
ac "github.com/tendermint/tendermint/account"
|
ac "github.com/tendermint/tendermint/account"
|
||||||
@ -61,16 +62,6 @@ func unpack(accInfo AccountInfo) (*vm.Account, bool) {
|
|||||||
return accInfo.account, accInfo.deleted
|
return accInfo.account, accInfo.deleted
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to add the origin of the tx to VMAppState.
|
|
||||||
func (vas *VMAppState) AddAccount(account *vm.Account) error {
|
|
||||||
if _, ok := vas.accounts[account.Address.String()]; ok {
|
|
||||||
return Errorf("Account already exists: %X", account.Address)
|
|
||||||
} else {
|
|
||||||
vas.accounts[account.Address.String()] = AccountInfo{account, false}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vas *VMAppState) GetAccount(addr vm.Word) (*vm.Account, error) {
|
func (vas *VMAppState) GetAccount(addr vm.Word) (*vm.Account, error) {
|
||||||
account, deleted := unpack(vas.accounts[addr.String()])
|
account, deleted := unpack(vas.accounts[addr.String()])
|
||||||
if deleted {
|
if deleted {
|
||||||
@ -175,6 +166,7 @@ func (vas *VMAppState) SetStorage(addr vm.Word, key vm.Word, value vm.Word) (boo
|
|||||||
return ok, nil
|
return ok, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CONTRACT the updates are in deterministic order.
|
||||||
func (vas *VMAppState) Sync() {
|
func (vas *VMAppState) Sync() {
|
||||||
|
|
||||||
// Determine order for accounts
|
// Determine order for accounts
|
||||||
@ -200,18 +192,36 @@ func (vas *VMAppState) Sync() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update or delete storage items.
|
// Determine order for storage updates
|
||||||
|
// The address comes first so it'll be grouped.
|
||||||
|
storageKeyStrs := []string{}
|
||||||
|
for keyStr := range vas.storage {
|
||||||
|
storageKeyStrs = append(storageKeyStrs, keyStr)
|
||||||
|
}
|
||||||
|
sort.Strings(storageKeyStrs)
|
||||||
|
|
||||||
|
// Update storage for all account/key.
|
||||||
storage := merkle.NewIAVLTree(
|
storage := merkle.NewIAVLTree(
|
||||||
binary.BasicCodec, // TODO change
|
binary.BasicCodec, // TODO change
|
||||||
binary.BasicCodec, // TODO change
|
binary.BasicCodec, // TODO change
|
||||||
1024, // TODO change.
|
1024, // TODO change.
|
||||||
vas.state.DB,
|
vas.state.DB,
|
||||||
)
|
)
|
||||||
|
var currentAccount *vm.Account
|
||||||
for addrKey, value := range vas.storage {
|
var deleted bool
|
||||||
addrKeyBytes := []byte(addrKey)
|
for _, storageKey := range storageKeyStrs {
|
||||||
|
value := vas.storage[storageKey]
|
||||||
|
addrKeyBytes := []byte(storageKey)
|
||||||
addr := addrKeyBytes[:32]
|
addr := addrKeyBytes[:32]
|
||||||
key := addrKeyBytes[32:]
|
key := addrKeyBytes[32:]
|
||||||
|
if currentAccount == nil || !bytes.Equal(currentAccount.Address[:], addr) {
|
||||||
|
currentAccount, deleted = unpack(vas.accounts[string(addr)])
|
||||||
|
if deleted {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
storageRoot := currentAccount.StorageRoot
|
||||||
|
storage.Load(storageRoot.Bytes())
|
||||||
|
}
|
||||||
if value.IsZero() {
|
if value.IsZero() {
|
||||||
_, removed := storage.Remove(key)
|
_, removed := storage.Remove(key)
|
||||||
if !removed {
|
if !removed {
|
||||||
|
8
vm/vm.go
8
vm/vm.go
@ -530,7 +530,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
|||||||
fmt.Printf(" => %v\n", log)
|
fmt.Printf(" => %v\n", log)
|
||||||
|
|
||||||
case CREATE: // 0xF0
|
case CREATE: // 0xF0
|
||||||
value := stack.Pop64()
|
contractValue := stack.Pop64()
|
||||||
offset, size := stack.Pop64(), stack.Pop64()
|
offset, size := stack.Pop64(), stack.Pop64()
|
||||||
input, ok := subslice(memory, offset, size)
|
input, ok := subslice(memory, offset, size)
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -538,19 +538,19 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check balance
|
// Check balance
|
||||||
if caller.Balance < value {
|
if callee.Balance < contractValue {
|
||||||
return nil, firstErr(err, ErrInsufficientBalance)
|
return nil, firstErr(err, ErrInsufficientBalance)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO charge for gas to create account _ the code length * GasCreateByte
|
// TODO charge for gas to create account _ the code length * GasCreateByte
|
||||||
|
|
||||||
newAccount, err := vm.appState.CreateAccount(caller)
|
newAccount, err := vm.appState.CreateAccount(callee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
stack.Push(Zero)
|
stack.Push(Zero)
|
||||||
fmt.Printf(" (*) 0x0 %v\n", err)
|
fmt.Printf(" (*) 0x0 %v\n", err)
|
||||||
} else {
|
} else {
|
||||||
// Run the input to get the contract code.
|
// Run the input to get the contract code.
|
||||||
ret, err_ := vm.Call(callee, newAccount, input, input, value, gas)
|
ret, err_ := vm.Call(callee, newAccount, input, input, contractValue, gas)
|
||||||
if err_ != nil {
|
if err_ != nil {
|
||||||
stack.Push(Zero)
|
stack.Push(Zero)
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user