@@ -2,11 +2,8 @@ package ledgerforevaluator
22
33import (
44 "context"
5- "errors"
65 "fmt"
76
8- "github.com/algorand/go-algorand/config"
9- "github.com/algorand/go-algorand/crypto"
107 "github.com/algorand/go-algorand/data/basics"
118 "github.com/algorand/go-algorand/data/bookkeeping"
129 "github.com/algorand/go-algorand/data/transactions"
@@ -44,26 +41,24 @@ var statements = map[string]string{
4441 "WHERE addr = $1 AND NOT deleted" ,
4542}
4643
47- // LedgerForEvaluator implements the ledgerForEvaluator interface from
44+ // LedgerForEvaluator implements the indexerLedgerForEval interface from
4845// go-algorand ledger/eval.go and is used for accounting.
4946type LedgerForEvaluator struct {
50- tx pgx.Tx
51- genesisHash crypto.Digest
47+ tx pgx.Tx
5248 // Indexer currently does not store the balances of special account, but
5349 // go-algorand's eval checks that they satisfy the minimum balance. We thus return
5450 // a fake amount.
5551 // TODO: remove.
5652 specialAddresses transactions.SpecialAddresses
57- // Value is nil if account was looked up but not found.
58- preloadedAccountData map [basics.Address ]* basics.AccountData
53+ latestRound basics.Round
5954}
6055
6156// MakeLedgerForEvaluator creates a LedgerForEvaluator object.
62- func MakeLedgerForEvaluator (tx pgx.Tx , genesisHash crypto. Digest , specialAddresses transactions. SpecialAddresses ) (LedgerForEvaluator , error ) {
57+ func MakeLedgerForEvaluator (tx pgx.Tx , specialAddresses transactions. SpecialAddresses , latestRound basics. Round ) (LedgerForEvaluator , error ) {
6358 l := LedgerForEvaluator {
6459 tx : tx ,
65- genesisHash : genesisHash ,
6660 specialAddresses : specialAddresses ,
61+ latestRound : latestRound ,
6762 }
6863
6964 for name , query := range statements {
@@ -84,9 +79,9 @@ func (l *LedgerForEvaluator) Close() {
8479 }
8580}
8681
87- // BlockHdr is part of go-algorand's ledgerForEvaluator interface.
88- func (l LedgerForEvaluator ) BlockHdr ( round basics. Round ) (bookkeeping.BlockHeader , error ) {
89- row := l .tx .QueryRow (context .Background (), blockHeaderStmtName , uint64 (round ))
82+ // LatestBlockHdr is part of go-algorand's indexerLedgerForEval interface.
83+ func (l LedgerForEvaluator ) LatestBlockHdr ( ) (bookkeeping.BlockHeader , error ) {
84+ row := l .tx .QueryRow (context .Background (), blockHeaderStmtName , uint64 (l . latestRound ))
9085
9186 var header []byte
9287 err := row .Scan (& header )
@@ -102,12 +97,6 @@ func (l LedgerForEvaluator) BlockHdr(round basics.Round) (bookkeeping.BlockHeade
10297 return res , nil
10398}
10499
105- // CheckDup is part of go-algorand's ledgerForEvaluator interface.
106- func (l LedgerForEvaluator ) CheckDup (config.ConsensusParams , basics.Round , basics.Round , basics.Round , transactions.Txid , ledger.TxLease ) error {
107- // This function is not used by evaluator.
108- return errors .New ("CheckDup() not implemented" )
109- }
110-
111100func (l * LedgerForEvaluator ) isSpecialAddress (address basics.Address ) bool {
112101 return (address == l .specialAddresses .FeeSink ) ||
113102 (address == l .specialAddresses .RewardsPool )
@@ -252,8 +241,8 @@ func (l *LedgerForEvaluator) parseAccountAppTable(rows pgx.Rows) (map[basics.App
252241 return res , nil
253242}
254243
255- // Load rows from the account table for the given addresses. nil is stored for those
256- // accounts that were not found. Uses batching.
244+ // Load rows from the account table for the given addresses except the special accounts.
245+ // nil is stored for those accounts that were not found. Uses batching.
257246func (l * LedgerForEvaluator ) loadAccountTable (addresses map [basics.Address ]struct {}) (map [basics.Address ]* basics.AccountData , error ) {
258247 addressesArr := make ([]basics.Address , 0 , len (addresses ))
259248 for address := range addresses {
@@ -375,9 +364,8 @@ func (l *LedgerForEvaluator) loadCreatables(accountDataMap *map[basics.Address]*
375364 return nil
376365}
377366
378- // Return a map with all accounts for the given addresses, with nil for those accounts
379- // that do not exist.
380- func (l * LedgerForEvaluator ) loadAccounts (addresses map [basics.Address ]struct {}) (map [basics.Address ]* basics.AccountData , error ) {
367+ // LookupWithoutRewards is part of go-algorand's indexerLedgerForEval interface.
368+ func (l LedgerForEvaluator ) LookupWithoutRewards (addresses map [basics.Address ]struct {}) (map [basics.Address ]* basics.AccountData , error ) {
381369 res , err := l .loadAccountTable (addresses )
382370 if err != nil {
383371 return nil , fmt .Errorf ("loadAccounts() err: %w" , err )
@@ -388,96 +376,101 @@ func (l *LedgerForEvaluator) loadAccounts(addresses map[basics.Address]struct{})
388376 return nil , fmt .Errorf ("loadAccounts() err: %w" , err )
389377 }
390378
379+ // Add special accounts if needed.
380+ for address := range addresses {
381+ if l .isSpecialAddress (address ) {
382+ // The balance of a special address must pass the minimum balance check in
383+ // go-algorand's evaluator, so return a sufficiently large balance.
384+ var balance uint64 = 1000 * 1000 * 1000 * 1000 * 1000
385+ accountData := new (basics.AccountData )
386+ * accountData = basics.AccountData {
387+ MicroAlgos : basics.MicroAlgos {Raw : balance },
388+ }
389+ res [address ] = accountData
390+ }
391+ }
392+
391393 return res , nil
392394}
393395
394- // PreloadAccounts loads the account data for the given addresses and stores them
395- // in the internal cache.
396- func (l * LedgerForEvaluator ) PreloadAccounts (addresses map [basics.Address ]struct {}) error {
397- accountData , err := l .loadAccounts (addresses )
396+ func (l * LedgerForEvaluator ) parseAddress (row pgx.Row ) (basics.Address , bool /*exists*/ , error ) {
397+ var buf []byte
398+ err := row .Scan (& buf )
399+ if err == pgx .ErrNoRows {
400+ return basics.Address {}, false , nil
401+ }
398402 if err != nil {
399- return err
403+ return basics. Address {}, false , fmt . Errorf ( "parseAddress() err: %w" , err )
400404 }
401405
402- l .preloadedAccountData = accountData
403- return nil
406+ var address basics.Address
407+ copy (address [:], buf )
408+
409+ return address , true , nil
404410}
405411
406- // LookupWithoutRewards is part of go-algorand's ledgerForEvaluator interface.
407- func (l LedgerForEvaluator ) LookupWithoutRewards (round basics.Round , address basics.Address ) (basics.AccountData , basics.Round , error ) {
408- // The balance of a special address must pass the minimum balance check in
409- // go-algorand's evaluator, so return a sufficiently large balance.
410- if l .isSpecialAddress (address ) {
411- var balance uint64 = 1000 * 1000 * 1000 * 1000 * 1000
412- accountData := basics.AccountData {
413- MicroAlgos : basics.MicroAlgos {Raw : balance },
414- }
415- return accountData , round , nil
412+ // GetAssetCreator is part of go-algorand's indexerLedgerForEval interface.
413+ func (l LedgerForEvaluator ) GetAssetCreator (indices map [basics.AssetIndex ]struct {}) (map [basics.AssetIndex ]ledger.FoundAddress , error ) {
414+ indicesArr := make ([]basics.AssetIndex , 0 , len (indices ))
415+ for index := range indices {
416+ indicesArr = append (indicesArr , index )
416417 }
417418
418- if accountData , ok := l .preloadedAccountData [address ]; ok {
419- if accountData == nil {
420- return basics.AccountData {}, round , nil
421- }
422- return * accountData , round , nil
419+ var batch pgx.Batch
420+ for _ , index := range indicesArr {
421+ batch .Queue (assetCreatorStmtName , uint64 (index ))
423422 }
424423
425- // Account was not preloaded.
426- accountDataMap , err := l .loadAccounts (map [basics.Address ]struct {}{address : {}})
427- if err != nil {
428- return basics.AccountData {}, basics .Round (0 ), err
429- }
430- accountData := accountDataMap [address ]
424+ results := l .tx .SendBatch (context .Background (), & batch )
425+ res := make (map [basics.AssetIndex ]ledger.FoundAddress , len (indices ))
426+ for _ , index := range indicesArr {
427+ row := results .QueryRow ()
428+
429+ address , exists , err := l .parseAddress (row )
430+ if err != nil {
431+ return nil , fmt .Errorf ("GetAssetCreator() err: %w" , err )
432+ }
431433
432- if accountData == nil {
433- return basics.AccountData {}, round , nil
434+ res [index ] = ledger.FoundAddress {Address : address , Exists : exists }
434435 }
435- return * accountData , round , nil
436- }
436+ results .Close ()
437437
438- // GetCreatorForRound is part of go-algorand's ledgerForEvaluator interface.
439- func (l LedgerForEvaluator ) GetCreatorForRound (_ basics.Round , cindex basics.CreatableIndex , ctype basics.CreatableType ) (basics.Address , bool , error ) {
440- var row pgx.Row
438+ return res , nil
439+ }
441440
442- switch ctype {
443- case basics .AssetCreatable :
444- row = l .tx .QueryRow (context .Background (), assetCreatorStmtName , uint64 (cindex ))
445- case basics .AppCreatable :
446- row = l .tx .QueryRow (context .Background (), appCreatorStmtName , uint64 (cindex ))
447- default :
448- panic ("unknown creatable type" )
441+ // GetAppCreator is part of go-algorand's indexerLedgerForEval interface.
442+ func (l LedgerForEvaluator ) GetAppCreator (indices map [basics.AppIndex ]struct {}) (map [basics.AppIndex ]ledger.FoundAddress , error ) {
443+ indicesArr := make ([]basics.AppIndex , 0 , len (indices ))
444+ for index := range indices {
445+ indicesArr = append (indicesArr , index )
449446 }
450447
451- var buf []byte
452- err := row .Scan (& buf )
453- if err == pgx .ErrNoRows {
454- return basics.Address {}, false , nil
455- }
456- if err != nil {
457- return basics.Address {}, false , fmt .Errorf ("GetCreatorForRound() err: %w" , err )
448+ var batch pgx.Batch
449+ for _ , index := range indicesArr {
450+ batch .Queue (appCreatorStmtName , uint64 (index ))
458451 }
459452
460- var address basics.Address
461- copy (address [:], buf )
453+ results := l .tx .SendBatch (context .Background (), & batch )
454+ res := make (map [basics.AppIndex ]ledger.FoundAddress , len (indices ))
455+ for _ , index := range indicesArr {
456+ row := results .QueryRow ()
462457
463- return address , true , nil
464- }
458+ address , exists , err := l .parseAddress (row )
459+ if err != nil {
460+ return nil , fmt .Errorf ("GetAppCreator() err: %w" , err )
461+ }
462+
463+ res [index ] = ledger.FoundAddress {Address : address , Exists : exists }
464+ }
465+ results .Close ()
465466
466- // GenesisHash is part of go-algorand's ledgerForEvaluator interface.
467- func (l LedgerForEvaluator ) GenesisHash () crypto.Digest {
468- return l .genesisHash
467+ return res , nil
469468}
470469
471- // Totals is part of go-algorand's ledgerForEvaluator interface.
472- func (l LedgerForEvaluator ) Totals (round basics. Round ) (ledgercore.AccountTotals , error ) {
470+ // Totals is part of go-algorand's indexerLedgerForEval interface.
471+ func (l LedgerForEvaluator ) Totals () (ledgercore.AccountTotals , error ) {
473472 // The evaluator uses totals only for recomputing the rewards pool balance. Indexer
474473 // does not currently compute this balance, and we can return an empty struct
475474 // here.
476475 return ledgercore.AccountTotals {}, nil
477476}
478-
479- // CompactCertVoters is part of go-algorand's ledgerForEvaluator interface.
480- func (l LedgerForEvaluator ) CompactCertVoters (basics.Round ) (* ledger.VotersForRound , error ) {
481- // This function is not used by evaluator.
482- return nil , errors .New ("CompactCertVoters() not implemented" )
483- }
0 commit comments