diff --git a/data/transactions/verify/artifact_test.go b/data/transactions/verify/artifact_test.go
new file mode 100644
index 0000000000..8444dfa353
--- /dev/null
+++ b/data/transactions/verify/artifact_test.go
@@ -0,0 +1,100 @@
+// Copyright (C) 2019-2022 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see .
+
+package verify
+
+import (
+ "testing"
+
+ "github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/data/bookkeeping"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/data/transactions/logic"
+ "github.com/algorand/go-algorand/data/txntest"
+ "github.com/algorand/go-algorand/protocol"
+
+ "github.com/stretchr/testify/require"
+)
+
+// test/benchmark real programs found in the wild (testnet/mainnet).
+
+// BenchmarkTinyMan tries to reproduce
+// https://algoexplorer.io/tx/group/d1bUcqFbNZDMIdcreM9Vw2jzOIZIa2UzDgTTlr2Sl4o%3D
+// which is an algo to USDC swap. The source code below is extracted from
+// algoexplorer, which adds some unusual stuff as comments
+func BenchmarkTinyMan(b *testing.B) {
+ txns := txntest.CreateTinyManTxGroup(b, false)
+ b.Run("eval-lsig-signature", func(b *testing.B) {
+ stxns, _ := txntest.CreateTinyManSignedTxGroup(b, txns)
+ require.NotEmpty(b, stxns[0].Sig)
+ require.NotEmpty(b, stxns[1].Lsig.Logic)
+ require.NotEmpty(b, stxns[2].Sig)
+ require.NotEmpty(b, stxns[3].Lsig.Logic)
+ txgroup := transactions.WrapSignedTxnsWithAD(stxns)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ proto := config.Consensus[protocol.ConsensusCurrentVersion]
+ ep := logic.EvalParams{
+ Proto: &proto,
+ TxnGroup: txgroup,
+ SigLedger: &logic.NoHeaderLedger{},
+ }
+ pass, err := logic.EvalSignature(1, &ep)
+ require.NoError(b, err)
+ require.True(b, pass)
+ pass, err = logic.EvalSignature(3, &ep)
+ require.NoError(b, err)
+ require.True(b, pass)
+ }
+ })
+
+ hdr := bookkeeping.BlockHeader{
+ UpgradeState: bookkeeping.UpgradeState{
+ CurrentProtocol: protocol.ConsensusCurrentVersion,
+ },
+ }
+
+ b.Run("group-check-actual", func(b *testing.B) {
+ stxnss := make([][]transactions.SignedTxn, b.N)
+ for i := 0; i < b.N; i++ {
+ txns := txntest.CreateTinyManTxGroup(b, true)
+ stxnss[i], _ = txntest.CreateTinyManSignedTxGroup(b, txns)
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := TxnGroup(stxnss[i], hdr, nil, &logic.NoHeaderLedger{})
+ require.NoError(b, err)
+ }
+ })
+
+ b.Run("group-check-all-crypto", func(b *testing.B) {
+ stxns, secrets := txntest.CreateTinyManSignedTxGroup(b, txns)
+ stxns[1] = stxns[1].Txn.Sign(secrets[0])
+ stxns[3] = stxns[3].Txn.Sign(secrets[0])
+ require.Empty(b, stxns[0].Lsig.Logic)
+ require.Empty(b, stxns[1].Lsig.Logic)
+ require.Empty(b, stxns[2].Lsig.Logic)
+ require.Empty(b, stxns[3].Lsig.Logic)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := TxnGroup(stxns, hdr, nil, &logic.NoHeaderLedger{})
+ require.NoError(b, err)
+ }
+ })
+}
diff --git a/data/txntest/defi.go b/data/txntest/defi.go
new file mode 100644
index 0000000000..a16d44d202
--- /dev/null
+++ b/data/txntest/defi.go
@@ -0,0 +1,548 @@
+// Copyright (C) 2019-2022 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see .
+
+package txntest
+
+import (
+ "testing"
+
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/data/transactions/logic"
+ "github.com/stretchr/testify/require"
+)
+
+// Test/benchmark real programs found in the wild (testnet/mainnet).
+
+// CreateTinyManTxGroup repro this tx group by tinyman
+// https://algoexplorer.io/tx/group/d1bUcqFbNZDMIdcreM9Vw2jzOIZIa2UzDgTTlr2Sl4o%3D
+func CreateTinyManTxGroup(tb testing.TB, randNote bool) []Txn {
+ user, err := basics.UnmarshalChecksumAddress("W2IZ3EHDRW2IQNPC33CI2CXSLMFCFICVKQVWIYLJWXCTD765RW47ONNCEY")
+ require.NoError(tb, err)
+
+ luser, err := basics.UnmarshalChecksumAddress("FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA")
+ require.NoError(tb, err)
+
+ var note []byte = nil
+ if randNote {
+ note = make([]byte, 12)
+ crypto.RandBytes(note[:])
+ }
+
+ fees := Txn{
+ Type: "pay",
+ Fee: 1000,
+ Sender: user,
+ Receiver: luser,
+ Amount: 2000, // must cover the luser fees in appcall and withdraw
+ Note: note,
+ }
+
+ appcall := Txn{
+ Type: "appl",
+ Fee: 1000,
+ Sender: luser,
+ ApplicationID: 552635992,
+ Accounts: []basics.Address{user},
+ Note: note,
+ }.Args("swap", "fo")
+
+ deposit := Txn{
+ Type: "axfer",
+ Fee: 1000,
+ Sender: user,
+ AssetReceiver: luser,
+ Note: note,
+ }
+
+ withdraw := Txn{
+ Type: "pay",
+ Fee: 1000,
+ Sender: luser,
+ Receiver: user,
+ Note: note,
+ }
+ return []Txn{fees, *appcall, deposit, withdraw}
+}
+
+// CreateTinyManSignedTxGroup repro this tx group by tinyman
+// https://algoexplorer.io/tx/group/d1bUcqFbNZDMIdcreM9Vw2jzOIZIa2UzDgTTlr2Sl4o%3D
+// which is an algo to USDC swap. The source code below is extracted from
+// algoexplorer, which adds some unusual stuff as comments
+func CreateTinyManSignedTxGroup(tb testing.TB, txns []Txn) ([]transactions.SignedTxn, []*crypto.SignatureSecrets) {
+ lsig := `
+ #pragma version 4
+ intcblock 1 0 0 31566704 3 4 5 6
+ intc_3 // 31566704
+ intc_2 // 0
+ >
+ assert
+ txn CloseRemainderTo // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ
+ global ZeroAddress
+ ==
+ assert
+ txn AssetCloseTo // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ
+ global ZeroAddress
+ ==
+ assert
+ txn RekeyTo // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ
+ global ZeroAddress
+ ==
+ assert
+ global GroupSize // size=4
+ intc_0 // 1
+ >
+ assert
+ gtxn 1 Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert
+ gtxn 1 TypeEnum
+ intc 7 // 6
+ ==
+ assert
+ gtxn 1 ApplicationID // id=552635992
+ pushint 552635992
+ ==
+ assert // PC=65
+ gtxn 1 OnCompletion
+ intc_0 // 1
+ ==
+ gtxn 1 NumAppArgs // index=2
+ intc 4 // 3
+ ==
+ &&
+ gtxna 1 ApplicationArgs 0 // arg=73776170
+ pushbytes 0x626f6f747374726170 // "bootstrap"
+ ==
+ &&
+ bnz label1
+ gtxn 1 OnCompletion
+ intc_1 // 0
+ ==
+ assert
+ gtxn 1 NumAppArgs // index=2
+ pushint 2
+ ==
+ gtxna 1 ApplicationArgs 0 // arg=73776170
+ pushbytes 0x73776170 // "swap"
+ ==
+ &&
+ bnz label2
+ gtxn 1 NumAppArgs // index=2
+ intc_0 // 1
+ ==
+ assert
+ gtxna 1 ApplicationArgs 0 // arg=73776170
+ pushbytes 0x6d696e74 // "mint"
+ ==
+ bnz label3
+ gtxna 1 ApplicationArgs 0 // arg=73776170
+ pushbytes 0x6275726e // "burn"
+ ==
+ bnz label4
+ gtxna 1 ApplicationArgs 0 // arg=73776170
+ pushbytes 0x72656465656d // "redeem"
+ ==
+ bnz label5
+ gtxna 1 ApplicationArgs 0 // arg=73776170
+ pushbytes 0x66656573 // "fees"
+ ==
+ bnz label6
+ err
+label1:
+ intc 6 // 5
+ intc 5 // 4
+ intc_2 // 0
+ intc_1 // 0
+ ==
+ select
+ global GroupSize // size=4
+ ==
+ assert
+ gtxna 1 ApplicationArgs 1 // arg=666f
+ btoi
+ intc_3 // 31566704
+ ==
+ gtxna 1 ApplicationArgs 2
+ btoi
+ intc_2 // 0
+ ==
+ &&
+ assert
+ gtxn 2 Sender // W2IZ3EHDRW2IQNPC33CI2CXSLMFCFICVKQVWIYLJWXCTD765RW47ONNCEY
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert
+ gtxn 2 TypeEnum
+ intc 4 // 3
+ ==
+ assert
+ gtxn 2 ConfigAsset // id=0
+ intc_1 // 0
+ ==
+ assert
+ gtxn 2 ConfigAssetTotal // total=0.
+ intc_1 // 0
+ ~
+ ==
+ assert
+ gtxn 2 ConfigAssetDecimals // dec=0
+ intc 7 // 6
+ ==
+ assert
+ gtxn 2 ConfigAssetDefaultFrozen // default=false
+ intc_1 // 0
+ ==
+ assert
+ gtxn 2 ConfigAssetUnitName //
+ pushbytes 0x544d504f4f4c3131 // "TMPOOL11"
+ ==
+ assert
+ gtxn 2 ConfigAssetName //
+ substring 0 15
+ pushbytes 0x54696e796d616e506f6f6c312e3120 // "TinymanPool1.1 "
+ ==
+ assert
+ gtxn 2 ConfigAssetURL //
+ pushbytes 0x68747470733a2f2f74696e796d616e2e6f7267 // "https://tinyman.org"
+ ==
+ assert
+ gtxn 2 ConfigAssetManager
+ global ZeroAddress
+ ==
+ assert
+ gtxn 2 ConfigAssetReserve
+ global ZeroAddress
+ ==
+ assert
+ gtxn 2 ConfigAssetFreeze
+ global ZeroAddress
+ ==
+ assert
+ gtxn 2 ConfigAssetClawback
+ global ZeroAddress
+ ==
+ assert
+ gtxn 3 Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert
+ gtxn 3 TypeEnum
+ intc 5 // 4
+ ==
+ assert
+ gtxn 3 XferAsset // id=0
+ intc_3 // 31566704
+ ==
+ assert
+ gtxn 3 AssetReceiver // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert
+ gtxn 3 AssetAmount
+ intc_1 // 0
+ ==
+ assert
+ intc_2 // 0
+ intc_1 // 0
+ !=
+ bnz label7
+ gtxn 1 Fee // 0.001000
+ gtxn 2 Fee // 0.001000
+ +
+ gtxn 3 Fee // 0.001000
+ +
+ store 1
+ b label8
+label7:
+ gtxn 4 Sender
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert
+ gtxn 4 TypeEnum
+ intc 5 // 4
+ ==
+ assert
+ gtxn 4 XferAsset
+ intc_2 // 0
+ ==
+ assert
+ gtxn 4 AssetReceiver
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert
+ gtxn 4 AssetAmount
+ intc_1 // 0
+ ==
+ assert
+ gtxn 1 Fee // 0.001000
+ gtxn 2 Fee // 0.001000
+ +
+ gtxn 3 Fee // 0.001000
+ +
+ gtxn 4 Fee
+ +
+ store 1
+ b label8
+label3:
+ global GroupSize // size=4
+ intc 6 // 5
+ ==
+ assert
+ gtxna 1 Accounts 1
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ !=
+ assert
+ gtxna 1 Accounts 1
+ gtxn 4 AssetReceiver
+ ==
+ assert
+ gtxn 2 Sender // W2IZ3EHDRW2IQNPC33CI2CXSLMFCFICVKQVWIYLJWXCTD765RW47ONNCEY
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ !=
+ assert
+ gtxn 2 AssetReceiver // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert
+ gtxn 3 Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ gtxn 2 Sender // W2IZ3EHDRW2IQNPC33CI2CXSLMFCFICVKQVWIYLJWXCTD765RW47ONNCEY
+ ==
+ assert
+ gtxn 2 XferAsset // id=31566704
+ intc_3 // 31566704
+ ==
+ assert
+ gtxn 3 AssetReceiver // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ
+ gtxn 3 Receiver // W2IZ3EHDRW2IQNPC33CI2CXSLMFCFICVKQVWIYLJWXCTD765RW47ONNCEY
+ gtxn 3 TypeEnum
+ intc_0 // 1
+ ==
+ select
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert
+ gtxn 3 XferAsset // id=0
+ intc_1 // 0
+ gtxn 3 TypeEnum
+ intc_0 // 1
+ ==
+ select
+ intc_2 // 0
+ ==
+ assert
+ gtxn 4 Sender
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert
+ gtxn 4 AssetReceiver
+ gtxn 2 Sender // W2IZ3EHDRW2IQNPC33CI2CXSLMFCFICVKQVWIYLJWXCTD765RW47ONNCEY
+ ==
+ assert
+ gtxn 1 Fee // 0.001000
+ gtxn 4 Fee
+ +
+ store 1
+ b label8
+label4:
+ global GroupSize // size=4
+ intc 6 // 5
+ ==
+ assert
+ gtxna 1 Accounts 1
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ !=
+ assert
+ gtxna 1 Accounts 1
+ gtxn 2 AssetReceiver // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert
+ gtxn 3 AssetReceiver // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ
+ gtxn 3 Receiver // W2IZ3EHDRW2IQNPC33CI2CXSLMFCFICVKQVWIYLJWXCTD765RW47ONNCEY
+ gtxn 3 TypeEnum
+ intc_0 // 1
+ ==
+ select
+ gtxna 1 Accounts 1
+ ==
+ assert
+ gtxn 2 Sender // W2IZ3EHDRW2IQNPC33CI2CXSLMFCFICVKQVWIYLJWXCTD765RW47ONNCEY
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert
+ gtxn 2 AssetReceiver // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ gtxn 4 Sender
+ ==
+ assert
+ gtxn 2 XferAsset // id=31566704
+ intc_3 // 31566704
+ ==
+ assert
+ gtxn 3 Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert
+ gtxn 3 AssetReceiver // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ
+ gtxn 3 Receiver // W2IZ3EHDRW2IQNPC33CI2CXSLMFCFICVKQVWIYLJWXCTD765RW47ONNCEY
+ gtxn 3 TypeEnum
+ intc_0 // 1
+ ==
+ select
+ gtxn 4 Sender
+ ==
+ assert
+ gtxn 3 XferAsset // id=0
+ intc_1 // 0
+ gtxn 3 TypeEnum
+ intc_0 // 1
+ ==
+ select
+ intc_2 // 0
+ ==
+ assert
+ gtxn 4 Sender
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ !=
+ assert
+ gtxn 4 AssetReceiver
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert
+ gtxn 1 Fee // 0.001000
+ gtxn 2 Fee // 0.001000
+ +
+ gtxn 3 Fee // 0.001000
+ +
+ store 1
+ b label8
+label2: // swap
+ global GroupSize // size=4
+ intc 5 // 4
+ ==
+ assert
+ gtxna 1 Accounts 1
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ !=
+ assert
+ gtxn 2 Sender // W2IZ3EHDRW2IQNPC33CI2CXSLMFCFICVKQVWIYLJWXCTD765RW47ONNCEY
+ gtxna 1 Accounts 1
+ ==
+ assert // PC=718
+ gtxn 2 Sender // W2IZ3EHDRW2IQNPC33CI2CXSLMFCFICVKQVWIYLJWXCTD765RW47ONNCEY
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ !=
+ assert
+ gtxn 3 Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert // PC=732
+ gtxn 2 AssetReceiver // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ gtxn 2 Receiver // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ
+ gtxn 2 TypeEnum
+ intc_0 // 1
+ ==
+ select
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert
+ gtxn 3 AssetReceiver // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ
+ gtxn 3 Receiver // W2IZ3EHDRW2IQNPC33CI2CXSLMFCFICVKQVWIYLJWXCTD765RW47ONNCEY
+ gtxn 3 TypeEnum
+ intc_0 // 1
+ ==
+ select
+ gtxn 2 Sender // W2IZ3EHDRW2IQNPC33CI2CXSLMFCFICVKQVWIYLJWXCTD765RW47ONNCEY
+ ==
+ assert // PC=765
+ gtxn 1 Fee // 0.001000
+ gtxn 3 Fee // 0.001000
+ +
+ store 1
+ b label8
+label5:
+ global GroupSize // size=4
+ intc 4 // 3
+ ==
+ assert
+ gtxna 1 Accounts 1
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ !=
+ assert
+ gtxn 2 AssetReceiver // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ gtxn 2 Receiver // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ
+ gtxn 2 TypeEnum
+ intc_0 // 1
+ ==
+ select
+ gtxna 1 Accounts 1
+ ==
+ assert
+ gtxn 1 Fee // 0.001000
+ gtxn 2 Fee // 0.001000
+ +
+ store 1
+ b label8
+label6:
+ global GroupSize // size=4
+ intc 4 // 3
+ ==
+ assert
+ gtxn 1 Fee // 0.001000
+ gtxn 2 Fee // 0.001000
+ +
+ store 1
+ b label8
+label8:
+ gtxn 0 Sender // W2IZ3EHDRW2IQNPC33CI2CXSLMFCFICVKQVWIYLJWXCTD765RW47ONNCEY
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ !=
+ assert
+ gtxn 0 Receiver // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ txn Sender // FPOU46NBKTWUZCNMNQNXRWNW3SMPOOK4ZJIN5WSILCWP662ANJLTXVRUKA
+ ==
+ assert // PC=853
+ gtxn 0 Amount // 0.002000
+ load 1
+ >=
+ return
+`
+ ops, err := logic.AssembleString(lsig)
+ require.NoError(tb, err)
+
+ stxns := SignedTxns(&txns[0], &txns[1], &txns[2], &txns[3])
+ stxns[1].Lsig.Logic = ops.Program
+ stxns[3].Lsig.Logic = ops.Program
+
+ // add in some signatures, so TxnGroup can succeed. A randomly generated
+ // private key. The actual value does not matter, as long as this is a valid
+ // private key.
+ signer := crypto.PrivateKey{
+ 128, 128, 92, 23, 212, 119, 175, 51, 157, 2, 165,
+ 215, 137, 37, 82, 42, 52, 227, 54, 41, 243, 67,
+ 141, 76, 208, 17, 199, 17, 140, 46, 113, 0, 159,
+ 50, 105, 52, 77, 104, 118, 200, 104, 220, 105, 21,
+ 147, 162, 191, 236, 115, 201, 197, 128, 8, 91, 224,
+ 78, 104, 209, 2, 185, 110, 28, 42, 97,
+ }
+ secrets, err := crypto.SecretKeyToSignatureSecrets(signer)
+ require.NoError(tb, err)
+
+ stxns[0] = stxns[0].Txn.Sign(secrets)
+ stxns[2] = stxns[2].Txn.Sign(secrets)
+ return stxns, []*crypto.SignatureSecrets{secrets}
+}