Skip to content

Commit

Permalink
Merge pull request #17 from algorand/relstable3.13.3
Browse files Browse the repository at this point in the history
go-algorand v3.13.3-stable
  • Loading branch information
onetechnical authored Jan 19, 2023
2 parents fc985a1 + aa42ea1 commit 9ddd136
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 4 deletions.
2 changes: 1 addition & 1 deletion buildnumber.dat
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2
3
134 changes: 134 additions & 0 deletions ledger/applications_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@ package ledger

import (
"encoding/hex"
"fmt"
"path/filepath"
"testing"
"time"

"github.com/stretchr/testify/require"

"github.com/algorand/go-algorand/agreement"
"github.com/algorand/go-algorand/config"
"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"
Expand Down Expand Up @@ -1300,3 +1304,133 @@ int 1
err = l.appendUnvalidatedSignedTx(t, genesisInitState.Accounts, signedLsigPayment, transactions.ApplyData{})
a.NoError(err)
}

func TestAppEmptyBox(t *testing.T) {
partitiontest.PartitionTest(t)

a := require.New(t)
source := `#pragma version 8
txn ApplicationID
int 0
==
bnz create_box
// otherwise delete the box
byte "boxname"
box_del
return
create_box:
byte "boxname"
int 0
box_create
return
`

ops, err := logic.AssembleString(source)
a.NoError(err, ops.Errors)
a.Greater(len(ops.Program), 1)
program := ops.Program

proto := config.Consensus[protocol.ConsensusCurrentVersion]
genesisInitState, initKeys := ledgertesting.GenerateInitState(t, protocol.ConsensusCurrentVersion, 1000000)

creator, err := basics.UnmarshalChecksumAddress("3LN5DBFC2UTPD265LQDP3LMTLGZCQ5M3JV7XTVTGRH5CKSVNQVDFPN6FG4")
a.NoError(err)
a.Contains(genesisInitState.Accounts, creator)

dbName := fmt.Sprintf("%s.%d", t.Name(), crypto.RandUint64())
dbPrefix := filepath.Join(t.TempDir(), dbName)

cfg := config.GetDefaultLocal()
cfg.MaxAcctLookback = 2
l1, err := OpenLedger(logging.Base(), dbPrefix, false, genesisInitState, cfg)
a.NoError(err)
defer l1.Close()

genesisID := t.Name()
txHeader := transactions.Header{
Sender: creator,
Fee: basics.MicroAlgos{Raw: proto.MinTxnFee * 2},
FirstValid: l1.Latest() + 1,
LastValid: l1.Latest() + 10,
GenesisID: genesisID,
GenesisHash: genesisInitState.GenesisHash,
}

appIdx := basics.AppIndex(2) // second tnx => idx = 2

// fund app account
fundingPayment := transactions.Transaction{
Type: protocol.PaymentTx,
Header: txHeader,
PaymentTxnFields: transactions.PaymentTxnFields{
Receiver: appIdx.Address(),
Amount: basics.MicroAlgos{Raw: 100*proto.MinBalance + proto.MinTxnFee},
},
}
err = l1.appendUnvalidatedTx(t, genesisInitState.Accounts, initKeys, fundingPayment, transactions.ApplyData{})
a.NoError(err)

// create application
approvalProgram := program
clearStateProgram := []byte("\x08") // empty
appCreateFields := transactions.ApplicationCallTxnFields{
ApprovalProgram: approvalProgram,
ClearStateProgram: clearStateProgram,
GlobalStateSchema: basics.StateSchema{NumByteSlice: 0},
LocalStateSchema: basics.StateSchema{NumByteSlice: 0},
Boxes: []transactions.BoxRef{{Name: []byte("boxname")}},
}
appCreate := transactions.Transaction{
Type: protocol.ApplicationCallTx,
Header: txHeader,
ApplicationCallTxnFields: appCreateFields,
}
err = l1.appendUnvalidatedTx(t, genesisInitState.Accounts, initKeys, appCreate, transactions.ApplyData{ApplicationID: 2})
a.NoError(err)

// few empty blocks to reset deltas and flush
for i := 0; i < 10; i++ {
blk := makeNewEmptyBlock(t, l1, genesisID, genesisInitState.Accounts)
l1.AddBlock(blk, agreement.Certificate{})
}

app, err := l1.LookupApplication(l1.Latest(), creator, appIdx)
a.NoError(err)
a.Greater(len(app.AppParams.ApprovalProgram), 0)

commitRound(10, 0, l1)

// restart
l1.Close()

l2, err := OpenLedger(logging.Base(), dbPrefix, false, genesisInitState, cfg)
a.NoError(err)
defer l2.Close()

app, err = l2.LookupApplication(l2.Latest(), creator, appIdx)
a.NoError(err)
a.Greater(len(app.AppParams.ApprovalProgram), 0)

txHeader = transactions.Header{
Sender: creator,
Fee: basics.MicroAlgos{Raw: proto.MinTxnFee * 2},
FirstValid: l2.Latest() + 1,
LastValid: l2.Latest() + 10,
GenesisID: genesisID,
GenesisHash: genesisInitState.GenesisHash,
}

appCallFields := transactions.ApplicationCallTxnFields{
ApplicationID: appIdx,
Boxes: []transactions.BoxRef{{Name: []byte("boxname")}},
}
appCall := transactions.Transaction{
Type: protocol.ApplicationCallTx,
Header: txHeader,
ApplicationCallTxnFields: appCallFields,
}
err = l2.appendUnvalidatedTx(t, genesisInitState.Accounts, initKeys, appCall, transactions.ApplyData{})
a.NoError(err)

}
10 changes: 7 additions & 3 deletions ledger/store/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func AccountsInitDbQueries(q db.Queryable) (*accountsDbQueries, error) {
return nil, err
}

qs.lookupKvPairStmt, err = q.Prepare("SELECT acctrounds.rnd, kvstore.value FROM acctrounds LEFT JOIN kvstore ON key = ? WHERE id='acctbase';")
qs.lookupKvPairStmt, err = q.Prepare("SELECT acctrounds.rnd, kvstore.key, kvstore.value FROM acctrounds LEFT JOIN kvstore ON key = ? WHERE id='acctbase';")
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -253,9 +253,10 @@ func (qs *accountsDbQueries) ListCreatables(maxIdx basics.CreatableIndex, maxRes
// LookupKeyValue returns the application boxed value associated with the key.
func (qs *accountsDbQueries) LookupKeyValue(key string) (pv PersistedKVData, err error) {
err = db.Retry(func() error {
var rawkey []byte
var val []byte
// Cast to []byte to avoid interpretation as character string, see note in upsertKvPair
err := qs.lookupKvPairStmt.QueryRow([]byte(key)).Scan(&pv.Round, &val)
err := qs.lookupKvPairStmt.QueryRow([]byte(key)).Scan(&pv.Round, &rawkey, &val)
if err != nil {
// this should never happen; it indicates that we don't have a current round in the acctrounds table.
if err == sql.ErrNoRows {
Expand All @@ -264,7 +265,10 @@ func (qs *accountsDbQueries) LookupKeyValue(key string) (pv PersistedKVData, err
}
return err
}
if val != nil { // We got a non-null value, so it exists
if rawkey != nil { // We got a non-null key, so it exists
if val == nil {
val = []byte{}
}
pv.Value = val
return nil
}
Expand Down

0 comments on commit 9ddd136

Please sign in to comment.