From 208154f3c13364dc306a2d0f982efbe42a5c21af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 26 Oct 2023 10:46:56 -0700 Subject: [PATCH] commit storage temporarily before creating account, so host can observe existing writes --- runtime/runtime_test.go | 13 ++++++++++++- runtime/stdlib/account.go | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index f19f19b04d..9c6a9c400f 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -3231,6 +3231,9 @@ func TestRuntimeTransaction_CreateAccount(t *testing.T) { script := []byte(` transaction { prepare(signer: AuthAccount) { + // Important: Perform a write which will be pending until the end of the transaction, + // but should be (temporarily) committed when the AuthAccount constructor is called + signer.save(42, to: /storage/answer) AuthAccount(payer: signer) } } @@ -3238,12 +3241,20 @@ func TestRuntimeTransaction_CreateAccount(t *testing.T) { var events []cadence.Event + var performedWrite bool + + onWrite := func(owner, key, value []byte) { + performedWrite = true + } + runtimeInterface := &testRuntimeInterface{ - storage: newTestLedger(nil, nil), + storage: newTestLedger(nil, onWrite), getSigningAccounts: func() ([]Address, error) { return []Address{{42}}, nil }, createAccount: func(payer Address) (address Address, err error) { + // Check that pending writes were committed before + assert.True(t, performedWrite) return Address{42}, nil }, emitEvent: func(event cadence.Event) error { diff --git a/runtime/stdlib/account.go b/runtime/stdlib/account.go index 45b0a17d2a..f56cfada2d 100644 --- a/runtime/stdlib/account.go +++ b/runtime/stdlib/account.go @@ -64,6 +64,10 @@ type AccountIDGenerator interface { GenerateAccountID(address common.Address) (uint64, error) } +type StorageCommitter interface { + CommitStorageTemporarily(inter *interpreter.Interpreter) error +} + type AuthAccountHandler interface { AccountIDGenerator BalanceProvider @@ -77,6 +81,7 @@ type AuthAccountHandler interface { } type AccountCreator interface { + StorageCommitter EventEmitter AuthAccountHandler // CreateAccount creates a new account. @@ -120,6 +125,11 @@ func NewAuthAccountConstructor(creator AccountCreator) StandardLibraryValue { payerAddress := payerAddressValue.ToAddress() + err := creator.CommitStorageTemporarily(inter) + if err != nil { + panic(err) + } + addressValue := interpreter.NewAddressValueFromConstructor( inter, func() (address common.Address) { @@ -383,7 +393,7 @@ func newAccountAvailableBalanceGetFunction( } type StorageUsedProvider interface { - CommitStorageTemporarily(inter *interpreter.Interpreter) error + StorageCommitter // GetStorageUsed gets storage used in bytes by the address at the moment of the function call. GetStorageUsed(address common.Address) (uint64, error) } @@ -422,7 +432,7 @@ func newStorageUsedGetFunction( } type StorageCapacityProvider interface { - CommitStorageTemporarily(inter *interpreter.Interpreter) error + StorageCommitter // GetStorageCapacity gets storage capacity in bytes on the address. GetStorageCapacity(address common.Address) (uint64, error) }