-
Notifications
You must be signed in to change notification settings - Fork 486
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AVM: Allow immutable access to foreign app accounts #3994
Changes from 10 commits
f79d2dd
fe7898e
2804373
4f81772
45e46fd
380cca3
b9e160c
a10d253
26a0660
10aa9df
2166891
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2907,3 +2907,31 @@ itxn_submit | |
|
||
TestApp(t, source, ep, "appl depth (8) exceeded") | ||
} | ||
|
||
func TestForeignAppAccountAccess(t *testing.T) { | ||
partitiontest.PartitionTest(t) | ||
|
||
ep, tx, ledger := MakeSampleEnv() | ||
ledger.NewAccount(appAddr(888), 50_000) | ||
tx.ForeignApps = []basics.AppIndex{basics.AppIndex(2)} | ||
|
||
// This app looks itself up in the ledger, so we need to put it in there. | ||
ledger.NewApp(tx.Sender, 2, basics.AppParams{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you change this Also I think that comment is a cut-n-paste. The app isn't looking itself up. The app being tested looks up this app. |
||
ApprovalProgram: TestProg(t, "int 1", AssemblerMaxVersion).Program, | ||
ClearStateProgram: TestProg(t, "int 1", AssemblerMaxVersion).Program, | ||
}) | ||
|
||
TestApp(t, ` | ||
itxn_begin | ||
int pay | ||
itxn_field TypeEnum | ||
int 100 | ||
itxn_field Amount | ||
txn Applications 1 | ||
app_params_get AppAddress | ||
assert | ||
itxn_field Receiver | ||
itxn_submit | ||
int 1 | ||
`, ep) | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -3058,3 +3058,222 @@ check: | |||||||||
txns(t, l, eval, &fundA, &callA) | ||||||||||
endBlock(t, l, eval) | ||||||||||
} | ||||||||||
|
||||||||||
func TestForeignAppAccountsAccessible(t *testing.T) { | ||||||||||
partitiontest.PartitionTest(t) | ||||||||||
|
||||||||||
genBalances, addrs, _ := ledgertesting.NewTestGenesis() | ||||||||||
testConsensusRange(t, 32, 0, func(t *testing.T, ver int) { | ||||||||||
dl := NewDoubleLedger(t, genBalances, consensusByNumber[ver]) | ||||||||||
defer dl.Close() | ||||||||||
|
||||||||||
appA := txntest.Txn{ | ||||||||||
Type: "appl", | ||||||||||
Sender: addrs[0], | ||||||||||
ApprovalProgram: main(` | ||||||||||
int 3 | ||||||||||
int 3 | ||||||||||
== | ||||||||||
assert | ||||||||||
`), | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can actually leave this out and txntest.Txn will supply a passing ApprovalProgram. |
||||||||||
} | ||||||||||
|
||||||||||
appB := txntest.Txn{ | ||||||||||
Type: "appl", | ||||||||||
Sender: addrs[0], | ||||||||||
ApprovalProgram: main(` | ||||||||||
itxn_begin | ||||||||||
int pay; itxn_field TypeEnum | ||||||||||
int 100; itxn_field Amount | ||||||||||
txn Applications 1 | ||||||||||
app_params_get AppAddress | ||||||||||
assert | ||||||||||
itxn_field Receiver | ||||||||||
itxn_submit | ||||||||||
`), | ||||||||||
} | ||||||||||
|
||||||||||
dl.beginBlock() | ||||||||||
dl.txgroup("", &appA, &appB) | ||||||||||
vb := dl.endBlock() | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
unless they actually need to be in a txgroup, rather than just run sequentially. |
||||||||||
index0 := vb.Block().Payset[0].ApplicationID | ||||||||||
index1 := vb.Block().Payset[1].ApplicationID | ||||||||||
|
||||||||||
fund1 := txntest.Txn{ | ||||||||||
Type: "pay", | ||||||||||
Sender: addrs[0], | ||||||||||
Receiver: index1.Address(), | ||||||||||
Amount: 1_000_000_000, | ||||||||||
} | ||||||||||
fund0 := fund1 | ||||||||||
fund0.Receiver = index0.Address() | ||||||||||
fund1.Receiver = index1.Address() | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to rewriting the same value, as |
||||||||||
|
||||||||||
callTx := txntest.Txn{ | ||||||||||
Type: "appl", | ||||||||||
Sender: addrs[2], | ||||||||||
ApplicationID: index1, | ||||||||||
ForeignApps: []basics.AppIndex{index0}, | ||||||||||
} | ||||||||||
|
||||||||||
dl.beginBlock() | ||||||||||
if ver <= 32 { | ||||||||||
dl.txgroup("invalid Account reference", &fund0, &fund1, &callTx) | ||||||||||
dl.endBlock() | ||||||||||
return | ||||||||||
} | ||||||||||
|
||||||||||
dl.txgroup("", &fund0, &fund1, &callTx) | ||||||||||
vb = dl.endBlock() | ||||||||||
|
||||||||||
require.Equal(t, index0.Address(), vb.Block().Payset[2].EvalDelta.InnerTxns[0].Txn.Receiver) | ||||||||||
require.Equal(t, uint64(100), vb.Block().Payset[2].EvalDelta.InnerTxns[0].Txn.Amount.Raw) | ||||||||||
}) | ||||||||||
} | ||||||||||
|
||||||||||
// While accounts of foreign apps are available in most context, they still | ||||||||||
// cannot be used as mutable references; ie the accounts cannot be used by | ||||||||||
// opcodes that modify local storage. | ||||||||||
func TestForeignAppAccountsImmutable(t *testing.T) { | ||||||||||
algoidurovic marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
partitiontest.PartitionTest(t) | ||||||||||
|
||||||||||
genBalances, addrs, _ := ledgertesting.NewTestGenesis() | ||||||||||
l := newTestLedger(t, genBalances) | ||||||||||
defer l.Close() | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice if this was also testConsensusRange so that it tests all the versions, starting with the first that works, through vFuture as we add more and more versions. |
||||||||||
|
||||||||||
appA := txntest.Txn{ | ||||||||||
Type: "appl", | ||||||||||
Sender: addrs[0], | ||||||||||
ApprovalProgram: main(` | ||||||||||
int 3 | ||||||||||
int 3 | ||||||||||
== | ||||||||||
assert | ||||||||||
`), | ||||||||||
} | ||||||||||
|
||||||||||
appB := txntest.Txn{ | ||||||||||
Type: "appl", | ||||||||||
Sender: addrs[0], | ||||||||||
ApprovalProgram: main(` | ||||||||||
txn Applications 1 | ||||||||||
app_params_get AppAddress | ||||||||||
byte "X" | ||||||||||
byte "ABC" | ||||||||||
app_local_put | ||||||||||
int 1 | ||||||||||
`), | ||||||||||
} | ||||||||||
|
||||||||||
eval := nextBlock(t, l) | ||||||||||
txns(t, l, eval, &appA, &appB) | ||||||||||
vb := endBlock(t, l, eval) | ||||||||||
index0 := vb.Block().Payset[0].ApplicationID | ||||||||||
index1 := vb.Block().Payset[1].ApplicationID | ||||||||||
|
||||||||||
fund1 := txntest.Txn{ | ||||||||||
Type: "pay", | ||||||||||
Sender: addrs[0], | ||||||||||
Receiver: index1.Address(), | ||||||||||
Amount: 1_000_000_000, | ||||||||||
} | ||||||||||
fund0 := fund1 | ||||||||||
fund0.Receiver = index0.Address() | ||||||||||
fund1.Receiver = index1.Address() | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same |
||||||||||
|
||||||||||
callTx := txntest.Txn{ | ||||||||||
Type: "appl", | ||||||||||
Sender: addrs[2], | ||||||||||
ApplicationID: index1, | ||||||||||
ForeignApps: []basics.AppIndex{index0}, | ||||||||||
} | ||||||||||
eval = nextBlock(t, l) | ||||||||||
txns(t, l, eval, &fund0, &fund1) | ||||||||||
txn(t, l, eval, &callTx, "invalid Account reference") | ||||||||||
endBlock(t, l, eval) | ||||||||||
} | ||||||||||
|
||||||||||
// In the case where the foreign app account is also provided in the | ||||||||||
// transaction's account field, mutable references should be allowed. | ||||||||||
func TestForeignAppAccountsMutable(t *testing.T) { | ||||||||||
partitiontest.PartitionTest(t) | ||||||||||
|
||||||||||
genBalances, addrs, _ := ledgertesting.NewTestGenesis() | ||||||||||
testConsensusRange(t, 32, 0, func(t *testing.T, ver int) { | ||||||||||
dl := NewDoubleLedger(t, genBalances, consensusByNumber[ver]) | ||||||||||
defer dl.Close() | ||||||||||
|
||||||||||
appA := txntest.Txn{ | ||||||||||
Type: "appl", | ||||||||||
Sender: addrs[0], | ||||||||||
ApprovalProgram: main(` | ||||||||||
itxn_begin | ||||||||||
int appl | ||||||||||
itxn_field TypeEnum | ||||||||||
txn Applications 1 | ||||||||||
itxn_field ApplicationID | ||||||||||
int OptIn | ||||||||||
itxn_field OnCompletion | ||||||||||
itxn_submit | ||||||||||
`), | ||||||||||
} | ||||||||||
|
||||||||||
appB := txntest.Txn{ | ||||||||||
Type: "appl", | ||||||||||
Sender: addrs[0], | ||||||||||
ApprovalProgram: main(` | ||||||||||
txn OnCompletion | ||||||||||
int OptIn | ||||||||||
== | ||||||||||
bnz done | ||||||||||
txn Applications 1 | ||||||||||
app_params_get AppAddress | ||||||||||
assert | ||||||||||
byte "X" | ||||||||||
byte "Y" | ||||||||||
app_local_put | ||||||||||
done: | ||||||||||
`), | ||||||||||
LocalStateSchema: basics.StateSchema{ | ||||||||||
NumByteSlice: 1, | ||||||||||
}, | ||||||||||
} | ||||||||||
|
||||||||||
dl.beginBlock() | ||||||||||
dl.txgroup("", &appA, &appB) | ||||||||||
vb := dl.endBlock() | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
unless they actually need to be in a txgroup, rather than just run sequentially. |
||||||||||
index0 := vb.Block().Payset[0].ApplicationID | ||||||||||
index1 := vb.Block().Payset[1].ApplicationID | ||||||||||
|
||||||||||
fund1 := txntest.Txn{ | ||||||||||
Type: "pay", | ||||||||||
Sender: addrs[0], | ||||||||||
Receiver: index1.Address(), | ||||||||||
Amount: 1_000_000_000, | ||||||||||
} | ||||||||||
fund0 := fund1 | ||||||||||
fund0.Receiver = index0.Address() | ||||||||||
fund1.Receiver = index1.Address() | ||||||||||
|
||||||||||
callA := txntest.Txn{ | ||||||||||
Type: "appl", | ||||||||||
Sender: addrs[2], | ||||||||||
ApplicationID: index0, | ||||||||||
ForeignApps: []basics.AppIndex{index1}, | ||||||||||
} | ||||||||||
|
||||||||||
callB := txntest.Txn{ | ||||||||||
Type: "appl", | ||||||||||
Sender: addrs[2], | ||||||||||
ApplicationID: index1, | ||||||||||
ForeignApps: []basics.AppIndex{index0}, | ||||||||||
Accounts: []basics.Address{index0.Address()}, | ||||||||||
} | ||||||||||
|
||||||||||
dl.beginBlock() | ||||||||||
dl.txgroup("", &fund0, &fund1, &callA, &callB) | ||||||||||
vb = dl.endBlock() | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
unless they actually need to be in a txgroup, rather than just run sequentially. |
||||||||||
|
||||||||||
require.Equal(t, "Y", vb.Block().Payset[3].EvalDelta.LocalDeltas[1]["X"].Bytes) | ||||||||||
}) | ||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.