5
5
"encoding/base64"
6
6
"errors"
7
7
"fmt"
8
+ "slices"
8
9
"sort"
9
10
"strconv"
10
11
"strings"
@@ -34,19 +35,6 @@ func decodeDigest(str *string, field string, errorArr []string) (string, []strin
34
35
return "" , errorArr
35
36
}
36
37
37
- // decodeAddress returns the byte representation of the input string, or appends an error to errorArr
38
- func decodeAddress (str * string , field string , errorArr []string ) ([]byte , []string ) {
39
- if str != nil {
40
- addr , err := sdk .DecodeAddress (* str )
41
- if err != nil {
42
- return nil , append (errorArr , fmt .Sprintf ("%s '%s': %v" , errUnableToParseAddress , field , err ))
43
- }
44
- return addr [:], errorArr
45
- }
46
- // Pass through
47
- return nil , errorArr
48
- }
49
-
50
38
// decodeAddress converts the role information into a bitmask, or appends an error to errorArr
51
39
func decodeAddressRole (role * string , excludeCloseTo * bool , errorArr []string ) (idb.AddressRole , []string ) {
52
40
// If the string is nil, return early.
@@ -298,6 +286,94 @@ func txnRowToTransaction(row idb.TxnRow) (generated.Transaction, error) {
298
286
return txn , nil
299
287
}
300
288
289
+ func hdrRowToBlock (row idb.BlockRow ) generated.Block {
290
+
291
+ rewards := generated.BlockRewards {
292
+ FeeSink : row .BlockHeader .FeeSink .String (),
293
+ RewardsCalculationRound : uint64 (row .BlockHeader .RewardsRecalculationRound ),
294
+ RewardsLevel : row .BlockHeader .RewardsLevel ,
295
+ RewardsPool : row .BlockHeader .RewardsPool .String (),
296
+ RewardsRate : row .BlockHeader .RewardsRate ,
297
+ RewardsResidue : row .BlockHeader .RewardsResidue ,
298
+ }
299
+
300
+ upgradeState := generated.BlockUpgradeState {
301
+ CurrentProtocol : string (row .BlockHeader .CurrentProtocol ),
302
+ NextProtocol : strPtr (string (row .BlockHeader .NextProtocol )),
303
+ NextProtocolApprovals : uint64Ptr (row .BlockHeader .NextProtocolApprovals ),
304
+ NextProtocolSwitchOn : uint64Ptr (uint64 (row .BlockHeader .NextProtocolSwitchOn )),
305
+ NextProtocolVoteBefore : uint64Ptr (uint64 (row .BlockHeader .NextProtocolVoteBefore )),
306
+ }
307
+
308
+ upgradeVote := generated.BlockUpgradeVote {
309
+ UpgradeApprove : boolPtr (row .BlockHeader .UpgradeApprove ),
310
+ UpgradeDelay : uint64Ptr (uint64 (row .BlockHeader .UpgradeDelay )),
311
+ UpgradePropose : strPtr (string (row .BlockHeader .UpgradePropose )),
312
+ }
313
+
314
+ var partUpdates * generated.ParticipationUpdates = & generated.ParticipationUpdates {}
315
+ if len (row .BlockHeader .ExpiredParticipationAccounts ) > 0 {
316
+ addrs := make ([]string , len (row .BlockHeader .ExpiredParticipationAccounts ))
317
+ for i := 0 ; i < len (addrs ); i ++ {
318
+ addrs [i ] = row .BlockHeader .ExpiredParticipationAccounts [i ].String ()
319
+ }
320
+ partUpdates .ExpiredParticipationAccounts = strArrayPtr (addrs )
321
+ }
322
+ if len (row .BlockHeader .AbsentParticipationAccounts ) > 0 {
323
+ addrs := make ([]string , len (row .BlockHeader .AbsentParticipationAccounts ))
324
+ for i := 0 ; i < len (addrs ); i ++ {
325
+ addrs [i ] = row .BlockHeader .AbsentParticipationAccounts [i ].String ()
326
+ }
327
+ partUpdates .AbsentParticipationAccounts = strArrayPtr (addrs )
328
+ }
329
+ if * partUpdates == (generated.ParticipationUpdates {}) {
330
+ partUpdates = nil
331
+ }
332
+
333
+ // order these so they're deterministic
334
+ orderedTrackingTypes := make ([]sdk.StateProofType , len (row .BlockHeader .StateProofTracking ))
335
+ trackingArray := make ([]generated.StateProofTracking , len (row .BlockHeader .StateProofTracking ))
336
+ elems := 0
337
+ for key := range row .BlockHeader .StateProofTracking {
338
+ orderedTrackingTypes [elems ] = key
339
+ elems ++
340
+ }
341
+ slices .Sort (orderedTrackingTypes )
342
+ for i := 0 ; i < len (orderedTrackingTypes ); i ++ {
343
+ stpfTracking := row .BlockHeader .StateProofTracking [orderedTrackingTypes [i ]]
344
+ thing1 := generated.StateProofTracking {
345
+ NextRound : uint64Ptr (uint64 (stpfTracking .StateProofNextRound )),
346
+ Type : uint64Ptr (uint64 (orderedTrackingTypes [i ])),
347
+ VotersCommitment : byteSliceOmitZeroPtr (stpfTracking .StateProofVotersCommitment ),
348
+ OnlineTotalWeight : uint64Ptr (uint64 (stpfTracking .StateProofOnlineTotalWeight )),
349
+ }
350
+ trackingArray [orderedTrackingTypes [i ]] = thing1
351
+ }
352
+
353
+ ret := generated.Block {
354
+ Bonus : uint64PtrOrNil (uint64 (row .BlockHeader .Bonus )),
355
+ FeesCollected : uint64PtrOrNil (uint64 (row .BlockHeader .FeesCollected )),
356
+ GenesisHash : row .BlockHeader .GenesisHash [:],
357
+ GenesisId : row .BlockHeader .GenesisID ,
358
+ ParticipationUpdates : partUpdates ,
359
+ PreviousBlockHash : row .BlockHeader .Branch [:],
360
+ Proposer : addrPtr (row .BlockHeader .Proposer ),
361
+ ProposerPayout : uint64PtrOrNil (uint64 (row .BlockHeader .ProposerPayout )),
362
+ Rewards : & rewards ,
363
+ Round : uint64 (row .BlockHeader .Round ),
364
+ Seed : row .BlockHeader .Seed [:],
365
+ StateProofTracking : & trackingArray ,
366
+ Timestamp : uint64 (row .BlockHeader .TimeStamp ),
367
+ Transactions : nil ,
368
+ TransactionsRoot : row .BlockHeader .TxnCommitments .NativeSha512_256Commitment [:],
369
+ TransactionsRootSha256 : row .BlockHeader .TxnCommitments .Sha256Commitment [:],
370
+ TxnCounter : uint64Ptr (row .BlockHeader .TxnCounter ),
371
+ UpgradeState : & upgradeState ,
372
+ UpgradeVote : & upgradeVote ,
373
+ }
374
+ return ret
375
+ }
376
+
301
377
func signedTxnWithAdToTransaction (stxn * sdk.SignedTxnWithAD , extra rowData ) (generated.Transaction , error ) {
302
378
var payment * generated.TransactionPayment
303
379
var keyreg * generated.TransactionKeyreg
@@ -640,9 +716,14 @@ func edIndexToAddress(index uint64, txn sdk.Transaction, shared []sdk.Address) (
640
716
}
641
717
642
718
func (si * ServerImplementation ) assetParamsToAssetQuery (params generated.SearchForAssetsParams ) (idb.AssetsQuery , error ) {
643
- creator , errorArr := decodeAddress (params .Creator , "creator" , make ([]string , 0 ))
644
- if len (errorArr ) != 0 {
645
- return idb.AssetsQuery {}, errors .New (errUnableToParseAddress )
719
+
720
+ var creatorAddressBytes []byte
721
+ if params .Creator != nil {
722
+ creator , err := sdk .DecodeAddress (* params .Creator )
723
+ if err != nil {
724
+ return idb.AssetsQuery {}, fmt .Errorf ("unable to parse creator address: %w" , err )
725
+ }
726
+ creatorAddressBytes = creator [:]
646
727
}
647
728
648
729
var assetGreaterThan * uint64
@@ -657,7 +738,7 @@ func (si *ServerImplementation) assetParamsToAssetQuery(params generated.SearchF
657
738
query := idb.AssetsQuery {
658
739
AssetID : params .AssetId ,
659
740
AssetIDGreaterThan : assetGreaterThan ,
660
- Creator : creator ,
741
+ Creator : creatorAddressBytes ,
661
742
Name : strOrDefault (params .Name ),
662
743
Unit : strOrDefault (params .Unit ),
663
744
Query : "" ,
@@ -669,9 +750,14 @@ func (si *ServerImplementation) assetParamsToAssetQuery(params generated.SearchF
669
750
}
670
751
671
752
func (si * ServerImplementation ) appParamsToApplicationQuery (params generated.SearchForApplicationsParams ) (idb.ApplicationQuery , error ) {
672
- addr , errorArr := decodeAddress (params .Creator , "creator" , make ([]string , 0 ))
673
- if len (errorArr ) != 0 {
674
- return idb.ApplicationQuery {}, errors .New (errUnableToParseAddress )
753
+
754
+ var creatorAddressBytes []byte
755
+ if params .Creator != nil {
756
+ addr , err := sdk .DecodeAddress (* params .Creator )
757
+ if err != nil {
758
+ return idb.ApplicationQuery {}, fmt .Errorf ("unable to parse creator address: %w" , err )
759
+ }
760
+ creatorAddressBytes = addr [:]
675
761
}
676
762
677
763
var appGreaterThan * uint64
@@ -686,7 +772,7 @@ func (si *ServerImplementation) appParamsToApplicationQuery(params generated.Sea
686
772
return idb.ApplicationQuery {
687
773
ApplicationID : params .ApplicationId ,
688
774
ApplicationIDGreaterThan : appGreaterThan ,
689
- Address : addr ,
775
+ Address : creatorAddressBytes ,
690
776
IncludeDeleted : boolOrDefault (params .IncludeAll ),
691
777
Limit : min (uintOrDefaultValue (params .Limit , si .opts .DefaultApplicationsLimit ), si .opts .MaxApplicationsLimit ),
692
778
}, nil
@@ -708,7 +794,15 @@ func (si *ServerImplementation) transactionParamsToTransactionFilter(params gene
708
794
filter .NextToken = strOrDefault (params .Next )
709
795
710
796
// Address
711
- filter .Address , errorArr = decodeAddress (params .Address , "address" , errorArr )
797
+ if params .Address != nil {
798
+ addr , err := sdk .DecodeAddress (* params .Address )
799
+ if err != nil {
800
+ errorArr = append (errorArr , fmt .Sprintf ("%s: %v" , errUnableToParseAddress , err ))
801
+ }
802
+ filter .Address = addr [:]
803
+ }
804
+
805
+ // Txid
712
806
filter .Txid , errorArr = decodeDigest (params .Txid , "txid" , errorArr )
713
807
714
808
// Byte array
@@ -749,6 +843,112 @@ func (si *ServerImplementation) transactionParamsToTransactionFilter(params gene
749
843
return
750
844
}
751
845
846
+ func (si * ServerImplementation ) blockParamsToBlockFilter (params generated.SearchForBlockHeadersParams ) (filter idb.BlockHeaderFilter , err error ) {
847
+
848
+ var errs []error
849
+
850
+ // Integer
851
+ filter .Limit = min (uintOrDefaultValue (params .Limit , si .opts .DefaultBlocksLimit ), si .opts .MaxBlocksLimit )
852
+ // If min/max are mixed up
853
+ //
854
+ // This check is performed here instead of in validateBlockFilter because
855
+ // when converting params into a filter, the next token is merged with params.MinRound.
856
+ if params .MinRound != nil && params .MaxRound != nil && * params .MinRound > * params .MaxRound {
857
+ errs = append (errs , errors .New (errInvalidRoundMinMax ))
858
+ }
859
+ filter .MaxRound = params .MaxRound
860
+ filter .MinRound = params .MinRound
861
+
862
+ // String
863
+ if params .Next != nil {
864
+ n , err := idb .DecodeBlockRowNext (* params .Next )
865
+ if err != nil {
866
+ errs = append (errs , fmt .Errorf ("%s: %w" , errUnableToParseNext , err ))
867
+ }
868
+ // Set the MinRound
869
+ if filter .MinRound == nil {
870
+ filter .MinRound = uint64Ptr (n + 1 )
871
+ } else {
872
+ filter .MinRound = uint64Ptr (max (* filter .MinRound , n + 1 ))
873
+ }
874
+ }
875
+
876
+ // Time
877
+ if params .AfterTime != nil {
878
+ filter .AfterTime = * params .AfterTime
879
+ }
880
+ if params .BeforeTime != nil {
881
+ filter .BeforeTime = * params .BeforeTime
882
+ }
883
+
884
+ // Address list
885
+ {
886
+ // Make sure at most one of the participation parameters is set
887
+ numParticipationFilters := 0
888
+ if params .Proposers != nil {
889
+ numParticipationFilters ++
890
+ }
891
+ if params .Expired != nil {
892
+ numParticipationFilters ++
893
+ }
894
+ if params .Absent != nil {
895
+ numParticipationFilters ++
896
+ }
897
+ if numParticipationFilters > 1 {
898
+ errs = append (errs , errors .New ("only one of `proposer`, `expired`, or `absent` can be specified" ))
899
+ }
900
+
901
+ // Validate the number of items in the participation account lists
902
+ if params .Proposers != nil && uint64 (len (* params .Proposers )) > si .opts .MaxAccountListSize {
903
+ errs = append (errs , fmt .Errorf ("proposers list too long, max size is %d" , si .opts .MaxAccountListSize ))
904
+ }
905
+ if params .Expired != nil && uint64 (len (* params .Expired )) > si .opts .MaxAccountListSize {
906
+ errs = append (errs , fmt .Errorf ("expired list too long, max size is %d" , si .opts .MaxAccountListSize ))
907
+ }
908
+ if params .Absent != nil && uint64 (len (* params .Absent )) > si .opts .MaxAccountListSize {
909
+ errs = append (errs , fmt .Errorf ("absent list too long, max size is %d" , si .opts .MaxAccountListSize ))
910
+ }
911
+
912
+ filter .Proposers = make (map [sdk.Address ]struct {}, 0 )
913
+ if params .Proposers != nil {
914
+ for _ , s := range * params .Proposers {
915
+ addr , err := sdk .DecodeAddress (s )
916
+ if err != nil {
917
+ errs = append (errs , fmt .Errorf ("unable to parse proposer address `%s`: %w" , s , err ))
918
+ } else {
919
+ filter .Proposers [addr ] = struct {}{}
920
+ }
921
+ }
922
+ }
923
+
924
+ filter .ExpiredParticipationAccounts = make (map [sdk.Address ]struct {}, 0 )
925
+ if params .Expired != nil {
926
+ for _ , s := range * params .Expired {
927
+ addr , err := sdk .DecodeAddress (s )
928
+ if err != nil {
929
+ errs = append (errs , fmt .Errorf ("unable to parse expired address `%s`: %w" , s , err ))
930
+ } else {
931
+ filter .ExpiredParticipationAccounts [addr ] = struct {}{}
932
+ }
933
+ }
934
+ }
935
+
936
+ filter .AbsentParticipationAccounts = make (map [sdk.Address ]struct {}, 0 )
937
+ if params .Absent != nil {
938
+ for _ , s := range * params .Absent {
939
+ addr , err := sdk .DecodeAddress (s )
940
+ if err != nil {
941
+ errs = append (errs , fmt .Errorf ("unable to parse absent address `%s`: %w" , s , err ))
942
+ } else {
943
+ filter .AbsentParticipationAccounts [addr ] = struct {}{}
944
+ }
945
+ }
946
+ }
947
+ }
948
+
949
+ return filter , errors .Join (errs ... )
950
+ }
951
+
752
952
func (si * ServerImplementation ) maxAccountsErrorToAccountsErrorResponse (maxErr idb.MaxAPIResourcesPerAccountError ) generated.ErrorResponse {
753
953
addr := maxErr .Address .String ()
754
954
max := uint64 (si .opts .MaxAPIResourcesPerAccount )
0 commit comments