Skip to content

Commit ca994d3

Browse files
committed
More complete txx_* order checking, better pay, axfer in teal
1 parent 8084e69 commit ca994d3

File tree

8 files changed

+541
-203
lines changed

8 files changed

+541
-203
lines changed

data/transactions/logic/eval.go

Lines changed: 59 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -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

23142316
func (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
27582771
func 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

32613274
func 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

32723282
func 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-
33173316
func (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

33313330
func 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

Comments
 (0)