Browse Source

Fixed issues from review with Ethan

pull/32/head
Jae Kwon 9 years ago
parent
commit
55d8e29e32
4 changed files with 40 additions and 26 deletions
  1. +5
    -2
      merkle/iavl_tree.go
  2. +7
    -6
      state/state.go
  3. +24
    -14
      state/vm_app_state.go
  4. +4
    -4
      vm/vm.go

+ 5
- 2
merkle/iavl_tree.go View File

@ -120,11 +120,14 @@ func (t *IAVLTree) Save() []byte {
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) {
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{}) {


+ 7
- 6
state/state.go View File

@ -320,7 +320,7 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
err error = nil
caller *vm.Account = toVMAccount(inAcc)
callee *vm.Account = nil
appState = NewVMAppState(s)
appState = NewVMAppState(s) // TODO: confusing.
params = vm.Params{
BlockHeight: uint64(s.LastBlockHeight),
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.AddAccount(callee) // because we adjusted by input above.
appState.UpdateAccount(caller) // because we adjusted by input above, and bumped nonce maybe.
appState.UpdateAccount(callee) // because we adjusted by input above.
vmach := vm.NewVM(appState, params, caller.Address)
ret, err_ := vmach.Call(caller, callee, outAcc.Code, tx.Data, value, &gas)
if err_ != nil {
// NOTE: Call() transfers the value from caller to callee iff call succeeds.
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.
inAcc.Balance -= tx.Fee
s.UpdateAccount(inAcc)
@ -357,7 +358,7 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
appState.Sync()
}
// 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 {
// The mempool does not call txs until
// the proposer determines the order of txs.


+ 24
- 14
state/vm_app_state.go View File

@ -1,6 +1,7 @@
package state
import (
"bytes"
"sort"
ac "github.com/tendermint/tendermint/account"
@ -61,16 +62,6 @@ func unpack(accInfo AccountInfo) (*vm.Account, bool) {
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) {
account, deleted := unpack(vas.accounts[addr.String()])
if deleted {
@ -175,6 +166,7 @@ func (vas *VMAppState) SetStorage(addr vm.Word, key vm.Word, value vm.Word) (boo
return ok, nil
}
// CONTRACT the updates are in deterministic order.
func (vas *VMAppState) Sync() {
// 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(
binary.BasicCodec, // TODO change
binary.BasicCodec, // TODO change
1024, // TODO change.
vas.state.DB,
)
for addrKey, value := range vas.storage {
addrKeyBytes := []byte(addrKey)
var currentAccount *vm.Account
var deleted bool
for _, storageKey := range storageKeyStrs {
value := vas.storage[storageKey]
addrKeyBytes := []byte(storageKey)
addr := 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() {
_, removed := storage.Remove(key)
if !removed {


+ 4
- 4
vm/vm.go View File

@ -530,7 +530,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
fmt.Printf(" => %v\n", log)
case CREATE: // 0xF0
value := stack.Pop64()
contractValue := stack.Pop64()
offset, size := stack.Pop64(), stack.Pop64()
input, ok := subslice(memory, offset, size)
if !ok {
@ -538,19 +538,19 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
}
// Check balance
if caller.Balance < value {
if callee.Balance < contractValue {
return nil, firstErr(err, ErrInsufficientBalance)
}
// 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 {
stack.Push(Zero)
fmt.Printf(" (*) 0x0 %v\n", err)
} else {
// 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 {
stack.Push(Zero)
} else {


Loading…
Cancel
Save