mirror of
https://github.com/fluencelabs/tendermint
synced 2025-05-25 20:21:21 +00:00
Address is generated with VMAppState, and it increments the nonce too.
This commit is contained in:
parent
36dca3981b
commit
b7553e2bfe
@ -277,8 +277,10 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
|
|||||||
return nil
|
return nil
|
||||||
|
|
||||||
case *blk.CallTx:
|
case *blk.CallTx:
|
||||||
|
var inAcc, outAcc *account.Account
|
||||||
|
|
||||||
// Validate input
|
// Validate input
|
||||||
inAcc := s.GetAccount(tx.Input.Address)
|
inAcc = s.GetAccount(tx.Input.Address)
|
||||||
if inAcc == nil {
|
if inAcc == nil {
|
||||||
return blk.ErrTxInvalidAddress
|
return blk.ErrTxInvalidAddress
|
||||||
}
|
}
|
||||||
@ -295,13 +297,16 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
|
|||||||
return blk.ErrTxInsufficientFunds
|
return blk.ErrTxInsufficientFunds
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate output
|
createAccount := len(tx.Address) == 0
|
||||||
if len(tx.Address) != 20 {
|
if !createAccount {
|
||||||
return blk.ErrTxInvalidAddress
|
// Validate output
|
||||||
}
|
if len(tx.Address) != 20 {
|
||||||
outAcc := s.GetAccount(tx.Address)
|
return blk.ErrTxInvalidAddress
|
||||||
if outAcc == nil {
|
}
|
||||||
return blk.ErrTxInvalidAddress
|
outAcc = s.GetAccount(tx.Address)
|
||||||
|
if outAcc == nil {
|
||||||
|
return blk.ErrTxInvalidAddress
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Good!
|
// Good!
|
||||||
@ -316,9 +321,18 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
|
|||||||
BlockTime: s.LastBlockTime.Unix(),
|
BlockTime: s.LastBlockTime.Unix(),
|
||||||
GasLimit: 10000000,
|
GasLimit: 10000000,
|
||||||
}
|
}
|
||||||
caller := toVMAccount(inAcc)
|
var caller, callee *vm.Account
|
||||||
callee := toVMAccount(outAcc)
|
var err error
|
||||||
appState.AddAccount(caller) // because we adjusted by input above.
|
caller = toVMAccount(inAcc)
|
||||||
|
if outAcc == nil {
|
||||||
|
callee = toVMAccount(outAcc)
|
||||||
|
} else {
|
||||||
|
callee, err = appState.CreateAccount(caller)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
appState.AddAccount(caller) // because we adjusted by input above, and bumped nonce maybe.
|
||||||
appState.AddAccount(callee) // because we adjusted by input above.
|
appState.AddAccount(callee) // because we adjusted by input above.
|
||||||
vmach := vm.NewVM(appState, params, caller.Address)
|
vmach := vm.NewVM(appState, params, caller.Address)
|
||||||
gas := tx.GasLimit
|
gas := tx.GasLimit
|
||||||
@ -330,6 +344,9 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
|
|||||||
// Throw away 'appState' which holds incomplete updates.
|
// Throw away 'appState' which holds incomplete updates.
|
||||||
} else {
|
} else {
|
||||||
// Success
|
// Success
|
||||||
|
if createAccount {
|
||||||
|
callee.Code = ret
|
||||||
|
}
|
||||||
appState.Sync()
|
appState.Sync()
|
||||||
}
|
}
|
||||||
// Create a receipt from the ret and whether errored.
|
// Create a receipt from the ret and whether errored.
|
||||||
@ -339,6 +356,8 @@ func (s *State) ExecTx(tx_ blk.Tx, runCall bool) error {
|
|||||||
// the proposer determines the order of txs.
|
// the proposer determines the order of txs.
|
||||||
// So mempool will skip the actual .Call(),
|
// So mempool will skip the actual .Call(),
|
||||||
// and only deduct from the caller's balance.
|
// and only deduct from the caller's balance.
|
||||||
|
inAcc.Balance -= value
|
||||||
|
s.UpdateAccount(inAcc)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
"github.com/tendermint/tendermint/merkle"
|
"github.com/tendermint/tendermint/merkle"
|
||||||
"github.com/tendermint/tendermint/vm"
|
"github.com/tendermint/tendermint/vm"
|
||||||
|
"github.com/tendermint/tendermint/vm/sha3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Converts state.Account to vm.Account struct.
|
// Converts state.Account to vm.Account struct.
|
||||||
@ -115,7 +116,18 @@ func (vas *VMAppState) DeleteAccount(account *vm.Account) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vas *VMAppState) CreateAccount(addr vm.Word) (*vm.Account, error) {
|
// Creates a 20 byte address and bumps the creator's nonce.
|
||||||
|
func (vas *VMAppState) CreateAccount(creator *vm.Account) (*vm.Account, error) {
|
||||||
|
|
||||||
|
// Generate an address
|
||||||
|
nonce := creator.Nonce
|
||||||
|
creator.Nonce += 1
|
||||||
|
temp := make([]byte, 32+8)
|
||||||
|
copy(temp, creator.Address[:])
|
||||||
|
vm.PutUint64(temp[32:], nonce)
|
||||||
|
addr := vm.RightPadWord(sha3.Sha3(temp)[:20])
|
||||||
|
|
||||||
|
// Create account from address.
|
||||||
account, deleted := unpack(vas.accounts[addr.String()])
|
account, deleted := unpack(vas.accounts[addr.String()])
|
||||||
if deleted || account == nil {
|
if deleted || account == nil {
|
||||||
account = &vm.Account{
|
account = &vm.Account{
|
||||||
@ -128,7 +140,8 @@ func (vas *VMAppState) CreateAccount(addr vm.Word) (*vm.Account, error) {
|
|||||||
vas.accounts[addr.String()] = AccountInfo{account, false}
|
vas.accounts[addr.String()] = AccountInfo{account, false}
|
||||||
return account, nil
|
return account, nil
|
||||||
} else {
|
} else {
|
||||||
return nil, Errorf("Account already exists: %X", addr)
|
panic(Fmt("Could not create account, address already exists: %X", addr))
|
||||||
|
// return nil, Errorf("Account already exists: %X", addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/vm"
|
. "github.com/tendermint/tendermint/vm"
|
||||||
|
"github.com/tendermint/tendermint/vm/sha3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FakeAppState struct {
|
type FakeAppState struct {
|
||||||
@ -43,7 +44,8 @@ func (fas *FakeAppState) DeleteAccount(account *Account) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fas *FakeAppState) CreateAccount(addr Word) (*Account, error) {
|
func (fas *FakeAppState) CreateAccount(creator *Account) (*Account, error) {
|
||||||
|
addr := createAddress(creator)
|
||||||
account := fas.accounts[addr.String()]
|
account := fas.accounts[addr.String()]
|
||||||
if account == nil {
|
if account == nil {
|
||||||
return &Account{
|
return &Account{
|
||||||
@ -102,16 +104,24 @@ func main() {
|
|||||||
ourVm := NewVM(appState, params, Zero)
|
ourVm := NewVM(appState, params, Zero)
|
||||||
|
|
||||||
// Create accounts
|
// Create accounts
|
||||||
account1, err := appState.CreateAccount(Uint64ToWord(100))
|
account1 := &Account{
|
||||||
if err != nil {
|
Address: Uint64ToWord(100),
|
||||||
panic(err)
|
|
||||||
}
|
}
|
||||||
account2, err := appState.CreateAccount(Uint64ToWord(101))
|
account2 := &Account{
|
||||||
if err != nil {
|
Address: Uint64ToWord(101),
|
||||||
panic(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var gas uint64 = 1000
|
var gas uint64 = 1000
|
||||||
output, err := ourVm.Call(account1, account2, []byte{0x60, 0x01, 0x60, 0x01}, []byte{}, 0, &gas)
|
output, err := ourVm.Call(account1, account2, []byte{0x60, 0x01, 0x60, 0x01}, []byte{}, 0, &gas)
|
||||||
fmt.Printf("Output: %v Error: %v\n", output, err)
|
fmt.Printf("Output: %v Error: %v\n", output, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Creates a 20 byte address and bumps the nonce.
|
||||||
|
func createAddress(creator *Account) Word {
|
||||||
|
nonce := creator.Nonce
|
||||||
|
creator.Nonce += 1
|
||||||
|
temp := make([]byte, 32+8)
|
||||||
|
copy(temp, creator.Address[:])
|
||||||
|
PutUint64(temp[32:], nonce)
|
||||||
|
return RightPadWord(sha3.Sha3(temp)[:20])
|
||||||
|
}
|
||||||
|
@ -48,7 +48,7 @@ type AppState interface {
|
|||||||
GetAccount(addr Word) (*Account, error)
|
GetAccount(addr Word) (*Account, error)
|
||||||
UpdateAccount(*Account) error
|
UpdateAccount(*Account) error
|
||||||
DeleteAccount(*Account) error
|
DeleteAccount(*Account) error
|
||||||
CreateAccount(addr Word) (*Account, error)
|
CreateAccount(*Account) (*Account, error)
|
||||||
|
|
||||||
// Storage
|
// Storage
|
||||||
GetStorage(Word, Word) (Word, error)
|
GetStorage(Word, Word) (Word, error)
|
||||||
|
16
vm/vm.go
16
vm/vm.go
@ -46,6 +46,7 @@ func NewVM(appState AppState, params Params, origin Word) *VM {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CONTRACT appState is aware of caller and callee, so we can just mutate them.
|
||||||
// value: To be transferred from caller to callee. Refunded upon error.
|
// value: To be transferred from caller to callee. Refunded upon error.
|
||||||
// gas: Available gas. No refunds for gas.
|
// gas: Available gas. No refunds for gas.
|
||||||
func (vm *VM) Call(caller, callee *Account, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
|
func (vm *VM) Call(caller, callee *Account, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
|
||||||
@ -541,14 +542,9 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
|||||||
return nil, firstErr(err, ErrInsufficientBalance)
|
return nil, firstErr(err, ErrInsufficientBalance)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new address
|
|
||||||
nonce := caller.Nonce
|
|
||||||
addr := createAddress(caller.Address, nonce)
|
|
||||||
caller.Nonce += 1
|
|
||||||
|
|
||||||
// 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(addr)
|
newAccount, err := vm.appState.CreateAccount(caller)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
stack.Push(Zero)
|
stack.Push(Zero)
|
||||||
fmt.Printf(" (*) 0x0 %v\n", err)
|
fmt.Printf(" (*) 0x0 %v\n", err)
|
||||||
@ -708,14 +704,6 @@ func useGas(gas *uint64, gasToUse uint64) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a 20 byte address from the creatorAddr and nonce.
|
|
||||||
func createAddress(creatorAddr Word, nonce uint64) Word {
|
|
||||||
temp := make([]byte, 32+8)
|
|
||||||
copy(temp, creatorAddr[:])
|
|
||||||
PutUint64(temp[32:], nonce)
|
|
||||||
return RightPadWord(sha3.Sha3(temp)[:20])
|
|
||||||
}
|
|
||||||
|
|
||||||
func transfer(from, to *Account, amount uint64) error {
|
func transfer(from, to *Account, amount uint64) error {
|
||||||
if from.Balance < amount {
|
if from.Balance < amount {
|
||||||
return ErrInsufficientBalance
|
return ErrInsufficientBalance
|
||||||
|
Loading…
x
Reference in New Issue
Block a user