@@ -310,15 +310,17 @@ type evalContext struct {
310310
311311 stack []stackValue
312312 callstack []int
313- subtxn transactions.Transaction // place to build for tx_submit
314- program []byte
315- pc int
316- nextpc int
317- err error
318- intc []uint64
319- bytec [][]byte
320- version uint64
321- scratch scratchSpace
313+
314+ subtxn * transactions.Transaction // place to build for tx_submit
315+
316+ program []byte
317+ pc int
318+ nextpc int
319+ err error
320+ intc []uint64
321+ bytec [][]byte
322+ version uint64
323+ scratch scratchSpace
322324
323325 cost int // cost incurred so far
324326 logCalls int // number of log calls so far
@@ -2290,9 +2292,9 @@ func (cx *evalContext) getApplicationID() (uint64, error) {
22902292 return uint64 (cx .Ledger .ApplicationID ()), nil
22912293}
22922294
2293- func (cx * evalContext ) getApplicationAddress () ([] byte , error ) {
2295+ func (cx * evalContext ) getApplicationAddress () (basics. Address , error ) {
22942296 if cx .Ledger == nil {
2295- return nil , fmt .Errorf ("ledger not available" )
2297+ return basics. Address {} , fmt .Errorf ("ledger not available" )
22962298 }
22972299
22982300 // Initialize appAddrCache if necessary
@@ -2308,7 +2310,7 @@ func (cx *evalContext) getApplicationAddress() ([]byte, error) {
23082310 cx .appAddrCache [appID ] = appAddr
23092311 }
23102312
2311- return appAddr [:] , nil
2313+ return appAddr , nil
23122314}
23132315
23142316func (cx * evalContext ) getCreatableID (groupIndex int ) (cid uint64 , err error ) {
@@ -2353,7 +2355,9 @@ func (cx *evalContext) globalFieldToStack(field GlobalField) (sv stackValue, err
23532355 case CurrentApplicationID :
23542356 sv .Uint , err = cx .getApplicationID ()
23552357 case CurrentApplicationAddress :
2356- sv .Bytes , err = cx .getApplicationAddress ()
2358+ var addr basics.Address
2359+ addr , err = cx .getApplicationAddress ()
2360+ sv .Bytes = addr [:]
23572361 case CreatorAddress :
23582362 sv .Bytes , err = cx .getCreatorAddress ()
23592363 default :
@@ -2742,14 +2746,23 @@ func opExtract64Bits(cx *evalContext) {
27422746 opExtractNBytes (cx , 8 ) // extract 8 bytes
27432747}
27442748
2745- func accountReference (cx * evalContext , account stackValue ) (basics.Address , uint64 , error ) {
2749+ func (cx * evalContext ) accountReference ( account stackValue ) (basics.Address , uint64 , error ) {
27462750 if account .argType () == StackUint64 {
27472751 addr , err := cx .Txn .Txn .AddressByIndex (account .Uint , cx .Txn .Txn .Sender )
27482752 return addr , account .Uint , err
27492753 }
27502754 addr := basics.Address {}
27512755 copy (addr [:], account .Bytes )
27522756 idx , err := cx .Txn .Txn .IndexByAddress (addr , cx .Txn .Txn .Sender )
2757+
2758+ if err != nil {
2759+ // Application address is acceptable. index is meaningless though
2760+ appAddr , _ := cx .getApplicationAddress ()
2761+ if appAddr == addr {
2762+ return addr , uint64 (0xffffffffffffffff ), nil
2763+ }
2764+ }
2765+
27532766 return addr , idx , err
27542767}
27552768
@@ -2758,7 +2771,7 @@ type opQuery func(basics.Address, *config.ConsensusParams) (basics.MicroAlgos, e
27582771func opBalanceQuery (cx * evalContext , query opQuery , item string ) error {
27592772 last := len (cx .stack ) - 1 // account (index or actual address)
27602773
2761- addr , _ , err := accountReference (cx , cx .stack [last ])
2774+ addr , _ , err := cx . accountReference (cx .stack [last ])
27622775 if err != nil {
27632776 return err
27642777 }
@@ -2807,7 +2820,7 @@ func opAppOptedIn(cx *evalContext) {
28072820 return
28082821 }
28092822
2810- addr , _ , err := accountReference (cx , cx .stack [prev ])
2823+ addr , _ , err := cx . accountReference (cx .stack [prev ])
28112824 if err != nil {
28122825 cx .err = err
28132826 return
@@ -2881,7 +2894,7 @@ func opAppLocalGetImpl(cx *evalContext, appID uint64, key []byte, acct stackValu
28812894 return
28822895 }
28832896
2884- addr , accountIdx , err := accountReference (cx , acct )
2897+ addr , accountIdx , err := cx . accountReference (acct )
28852898 if err != nil {
28862899 return
28872900 }
@@ -2973,7 +2986,7 @@ func opAppLocalPut(cx *evalContext) {
29732986 return
29742987 }
29752988
2976- addr , accountIdx , err := accountReference (cx , cx .stack [pprev ])
2989+ addr , accountIdx , err := cx . accountReference (cx .stack [pprev ])
29772990 if err == nil {
29782991 err = cx .Ledger .SetLocal (addr , key , sv .toTealValue (), accountIdx )
29792992 }
@@ -3018,7 +3031,7 @@ func opAppLocalDel(cx *evalContext) {
30183031 return
30193032 }
30203033
3021- addr , accountIdx , err := accountReference (cx , cx .stack [prev ])
3034+ addr , accountIdx , err := cx . accountReference (cx .stack [prev ])
30223035 if err == nil {
30233036 err = cx .Ledger .DelLocal (addr , key , accountIdx )
30243037 }
@@ -3133,7 +3146,7 @@ func opAssetHoldingGet(cx *evalContext) {
31333146
31343147 fieldIdx := uint64 (cx .program [cx .pc + 1 ])
31353148
3136- addr , _ , err := accountReference (cx , cx .stack [prev ])
3149+ addr , _ , err := cx . accountReference (cx .stack [prev ])
31373150 if err != nil {
31383151 cx .err = err
31393152 return
@@ -3259,27 +3272,26 @@ func opLog(cx *evalContext) {
32593272}
32603273
32613274func authorizedSender (cx * evalContext , addr basics.Address ) bool {
3262- appAddrBytes , err := cx .getApplicationAddress ()
3275+ appAddr , err := cx .getApplicationAddress ()
32633276 if err != nil {
32643277 return false
32653278 }
3266- var appAddr basics.Address
3267- copy (appAddr [:], appAddrBytes )
3268- auth := cx .Ledger .Authorizer (addr )
3269- return appAddr == auth
3279+ return appAddr == cx .Ledger .Authorizer (addr )
32703280}
32713281
32723282func opTxBegin (cx * evalContext ) {
3283+ if cx .subtxn != nil {
3284+ cx .err = errors .New ("tx_begin without tx_submit" )
3285+ return
3286+ }
32733287 // Start fresh
3274- cx .subtxn = transactions.Transaction {}
3288+ cx .subtxn = & transactions.Transaction {}
32753289 // Fill in defaults.
3276- bytes , err := cx .getApplicationAddress ()
3290+ addr , err := cx .getApplicationAddress ()
32773291 if err != nil {
32783292 cx .err = err
32793293 return
32803294 }
3281- var addr basics.Address
3282- copy (addr [:], bytes )
32833295
32843296 fee := cx .Proto .MinTxnFee
32853297 if cx .FeeCredit != nil {
@@ -3301,19 +3313,6 @@ func opTxBegin(cx *evalContext) {
33013313 }
33023314}
33033315
3304- func (cx * evalContext ) availableAddress (sv stackValue ) (basics.Address , error ) {
3305- addr , err := sv .address ()
3306- if err != nil {
3307- return basics.Address {}, err
3308- }
3309- // Ensure that addr from Accounts.
3310- _ , err = cx .Txn .Txn .IndexByAddress (addr , cx .Txn .Txn .Sender )
3311- if err != nil {
3312- return basics.Address {}, err
3313- }
3314- return addr , nil
3315- }
3316-
33173316func (cx * evalContext ) availableAsset (sv stackValue ) (basics.AssetIndex , error ) {
33183317 aid , err := sv .uint ()
33193318 if err != nil {
@@ -3329,6 +3328,10 @@ func (cx *evalContext) availableAsset(sv stackValue) (basics.AssetIndex, error)
33293328}
33303329
33313330func opTxField (cx * evalContext ) {
3331+ if cx .subtxn == nil {
3332+ cx .err = errors .New ("tx_field without tx_begin" )
3333+ return
3334+ }
33323335 last := len (cx .stack ) - 1
33333336 field := TxnField (uint64 (cx .program [cx .pc + 1 ]))
33343337 sv := cx .stack [last ]
@@ -3343,7 +3346,7 @@ func opTxField(cx *evalContext) {
33433346 }
33443347
33453348 case Sender :
3346- cx .subtxn .Sender , cx .err = cx .availableAddress (sv )
3349+ cx .subtxn .Sender , _ , cx .err = cx .accountReference (sv )
33473350 case Fee :
33483351 cx .subtxn .Fee .Raw , cx .err = sv .uint ()
33493352 // FirstValid, LastValid unsettable: no motivation
@@ -3356,22 +3359,22 @@ func opTxField(cx *evalContext) {
33563359 // KeyReg not allowed yet, so no fields settable
33573360
33583361 case Receiver :
3359- cx .subtxn .Receiver , cx .err = cx .availableAddress (sv )
3362+ cx .subtxn .Receiver , _ , cx .err = cx .accountReference (sv )
33603363 case Amount :
33613364 cx .subtxn .Amount .Raw , cx .err = sv .uint ()
33623365 case CloseRemainderTo :
3363- cx .subtxn .CloseRemainderTo , cx .err = cx .availableAddress (sv )
3366+ cx .subtxn .CloseRemainderTo , _ , cx .err = cx .accountReference (sv )
33643367
33653368 case XferAsset :
33663369 cx .subtxn .XferAsset , cx .err = cx .availableAsset (sv )
33673370 case AssetAmount :
33683371 cx .subtxn .AssetAmount , cx .err = sv .uint ()
33693372 case AssetSender :
3370- cx .subtxn .AssetSender , cx .err = cx .availableAddress (sv )
3373+ cx .subtxn .AssetSender , _ , cx .err = cx .accountReference (sv )
33713374 case AssetReceiver :
3372- cx .subtxn .AssetReceiver , cx .err = cx .availableAddress (sv )
3375+ cx .subtxn .AssetReceiver , _ , cx .err = cx .accountReference (sv )
33733376 case AssetCloseTo :
3374- cx .subtxn .AssetCloseTo , cx .err = cx .availableAddress (sv )
3377+ cx .subtxn .AssetCloseTo , _ , cx .err = cx .accountReference (sv )
33753378
33763379 // acfg likely next
33773380
@@ -3392,6 +3395,11 @@ func opTxSubmit(cx *evalContext) {
33923395 return
33933396 }
33943397
3398+ if cx .subtxn == nil {
3399+ cx .err = errors .New ("tx_submit without tx_begin" )
3400+ return
3401+ }
3402+
33953403 // Error out on anything unusual. Allow pay, axfer.
33963404 switch cx .subtxn .Type {
33973405 case protocol .PaymentTx , protocol .AssetTransferTx :
@@ -3437,5 +3445,7 @@ func opTxSubmit(cx *evalContext) {
34373445 }
34383446 }
34393447
3440- cx .err = cx .Ledger .Perform (& cx .subtxn , * cx .Specials )
3448+ cx .err = cx .Ledger .Perform (cx .subtxn , * cx .Specials )
3449+
3450+ cx .subtxn = nil
34413451}
0 commit comments