summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTsachi Herman <tsachi.herman@algorand.com>2021-10-07 18:40:01 -0400
committerTsachi Herman <tsachi.herman@algorand.com>2021-10-07 18:40:01 -0400
commit60843dee81b786768d910b234d52f62746bf932e (patch)
treee42b0c2c52480b1fcaec9b3eaa66b0067ceef870
parent4629c44dea5798be38476bdbe5c6bf49930fe866 (diff)
parentc59326f657e4b7ae2104446ecbd9d9f5ce98d1ad (diff)
Merge branch 'master' into tolik/eval-for-indexer-resourcestolik/eval-for-indexer-resources
-rw-r--r--Makefile2
-rw-r--r--agreement/msgp_gen.go1283
-rw-r--r--catchup/fetcher_test.go6
-rw-r--r--catchup/peerSelector_test.go5
-rw-r--r--config/config.go25
-rw-r--r--config/consensus.go14
-rw-r--r--config/local_defaults.go184
-rw-r--r--crypto/compactcert/common.go2
-rw-r--r--crypto/compactcert/msgp_gen.go24
-rw-r--r--crypto/compactcert/structs.go14
-rw-r--r--crypto/curve25519.go15
-rw-r--r--crypto/msgp_gen.go46
-rw-r--r--crypto/multisig.go9
-rw-r--r--crypto/multisig_test.go2
-rw-r--r--crypto/vrf.go5
-rw-r--r--data/basics/msgp_gen.go6
-rw-r--r--data/basics/userBalance.go15
-rw-r--r--data/bookkeeping/block.go15
-rw-r--r--data/bookkeeping/msgp_gen.go922
-rw-r--r--data/bookkeeping/msgp_gen_test.go60
-rw-r--r--data/pooldata/msgp_gen.go91
-rw-r--r--data/pooldata/msgp_gen_test.go73
-rw-r--r--data/pooldata/signedTxGroup.go63
-rw-r--r--data/pools/transactionPool.go193
-rw-r--r--data/pools/transactionPool_test.go40
-rw-r--r--data/transactions/application.go24
-rw-r--r--data/transactions/application_test.go8
-rw-r--r--data/transactions/logic/README.md5
-rw-r--r--data/transactions/logic/TEAL_opcodes.md13
-rw-r--r--data/transactions/logic/assembler_test.go32
-rw-r--r--data/transactions/logic/doc.go7
-rw-r--r--data/transactions/logic/eval.go266
-rw-r--r--data/transactions/logic/evalAppTxn_test.go162
-rw-r--r--data/transactions/logic/evalStateful_test.go2
-rw-r--r--data/transactions/logic/eval_test.go69
-rw-r--r--data/transactions/logic/fields.go36
-rw-r--r--data/transactions/logic/opcodes.go3
-rw-r--r--data/transactions/logictest/ledger.go23
-rw-r--r--data/transactions/msgp_gen.go76
-rw-r--r--data/transactions/transaction.go5
-rw-r--r--data/transactions/verify/verifiedTxnCache.go26
-rw-r--r--data/txHandler.go244
-rw-r--r--data/txHandler_test.go172
-rw-r--r--go.mod1
-rw-r--r--go.sum30
-rw-r--r--installer/config.json.example8
-rw-r--r--ledger/README.md10
-rw-r--r--ledger/appcow.go7
-rw-r--r--ledger/applications.go15
-rw-r--r--ledger/apply/apply.go23
-rw-r--r--ledger/apptxn_test.go199
-rw-r--r--ledger/eval.go191
-rw-r--r--ledger/evalIndexer.go2
-rw-r--r--ledger/evalIndexer_test.go66
-rw-r--r--ledger/eval_test.go334
-rw-r--r--ledger/ledger_perf_test.go2
-rw-r--r--ledger/ledgercore/error.go9
-rw-r--r--logging/telemetryspec/metric.go61
-rw-r--r--network/ping.go2
-rw-r--r--network/wsNetwork.go23
-rw-r--r--network/wsNetwork_test.go225
-rw-r--r--network/wsPeer.go90
-rw-r--r--node/assemble_test.go4
-rw-r--r--node/node.go61
-rw-r--r--node/txnSyncConn.go240
-rw-r--r--protocol/tags.go1
-rw-r--r--protocol/txntype.go12
-rw-r--r--rpcs/blockService_test.go7
-rw-r--r--rpcs/txService.go6
-rw-r--r--rpcs/txSyncer.go3
-rw-r--r--rpcs/txSyncer_test.go45
-rw-r--r--test/e2e-go/cli/goal/expect/goalNodeTest.exp25
-rw-r--r--test/e2e-go/features/participation/participationExpiration_test.go172
-rw-r--r--test/e2e-go/features/partitionRecovery/partitionRecovery_test.go12
-rw-r--r--test/e2e-go/features/transactions/messageRate_test.go248
-rw-r--r--test/e2e-go/features/transactions/txnsync_test.go376
-rwxr-xr-xtest/scripts/e2e_subs/app-assets.sh43
-rwxr-xr-xtest/scripts/e2e_subs/app-group.py77
-rwxr-xr-xtest/scripts/e2e_subs/app-rekey.py81
-rwxr-xr-xtest/scripts/e2e_subs/example.py13
-rwxr-xr-xtest/scripts/e2e_subs/goal/goal.py53
-rw-r--r--test/testdata/configs/config-v17.json96
-rw-r--r--test/testdata/mainnetblocksbin0 -> 25415596 bytes
-rw-r--r--test/testdata/nettemplates/OneNodeTwoRelays.json30
-rw-r--r--test/testdata/nettemplates/TwoNodes50EachWithTwoRelays.json41
-rw-r--r--test/testdata/nettemplates/TwoNodesExpiredOfflineV29.json36
-rw-r--r--test/testdata/nettemplates/TwoNodesExpiredOfflineVFuture.json36
-rw-r--r--txnsync/bitmask.go250
-rw-r--r--txnsync/bitmask_test.go252
-rw-r--r--txnsync/bloomFilter.go239
-rw-r--r--txnsync/bloomFilter_test.go366
-rw-r--r--txnsync/emulatorCore_test.go267
-rw-r--r--txnsync/emulatorLogger_test.go151
-rw-r--r--txnsync/emulatorNode_test.go393
-rw-r--r--txnsync/emulatorTimer_test.go122
-rw-r--r--txnsync/emulator_test.go781
-rw-r--r--txnsync/encodedgroups_test.go132
-rw-r--r--txnsync/encodedgroupsmarshalers.go795
-rw-r--r--txnsync/encodedgroupstypes.go372
-rw-r--r--txnsync/encodedgroupsunmarshalers.go648
-rw-r--r--txnsync/exchange.go91
-rw-r--r--txnsync/incoming.go313
-rw-r--r--txnsync/incoming_test.go343
-rw-r--r--txnsync/interfaces.go113
-rw-r--r--txnsync/logger.go88
-rw-r--r--txnsync/mainloop.go437
-rw-r--r--txnsync/mainloop_test.go71
-rw-r--r--txnsync/metrics.go28
-rw-r--r--txnsync/msgbuffers.go76
-rw-r--r--txnsync/msgbuffers_test.go143
-rw-r--r--txnsync/msgorderingheap.go100
-rw-r--r--txnsync/msgorderingheap_test.go271
-rw-r--r--txnsync/msgp_gen.go35449
-rw-r--r--txnsync/msgp_gen_test.go1693
-rw-r--r--txnsync/outgoing.go334
-rw-r--r--txnsync/outgoing_test.go612
-rw-r--r--txnsync/peer.go849
-rw-r--r--txnsync/peer_test.go1000
-rw-r--r--txnsync/peerscheduler.go200
-rw-r--r--txnsync/peerscheduler_test.go283
-rw-r--r--txnsync/profiler.go210
-rw-r--r--txnsync/profiler_test.go269
-rw-r--r--txnsync/sent_filter.go82
-rw-r--r--txnsync/sent_filter_test.go57
-rw-r--r--txnsync/service.go78
-rw-r--r--txnsync/service_test.go165
-rw-r--r--txnsync/transactionCache.go374
-rw-r--r--txnsync/transactionCache_test.go333
-rw-r--r--txnsync/txngroups.go224
-rw-r--r--txnsync/txngroups_test.go530
-rw-r--r--util/bloom/bloom.go21
-rw-r--r--util/bloom/bloom_test.go28
-rw-r--r--util/bloom/generic.go27
-rw-r--r--util/bloom/xor.go277
-rw-r--r--util/bloom/xor_test.go322
-rw-r--r--util/compress/deflate.go174
-rw-r--r--util/compress/deflate_test.go123
-rw-r--r--util/compress/libdeflate/.cirrus.yml8
-rw-r--r--util/compress/libdeflate/.github/workflows/ci.yml123
-rw-r--r--util/compress/libdeflate/.gitignore21
-rw-r--r--util/compress/libdeflate/COPYING21
-rw-r--r--util/compress/libdeflate/Makefile372
-rw-r--r--util/compress/libdeflate/Makefile.msc65
-rw-r--r--util/compress/libdeflate/NEWS200
-rw-r--r--util/compress/libdeflate/README.md283
-rw-r--r--util/compress/libdeflate/common/common_defs.h334
-rw-r--r--util/compress/libdeflate/common/compiler_gcc.h201
-rw-r--r--util/compress/libdeflate/common/compiler_msc.h80
-rw-r--r--util/compress/libdeflate/lib/adler32.c130
-rw-r--r--util/compress/libdeflate/lib/adler32_vec_template.h124
-rw-r--r--util/compress/libdeflate/lib/arm/adler32_impl.h125
-rw-r--r--util/compress/libdeflate/lib/arm/cpu_features.c133
-rw-r--r--util/compress/libdeflate/lib/arm/cpu_features.h40
-rw-r--r--util/compress/libdeflate/lib/arm/crc32_impl.h247
-rw-r--r--util/compress/libdeflate/lib/arm/matchfinder_impl.h86
-rw-r--r--util/compress/libdeflate/lib/bt_matchfinder.h363
-rw-r--r--util/compress/libdeflate/lib/cpu_features_common.h88
-rw-r--r--util/compress/libdeflate/lib/crc32.c313
-rw-r--r--util/compress/libdeflate/lib/crc32_table.h526
-rw-r--r--util/compress/libdeflate/lib/crc32_vec_template.h61
-rw-r--r--util/compress/libdeflate/lib/decompress_template.h421
-rw-r--r--util/compress/libdeflate/lib/deflate_compress.c2854
-rw-r--r--util/compress/libdeflate/lib/deflate_compress.h13
-rw-r--r--util/compress/libdeflate/lib/deflate_constants.h66
-rw-r--r--util/compress/libdeflate/lib/deflate_decompress.c1000
-rw-r--r--util/compress/libdeflate/lib/gzip_compress.c95
-rw-r--r--util/compress/libdeflate/lib/gzip_constants.h45
-rw-r--r--util/compress/libdeflate/lib/gzip_decompress.c148
-rw-r--r--util/compress/libdeflate/lib/hc_matchfinder.h412
-rw-r--r--util/compress/libdeflate/lib/lib_common.h67
-rw-r--r--util/compress/libdeflate/lib/matchfinder_common.h176
-rw-r--r--util/compress/libdeflate/lib/unaligned.h228
-rw-r--r--util/compress/libdeflate/lib/utils.c142
-rw-r--r--util/compress/libdeflate/lib/x86/adler32_impl.h337
-rw-r--r--util/compress/libdeflate/lib/x86/cpu_features.c152
-rw-r--r--util/compress/libdeflate/lib/x86/cpu_features.h41
-rw-r--r--util/compress/libdeflate/lib/x86/crc32_impl.h92
-rw-r--r--util/compress/libdeflate/lib/x86/crc32_pclmul_template.h262
-rw-r--r--util/compress/libdeflate/lib/x86/decompress_impl.h31
-rw-r--r--util/compress/libdeflate/lib/x86/matchfinder_impl.h122
-rw-r--r--util/compress/libdeflate/lib/zlib_compress.c87
-rw-r--r--util/compress/libdeflate/lib/zlib_constants.h21
-rw-r--r--util/compress/libdeflate/lib/zlib_decompress.c108
-rw-r--r--util/compress/libdeflate/libdeflate.h366
-rw-r--r--util/compress/libdeflate/programs/benchmark.c696
-rw-r--r--util/compress/libdeflate/programs/checksum.c207
-rw-r--r--util/compress/libdeflate/programs/gzip.c658
-rw-r--r--util/compress/libdeflate/programs/prog_util.c496
-rw-r--r--util/compress/libdeflate/programs/prog_util.h179
-rw-r--r--util/compress/libdeflate/programs/test_checksums.c196
-rw-r--r--util/compress/libdeflate/programs/test_custom_malloc.c85
-rw-r--r--util/compress/libdeflate/programs/test_incomplete_codes.c385
-rw-r--r--util/compress/libdeflate/programs/test_litrunlen_overflow.c72
-rw-r--r--util/compress/libdeflate/programs/test_slow_decompression.c472
-rw-r--r--util/compress/libdeflate/programs/test_trailing_bytes.c152
-rw-r--r--util/compress/libdeflate/programs/test_util.c243
-rw-r--r--util/compress/libdeflate/programs/test_util.h67
-rw-r--r--util/compress/libdeflate/programs/tgetopt.c118
-rw-r--r--util/compress/libdeflate/scripts/afl-fuzz/Makefile12
-rw-r--r--util/compress/libdeflate/scripts/afl-fuzz/deflate_compress/fuzz.c40
-rw-r--r--util/compress/libdeflate/scripts/afl-fuzz/deflate_compress/inputs/0bin0 -> 500 bytes
-rw-r--r--util/compress/libdeflate/scripts/afl-fuzz/deflate_decompress/fuzz.c28
-rw-r--r--util/compress/libdeflate/scripts/afl-fuzz/deflate_decompress/inputs/03
-rw-r--r--util/compress/libdeflate/scripts/afl-fuzz/gzip_decompress/fuzz.c28
-rw-r--r--util/compress/libdeflate/scripts/afl-fuzz/gzip_decompress/inputs/0bin0 -> 187 bytes
-rwxr-xr-xutil/compress/libdeflate/scripts/afl-fuzz/prepare_for_fuzz.sh14
-rw-r--r--util/compress/libdeflate/scripts/afl-fuzz/zlib_decompress/fuzz.c28
-rw-r--r--util/compress/libdeflate/scripts/afl-fuzz/zlib_decompress/inputs/03
-rwxr-xr-xutil/compress/libdeflate/scripts/android_build.sh108
-rwxr-xr-xutil/compress/libdeflate/scripts/android_tests.sh69
-rwxr-xr-xutil/compress/libdeflate/scripts/checksum_benchmarks.sh167
-rwxr-xr-xutil/compress/libdeflate/scripts/detect.sh63
-rw-r--r--util/compress/libdeflate/scripts/exec_tests.sh34
-rw-r--r--util/compress/libdeflate/scripts/gen_crc32_multipliers.c108
-rw-r--r--util/compress/libdeflate/scripts/gen_crc32_table.c100
-rwxr-xr-xutil/compress/libdeflate/scripts/gzip_tests.sh490
-rwxr-xr-xutil/compress/libdeflate/scripts/make-windows-releases.sh20
-rwxr-xr-xutil/compress/libdeflate/scripts/msc_test.bat3
-rwxr-xr-xutil/compress/libdeflate/scripts/pgo_build.sh23
-rwxr-xr-xutil/compress/libdeflate/scripts/produce_gzip_benchmark_table.sh37
-rwxr-xr-xutil/compress/libdeflate/scripts/run_tests.sh329
-rw-r--r--util/timers/deadlineMonitor.go48
-rw-r--r--util/timers/interface.go21
-rw-r--r--util/timers/monotonic.go13
224 files changed, 73373 insertions, 1531 deletions
diff --git a/Makefile b/Makefile
index 50613c6da..77a965887 100644
--- a/Makefile
+++ b/Makefile
@@ -76,7 +76,7 @@ GOLDFLAGS := $(GOLDFLAGS_BASE) \
UNIT_TEST_SOURCES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && go list ./... | grep -v /go-algorand/test/ ))
ALGOD_API_PACKAGES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && cd daemon/algod/api; go list ./... ))
-MSGP_GENERATE := ./protocol ./protocol/test ./crypto ./crypto/compactcert ./data/basics ./data/transactions ./data/committee ./data/bookkeeping ./data/hashable ./agreement ./rpcs ./node ./ledger ./ledger/ledgercore ./compactcert
+MSGP_GENERATE := ./protocol ./protocol/test ./crypto ./crypto/compactcert ./data/basics ./data/transactions ./data/committee ./data/bookkeeping ./data/hashable ./agreement ./rpcs ./node ./ledger ./ledger/ledgercore ./compactcert ./txnsync ./data/pooldata
default: build
diff --git a/agreement/msgp_gen.go b/agreement/msgp_gen.go
index 61db86db6..4eb67496e 100644
--- a/agreement/msgp_gen.go
+++ b/agreement/msgp_gen.go
@@ -6,6 +6,7 @@ import (
"sort"
"github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/msgp/msgp"
@@ -1354,120 +1355,124 @@ func (z period) MsgIsZero() bool {
func (z *proposal) MarshalMsg(b []byte) (o []byte) {
o = msgp.Require(b, z.Msgsize())
// omitempty: check for empty values
- zb0003Len := uint32(27)
- var zb0003Mask uint32 /* 32 bits */
+ zb0004Len := uint32(28)
+ var zb0004Mask uint64 /* 34 bits */
if len((*z).unauthenticatedProposal.Block.BlockHeader.CompactCert) == 0 {
- zb0003Len--
- zb0003Mask |= 0x10
+ zb0004Len--
+ zb0004Mask |= 0x20
}
if (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsLevel == 0 {
- zb0003Len--
- zb0003Mask |= 0x20
+ zb0004Len--
+ zb0004Mask |= 0x40
}
if (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.FeeSink.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x40
+ zb0004Len--
+ zb0004Mask |= 0x80
}
if (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsResidue == 0 {
- zb0003Len--
- zb0003Mask |= 0x80
+ zb0004Len--
+ zb0004Mask |= 0x100
}
if (*z).unauthenticatedProposal.Block.BlockHeader.GenesisID == "" {
- zb0003Len--
- zb0003Mask |= 0x100
+ zb0004Len--
+ zb0004Mask |= 0x200
}
if (*z).unauthenticatedProposal.Block.BlockHeader.GenesisHash.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x200
+ zb0004Len--
+ zb0004Mask |= 0x400
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x400
+ zb0004Len--
+ zb0004Mask |= 0x800
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocol.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x800
+ zb0004Len--
+ zb0004Mask |= 0x1000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x1000
+ zb0004Len--
+ zb0004Mask |= 0x2000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolApprovals == 0 {
- zb0003Len--
- zb0003Mask |= 0x2000
+ zb0004Len--
+ zb0004Mask |= 0x4000
}
if (*z).unauthenticatedProposal.OriginalPeriod == 0 {
- zb0003Len--
- zb0003Mask |= 0x4000
+ zb0004Len--
+ zb0004Mask |= 0x8000
}
if (*z).unauthenticatedProposal.OriginalProposer.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x8000
+ zb0004Len--
+ zb0004Mask |= 0x10000
+ }
+ if len((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x20000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.Branch.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x10000
+ zb0004Len--
+ zb0004Mask |= 0x40000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x20000
+ zb0004Len--
+ zb0004Mask |= 0x80000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRate == 0 {
- zb0003Len--
- zb0003Mask |= 0x40000
+ zb0004Len--
+ zb0004Mask |= 0x100000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.Round.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x80000
+ zb0004Len--
+ zb0004Mask |= 0x200000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x100000
+ zb0004Len--
+ zb0004Mask |= 0x400000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsPool.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x200000
+ zb0004Len--
+ zb0004Mask |= 0x800000
}
if (*z).unauthenticatedProposal.SeedProof.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x400000
+ zb0004Len--
+ zb0004Mask |= 0x1000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.Seed.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x800000
+ zb0004Len--
+ zb0004Mask |= 0x2000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.TxnCounter == 0 {
- zb0003Len--
- zb0003Mask |= 0x1000000
+ zb0004Len--
+ zb0004Mask |= 0x4000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.TimeStamp == 0 {
- zb0003Len--
- zb0003Mask |= 0x2000000
+ zb0004Len--
+ zb0004Mask |= 0x8000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.TxnRoot.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x4000000
+ zb0004Len--
+ zb0004Mask |= 0x10000000
}
if (*z).unauthenticatedProposal.Block.Payset.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x8000000
+ zb0004Len--
+ zb0004Mask |= 0x20000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x10000000
+ zb0004Len--
+ zb0004Mask |= 0x40000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x20000000
+ zb0004Len--
+ zb0004Mask |= 0x80000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeApprove == false {
- zb0003Len--
- zb0003Mask |= 0x40000000
+ zb0004Len--
+ zb0004Mask |= 0x100000000
}
- // variable map header, size zb0003Len
- o = msgp.AppendMapHeader(o, zb0003Len)
- if zb0003Len != 0 {
- if (zb0003Mask & 0x10) == 0 { // if not empty
+ // variable map header, size zb0004Len
+ o = msgp.AppendMapHeader(o, zb0004Len)
+ if zb0004Len != 0 {
+ if (zb0004Mask & 0x20) == 0 { // if not empty
// string "cc"
o = append(o, 0xa2, 0x63, 0x63)
if (*z).unauthenticatedProposal.Block.BlockHeader.CompactCert == nil {
@@ -1487,132 +1492,144 @@ func (z *proposal) MarshalMsg(b []byte) (o []byte) {
o = zb0002.MarshalMsg(o)
}
}
- if (zb0003Mask & 0x20) == 0 { // if not empty
+ if (zb0004Mask & 0x40) == 0 { // if not empty
// string "earn"
o = append(o, 0xa4, 0x65, 0x61, 0x72, 0x6e)
o = msgp.AppendUint64(o, (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsLevel)
}
- if (zb0003Mask & 0x40) == 0 { // if not empty
+ if (zb0004Mask & 0x80) == 0 { // if not empty
// string "fees"
o = append(o, 0xa4, 0x66, 0x65, 0x65, 0x73)
o = (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.FeeSink.MarshalMsg(o)
}
- if (zb0003Mask & 0x80) == 0 { // if not empty
+ if (zb0004Mask & 0x100) == 0 { // if not empty
// string "frac"
o = append(o, 0xa4, 0x66, 0x72, 0x61, 0x63)
o = msgp.AppendUint64(o, (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsResidue)
}
- if (zb0003Mask & 0x100) == 0 { // if not empty
+ if (zb0004Mask & 0x200) == 0 { // if not empty
// string "gen"
o = append(o, 0xa3, 0x67, 0x65, 0x6e)
o = msgp.AppendString(o, (*z).unauthenticatedProposal.Block.BlockHeader.GenesisID)
}
- if (zb0003Mask & 0x200) == 0 { // if not empty
+ if (zb0004Mask & 0x400) == 0 { // if not empty
// string "gh"
o = append(o, 0xa2, 0x67, 0x68)
o = (*z).unauthenticatedProposal.Block.BlockHeader.GenesisHash.MarshalMsg(o)
}
- if (zb0003Mask & 0x400) == 0 { // if not empty
+ if (zb0004Mask & 0x800) == 0 { // if not empty
// string "nextbefore"
o = append(o, 0xaa, 0x6e, 0x65, 0x78, 0x74, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65)
o = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MarshalMsg(o)
}
- if (zb0003Mask & 0x800) == 0 { // if not empty
+ if (zb0004Mask & 0x1000) == 0 { // if not empty
// string "nextproto"
o = append(o, 0xa9, 0x6e, 0x65, 0x78, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f)
o = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocol.MarshalMsg(o)
}
- if (zb0003Mask & 0x1000) == 0 { // if not empty
+ if (zb0004Mask & 0x2000) == 0 { // if not empty
// string "nextswitch"
o = append(o, 0xaa, 0x6e, 0x65, 0x78, 0x74, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68)
o = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MarshalMsg(o)
}
- if (zb0003Mask & 0x2000) == 0 { // if not empty
+ if (zb0004Mask & 0x4000) == 0 { // if not empty
// string "nextyes"
o = append(o, 0xa7, 0x6e, 0x65, 0x78, 0x74, 0x79, 0x65, 0x73)
o = msgp.AppendUint64(o, (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolApprovals)
}
- if (zb0003Mask & 0x4000) == 0 { // if not empty
+ if (zb0004Mask & 0x8000) == 0 { // if not empty
// string "oper"
o = append(o, 0xa4, 0x6f, 0x70, 0x65, 0x72)
o = msgp.AppendUint64(o, uint64((*z).unauthenticatedProposal.OriginalPeriod))
}
- if (zb0003Mask & 0x8000) == 0 { // if not empty
+ if (zb0004Mask & 0x10000) == 0 { // if not empty
// string "oprop"
o = append(o, 0xa5, 0x6f, 0x70, 0x72, 0x6f, 0x70)
o = (*z).unauthenticatedProposal.OriginalProposer.MarshalMsg(o)
}
- if (zb0003Mask & 0x10000) == 0 { // if not empty
+ if (zb0004Mask & 0x20000) == 0 { // if not empty
+ // string "partupdrmv"
+ o = append(o, 0xaa, 0x70, 0x61, 0x72, 0x74, 0x75, 0x70, 0x64, 0x72, 0x6d, 0x76)
+ if (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts)))
+ }
+ for zb0003 := range (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ o = (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].MarshalMsg(o)
+ }
+ }
+ if (zb0004Mask & 0x40000) == 0 { // if not empty
// string "prev"
o = append(o, 0xa4, 0x70, 0x72, 0x65, 0x76)
o = (*z).unauthenticatedProposal.Block.BlockHeader.Branch.MarshalMsg(o)
}
- if (zb0003Mask & 0x20000) == 0 { // if not empty
+ if (zb0004Mask & 0x80000) == 0 { // if not empty
// string "proto"
o = append(o, 0xa5, 0x70, 0x72, 0x6f, 0x74, 0x6f)
o = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.CurrentProtocol.MarshalMsg(o)
}
- if (zb0003Mask & 0x40000) == 0 { // if not empty
+ if (zb0004Mask & 0x100000) == 0 { // if not empty
// string "rate"
o = append(o, 0xa4, 0x72, 0x61, 0x74, 0x65)
o = msgp.AppendUint64(o, (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRate)
}
- if (zb0003Mask & 0x80000) == 0 { // if not empty
+ if (zb0004Mask & 0x200000) == 0 { // if not empty
// string "rnd"
o = append(o, 0xa3, 0x72, 0x6e, 0x64)
o = (*z).unauthenticatedProposal.Block.BlockHeader.Round.MarshalMsg(o)
}
- if (zb0003Mask & 0x100000) == 0 { // if not empty
+ if (zb0004Mask & 0x400000) == 0 { // if not empty
// string "rwcalr"
o = append(o, 0xa6, 0x72, 0x77, 0x63, 0x61, 0x6c, 0x72)
o = (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRecalculationRound.MarshalMsg(o)
}
- if (zb0003Mask & 0x200000) == 0 { // if not empty
+ if (zb0004Mask & 0x800000) == 0 { // if not empty
// string "rwd"
o = append(o, 0xa3, 0x72, 0x77, 0x64)
o = (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsPool.MarshalMsg(o)
}
- if (zb0003Mask & 0x400000) == 0 { // if not empty
+ if (zb0004Mask & 0x1000000) == 0 { // if not empty
// string "sdpf"
o = append(o, 0xa4, 0x73, 0x64, 0x70, 0x66)
o = (*z).unauthenticatedProposal.SeedProof.MarshalMsg(o)
}
- if (zb0003Mask & 0x800000) == 0 { // if not empty
+ if (zb0004Mask & 0x2000000) == 0 { // if not empty
// string "seed"
o = append(o, 0xa4, 0x73, 0x65, 0x65, 0x64)
o = (*z).unauthenticatedProposal.Block.BlockHeader.Seed.MarshalMsg(o)
}
- if (zb0003Mask & 0x1000000) == 0 { // if not empty
+ if (zb0004Mask & 0x4000000) == 0 { // if not empty
// string "tc"
o = append(o, 0xa2, 0x74, 0x63)
o = msgp.AppendUint64(o, (*z).unauthenticatedProposal.Block.BlockHeader.TxnCounter)
}
- if (zb0003Mask & 0x2000000) == 0 { // if not empty
+ if (zb0004Mask & 0x8000000) == 0 { // if not empty
// string "ts"
o = append(o, 0xa2, 0x74, 0x73)
o = msgp.AppendInt64(o, (*z).unauthenticatedProposal.Block.BlockHeader.TimeStamp)
}
- if (zb0003Mask & 0x4000000) == 0 { // if not empty
+ if (zb0004Mask & 0x10000000) == 0 { // if not empty
// string "txn"
o = append(o, 0xa3, 0x74, 0x78, 0x6e)
o = (*z).unauthenticatedProposal.Block.BlockHeader.TxnRoot.MarshalMsg(o)
}
- if (zb0003Mask & 0x8000000) == 0 { // if not empty
+ if (zb0004Mask & 0x20000000) == 0 { // if not empty
// string "txns"
o = append(o, 0xa4, 0x74, 0x78, 0x6e, 0x73)
o = (*z).unauthenticatedProposal.Block.Payset.MarshalMsg(o)
}
- if (zb0003Mask & 0x10000000) == 0 { // if not empty
+ if (zb0004Mask & 0x40000000) == 0 { // if not empty
// string "upgradedelay"
o = append(o, 0xac, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x64, 0x65, 0x6c, 0x61, 0x79)
o = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeDelay.MarshalMsg(o)
}
- if (zb0003Mask & 0x20000000) == 0 { // if not empty
+ if (zb0004Mask & 0x80000000) == 0 { // if not empty
// string "upgradeprop"
o = append(o, 0xab, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x70, 0x72, 0x6f, 0x70)
o = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradePropose.MarshalMsg(o)
}
- if (zb0003Mask & 0x40000000) == 0 { // if not empty
+ if (zb0004Mask & 0x100000000) == 0 { // if not empty
// string "upgradeyes"
o = append(o, 0xaa, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x79, 0x65, 0x73)
o = msgp.AppendBool(o, (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeApprove)
@@ -1630,214 +1647,214 @@ func (_ *proposal) CanMarshalMsg(z interface{}) bool {
func (z *proposal) UnmarshalMsg(bts []byte) (o []byte, err error) {
var field []byte
_ = field
- var zb0003 int
- var zb0004 bool
- zb0003, zb0004, bts, err = msgp.ReadMapHeaderBytes(bts)
+ var zb0004 int
+ var zb0005 bool
+ zb0004, zb0005, bts, err = msgp.ReadMapHeaderBytes(bts)
if _, ok := err.(msgp.TypeError); ok {
- zb0003, zb0004, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ zb0004, zb0005, bts, err = msgp.ReadArrayHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err)
return
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.Round.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Round")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.Branch.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Branch")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.Seed.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Seed")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.TxnRoot.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TxnRoot")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.TimeStamp, bts, err = msgp.ReadInt64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TimeStamp")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.GenesisID, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "GenesisID")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.GenesisHash.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "GenesisHash")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.FeeSink.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "FeeSink")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsPool.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsPool")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsLevel, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsLevel")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRate, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsRate")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsResidue, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsResidue")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRecalculationRound.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsRecalculationRound")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.CurrentProtocol.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CurrentProtocol")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocol.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocol")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolApprovals, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolApprovals")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolVoteBefore")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolSwitchOn")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradePropose.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradePropose")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeDelay.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradeDelay")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeApprove, bts, err = msgp.ReadBoolBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradeApprove")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.TxnCounter, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TxnCounter")
return
}
}
- if zb0003 > 0 {
- zb0003--
- var zb0005 int
- var zb0006 bool
- zb0005, zb0006, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if zb0004 > 0 {
+ zb0004--
+ var zb0006 int
+ var zb0007 bool
+ zb0006, zb0007, bts, err = msgp.ReadMapHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
return
}
- if zb0005 > protocol.NumCompactCertTypes {
- err = msgp.ErrOverflow(uint64(zb0005), uint64(protocol.NumCompactCertTypes))
+ if zb0006 > protocol.NumCompactCertTypes {
+ err = msgp.ErrOverflow(uint64(zb0006), uint64(protocol.NumCompactCertTypes))
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
return
}
- if zb0006 {
+ if zb0007 {
(*z).unauthenticatedProposal.Block.BlockHeader.CompactCert = nil
} else if (*z).unauthenticatedProposal.Block.BlockHeader.CompactCert == nil {
- (*z).unauthenticatedProposal.Block.BlockHeader.CompactCert = make(map[protocol.CompactCertType]bookkeeping.CompactCertState, zb0005)
+ (*z).unauthenticatedProposal.Block.BlockHeader.CompactCert = make(map[protocol.CompactCertType]bookkeeping.CompactCertState, zb0006)
}
- for zb0005 > 0 {
+ for zb0006 > 0 {
var zb0001 protocol.CompactCertType
var zb0002 bookkeeping.CompactCertState
- zb0005--
+ zb0006--
bts, err = zb0001.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
@@ -1851,44 +1868,73 @@ func (z *proposal) UnmarshalMsg(bts []byte) (o []byte, err error) {
(*z).unauthenticatedProposal.Block.BlockHeader.CompactCert[zb0001] = zb0002
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
+ var zb0008 int
+ var zb0009 bool
+ zb0008, zb0009, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0008 > config.MaxProposedExpiredOnlineAccounts {
+ err = msgp.ErrOverflow(uint64(zb0008), uint64(config.MaxProposedExpiredOnlineAccounts))
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0009 {
+ (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = nil
+ } else if (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts != nil && cap((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) >= zb0008 {
+ (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = ((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts)[:zb0008]
+ } else {
+ (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = make([]basics.Address, zb0008)
+ }
+ for zb0003 := range (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts", zb0003)
+ return
+ }
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.Payset.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Payset")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.SeedProof.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "SeedProof")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
{
- var zb0007 uint64
- zb0007, bts, err = msgp.ReadUint64Bytes(bts)
+ var zb0010 uint64
+ zb0010, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "OriginalPeriod")
return
}
- (*z).unauthenticatedProposal.OriginalPeriod = period(zb0007)
+ (*z).unauthenticatedProposal.OriginalPeriod = period(zb0010)
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.OriginalProposer.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "OriginalProposer")
return
}
}
- if zb0003 > 0 {
- err = msgp.ErrTooManyArrayFields(zb0003)
+ if zb0004 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0004)
if err != nil {
err = msgp.WrapError(err, "struct-from-array")
return
@@ -1899,11 +1945,11 @@ func (z *proposal) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err)
return
}
- if zb0004 {
+ if zb0005 {
(*z) = proposal{}
}
- for zb0003 > 0 {
- zb0003--
+ for zb0004 > 0 {
+ zb0004--
field, bts, err = msgp.ReadMapKeyZC(bts)
if err != nil {
err = msgp.WrapError(err)
@@ -2043,27 +2089,27 @@ func (z *proposal) UnmarshalMsg(bts []byte) (o []byte, err error) {
return
}
case "cc":
- var zb0008 int
- var zb0009 bool
- zb0008, zb0009, bts, err = msgp.ReadMapHeaderBytes(bts)
+ var zb0011 int
+ var zb0012 bool
+ zb0011, zb0012, bts, err = msgp.ReadMapHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err, "CompactCert")
return
}
- if zb0008 > protocol.NumCompactCertTypes {
- err = msgp.ErrOverflow(uint64(zb0008), uint64(protocol.NumCompactCertTypes))
+ if zb0011 > protocol.NumCompactCertTypes {
+ err = msgp.ErrOverflow(uint64(zb0011), uint64(protocol.NumCompactCertTypes))
err = msgp.WrapError(err, "CompactCert")
return
}
- if zb0009 {
+ if zb0012 {
(*z).unauthenticatedProposal.Block.BlockHeader.CompactCert = nil
} else if (*z).unauthenticatedProposal.Block.BlockHeader.CompactCert == nil {
- (*z).unauthenticatedProposal.Block.BlockHeader.CompactCert = make(map[protocol.CompactCertType]bookkeeping.CompactCertState, zb0008)
+ (*z).unauthenticatedProposal.Block.BlockHeader.CompactCert = make(map[protocol.CompactCertType]bookkeeping.CompactCertState, zb0011)
}
- for zb0008 > 0 {
+ for zb0011 > 0 {
var zb0001 protocol.CompactCertType
var zb0002 bookkeeping.CompactCertState
- zb0008--
+ zb0011--
bts, err = zb0001.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "CompactCert")
@@ -2076,6 +2122,33 @@ func (z *proposal) UnmarshalMsg(bts []byte) (o []byte, err error) {
}
(*z).unauthenticatedProposal.Block.BlockHeader.CompactCert[zb0001] = zb0002
}
+ case "partupdrmv":
+ var zb0013 int
+ var zb0014 bool
+ zb0013, zb0014, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0013 > config.MaxProposedExpiredOnlineAccounts {
+ err = msgp.ErrOverflow(uint64(zb0013), uint64(config.MaxProposedExpiredOnlineAccounts))
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0014 {
+ (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = nil
+ } else if (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts != nil && cap((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) >= zb0013 {
+ (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = ((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts)[:zb0013]
+ } else {
+ (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = make([]basics.Address, zb0013)
+ }
+ for zb0003 := range (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts", zb0003)
+ return
+ }
+ }
case "txns":
bts, err = (*z).unauthenticatedProposal.Block.Payset.UnmarshalMsg(bts)
if err != nil {
@@ -2090,13 +2163,13 @@ func (z *proposal) UnmarshalMsg(bts []byte) (o []byte, err error) {
}
case "oper":
{
- var zb0010 uint64
- zb0010, bts, err = msgp.ReadUint64Bytes(bts)
+ var zb0015 uint64
+ zb0015, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "OriginalPeriod")
return
}
- (*z).unauthenticatedProposal.OriginalPeriod = period(zb0010)
+ (*z).unauthenticatedProposal.OriginalPeriod = period(zb0015)
}
case "oprop":
bts, err = (*z).unauthenticatedProposal.OriginalProposer.UnmarshalMsg(bts)
@@ -2132,13 +2205,17 @@ func (z *proposal) Msgsize() (s int) {
s += 0 + zb0001.Msgsize() + zb0002.Msgsize()
}
}
+ s += 11 + msgp.ArrayHeaderSize
+ for zb0003 := range (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ s += (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].Msgsize()
+ }
s += 5 + (*z).unauthenticatedProposal.Block.Payset.Msgsize() + 5 + (*z).unauthenticatedProposal.SeedProof.Msgsize() + 5 + msgp.Uint64Size + 6 + (*z).unauthenticatedProposal.OriginalProposer.Msgsize()
return
}
// MsgIsZero returns whether this is a zero value
func (z *proposal) MsgIsZero() bool {
- return ((*z).unauthenticatedProposal.Block.BlockHeader.Round.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Branch.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Seed.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnRoot.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TimeStamp == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.GenesisID == "") && ((*z).unauthenticatedProposal.Block.BlockHeader.GenesisHash.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.FeeSink.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsPool.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsLevel == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRate == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsResidue == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocol.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolApprovals == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeApprove == false) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnCounter == 0) && (len((*z).unauthenticatedProposal.Block.BlockHeader.CompactCert) == 0) && ((*z).unauthenticatedProposal.Block.Payset.MsgIsZero()) && ((*z).unauthenticatedProposal.SeedProof.MsgIsZero()) && ((*z).unauthenticatedProposal.OriginalPeriod == 0) && ((*z).unauthenticatedProposal.OriginalProposer.MsgIsZero())
+ return ((*z).unauthenticatedProposal.Block.BlockHeader.Round.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Branch.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Seed.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnRoot.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TimeStamp == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.GenesisID == "") && ((*z).unauthenticatedProposal.Block.BlockHeader.GenesisHash.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.FeeSink.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsPool.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsLevel == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRate == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsResidue == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocol.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolApprovals == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeApprove == false) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnCounter == 0) && (len((*z).unauthenticatedProposal.Block.BlockHeader.CompactCert) == 0) && (len((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) == 0) && ((*z).unauthenticatedProposal.Block.Payset.MsgIsZero()) && ((*z).unauthenticatedProposal.SeedProof.MsgIsZero()) && ((*z).unauthenticatedProposal.OriginalPeriod == 0) && ((*z).unauthenticatedProposal.OriginalProposer.MsgIsZero())
}
// MarshalMsg implements msgp.Marshaler
@@ -3017,124 +3094,128 @@ func (z step) MsgIsZero() bool {
func (z *transmittedPayload) MarshalMsg(b []byte) (o []byte) {
o = msgp.Require(b, z.Msgsize())
// omitempty: check for empty values
- zb0003Len := uint32(28)
- var zb0003Mask uint64 /* 33 bits */
+ zb0004Len := uint32(29)
+ var zb0004Mask uint64 /* 35 bits */
if len((*z).unauthenticatedProposal.Block.BlockHeader.CompactCert) == 0 {
- zb0003Len--
- zb0003Mask |= 0x20
+ zb0004Len--
+ zb0004Mask |= 0x40
}
if (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsLevel == 0 {
- zb0003Len--
- zb0003Mask |= 0x40
+ zb0004Len--
+ zb0004Mask |= 0x80
}
if (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.FeeSink.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x80
+ zb0004Len--
+ zb0004Mask |= 0x100
}
if (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsResidue == 0 {
- zb0003Len--
- zb0003Mask |= 0x100
+ zb0004Len--
+ zb0004Mask |= 0x200
}
if (*z).unauthenticatedProposal.Block.BlockHeader.GenesisID == "" {
- zb0003Len--
- zb0003Mask |= 0x200
+ zb0004Len--
+ zb0004Mask |= 0x400
}
if (*z).unauthenticatedProposal.Block.BlockHeader.GenesisHash.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x400
+ zb0004Len--
+ zb0004Mask |= 0x800
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x800
+ zb0004Len--
+ zb0004Mask |= 0x1000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocol.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x1000
+ zb0004Len--
+ zb0004Mask |= 0x2000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x2000
+ zb0004Len--
+ zb0004Mask |= 0x4000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolApprovals == 0 {
- zb0003Len--
- zb0003Mask |= 0x4000
+ zb0004Len--
+ zb0004Mask |= 0x8000
}
if (*z).unauthenticatedProposal.OriginalPeriod == 0 {
- zb0003Len--
- zb0003Mask |= 0x8000
+ zb0004Len--
+ zb0004Mask |= 0x10000
}
if (*z).unauthenticatedProposal.OriginalProposer.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x10000
+ zb0004Len--
+ zb0004Mask |= 0x20000
+ }
+ if len((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x40000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.Branch.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x20000
+ zb0004Len--
+ zb0004Mask |= 0x80000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x40000
+ zb0004Len--
+ zb0004Mask |= 0x100000
}
if (*z).PriorVote.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x80000
+ zb0004Len--
+ zb0004Mask |= 0x200000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRate == 0 {
- zb0003Len--
- zb0003Mask |= 0x100000
+ zb0004Len--
+ zb0004Mask |= 0x400000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.Round.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x200000
+ zb0004Len--
+ zb0004Mask |= 0x800000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x400000
+ zb0004Len--
+ zb0004Mask |= 0x1000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsPool.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x800000
+ zb0004Len--
+ zb0004Mask |= 0x2000000
}
if (*z).unauthenticatedProposal.SeedProof.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x1000000
+ zb0004Len--
+ zb0004Mask |= 0x4000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.Seed.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x2000000
+ zb0004Len--
+ zb0004Mask |= 0x8000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.TxnCounter == 0 {
- zb0003Len--
- zb0003Mask |= 0x4000000
+ zb0004Len--
+ zb0004Mask |= 0x10000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.TimeStamp == 0 {
- zb0003Len--
- zb0003Mask |= 0x8000000
+ zb0004Len--
+ zb0004Mask |= 0x20000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.TxnRoot.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x10000000
+ zb0004Len--
+ zb0004Mask |= 0x40000000
}
if (*z).unauthenticatedProposal.Block.Payset.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x20000000
+ zb0004Len--
+ zb0004Mask |= 0x80000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x40000000
+ zb0004Len--
+ zb0004Mask |= 0x100000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x80000000
+ zb0004Len--
+ zb0004Mask |= 0x200000000
}
if (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeApprove == false {
- zb0003Len--
- zb0003Mask |= 0x100000000
+ zb0004Len--
+ zb0004Mask |= 0x400000000
}
- // variable map header, size zb0003Len
- o = msgp.AppendMapHeader(o, zb0003Len)
- if zb0003Len != 0 {
- if (zb0003Mask & 0x20) == 0 { // if not empty
+ // variable map header, size zb0004Len
+ o = msgp.AppendMapHeader(o, zb0004Len)
+ if zb0004Len != 0 {
+ if (zb0004Mask & 0x40) == 0 { // if not empty
// string "cc"
o = append(o, 0xa2, 0x63, 0x63)
if (*z).unauthenticatedProposal.Block.BlockHeader.CompactCert == nil {
@@ -3154,137 +3235,149 @@ func (z *transmittedPayload) MarshalMsg(b []byte) (o []byte) {
o = zb0002.MarshalMsg(o)
}
}
- if (zb0003Mask & 0x40) == 0 { // if not empty
+ if (zb0004Mask & 0x80) == 0 { // if not empty
// string "earn"
o = append(o, 0xa4, 0x65, 0x61, 0x72, 0x6e)
o = msgp.AppendUint64(o, (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsLevel)
}
- if (zb0003Mask & 0x80) == 0 { // if not empty
+ if (zb0004Mask & 0x100) == 0 { // if not empty
// string "fees"
o = append(o, 0xa4, 0x66, 0x65, 0x65, 0x73)
o = (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.FeeSink.MarshalMsg(o)
}
- if (zb0003Mask & 0x100) == 0 { // if not empty
+ if (zb0004Mask & 0x200) == 0 { // if not empty
// string "frac"
o = append(o, 0xa4, 0x66, 0x72, 0x61, 0x63)
o = msgp.AppendUint64(o, (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsResidue)
}
- if (zb0003Mask & 0x200) == 0 { // if not empty
+ if (zb0004Mask & 0x400) == 0 { // if not empty
// string "gen"
o = append(o, 0xa3, 0x67, 0x65, 0x6e)
o = msgp.AppendString(o, (*z).unauthenticatedProposal.Block.BlockHeader.GenesisID)
}
- if (zb0003Mask & 0x400) == 0 { // if not empty
+ if (zb0004Mask & 0x800) == 0 { // if not empty
// string "gh"
o = append(o, 0xa2, 0x67, 0x68)
o = (*z).unauthenticatedProposal.Block.BlockHeader.GenesisHash.MarshalMsg(o)
}
- if (zb0003Mask & 0x800) == 0 { // if not empty
+ if (zb0004Mask & 0x1000) == 0 { // if not empty
// string "nextbefore"
o = append(o, 0xaa, 0x6e, 0x65, 0x78, 0x74, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65)
o = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MarshalMsg(o)
}
- if (zb0003Mask & 0x1000) == 0 { // if not empty
+ if (zb0004Mask & 0x2000) == 0 { // if not empty
// string "nextproto"
o = append(o, 0xa9, 0x6e, 0x65, 0x78, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f)
o = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocol.MarshalMsg(o)
}
- if (zb0003Mask & 0x2000) == 0 { // if not empty
+ if (zb0004Mask & 0x4000) == 0 { // if not empty
// string "nextswitch"
o = append(o, 0xaa, 0x6e, 0x65, 0x78, 0x74, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68)
o = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MarshalMsg(o)
}
- if (zb0003Mask & 0x4000) == 0 { // if not empty
+ if (zb0004Mask & 0x8000) == 0 { // if not empty
// string "nextyes"
o = append(o, 0xa7, 0x6e, 0x65, 0x78, 0x74, 0x79, 0x65, 0x73)
o = msgp.AppendUint64(o, (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolApprovals)
}
- if (zb0003Mask & 0x8000) == 0 { // if not empty
+ if (zb0004Mask & 0x10000) == 0 { // if not empty
// string "oper"
o = append(o, 0xa4, 0x6f, 0x70, 0x65, 0x72)
o = msgp.AppendUint64(o, uint64((*z).unauthenticatedProposal.OriginalPeriod))
}
- if (zb0003Mask & 0x10000) == 0 { // if not empty
+ if (zb0004Mask & 0x20000) == 0 { // if not empty
// string "oprop"
o = append(o, 0xa5, 0x6f, 0x70, 0x72, 0x6f, 0x70)
o = (*z).unauthenticatedProposal.OriginalProposer.MarshalMsg(o)
}
- if (zb0003Mask & 0x20000) == 0 { // if not empty
+ if (zb0004Mask & 0x40000) == 0 { // if not empty
+ // string "partupdrmv"
+ o = append(o, 0xaa, 0x70, 0x61, 0x72, 0x74, 0x75, 0x70, 0x64, 0x72, 0x6d, 0x76)
+ if (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts)))
+ }
+ for zb0003 := range (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ o = (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].MarshalMsg(o)
+ }
+ }
+ if (zb0004Mask & 0x80000) == 0 { // if not empty
// string "prev"
o = append(o, 0xa4, 0x70, 0x72, 0x65, 0x76)
o = (*z).unauthenticatedProposal.Block.BlockHeader.Branch.MarshalMsg(o)
}
- if (zb0003Mask & 0x40000) == 0 { // if not empty
+ if (zb0004Mask & 0x100000) == 0 { // if not empty
// string "proto"
o = append(o, 0xa5, 0x70, 0x72, 0x6f, 0x74, 0x6f)
o = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.CurrentProtocol.MarshalMsg(o)
}
- if (zb0003Mask & 0x80000) == 0 { // if not empty
+ if (zb0004Mask & 0x200000) == 0 { // if not empty
// string "pv"
o = append(o, 0xa2, 0x70, 0x76)
o = (*z).PriorVote.MarshalMsg(o)
}
- if (zb0003Mask & 0x100000) == 0 { // if not empty
+ if (zb0004Mask & 0x400000) == 0 { // if not empty
// string "rate"
o = append(o, 0xa4, 0x72, 0x61, 0x74, 0x65)
o = msgp.AppendUint64(o, (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRate)
}
- if (zb0003Mask & 0x200000) == 0 { // if not empty
+ if (zb0004Mask & 0x800000) == 0 { // if not empty
// string "rnd"
o = append(o, 0xa3, 0x72, 0x6e, 0x64)
o = (*z).unauthenticatedProposal.Block.BlockHeader.Round.MarshalMsg(o)
}
- if (zb0003Mask & 0x400000) == 0 { // if not empty
+ if (zb0004Mask & 0x1000000) == 0 { // if not empty
// string "rwcalr"
o = append(o, 0xa6, 0x72, 0x77, 0x63, 0x61, 0x6c, 0x72)
o = (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRecalculationRound.MarshalMsg(o)
}
- if (zb0003Mask & 0x800000) == 0 { // if not empty
+ if (zb0004Mask & 0x2000000) == 0 { // if not empty
// string "rwd"
o = append(o, 0xa3, 0x72, 0x77, 0x64)
o = (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsPool.MarshalMsg(o)
}
- if (zb0003Mask & 0x1000000) == 0 { // if not empty
+ if (zb0004Mask & 0x4000000) == 0 { // if not empty
// string "sdpf"
o = append(o, 0xa4, 0x73, 0x64, 0x70, 0x66)
o = (*z).unauthenticatedProposal.SeedProof.MarshalMsg(o)
}
- if (zb0003Mask & 0x2000000) == 0 { // if not empty
+ if (zb0004Mask & 0x8000000) == 0 { // if not empty
// string "seed"
o = append(o, 0xa4, 0x73, 0x65, 0x65, 0x64)
o = (*z).unauthenticatedProposal.Block.BlockHeader.Seed.MarshalMsg(o)
}
- if (zb0003Mask & 0x4000000) == 0 { // if not empty
+ if (zb0004Mask & 0x10000000) == 0 { // if not empty
// string "tc"
o = append(o, 0xa2, 0x74, 0x63)
o = msgp.AppendUint64(o, (*z).unauthenticatedProposal.Block.BlockHeader.TxnCounter)
}
- if (zb0003Mask & 0x8000000) == 0 { // if not empty
+ if (zb0004Mask & 0x20000000) == 0 { // if not empty
// string "ts"
o = append(o, 0xa2, 0x74, 0x73)
o = msgp.AppendInt64(o, (*z).unauthenticatedProposal.Block.BlockHeader.TimeStamp)
}
- if (zb0003Mask & 0x10000000) == 0 { // if not empty
+ if (zb0004Mask & 0x40000000) == 0 { // if not empty
// string "txn"
o = append(o, 0xa3, 0x74, 0x78, 0x6e)
o = (*z).unauthenticatedProposal.Block.BlockHeader.TxnRoot.MarshalMsg(o)
}
- if (zb0003Mask & 0x20000000) == 0 { // if not empty
+ if (zb0004Mask & 0x80000000) == 0 { // if not empty
// string "txns"
o = append(o, 0xa4, 0x74, 0x78, 0x6e, 0x73)
o = (*z).unauthenticatedProposal.Block.Payset.MarshalMsg(o)
}
- if (zb0003Mask & 0x40000000) == 0 { // if not empty
+ if (zb0004Mask & 0x100000000) == 0 { // if not empty
// string "upgradedelay"
o = append(o, 0xac, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x64, 0x65, 0x6c, 0x61, 0x79)
o = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeDelay.MarshalMsg(o)
}
- if (zb0003Mask & 0x80000000) == 0 { // if not empty
+ if (zb0004Mask & 0x200000000) == 0 { // if not empty
// string "upgradeprop"
o = append(o, 0xab, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x70, 0x72, 0x6f, 0x70)
o = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradePropose.MarshalMsg(o)
}
- if (zb0003Mask & 0x100000000) == 0 { // if not empty
+ if (zb0004Mask & 0x400000000) == 0 { // if not empty
// string "upgradeyes"
o = append(o, 0xaa, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x79, 0x65, 0x73)
o = msgp.AppendBool(o, (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeApprove)
@@ -3302,214 +3395,214 @@ func (_ *transmittedPayload) CanMarshalMsg(z interface{}) bool {
func (z *transmittedPayload) UnmarshalMsg(bts []byte) (o []byte, err error) {
var field []byte
_ = field
- var zb0003 int
- var zb0004 bool
- zb0003, zb0004, bts, err = msgp.ReadMapHeaderBytes(bts)
+ var zb0004 int
+ var zb0005 bool
+ zb0004, zb0005, bts, err = msgp.ReadMapHeaderBytes(bts)
if _, ok := err.(msgp.TypeError); ok {
- zb0003, zb0004, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ zb0004, zb0005, bts, err = msgp.ReadArrayHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err)
return
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.Round.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Round")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.Branch.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Branch")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.Seed.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Seed")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.TxnRoot.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TxnRoot")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.TimeStamp, bts, err = msgp.ReadInt64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TimeStamp")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.GenesisID, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "GenesisID")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.GenesisHash.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "GenesisHash")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.FeeSink.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "FeeSink")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsPool.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsPool")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsLevel, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsLevel")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRate, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsRate")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsResidue, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsResidue")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRecalculationRound.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsRecalculationRound")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.CurrentProtocol.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CurrentProtocol")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocol.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocol")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolApprovals, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolApprovals")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolVoteBefore")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolSwitchOn")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradePropose.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradePropose")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeDelay.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradeDelay")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeApprove, bts, err = msgp.ReadBoolBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradeApprove")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).unauthenticatedProposal.Block.BlockHeader.TxnCounter, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TxnCounter")
return
}
}
- if zb0003 > 0 {
- zb0003--
- var zb0005 int
- var zb0006 bool
- zb0005, zb0006, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if zb0004 > 0 {
+ zb0004--
+ var zb0006 int
+ var zb0007 bool
+ zb0006, zb0007, bts, err = msgp.ReadMapHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
return
}
- if zb0005 > protocol.NumCompactCertTypes {
- err = msgp.ErrOverflow(uint64(zb0005), uint64(protocol.NumCompactCertTypes))
+ if zb0006 > protocol.NumCompactCertTypes {
+ err = msgp.ErrOverflow(uint64(zb0006), uint64(protocol.NumCompactCertTypes))
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
return
}
- if zb0006 {
+ if zb0007 {
(*z).unauthenticatedProposal.Block.BlockHeader.CompactCert = nil
} else if (*z).unauthenticatedProposal.Block.BlockHeader.CompactCert == nil {
- (*z).unauthenticatedProposal.Block.BlockHeader.CompactCert = make(map[protocol.CompactCertType]bookkeeping.CompactCertState, zb0005)
+ (*z).unauthenticatedProposal.Block.BlockHeader.CompactCert = make(map[protocol.CompactCertType]bookkeeping.CompactCertState, zb0006)
}
- for zb0005 > 0 {
+ for zb0006 > 0 {
var zb0001 protocol.CompactCertType
var zb0002 bookkeeping.CompactCertState
- zb0005--
+ zb0006--
bts, err = zb0001.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
@@ -3523,52 +3616,81 @@ func (z *transmittedPayload) UnmarshalMsg(bts []byte) (o []byte, err error) {
(*z).unauthenticatedProposal.Block.BlockHeader.CompactCert[zb0001] = zb0002
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
+ var zb0008 int
+ var zb0009 bool
+ zb0008, zb0009, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0008 > config.MaxProposedExpiredOnlineAccounts {
+ err = msgp.ErrOverflow(uint64(zb0008), uint64(config.MaxProposedExpiredOnlineAccounts))
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0009 {
+ (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = nil
+ } else if (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts != nil && cap((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) >= zb0008 {
+ (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = ((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts)[:zb0008]
+ } else {
+ (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = make([]basics.Address, zb0008)
+ }
+ for zb0003 := range (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts", zb0003)
+ return
+ }
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.Block.Payset.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Payset")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.SeedProof.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "SeedProof")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
{
- var zb0007 uint64
- zb0007, bts, err = msgp.ReadUint64Bytes(bts)
+ var zb0010 uint64
+ zb0010, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "OriginalPeriod")
return
}
- (*z).unauthenticatedProposal.OriginalPeriod = period(zb0007)
+ (*z).unauthenticatedProposal.OriginalPeriod = period(zb0010)
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).unauthenticatedProposal.OriginalProposer.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "OriginalProposer")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).PriorVote.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "PriorVote")
return
}
}
- if zb0003 > 0 {
- err = msgp.ErrTooManyArrayFields(zb0003)
+ if zb0004 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0004)
if err != nil {
err = msgp.WrapError(err, "struct-from-array")
return
@@ -3579,11 +3701,11 @@ func (z *transmittedPayload) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err)
return
}
- if zb0004 {
+ if zb0005 {
(*z) = transmittedPayload{}
}
- for zb0003 > 0 {
- zb0003--
+ for zb0004 > 0 {
+ zb0004--
field, bts, err = msgp.ReadMapKeyZC(bts)
if err != nil {
err = msgp.WrapError(err)
@@ -3723,27 +3845,27 @@ func (z *transmittedPayload) UnmarshalMsg(bts []byte) (o []byte, err error) {
return
}
case "cc":
- var zb0008 int
- var zb0009 bool
- zb0008, zb0009, bts, err = msgp.ReadMapHeaderBytes(bts)
+ var zb0011 int
+ var zb0012 bool
+ zb0011, zb0012, bts, err = msgp.ReadMapHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err, "CompactCert")
return
}
- if zb0008 > protocol.NumCompactCertTypes {
- err = msgp.ErrOverflow(uint64(zb0008), uint64(protocol.NumCompactCertTypes))
+ if zb0011 > protocol.NumCompactCertTypes {
+ err = msgp.ErrOverflow(uint64(zb0011), uint64(protocol.NumCompactCertTypes))
err = msgp.WrapError(err, "CompactCert")
return
}
- if zb0009 {
+ if zb0012 {
(*z).unauthenticatedProposal.Block.BlockHeader.CompactCert = nil
} else if (*z).unauthenticatedProposal.Block.BlockHeader.CompactCert == nil {
- (*z).unauthenticatedProposal.Block.BlockHeader.CompactCert = make(map[protocol.CompactCertType]bookkeeping.CompactCertState, zb0008)
+ (*z).unauthenticatedProposal.Block.BlockHeader.CompactCert = make(map[protocol.CompactCertType]bookkeeping.CompactCertState, zb0011)
}
- for zb0008 > 0 {
+ for zb0011 > 0 {
var zb0001 protocol.CompactCertType
var zb0002 bookkeeping.CompactCertState
- zb0008--
+ zb0011--
bts, err = zb0001.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "CompactCert")
@@ -3756,6 +3878,33 @@ func (z *transmittedPayload) UnmarshalMsg(bts []byte) (o []byte, err error) {
}
(*z).unauthenticatedProposal.Block.BlockHeader.CompactCert[zb0001] = zb0002
}
+ case "partupdrmv":
+ var zb0013 int
+ var zb0014 bool
+ zb0013, zb0014, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0013 > config.MaxProposedExpiredOnlineAccounts {
+ err = msgp.ErrOverflow(uint64(zb0013), uint64(config.MaxProposedExpiredOnlineAccounts))
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0014 {
+ (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = nil
+ } else if (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts != nil && cap((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) >= zb0013 {
+ (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = ((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts)[:zb0013]
+ } else {
+ (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = make([]basics.Address, zb0013)
+ }
+ for zb0003 := range (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ bts, err = (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts", zb0003)
+ return
+ }
+ }
case "txns":
bts, err = (*z).unauthenticatedProposal.Block.Payset.UnmarshalMsg(bts)
if err != nil {
@@ -3770,13 +3919,13 @@ func (z *transmittedPayload) UnmarshalMsg(bts []byte) (o []byte, err error) {
}
case "oper":
{
- var zb0010 uint64
- zb0010, bts, err = msgp.ReadUint64Bytes(bts)
+ var zb0015 uint64
+ zb0015, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "OriginalPeriod")
return
}
- (*z).unauthenticatedProposal.OriginalPeriod = period(zb0010)
+ (*z).unauthenticatedProposal.OriginalPeriod = period(zb0015)
}
case "oprop":
bts, err = (*z).unauthenticatedProposal.OriginalProposer.UnmarshalMsg(bts)
@@ -3818,13 +3967,17 @@ func (z *transmittedPayload) Msgsize() (s int) {
s += 0 + zb0001.Msgsize() + zb0002.Msgsize()
}
}
+ s += 11 + msgp.ArrayHeaderSize
+ for zb0003 := range (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ s += (*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].Msgsize()
+ }
s += 5 + (*z).unauthenticatedProposal.Block.Payset.Msgsize() + 5 + (*z).unauthenticatedProposal.SeedProof.Msgsize() + 5 + msgp.Uint64Size + 6 + (*z).unauthenticatedProposal.OriginalProposer.Msgsize() + 3 + (*z).PriorVote.Msgsize()
return
}
// MsgIsZero returns whether this is a zero value
func (z *transmittedPayload) MsgIsZero() bool {
- return ((*z).unauthenticatedProposal.Block.BlockHeader.Round.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Branch.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Seed.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnRoot.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TimeStamp == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.GenesisID == "") && ((*z).unauthenticatedProposal.Block.BlockHeader.GenesisHash.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.FeeSink.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsPool.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsLevel == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRate == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsResidue == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocol.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolApprovals == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeApprove == false) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnCounter == 0) && (len((*z).unauthenticatedProposal.Block.BlockHeader.CompactCert) == 0) && ((*z).unauthenticatedProposal.Block.Payset.MsgIsZero()) && ((*z).unauthenticatedProposal.SeedProof.MsgIsZero()) && ((*z).unauthenticatedProposal.OriginalPeriod == 0) && ((*z).unauthenticatedProposal.OriginalProposer.MsgIsZero()) && ((*z).PriorVote.MsgIsZero())
+ return ((*z).unauthenticatedProposal.Block.BlockHeader.Round.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Branch.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Seed.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnRoot.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TimeStamp == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.GenesisID == "") && ((*z).unauthenticatedProposal.Block.BlockHeader.GenesisHash.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.FeeSink.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsPool.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsLevel == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRate == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsResidue == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocol.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolApprovals == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeApprove == false) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnCounter == 0) && (len((*z).unauthenticatedProposal.Block.BlockHeader.CompactCert) == 0) && (len((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) == 0) && ((*z).unauthenticatedProposal.Block.Payset.MsgIsZero()) && ((*z).unauthenticatedProposal.SeedProof.MsgIsZero()) && ((*z).unauthenticatedProposal.OriginalPeriod == 0) && ((*z).unauthenticatedProposal.OriginalProposer.MsgIsZero()) && ((*z).PriorVote.MsgIsZero())
}
// MarshalMsg implements msgp.Marshaler
@@ -4494,120 +4647,124 @@ func (z *unauthenticatedEquivocationVote) MsgIsZero() bool {
func (z *unauthenticatedProposal) MarshalMsg(b []byte) (o []byte) {
o = msgp.Require(b, z.Msgsize())
// omitempty: check for empty values
- zb0003Len := uint32(27)
- var zb0003Mask uint32 /* 31 bits */
+ zb0004Len := uint32(28)
+ var zb0004Mask uint64 /* 33 bits */
if len((*z).Block.BlockHeader.CompactCert) == 0 {
- zb0003Len--
- zb0003Mask |= 0x10
+ zb0004Len--
+ zb0004Mask |= 0x20
}
if (*z).Block.BlockHeader.RewardsState.RewardsLevel == 0 {
- zb0003Len--
- zb0003Mask |= 0x20
+ zb0004Len--
+ zb0004Mask |= 0x40
}
if (*z).Block.BlockHeader.RewardsState.FeeSink.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x40
+ zb0004Len--
+ zb0004Mask |= 0x80
}
if (*z).Block.BlockHeader.RewardsState.RewardsResidue == 0 {
- zb0003Len--
- zb0003Mask |= 0x80
+ zb0004Len--
+ zb0004Mask |= 0x100
}
if (*z).Block.BlockHeader.GenesisID == "" {
- zb0003Len--
- zb0003Mask |= 0x100
+ zb0004Len--
+ zb0004Mask |= 0x200
}
if (*z).Block.BlockHeader.GenesisHash.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x200
+ zb0004Len--
+ zb0004Mask |= 0x400
}
if (*z).Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x400
+ zb0004Len--
+ zb0004Mask |= 0x800
}
if (*z).Block.BlockHeader.UpgradeState.NextProtocol.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x800
+ zb0004Len--
+ zb0004Mask |= 0x1000
}
if (*z).Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x1000
+ zb0004Len--
+ zb0004Mask |= 0x2000
}
if (*z).Block.BlockHeader.UpgradeState.NextProtocolApprovals == 0 {
- zb0003Len--
- zb0003Mask |= 0x2000
+ zb0004Len--
+ zb0004Mask |= 0x4000
}
if (*z).OriginalPeriod == 0 {
- zb0003Len--
- zb0003Mask |= 0x4000
+ zb0004Len--
+ zb0004Mask |= 0x8000
}
if (*z).OriginalProposer.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x8000
+ zb0004Len--
+ zb0004Mask |= 0x10000
+ }
+ if len((*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x20000
}
if (*z).Block.BlockHeader.Branch.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x10000
+ zb0004Len--
+ zb0004Mask |= 0x40000
}
if (*z).Block.BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x20000
+ zb0004Len--
+ zb0004Mask |= 0x80000
}
if (*z).Block.BlockHeader.RewardsState.RewardsRate == 0 {
- zb0003Len--
- zb0003Mask |= 0x40000
+ zb0004Len--
+ zb0004Mask |= 0x100000
}
if (*z).Block.BlockHeader.Round.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x80000
+ zb0004Len--
+ zb0004Mask |= 0x200000
}
if (*z).Block.BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x100000
+ zb0004Len--
+ zb0004Mask |= 0x400000
}
if (*z).Block.BlockHeader.RewardsState.RewardsPool.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x200000
+ zb0004Len--
+ zb0004Mask |= 0x800000
}
if (*z).SeedProof.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x400000
+ zb0004Len--
+ zb0004Mask |= 0x1000000
}
if (*z).Block.BlockHeader.Seed.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x800000
+ zb0004Len--
+ zb0004Mask |= 0x2000000
}
if (*z).Block.BlockHeader.TxnCounter == 0 {
- zb0003Len--
- zb0003Mask |= 0x1000000
+ zb0004Len--
+ zb0004Mask |= 0x4000000
}
if (*z).Block.BlockHeader.TimeStamp == 0 {
- zb0003Len--
- zb0003Mask |= 0x2000000
+ zb0004Len--
+ zb0004Mask |= 0x8000000
}
if (*z).Block.BlockHeader.TxnRoot.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x4000000
+ zb0004Len--
+ zb0004Mask |= 0x10000000
}
if (*z).Block.Payset.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x8000000
+ zb0004Len--
+ zb0004Mask |= 0x20000000
}
if (*z).Block.BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x10000000
+ zb0004Len--
+ zb0004Mask |= 0x40000000
}
if (*z).Block.BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x20000000
+ zb0004Len--
+ zb0004Mask |= 0x80000000
}
if (*z).Block.BlockHeader.UpgradeVote.UpgradeApprove == false {
- zb0003Len--
- zb0003Mask |= 0x40000000
+ zb0004Len--
+ zb0004Mask |= 0x100000000
}
- // variable map header, size zb0003Len
- o = msgp.AppendMapHeader(o, zb0003Len)
- if zb0003Len != 0 {
- if (zb0003Mask & 0x10) == 0 { // if not empty
+ // variable map header, size zb0004Len
+ o = msgp.AppendMapHeader(o, zb0004Len)
+ if zb0004Len != 0 {
+ if (zb0004Mask & 0x20) == 0 { // if not empty
// string "cc"
o = append(o, 0xa2, 0x63, 0x63)
if (*z).Block.BlockHeader.CompactCert == nil {
@@ -4627,132 +4784,144 @@ func (z *unauthenticatedProposal) MarshalMsg(b []byte) (o []byte) {
o = zb0002.MarshalMsg(o)
}
}
- if (zb0003Mask & 0x20) == 0 { // if not empty
+ if (zb0004Mask & 0x40) == 0 { // if not empty
// string "earn"
o = append(o, 0xa4, 0x65, 0x61, 0x72, 0x6e)
o = msgp.AppendUint64(o, (*z).Block.BlockHeader.RewardsState.RewardsLevel)
}
- if (zb0003Mask & 0x40) == 0 { // if not empty
+ if (zb0004Mask & 0x80) == 0 { // if not empty
// string "fees"
o = append(o, 0xa4, 0x66, 0x65, 0x65, 0x73)
o = (*z).Block.BlockHeader.RewardsState.FeeSink.MarshalMsg(o)
}
- if (zb0003Mask & 0x80) == 0 { // if not empty
+ if (zb0004Mask & 0x100) == 0 { // if not empty
// string "frac"
o = append(o, 0xa4, 0x66, 0x72, 0x61, 0x63)
o = msgp.AppendUint64(o, (*z).Block.BlockHeader.RewardsState.RewardsResidue)
}
- if (zb0003Mask & 0x100) == 0 { // if not empty
+ if (zb0004Mask & 0x200) == 0 { // if not empty
// string "gen"
o = append(o, 0xa3, 0x67, 0x65, 0x6e)
o = msgp.AppendString(o, (*z).Block.BlockHeader.GenesisID)
}
- if (zb0003Mask & 0x200) == 0 { // if not empty
+ if (zb0004Mask & 0x400) == 0 { // if not empty
// string "gh"
o = append(o, 0xa2, 0x67, 0x68)
o = (*z).Block.BlockHeader.GenesisHash.MarshalMsg(o)
}
- if (zb0003Mask & 0x400) == 0 { // if not empty
+ if (zb0004Mask & 0x800) == 0 { // if not empty
// string "nextbefore"
o = append(o, 0xaa, 0x6e, 0x65, 0x78, 0x74, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65)
o = (*z).Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MarshalMsg(o)
}
- if (zb0003Mask & 0x800) == 0 { // if not empty
+ if (zb0004Mask & 0x1000) == 0 { // if not empty
// string "nextproto"
o = append(o, 0xa9, 0x6e, 0x65, 0x78, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f)
o = (*z).Block.BlockHeader.UpgradeState.NextProtocol.MarshalMsg(o)
}
- if (zb0003Mask & 0x1000) == 0 { // if not empty
+ if (zb0004Mask & 0x2000) == 0 { // if not empty
// string "nextswitch"
o = append(o, 0xaa, 0x6e, 0x65, 0x78, 0x74, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68)
o = (*z).Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MarshalMsg(o)
}
- if (zb0003Mask & 0x2000) == 0 { // if not empty
+ if (zb0004Mask & 0x4000) == 0 { // if not empty
// string "nextyes"
o = append(o, 0xa7, 0x6e, 0x65, 0x78, 0x74, 0x79, 0x65, 0x73)
o = msgp.AppendUint64(o, (*z).Block.BlockHeader.UpgradeState.NextProtocolApprovals)
}
- if (zb0003Mask & 0x4000) == 0 { // if not empty
+ if (zb0004Mask & 0x8000) == 0 { // if not empty
// string "oper"
o = append(o, 0xa4, 0x6f, 0x70, 0x65, 0x72)
o = msgp.AppendUint64(o, uint64((*z).OriginalPeriod))
}
- if (zb0003Mask & 0x8000) == 0 { // if not empty
+ if (zb0004Mask & 0x10000) == 0 { // if not empty
// string "oprop"
o = append(o, 0xa5, 0x6f, 0x70, 0x72, 0x6f, 0x70)
o = (*z).OriginalProposer.MarshalMsg(o)
}
- if (zb0003Mask & 0x10000) == 0 { // if not empty
+ if (zb0004Mask & 0x20000) == 0 { // if not empty
+ // string "partupdrmv"
+ o = append(o, 0xaa, 0x70, 0x61, 0x72, 0x74, 0x75, 0x70, 0x64, 0x72, 0x6d, 0x76)
+ if (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts)))
+ }
+ for zb0003 := range (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ o = (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].MarshalMsg(o)
+ }
+ }
+ if (zb0004Mask & 0x40000) == 0 { // if not empty
// string "prev"
o = append(o, 0xa4, 0x70, 0x72, 0x65, 0x76)
o = (*z).Block.BlockHeader.Branch.MarshalMsg(o)
}
- if (zb0003Mask & 0x20000) == 0 { // if not empty
+ if (zb0004Mask & 0x80000) == 0 { // if not empty
// string "proto"
o = append(o, 0xa5, 0x70, 0x72, 0x6f, 0x74, 0x6f)
o = (*z).Block.BlockHeader.UpgradeState.CurrentProtocol.MarshalMsg(o)
}
- if (zb0003Mask & 0x40000) == 0 { // if not empty
+ if (zb0004Mask & 0x100000) == 0 { // if not empty
// string "rate"
o = append(o, 0xa4, 0x72, 0x61, 0x74, 0x65)
o = msgp.AppendUint64(o, (*z).Block.BlockHeader.RewardsState.RewardsRate)
}
- if (zb0003Mask & 0x80000) == 0 { // if not empty
+ if (zb0004Mask & 0x200000) == 0 { // if not empty
// string "rnd"
o = append(o, 0xa3, 0x72, 0x6e, 0x64)
o = (*z).Block.BlockHeader.Round.MarshalMsg(o)
}
- if (zb0003Mask & 0x100000) == 0 { // if not empty
+ if (zb0004Mask & 0x400000) == 0 { // if not empty
// string "rwcalr"
o = append(o, 0xa6, 0x72, 0x77, 0x63, 0x61, 0x6c, 0x72)
o = (*z).Block.BlockHeader.RewardsState.RewardsRecalculationRound.MarshalMsg(o)
}
- if (zb0003Mask & 0x200000) == 0 { // if not empty
+ if (zb0004Mask & 0x800000) == 0 { // if not empty
// string "rwd"
o = append(o, 0xa3, 0x72, 0x77, 0x64)
o = (*z).Block.BlockHeader.RewardsState.RewardsPool.MarshalMsg(o)
}
- if (zb0003Mask & 0x400000) == 0 { // if not empty
+ if (zb0004Mask & 0x1000000) == 0 { // if not empty
// string "sdpf"
o = append(o, 0xa4, 0x73, 0x64, 0x70, 0x66)
o = (*z).SeedProof.MarshalMsg(o)
}
- if (zb0003Mask & 0x800000) == 0 { // if not empty
+ if (zb0004Mask & 0x2000000) == 0 { // if not empty
// string "seed"
o = append(o, 0xa4, 0x73, 0x65, 0x65, 0x64)
o = (*z).Block.BlockHeader.Seed.MarshalMsg(o)
}
- if (zb0003Mask & 0x1000000) == 0 { // if not empty
+ if (zb0004Mask & 0x4000000) == 0 { // if not empty
// string "tc"
o = append(o, 0xa2, 0x74, 0x63)
o = msgp.AppendUint64(o, (*z).Block.BlockHeader.TxnCounter)
}
- if (zb0003Mask & 0x2000000) == 0 { // if not empty
+ if (zb0004Mask & 0x8000000) == 0 { // if not empty
// string "ts"
o = append(o, 0xa2, 0x74, 0x73)
o = msgp.AppendInt64(o, (*z).Block.BlockHeader.TimeStamp)
}
- if (zb0003Mask & 0x4000000) == 0 { // if not empty
+ if (zb0004Mask & 0x10000000) == 0 { // if not empty
// string "txn"
o = append(o, 0xa3, 0x74, 0x78, 0x6e)
o = (*z).Block.BlockHeader.TxnRoot.MarshalMsg(o)
}
- if (zb0003Mask & 0x8000000) == 0 { // if not empty
+ if (zb0004Mask & 0x20000000) == 0 { // if not empty
// string "txns"
o = append(o, 0xa4, 0x74, 0x78, 0x6e, 0x73)
o = (*z).Block.Payset.MarshalMsg(o)
}
- if (zb0003Mask & 0x10000000) == 0 { // if not empty
+ if (zb0004Mask & 0x40000000) == 0 { // if not empty
// string "upgradedelay"
o = append(o, 0xac, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x64, 0x65, 0x6c, 0x61, 0x79)
o = (*z).Block.BlockHeader.UpgradeVote.UpgradeDelay.MarshalMsg(o)
}
- if (zb0003Mask & 0x20000000) == 0 { // if not empty
+ if (zb0004Mask & 0x80000000) == 0 { // if not empty
// string "upgradeprop"
o = append(o, 0xab, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x70, 0x72, 0x6f, 0x70)
o = (*z).Block.BlockHeader.UpgradeVote.UpgradePropose.MarshalMsg(o)
}
- if (zb0003Mask & 0x40000000) == 0 { // if not empty
+ if (zb0004Mask & 0x100000000) == 0 { // if not empty
// string "upgradeyes"
o = append(o, 0xaa, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x79, 0x65, 0x73)
o = msgp.AppendBool(o, (*z).Block.BlockHeader.UpgradeVote.UpgradeApprove)
@@ -4770,214 +4939,214 @@ func (_ *unauthenticatedProposal) CanMarshalMsg(z interface{}) bool {
func (z *unauthenticatedProposal) UnmarshalMsg(bts []byte) (o []byte, err error) {
var field []byte
_ = field
- var zb0003 int
- var zb0004 bool
- zb0003, zb0004, bts, err = msgp.ReadMapHeaderBytes(bts)
+ var zb0004 int
+ var zb0005 bool
+ zb0004, zb0005, bts, err = msgp.ReadMapHeaderBytes(bts)
if _, ok := err.(msgp.TypeError); ok {
- zb0003, zb0004, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ zb0004, zb0005, bts, err = msgp.ReadArrayHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err)
return
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.BlockHeader.Round.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Round")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.BlockHeader.Branch.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Branch")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.BlockHeader.Seed.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Seed")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.BlockHeader.TxnRoot.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TxnRoot")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).Block.BlockHeader.TimeStamp, bts, err = msgp.ReadInt64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TimeStamp")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).Block.BlockHeader.GenesisID, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "GenesisID")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.BlockHeader.GenesisHash.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "GenesisHash")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.BlockHeader.RewardsState.FeeSink.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "FeeSink")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.BlockHeader.RewardsState.RewardsPool.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsPool")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).Block.BlockHeader.RewardsState.RewardsLevel, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsLevel")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).Block.BlockHeader.RewardsState.RewardsRate, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsRate")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).Block.BlockHeader.RewardsState.RewardsResidue, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsResidue")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.BlockHeader.RewardsState.RewardsRecalculationRound.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsRecalculationRound")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.BlockHeader.UpgradeState.CurrentProtocol.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CurrentProtocol")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.BlockHeader.UpgradeState.NextProtocol.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocol")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).Block.BlockHeader.UpgradeState.NextProtocolApprovals, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolApprovals")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolVoteBefore")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolSwitchOn")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.BlockHeader.UpgradeVote.UpgradePropose.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradePropose")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.BlockHeader.UpgradeVote.UpgradeDelay.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradeDelay")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).Block.BlockHeader.UpgradeVote.UpgradeApprove, bts, err = msgp.ReadBoolBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradeApprove")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).Block.BlockHeader.TxnCounter, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TxnCounter")
return
}
}
- if zb0003 > 0 {
- zb0003--
- var zb0005 int
- var zb0006 bool
- zb0005, zb0006, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if zb0004 > 0 {
+ zb0004--
+ var zb0006 int
+ var zb0007 bool
+ zb0006, zb0007, bts, err = msgp.ReadMapHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
return
}
- if zb0005 > protocol.NumCompactCertTypes {
- err = msgp.ErrOverflow(uint64(zb0005), uint64(protocol.NumCompactCertTypes))
+ if zb0006 > protocol.NumCompactCertTypes {
+ err = msgp.ErrOverflow(uint64(zb0006), uint64(protocol.NumCompactCertTypes))
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
return
}
- if zb0006 {
+ if zb0007 {
(*z).Block.BlockHeader.CompactCert = nil
} else if (*z).Block.BlockHeader.CompactCert == nil {
- (*z).Block.BlockHeader.CompactCert = make(map[protocol.CompactCertType]bookkeeping.CompactCertState, zb0005)
+ (*z).Block.BlockHeader.CompactCert = make(map[protocol.CompactCertType]bookkeeping.CompactCertState, zb0006)
}
- for zb0005 > 0 {
+ for zb0006 > 0 {
var zb0001 protocol.CompactCertType
var zb0002 bookkeeping.CompactCertState
- zb0005--
+ zb0006--
bts, err = zb0001.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
@@ -4991,44 +5160,73 @@ func (z *unauthenticatedProposal) UnmarshalMsg(bts []byte) (o []byte, err error)
(*z).Block.BlockHeader.CompactCert[zb0001] = zb0002
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
+ var zb0008 int
+ var zb0009 bool
+ zb0008, zb0009, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0008 > config.MaxProposedExpiredOnlineAccounts {
+ err = msgp.ErrOverflow(uint64(zb0008), uint64(config.MaxProposedExpiredOnlineAccounts))
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0009 {
+ (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = nil
+ } else if (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts != nil && cap((*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) >= zb0008 {
+ (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = ((*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts)[:zb0008]
+ } else {
+ (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = make([]basics.Address, zb0008)
+ }
+ for zb0003 := range (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ bts, err = (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts", zb0003)
+ return
+ }
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Block.Payset.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Payset")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).SeedProof.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "SeedProof")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
{
- var zb0007 uint64
- zb0007, bts, err = msgp.ReadUint64Bytes(bts)
+ var zb0010 uint64
+ zb0010, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "OriginalPeriod")
return
}
- (*z).OriginalPeriod = period(zb0007)
+ (*z).OriginalPeriod = period(zb0010)
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).OriginalProposer.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "OriginalProposer")
return
}
}
- if zb0003 > 0 {
- err = msgp.ErrTooManyArrayFields(zb0003)
+ if zb0004 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0004)
if err != nil {
err = msgp.WrapError(err, "struct-from-array")
return
@@ -5039,11 +5237,11 @@ func (z *unauthenticatedProposal) UnmarshalMsg(bts []byte) (o []byte, err error)
err = msgp.WrapError(err)
return
}
- if zb0004 {
+ if zb0005 {
(*z) = unauthenticatedProposal{}
}
- for zb0003 > 0 {
- zb0003--
+ for zb0004 > 0 {
+ zb0004--
field, bts, err = msgp.ReadMapKeyZC(bts)
if err != nil {
err = msgp.WrapError(err)
@@ -5183,27 +5381,27 @@ func (z *unauthenticatedProposal) UnmarshalMsg(bts []byte) (o []byte, err error)
return
}
case "cc":
- var zb0008 int
- var zb0009 bool
- zb0008, zb0009, bts, err = msgp.ReadMapHeaderBytes(bts)
+ var zb0011 int
+ var zb0012 bool
+ zb0011, zb0012, bts, err = msgp.ReadMapHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err, "CompactCert")
return
}
- if zb0008 > protocol.NumCompactCertTypes {
- err = msgp.ErrOverflow(uint64(zb0008), uint64(protocol.NumCompactCertTypes))
+ if zb0011 > protocol.NumCompactCertTypes {
+ err = msgp.ErrOverflow(uint64(zb0011), uint64(protocol.NumCompactCertTypes))
err = msgp.WrapError(err, "CompactCert")
return
}
- if zb0009 {
+ if zb0012 {
(*z).Block.BlockHeader.CompactCert = nil
} else if (*z).Block.BlockHeader.CompactCert == nil {
- (*z).Block.BlockHeader.CompactCert = make(map[protocol.CompactCertType]bookkeeping.CompactCertState, zb0008)
+ (*z).Block.BlockHeader.CompactCert = make(map[protocol.CompactCertType]bookkeeping.CompactCertState, zb0011)
}
- for zb0008 > 0 {
+ for zb0011 > 0 {
var zb0001 protocol.CompactCertType
var zb0002 bookkeeping.CompactCertState
- zb0008--
+ zb0011--
bts, err = zb0001.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "CompactCert")
@@ -5216,6 +5414,33 @@ func (z *unauthenticatedProposal) UnmarshalMsg(bts []byte) (o []byte, err error)
}
(*z).Block.BlockHeader.CompactCert[zb0001] = zb0002
}
+ case "partupdrmv":
+ var zb0013 int
+ var zb0014 bool
+ zb0013, zb0014, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0013 > config.MaxProposedExpiredOnlineAccounts {
+ err = msgp.ErrOverflow(uint64(zb0013), uint64(config.MaxProposedExpiredOnlineAccounts))
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0014 {
+ (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = nil
+ } else if (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts != nil && cap((*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) >= zb0013 {
+ (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = ((*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts)[:zb0013]
+ } else {
+ (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = make([]basics.Address, zb0013)
+ }
+ for zb0003 := range (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ bts, err = (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts", zb0003)
+ return
+ }
+ }
case "txns":
bts, err = (*z).Block.Payset.UnmarshalMsg(bts)
if err != nil {
@@ -5230,13 +5455,13 @@ func (z *unauthenticatedProposal) UnmarshalMsg(bts []byte) (o []byte, err error)
}
case "oper":
{
- var zb0010 uint64
- zb0010, bts, err = msgp.ReadUint64Bytes(bts)
+ var zb0015 uint64
+ zb0015, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "OriginalPeriod")
return
}
- (*z).OriginalPeriod = period(zb0010)
+ (*z).OriginalPeriod = period(zb0015)
}
case "oprop":
bts, err = (*z).OriginalProposer.UnmarshalMsg(bts)
@@ -5272,13 +5497,17 @@ func (z *unauthenticatedProposal) Msgsize() (s int) {
s += 0 + zb0001.Msgsize() + zb0002.Msgsize()
}
}
+ s += 11 + msgp.ArrayHeaderSize
+ for zb0003 := range (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ s += (*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].Msgsize()
+ }
s += 5 + (*z).Block.Payset.Msgsize() + 5 + (*z).SeedProof.Msgsize() + 5 + msgp.Uint64Size + 6 + (*z).OriginalProposer.Msgsize()
return
}
// MsgIsZero returns whether this is a zero value
func (z *unauthenticatedProposal) MsgIsZero() bool {
- return ((*z).Block.BlockHeader.Round.MsgIsZero()) && ((*z).Block.BlockHeader.Branch.MsgIsZero()) && ((*z).Block.BlockHeader.Seed.MsgIsZero()) && ((*z).Block.BlockHeader.TxnRoot.MsgIsZero()) && ((*z).Block.BlockHeader.TimeStamp == 0) && ((*z).Block.BlockHeader.GenesisID == "") && ((*z).Block.BlockHeader.GenesisHash.MsgIsZero()) && ((*z).Block.BlockHeader.RewardsState.FeeSink.MsgIsZero()) && ((*z).Block.BlockHeader.RewardsState.RewardsPool.MsgIsZero()) && ((*z).Block.BlockHeader.RewardsState.RewardsLevel == 0) && ((*z).Block.BlockHeader.RewardsState.RewardsRate == 0) && ((*z).Block.BlockHeader.RewardsState.RewardsResidue == 0) && ((*z).Block.BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeState.NextProtocol.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeState.NextProtocolApprovals == 0) && ((*z).Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeVote.UpgradeApprove == false) && ((*z).Block.BlockHeader.TxnCounter == 0) && (len((*z).Block.BlockHeader.CompactCert) == 0) && ((*z).Block.Payset.MsgIsZero()) && ((*z).SeedProof.MsgIsZero()) && ((*z).OriginalPeriod == 0) && ((*z).OriginalProposer.MsgIsZero())
+ return ((*z).Block.BlockHeader.Round.MsgIsZero()) && ((*z).Block.BlockHeader.Branch.MsgIsZero()) && ((*z).Block.BlockHeader.Seed.MsgIsZero()) && ((*z).Block.BlockHeader.TxnRoot.MsgIsZero()) && ((*z).Block.BlockHeader.TimeStamp == 0) && ((*z).Block.BlockHeader.GenesisID == "") && ((*z).Block.BlockHeader.GenesisHash.MsgIsZero()) && ((*z).Block.BlockHeader.RewardsState.FeeSink.MsgIsZero()) && ((*z).Block.BlockHeader.RewardsState.RewardsPool.MsgIsZero()) && ((*z).Block.BlockHeader.RewardsState.RewardsLevel == 0) && ((*z).Block.BlockHeader.RewardsState.RewardsRate == 0) && ((*z).Block.BlockHeader.RewardsState.RewardsResidue == 0) && ((*z).Block.BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeState.NextProtocol.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeState.NextProtocolApprovals == 0) && ((*z).Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeVote.UpgradeApprove == false) && ((*z).Block.BlockHeader.TxnCounter == 0) && (len((*z).Block.BlockHeader.CompactCert) == 0) && (len((*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) == 0) && ((*z).Block.Payset.MsgIsZero()) && ((*z).SeedProof.MsgIsZero()) && ((*z).OriginalPeriod == 0) && ((*z).OriginalProposer.MsgIsZero())
}
// MarshalMsg implements msgp.Marshaler
diff --git a/catchup/fetcher_test.go b/catchup/fetcher_test.go
index 65ace1345..13b0c7fe2 100644
--- a/catchup/fetcher_test.go
+++ b/catchup/fetcher_test.go
@@ -287,7 +287,11 @@ func (p *testUnicastPeer) Version() string {
return p.version
}
-func (p *testUnicastPeer) Unicast(ctx context.Context, msg []byte, tag protocol.Tag) error {
+func (p *testUnicastPeer) IsOutgoing() bool {
+ return false
+}
+
+func (p *testUnicastPeer) Unicast(ctx context.Context, msg []byte, tag protocol.Tag, callback network.UnicastWebsocketMessageStateCallback) error {
ps := p.gn.(*httpTestPeerSource)
var dispather network.MessageHandler
for _, v := range ps.dispatchHandlers {
diff --git a/catchup/peerSelector_test.go b/catchup/peerSelector_test.go
index 5c7bb9344..0147e1988 100644
--- a/catchup/peerSelector_test.go
+++ b/catchup/peerSelector_test.go
@@ -50,7 +50,7 @@ type mockUnicastPeer struct {
func (d *mockUnicastPeer) GetAddress() string {
return d.address
}
-func (d *mockUnicastPeer) Unicast(ctx context.Context, data []byte, tag protocol.Tag) error {
+func (d *mockUnicastPeer) Unicast(ctx context.Context, msg []byte, tag protocol.Tag, callback network.UnicastWebsocketMessageStateCallback) error {
return nil
}
func (d *mockUnicastPeer) Version() string {
@@ -62,6 +62,9 @@ func (d *mockUnicastPeer) Request(ctx context.Context, tag network.Tag, topics n
func (d *mockUnicastPeer) Respond(ctx context.Context, reqMsg network.IncomingMessage, topics network.Topics) (e error) {
return nil
}
+func (d *mockUnicastPeer) IsOutgoing() bool {
+ return false
+}
func TestPeerAddress(t *testing.T) {
partitiontest.PartitionTest(t)
diff --git a/config/config.go b/config/config.go
index 7ba869c06..71eaba88d 100644
--- a/config/config.go
+++ b/config/config.go
@@ -63,7 +63,7 @@ type Local struct {
// Version tracks the current version of the defaults so we can migrate old -> new
// This is specifically important whenever we decide to change the default value
// for an existing parameter. This field tag must be updated any time we add a new version.
- Version uint32 `version[0]:"0" version[1]:"1" version[2]:"2" version[3]:"3" version[4]:"4" version[5]:"5" version[6]:"6" version[7]:"7" version[8]:"8" version[9]:"9" version[10]:"10" version[11]:"11" version[12]:"12" version[13]:"13" version[14]:"14" version[15]:"15" version[16]:"16"`
+ Version uint32 `version[0]:"0" version[1]:"1" version[2]:"2" version[3]:"3" version[4]:"4" version[5]:"5" version[6]:"6" version[7]:"7" version[8]:"8" version[9]:"9" version[10]:"10" version[11]:"11" version[12]:"12" version[13]:"13" version[14]:"14" version[15]:"15" version[16]:"16" version[17]:"17"`
// environmental (may be overridden)
// When enabled, stores blocks indefinitally, otherwise, only the most recents blocks
@@ -97,7 +97,8 @@ type Local struct {
// IncomingConnectionsLimit specifies the max number of long-lived incoming
// connections. 0 means no connections allowed. -1 is unbounded.
- IncomingConnectionsLimit int `version[0]:"-1" version[1]:"10000"`
+ // Estimating 5MB per incoming connection, 5MB*800 = 4GB
+ IncomingConnectionsLimit int `version[0]:"-1" version[1]:"10000" version[17]:"800"`
// BroadcastConnectionsLimit specifies the number of connections that
// will receive broadcast (gossip) messages from this node. If the
@@ -418,6 +419,26 @@ type Local struct {
// features like catchpoint catchup would be rendered completly non-operational, and many of the node inner
// working would be completly dis-functional.
DisableNetworking bool `version[16]:"false"`
+
+ // ForceFetchTransactions allows to explicitly configure a node to retrieve all the transactions
+ // into it's transaction pool, even if those would not be required as the node doesn't
+ // participate in the consensus or used to relay transactions.
+ ForceFetchTransactions bool `version[17]:"false"`
+
+ // EnableVerbosedTransactionSyncLogging enables the transaction sync to write extensive
+ // message exchange information to the log file. This option is disabled by default,
+ // so that the log files would not grow too rapidly.
+ EnableVerbosedTransactionSyncLogging bool `version[17]:"false"`
+
+ // TransactionSyncDataExchangeRate overrides the auto-calculated data exchange rate between each
+ // two peers. The unit of the data exchange rate is in bytes per second. Setting the value to
+ // zero implies allowing the transaction sync to dynamically calculate the value.
+ TransactionSyncDataExchangeRate uint64 `version[17]:"0"`
+
+ // TransactionSyncSignificantMessageThreshold define the threshold used for a transaction sync
+ // message before it can be used for calculating the data exchange rate. Setting this to zero
+ // would use the default values. The threshold is defined in units of bytes.
+ TransactionSyncSignificantMessageThreshold uint64 `version[17]:"0"`
}
// Filenames of config files within the configdir (e.g. ~/.algorand)
diff --git a/config/consensus.go b/config/consensus.go
index c9589006e..f0ffa1a51 100644
--- a/config/consensus.go
+++ b/config/consensus.go
@@ -391,6 +391,10 @@ type ConsensusParams struct {
EnableKeyregCoherencyCheck bool
EnableExtraPagesOnAppUpdate bool
+
+ // MaxProposedExpiredOnlineAccounts is the maximum number of online accounts, which need
+ // to be taken offline, that would be proposed to be taken offline.
+ MaxProposedExpiredOnlineAccounts int
}
// PaysetCommitType enumerates possible ways for the block header to commit to
@@ -465,6 +469,10 @@ var MaxExtraAppProgramLen int
//supported supported by any of the consensus protocols. used for decoding purposes.
var MaxAvailableAppProgramLen int
+// MaxProposedExpiredOnlineAccounts is the maximum number of online accounts, which need
+// to be taken offline, that would be proposed to be taken offline.
+var MaxProposedExpiredOnlineAccounts int
+
func checkSetMax(value int, curMax *int) {
if value > *curMax {
*curMax = value
@@ -501,6 +509,7 @@ func checkSetAllocBounds(p ConsensusParams) {
// Its value is much larger than any possible reasonable MaxLogCalls value in future
checkSetMax(p.MaxAppProgramLen, &MaxLogCalls)
checkSetMax(p.MaxInnerTransactions, &MaxInnerTransactions)
+ checkSetMax(p.MaxProposedExpiredOnlineAccounts, &MaxProposedExpiredOnlineAccounts)
}
// SaveConfigurableConsensus saves the configurable protocols file to the provided data directory.
@@ -1042,6 +1051,11 @@ func initConsensusProtocols() {
vFuture.CompactCertWeightThreshold = (1 << 32) * 30 / 100
vFuture.CompactCertSecKQ = 128
+ // Enable TEAL 6 / AVM 1.1
+ vFuture.LogicSigVersion = 6
+
+ vFuture.MaxProposedExpiredOnlineAccounts = 32
+
Consensus[protocol.ConsensusFuture] = vFuture
}
diff --git a/config/local_defaults.go b/config/local_defaults.go
index 725409e73..c7a986bd7 100644
--- a/config/local_defaults.go
+++ b/config/local_defaults.go
@@ -20,94 +20,98 @@
package config
var defaultLocal = Local{
- Version: 16,
- AccountUpdatesStatsInterval: 5000000000,
- AccountsRebuildSynchronousMode: 1,
- AnnounceParticipationKey: true,
- Archival: false,
- BaseLoggerDebugLevel: 4,
- BlockServiceCustomFallbackEndpoints: "",
- BroadcastConnectionsLimit: -1,
- CadaverSizeTarget: 1073741824,
- CatchpointFileHistoryLength: 365,
- CatchpointInterval: 10000,
- CatchpointTracking: 0,
- CatchupBlockDownloadRetryAttempts: 1000,
- CatchupBlockValidateMode: 0,
- CatchupFailurePeerRefreshRate: 10,
- CatchupGossipBlockFetchTimeoutSec: 4,
- CatchupHTTPBlockFetchTimeoutSec: 4,
- CatchupLedgerDownloadRetryAttempts: 50,
- CatchupParallelBlocks: 16,
- ConnectionsRateLimitingCount: 60,
- ConnectionsRateLimitingWindowSeconds: 1,
- DNSBootstrapID: "<network>.algorand.network",
- DNSSecurityFlags: 1,
- DeadlockDetection: 0,
- DisableLocalhostConnectionRateLimit: true,
- DisableNetworking: false,
- DisableOutgoingConnectionThrottling: false,
- EnableAccountUpdatesStats: false,
- EnableAgreementReporting: false,
- EnableAgreementTimeMetrics: false,
- EnableAssembleStats: false,
- EnableBlockService: false,
- EnableBlockServiceFallbackToArchiver: true,
- EnableCatchupFromArchiveServers: false,
- EnableDeveloperAPI: false,
- EnableGossipBlockService: true,
- EnableIncomingMessageFilter: false,
- EnableLedgerService: false,
- EnableMetricReporting: false,
- EnableOutgoingNetworkMessageFiltering: true,
- EnablePingHandler: true,
- EnableProcessBlockStats: false,
- EnableProfiler: false,
- EnableRequestLogger: false,
- EnableTopAccountsReporting: false,
- EndpointAddress: "127.0.0.1:0",
- FallbackDNSResolverAddress: "",
- ForceRelayMessages: false,
- GossipFanout: 4,
- IncomingConnectionsLimit: 10000,
- IncomingMessageFilterBucketCount: 5,
- IncomingMessageFilterBucketSize: 512,
- IsIndexerActive: false,
- LedgerSynchronousMode: 2,
- LogArchiveMaxAge: "",
- LogArchiveName: "node.archive.log",
- LogSizeLimit: 1073741824,
- MaxCatchpointDownloadDuration: 7200000000000,
- MaxConnectionsPerIP: 30,
- MinCatchpointFileDownloadBytesPerSecond: 20480,
- NetAddress: "",
- NetworkMessageTraceServer: "",
- NetworkProtocolVersion: "",
- NodeExporterListenAddress: ":9100",
- NodeExporterPath: "./node_exporter",
- OptimizeAccountsDatabaseOnStartup: false,
- OutgoingMessageFilterBucketCount: 3,
- OutgoingMessageFilterBucketSize: 128,
- ParticipationKeysRefreshInterval: 60000000000,
- PeerConnectionsUpdateInterval: 3600,
- PeerPingPeriodSeconds: 0,
- PriorityPeers: map[string]bool{},
- PublicAddress: "",
- ReconnectTime: 60000000000,
- ReservedFDs: 256,
- RestReadTimeoutSeconds: 15,
- RestWriteTimeoutSeconds: 120,
- RunHosted: false,
- SuggestedFeeBlockHistory: 3,
- SuggestedFeeSlidingWindowSize: 50,
- TLSCertFile: "",
- TLSKeyFile: "",
- TelemetryToLog: true,
- TxPoolExponentialIncreaseFactor: 2,
- TxPoolSize: 15000,
- TxSyncIntervalSeconds: 60,
- TxSyncServeResponseSize: 1000000,
- TxSyncTimeoutSeconds: 30,
- UseXForwardedForAddressField: "",
- VerifiedTranscationsCacheSize: 30000,
+ Version: 17,
+ AccountUpdatesStatsInterval: 5000000000,
+ AccountsRebuildSynchronousMode: 1,
+ AnnounceParticipationKey: true,
+ Archival: false,
+ BaseLoggerDebugLevel: 4,
+ BlockServiceCustomFallbackEndpoints: "",
+ BroadcastConnectionsLimit: -1,
+ CadaverSizeTarget: 1073741824,
+ CatchpointFileHistoryLength: 365,
+ CatchpointInterval: 10000,
+ CatchpointTracking: 0,
+ CatchupBlockDownloadRetryAttempts: 1000,
+ CatchupBlockValidateMode: 0,
+ CatchupFailurePeerRefreshRate: 10,
+ CatchupGossipBlockFetchTimeoutSec: 4,
+ CatchupHTTPBlockFetchTimeoutSec: 4,
+ CatchupLedgerDownloadRetryAttempts: 50,
+ CatchupParallelBlocks: 16,
+ ConnectionsRateLimitingCount: 60,
+ ConnectionsRateLimitingWindowSeconds: 1,
+ DNSBootstrapID: "<network>.algorand.network",
+ DNSSecurityFlags: 1,
+ DeadlockDetection: 0,
+ DisableLocalhostConnectionRateLimit: true,
+ DisableNetworking: false,
+ DisableOutgoingConnectionThrottling: false,
+ EnableAccountUpdatesStats: false,
+ EnableAgreementReporting: false,
+ EnableAgreementTimeMetrics: false,
+ EnableAssembleStats: false,
+ EnableBlockService: false,
+ EnableBlockServiceFallbackToArchiver: true,
+ EnableCatchupFromArchiveServers: false,
+ EnableDeveloperAPI: false,
+ EnableGossipBlockService: true,
+ EnableIncomingMessageFilter: false,
+ EnableLedgerService: false,
+ EnableMetricReporting: false,
+ EnableOutgoingNetworkMessageFiltering: true,
+ EnablePingHandler: true,
+ EnableProcessBlockStats: false,
+ EnableProfiler: false,
+ EnableRequestLogger: false,
+ EnableTopAccountsReporting: false,
+ EnableVerbosedTransactionSyncLogging: false,
+ EndpointAddress: "127.0.0.1:0",
+ FallbackDNSResolverAddress: "",
+ ForceFetchTransactions: false,
+ ForceRelayMessages: false,
+ GossipFanout: 4,
+ IncomingConnectionsLimit: 800,
+ IncomingMessageFilterBucketCount: 5,
+ IncomingMessageFilterBucketSize: 512,
+ IsIndexerActive: false,
+ LedgerSynchronousMode: 2,
+ LogArchiveMaxAge: "",
+ LogArchiveName: "node.archive.log",
+ LogSizeLimit: 1073741824,
+ MaxCatchpointDownloadDuration: 7200000000000,
+ MaxConnectionsPerIP: 30,
+ MinCatchpointFileDownloadBytesPerSecond: 20480,
+ NetAddress: "",
+ NetworkMessageTraceServer: "",
+ NetworkProtocolVersion: "",
+ NodeExporterListenAddress: ":9100",
+ NodeExporterPath: "./node_exporter",
+ OptimizeAccountsDatabaseOnStartup: false,
+ OutgoingMessageFilterBucketCount: 3,
+ OutgoingMessageFilterBucketSize: 128,
+ ParticipationKeysRefreshInterval: 60000000000,
+ PeerConnectionsUpdateInterval: 3600,
+ PeerPingPeriodSeconds: 0,
+ PriorityPeers: map[string]bool{},
+ PublicAddress: "",
+ ReconnectTime: 60000000000,
+ ReservedFDs: 256,
+ RestReadTimeoutSeconds: 15,
+ RestWriteTimeoutSeconds: 120,
+ RunHosted: false,
+ SuggestedFeeBlockHistory: 3,
+ SuggestedFeeSlidingWindowSize: 50,
+ TLSCertFile: "",
+ TLSKeyFile: "",
+ TelemetryToLog: true,
+ TransactionSyncDataExchangeRate: 0,
+ TransactionSyncSignificantMessageThreshold: 0,
+ TxPoolExponentialIncreaseFactor: 2,
+ TxPoolSize: 15000,
+ TxSyncIntervalSeconds: 60,
+ TxSyncServeResponseSize: 1000000,
+ TxSyncTimeoutSeconds: 30,
+ UseXForwardedForAddressField: "",
+ VerifiedTranscationsCacheSize: 30000,
}
diff --git a/crypto/compactcert/common.go b/crypto/compactcert/common.go
index d2370d779..53b469bfd 100644
--- a/crypto/compactcert/common.go
+++ b/crypto/compactcert/common.go
@@ -113,5 +113,5 @@ func numReveals(signedWeight uint64, provenWeight uint64, secKQ uint64, bound ui
}
func (p Params) numReveals(signedWeight uint64) (uint64, error) {
- return numReveals(signedWeight, p.ProvenWeight, p.SecKQ, maxReveals)
+ return numReveals(signedWeight, p.ProvenWeight, p.SecKQ, MaxReveals)
}
diff --git a/crypto/compactcert/msgp_gen.go b/crypto/compactcert/msgp_gen.go
index a883b1cfa..60d36184f 100644
--- a/crypto/compactcert/msgp_gen.go
+++ b/crypto/compactcert/msgp_gen.go
@@ -189,8 +189,8 @@ func (z *Cert) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "struct-from-array", "SigProofs")
return
}
- if zb0007 > maxProofDigests {
- err = msgp.ErrOverflow(uint64(zb0007), uint64(maxProofDigests))
+ if zb0007 > MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0007), uint64(MaxProofDigests))
err = msgp.WrapError(err, "struct-from-array", "SigProofs")
return
}
@@ -218,8 +218,8 @@ func (z *Cert) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "struct-from-array", "PartProofs")
return
}
- if zb0009 > maxProofDigests {
- err = msgp.ErrOverflow(uint64(zb0009), uint64(maxProofDigests))
+ if zb0009 > MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0009), uint64(MaxProofDigests))
err = msgp.WrapError(err, "struct-from-array", "PartProofs")
return
}
@@ -247,8 +247,8 @@ func (z *Cert) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "struct-from-array", "Reveals")
return
}
- if zb0011 > maxReveals {
- err = msgp.ErrOverflow(uint64(zb0011), uint64(maxReveals))
+ if zb0011 > MaxReveals {
+ err = msgp.ErrOverflow(uint64(zb0011), uint64(MaxReveals))
err = msgp.WrapError(err, "struct-from-array", "Reveals")
return
}
@@ -317,8 +317,8 @@ func (z *Cert) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "SigProofs")
return
}
- if zb0013 > maxProofDigests {
- err = msgp.ErrOverflow(uint64(zb0013), uint64(maxProofDigests))
+ if zb0013 > MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0013), uint64(MaxProofDigests))
err = msgp.WrapError(err, "SigProofs")
return
}
@@ -344,8 +344,8 @@ func (z *Cert) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "PartProofs")
return
}
- if zb0015 > maxProofDigests {
- err = msgp.ErrOverflow(uint64(zb0015), uint64(maxProofDigests))
+ if zb0015 > MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0015), uint64(MaxProofDigests))
err = msgp.WrapError(err, "PartProofs")
return
}
@@ -371,8 +371,8 @@ func (z *Cert) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "Reveals")
return
}
- if zb0017 > maxReveals {
- err = msgp.ErrOverflow(uint64(zb0017), uint64(maxReveals))
+ if zb0017 > MaxReveals {
+ err = msgp.ErrOverflow(uint64(zb0017), uint64(MaxReveals))
err = msgp.WrapError(err, "Reveals")
return
}
diff --git a/crypto/compactcert/structs.go b/crypto/compactcert/structs.go
index 69faac522..c0e333868 100644
--- a/crypto/compactcert/structs.go
+++ b/crypto/compactcert/structs.go
@@ -91,9 +91,11 @@ type Reveal struct {
Part Participant `codec:"p"`
}
-// maxReveals is a bound on allocation and on numReveals to limit log computation
-const maxReveals = 1024
-const maxProofDigests = 20 * maxReveals
+// MaxReveals is a bound on allocation and on numReveals to limit log computation
+const MaxReveals = 1024
+
+// MaxProofDigests is a bound on allocation on number of proofs
+const MaxProofDigests = 20 * MaxReveals
// Cert represents a compact certificate.
type Cert struct {
@@ -101,13 +103,13 @@ type Cert struct {
SigCommit crypto.Digest `codec:"c"`
SignedWeight uint64 `codec:"w"`
- SigProofs []crypto.Digest `codec:"S,allocbound=maxProofDigests"`
- PartProofs []crypto.Digest `codec:"P,allocbound=maxProofDigests"`
+ SigProofs []crypto.Digest `codec:"S,allocbound=MaxProofDigests"`
+ PartProofs []crypto.Digest `codec:"P,allocbound=MaxProofDigests"`
// Reveals is a sparse map from the position being revealed
// to the corresponding elements from the sigs and participants
// arrays.
- Reveals map[uint64]Reveal `codec:"r,allocbound=maxReveals"`
+ Reveals map[uint64]Reveal `codec:"r,allocbound=MaxReveals"`
}
// SortUint64 implements sorting by uint64 keys for
diff --git a/crypto/curve25519.go b/crypto/curve25519.go
index e0bf278de..eede5d337 100644
--- a/crypto/curve25519.go
+++ b/crypto/curve25519.go
@@ -69,10 +69,19 @@ func init() {
// A Seed holds the entropy needed to generate cryptographic keys.
type Seed ed25519Seed
+// PublicKeyByteLength is the length, in bytes, of a public key
+const PublicKeyByteLength = 32
+
+// PrivateKeyByteLength is the length, in bytes, of a private key
+const PrivateKeyByteLength = 64
+
+// SignatureByteLength is the length, in bytes, of a signature
+const SignatureByteLength = 64
+
/* Classical signatures */
-type ed25519Signature [64]byte
-type ed25519PublicKey [32]byte
-type ed25519PrivateKey [64]byte
+type ed25519Signature [SignatureByteLength]byte
+type ed25519PublicKey [PublicKeyByteLength]byte
+type ed25519PrivateKey [PrivateKeyByteLength]byte
type ed25519Seed [32]byte
// MasterDerivationKey is used to derive ed25519 keys for use in wallets
diff --git a/crypto/msgp_gen.go b/crypto/msgp_gen.go
index 84fe8622e..4690dbfc4 100644
--- a/crypto/msgp_gen.go
+++ b/crypto/msgp_gen.go
@@ -379,8 +379,8 @@ func (z *MultisigSig) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "struct-from-array", "Subsigs")
return
}
- if zb0004 > maxMultisig {
- err = msgp.ErrOverflow(uint64(zb0004), uint64(maxMultisig))
+ if zb0004 > MaxMultisig {
+ err = msgp.ErrOverflow(uint64(zb0004), uint64(MaxMultisig))
err = msgp.WrapError(err, "struct-from-array", "Subsigs")
return
}
@@ -442,8 +442,8 @@ func (z *MultisigSig) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "Subsigs")
return
}
- if zb0006 > maxMultisig {
- err = msgp.ErrOverflow(uint64(zb0006), uint64(maxMultisig))
+ if zb0006 > MaxMultisig {
+ err = msgp.ErrOverflow(uint64(zb0006), uint64(MaxMultisig))
err = msgp.WrapError(err, "Subsigs")
return
}
@@ -613,7 +613,7 @@ func (_ *MultisigSubsig) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *MultisigSubsig) Msgsize() (s int) {
- s = 1 + 3 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 2 + msgp.ArrayHeaderSize + (64 * (msgp.ByteSize))
+ s = 1 + 3 + msgp.ArrayHeaderSize + (PublicKeyByteLength * (msgp.ByteSize)) + 2 + msgp.ArrayHeaderSize + (SignatureByteLength * (msgp.ByteSize))
return
}
@@ -792,7 +792,7 @@ func (_ *OneTimeSignature) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *OneTimeSignature) Msgsize() (s int) {
- s = 1 + 2 + msgp.ArrayHeaderSize + (64 * (msgp.ByteSize)) + 2 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 3 + msgp.ArrayHeaderSize + (64 * (msgp.ByteSize)) + 3 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 4 + msgp.ArrayHeaderSize + (64 * (msgp.ByteSize)) + 4 + msgp.ArrayHeaderSize + (64 * (msgp.ByteSize))
+ s = 1 + 2 + msgp.ArrayHeaderSize + (SignatureByteLength * (msgp.ByteSize)) + 2 + msgp.ArrayHeaderSize + (PublicKeyByteLength * (msgp.ByteSize)) + 3 + msgp.ArrayHeaderSize + (SignatureByteLength * (msgp.ByteSize)) + 3 + msgp.ArrayHeaderSize + (PublicKeyByteLength * (msgp.ByteSize)) + 4 + msgp.ArrayHeaderSize + (SignatureByteLength * (msgp.ByteSize)) + 4 + msgp.ArrayHeaderSize + (SignatureByteLength * (msgp.ByteSize))
return
}
@@ -1114,7 +1114,7 @@ func (_ *OneTimeSignatureSecrets) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *OneTimeSignatureSecrets) Msgsize() (s int) {
- s = 1 + 25 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 6 + msgp.Uint64Size + 4 + msgp.ArrayHeaderSize
+ s = 1 + 25 + msgp.ArrayHeaderSize + (PublicKeyByteLength * (msgp.ByteSize)) + 6 + msgp.Uint64Size + 4 + msgp.ArrayHeaderSize
for zb0002 := range (*z).OneTimeSignatureSecretsPersistent.Batches {
s += (*z).OneTimeSignatureSecretsPersistent.Batches[zb0002].Msgsize()
}
@@ -1122,7 +1122,7 @@ func (z *OneTimeSignatureSecrets) Msgsize() (s int) {
for zb0003 := range (*z).OneTimeSignatureSecretsPersistent.Offsets {
s += (*z).OneTimeSignatureSecretsPersistent.Offsets[zb0003].Msgsize()
}
- s += 7 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 10 + msgp.ArrayHeaderSize + (64 * (msgp.ByteSize))
+ s += 7 + msgp.ArrayHeaderSize + (PublicKeyByteLength * (msgp.ByteSize)) + 10 + msgp.ArrayHeaderSize + (SignatureByteLength * (msgp.ByteSize))
return
}
@@ -1444,7 +1444,7 @@ func (_ *OneTimeSignatureSecretsPersistent) CanUnmarshalMsg(z interface{}) bool
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *OneTimeSignatureSecretsPersistent) Msgsize() (s int) {
- s = 1 + 25 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 6 + msgp.Uint64Size + 4 + msgp.ArrayHeaderSize
+ s = 1 + 25 + msgp.ArrayHeaderSize + (PublicKeyByteLength * (msgp.ByteSize)) + 6 + msgp.Uint64Size + 4 + msgp.ArrayHeaderSize
for zb0002 := range (*z).Batches {
s += (*z).Batches[zb0002].Msgsize()
}
@@ -1452,7 +1452,7 @@ func (z *OneTimeSignatureSecretsPersistent) Msgsize() (s int) {
for zb0003 := range (*z).Offsets {
s += (*z).Offsets[zb0003].Msgsize()
}
- s += 7 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 10 + msgp.ArrayHeaderSize + (64 * (msgp.ByteSize))
+ s += 7 + msgp.ArrayHeaderSize + (PublicKeyByteLength * (msgp.ByteSize)) + 10 + msgp.ArrayHeaderSize + (SignatureByteLength * (msgp.ByteSize))
return
}
@@ -1563,7 +1563,7 @@ func (_ *OneTimeSignatureSubkeyBatchID) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *OneTimeSignatureSubkeyBatchID) Msgsize() (s int) {
- s = 1 + 3 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 6 + msgp.Uint64Size
+ s = 1 + 3 + msgp.ArrayHeaderSize + (PublicKeyByteLength * (msgp.ByteSize)) + 6 + msgp.Uint64Size
return
}
@@ -1691,7 +1691,7 @@ func (_ *OneTimeSignatureSubkeyOffsetID) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *OneTimeSignatureSubkeyOffsetID) Msgsize() (s int) {
- s = 1 + 3 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 6 + msgp.Uint64Size + 4 + msgp.Uint64Size
+ s = 1 + 3 + msgp.ArrayHeaderSize + (PublicKeyByteLength * (msgp.ByteSize)) + 6 + msgp.Uint64Size + 4 + msgp.Uint64Size
return
}
@@ -1730,7 +1730,7 @@ func (_ *OneTimeSignatureVerifier) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *OneTimeSignatureVerifier) Msgsize() (s int) {
- s = msgp.ArrayHeaderSize + (32 * (msgp.ByteSize))
+ s = msgp.ArrayHeaderSize + (PublicKeyByteLength * (msgp.ByteSize))
return
}
@@ -1769,7 +1769,7 @@ func (_ *PrivateKey) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *PrivateKey) Msgsize() (s int) {
- s = msgp.ArrayHeaderSize + (64 * (msgp.ByteSize))
+ s = msgp.ArrayHeaderSize + (PrivateKeyByteLength * (msgp.ByteSize))
return
}
@@ -1808,7 +1808,7 @@ func (_ *PublicKey) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *PublicKey) Msgsize() (s int) {
- s = msgp.ArrayHeaderSize + (32 * (msgp.ByteSize))
+ s = msgp.ArrayHeaderSize + (PublicKeyByteLength * (msgp.ByteSize))
return
}
@@ -1886,7 +1886,7 @@ func (_ *Signature) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *Signature) Msgsize() (s int) {
- s = msgp.ArrayHeaderSize + (64 * (msgp.ByteSize))
+ s = msgp.ArrayHeaderSize + (SignatureByteLength * (msgp.ByteSize))
return
}
@@ -1997,7 +1997,7 @@ func (_ *SignatureSecrets) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *SignatureSecrets) Msgsize() (s int) {
- s = 1 + 18 + (*z).SignatureVerifier.Msgsize() + 3 + msgp.ArrayHeaderSize + (64 * (msgp.ByteSize))
+ s = 1 + 18 + (*z).SignatureVerifier.Msgsize() + 3 + msgp.ArrayHeaderSize + (PrivateKeyByteLength * (msgp.ByteSize))
return
}
@@ -2108,7 +2108,7 @@ func (_ *VRFSecrets) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *VRFSecrets) Msgsize() (s int) {
- s = 1 + 3 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 3 + msgp.ArrayHeaderSize + (64 * (msgp.ByteSize))
+ s = 1 + 3 + msgp.ArrayHeaderSize + (VrfPubkeyByteLength * (msgp.ByteSize)) + 3 + msgp.ArrayHeaderSize + (64 * (msgp.ByteSize))
return
}
@@ -2264,7 +2264,7 @@ func (_ *VrfPubkey) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *VrfPubkey) Msgsize() (s int) {
- s = msgp.ArrayHeaderSize + (32 * (msgp.ByteSize))
+ s = msgp.ArrayHeaderSize + (VrfPubkeyByteLength * (msgp.ByteSize))
return
}
@@ -2303,7 +2303,7 @@ func (_ *ed25519PrivateKey) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *ed25519PrivateKey) Msgsize() (s int) {
- s = msgp.ArrayHeaderSize + (64 * (msgp.ByteSize))
+ s = msgp.ArrayHeaderSize + (PrivateKeyByteLength * (msgp.ByteSize))
return
}
@@ -2342,7 +2342,7 @@ func (_ *ed25519PublicKey) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *ed25519PublicKey) Msgsize() (s int) {
- s = msgp.ArrayHeaderSize + (32 * (msgp.ByteSize))
+ s = msgp.ArrayHeaderSize + (PublicKeyByteLength * (msgp.ByteSize))
return
}
@@ -2420,7 +2420,7 @@ func (_ *ed25519Signature) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *ed25519Signature) Msgsize() (s int) {
- s = msgp.ArrayHeaderSize + (64 * (msgp.ByteSize))
+ s = msgp.ArrayHeaderSize + (SignatureByteLength * (msgp.ByteSize))
return
}
@@ -2565,7 +2565,7 @@ func (_ *ephemeralSubkey) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *ephemeralSubkey) Msgsize() (s int) {
- s = 1 + 3 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 3 + msgp.ArrayHeaderSize + (64 * (msgp.ByteSize)) + 6 + msgp.ArrayHeaderSize + (64 * (msgp.ByteSize)) + 5 + msgp.ArrayHeaderSize + (64 * (msgp.ByteSize))
+ s = 1 + 3 + msgp.ArrayHeaderSize + (PublicKeyByteLength * (msgp.ByteSize)) + 3 + msgp.ArrayHeaderSize + (PrivateKeyByteLength * (msgp.ByteSize)) + 6 + msgp.ArrayHeaderSize + (SignatureByteLength * (msgp.ByteSize)) + 5 + msgp.ArrayHeaderSize + (SignatureByteLength * (msgp.ByteSize))
return
}
diff --git a/crypto/multisig.go b/crypto/multisig.go
index 6c9a1ca66..886d2cb62 100644
--- a/crypto/multisig.go
+++ b/crypto/multisig.go
@@ -38,7 +38,7 @@ type MultisigSig struct {
Version uint8 `codec:"v"`
Threshold uint8 `codec:"thr"`
- Subsigs []MultisigSubsig `codec:"subsig,allocbound=maxMultisig"`
+ Subsigs []MultisigSubsig `codec:"subsig,allocbound=MaxMultisig"`
}
// MultisigPreimageFromPKs makes an empty MultisigSig for a given preimage. It should be renamed.
@@ -76,7 +76,9 @@ func (msig MultisigSig) Preimage() (version, threshold uint8, pks []PublicKey) {
}
const multiSigString = "MultisigAddr"
-const maxMultisig = 255
+
+// MaxMultisig is a bound on allocation and on the number of subsigs
+const MaxMultisig = 255
// MultisigAddrGen identifes the exact group, version,
// and devices (Public keys) that it requires to sign
@@ -256,8 +258,9 @@ func MultisigBatchVerify(msg Hashable, addr Digest, sig MultisigSig, batchVerifi
}
// check that we don't have too many multisig subsigs
- if len(sig.Subsigs) > maxMultisig {
+ if len(sig.Subsigs) > MaxMultisig {
err = errInvalidNumberOfSignature
+
return
}
diff --git a/crypto/multisig_test.go b/crypto/multisig_test.go
index 8636331bf..492c3cfe8 100644
--- a/crypto/multisig_test.go
+++ b/crypto/multisig_test.go
@@ -297,7 +297,7 @@ func TestMoreThanMaxSigsInMultisig(t *testing.T) {
var s Seed
var secrets []*SecretKey
var pks []PublicKey
- multiSigLen := maxMultisig + 1
+ multiSigLen := MaxMultisig + 1
txid := TestingHashable{[]byte("test: txid 1000")}
version := uint8(1)
threshold := uint8(1)
diff --git a/crypto/vrf.go b/crypto/vrf.go
index 88e314485..36a6e8270 100644
--- a/crypto/vrf.go
+++ b/crypto/vrf.go
@@ -45,6 +45,9 @@ type VRFVerifier = VrfPubkey
// VRFProof is a deprecated name for VrfProof
type VRFProof = VrfProof
+// VrfPubkeyByteLength is the size, in bytes, of a VRF public key.
+const VrfPubkeyByteLength = 32
+
// VRFSecrets is a wrapper for a VRF keypair. Use *VrfPrivkey instead
type VRFSecrets struct {
_struct struct{} `codec:""`
@@ -68,7 +71,7 @@ type (
// Specifically, we use a 64-byte ed25519 private key (the latter 32-bytes are the precomputed public key)
VrfPrivkey [64]byte
// A VrfPubkey is a public key that can be used to verify VRF proofs.
- VrfPubkey [32]byte
+ VrfPubkey [VrfPubkeyByteLength]byte
// A VrfProof for a message can be generated with a secret key and verified against a public key, like a signature.
// Proofs are malleable, however, for a given message and public key, the VRF output that can be computed from a proof is unique.
VrfProof [80]byte
diff --git a/data/basics/msgp_gen.go b/data/basics/msgp_gen.go
index 8e61362d6..73a759331 100644
--- a/data/basics/msgp_gen.go
+++ b/data/basics/msgp_gen.go
@@ -2533,7 +2533,7 @@ func (z *AssetParams) MarshalMsg(b []byte) (o []byte) {
// omitempty: check for empty values
zb0002Len := uint32(11)
var zb0002Mask uint16 /* 12 bits */
- if (*z).MetadataHash == ([32]byte{}) {
+ if (*z).MetadataHash == ([MetadataHashLength]byte{}) {
zb0002Len--
zb0002Mask |= 0x2
}
@@ -2854,13 +2854,13 @@ func (_ *AssetParams) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *AssetParams) Msgsize() (s int) {
- s = 1 + 2 + msgp.Uint64Size + 3 + msgp.Uint32Size + 3 + msgp.BoolSize + 3 + msgp.StringPrefixSize + len((*z).UnitName) + 3 + msgp.StringPrefixSize + len((*z).AssetName) + 3 + msgp.StringPrefixSize + len((*z).URL) + 3 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 2 + (*z).Manager.Msgsize() + 2 + (*z).Reserve.Msgsize() + 2 + (*z).Freeze.Msgsize() + 2 + (*z).Clawback.Msgsize()
+ s = 1 + 2 + msgp.Uint64Size + 3 + msgp.Uint32Size + 3 + msgp.BoolSize + 3 + msgp.StringPrefixSize + len((*z).UnitName) + 3 + msgp.StringPrefixSize + len((*z).AssetName) + 3 + msgp.StringPrefixSize + len((*z).URL) + 3 + msgp.ArrayHeaderSize + (MetadataHashLength * (msgp.ByteSize)) + 2 + (*z).Manager.Msgsize() + 2 + (*z).Reserve.Msgsize() + 2 + (*z).Freeze.Msgsize() + 2 + (*z).Clawback.Msgsize()
return
}
// MsgIsZero returns whether this is a zero value
func (z *AssetParams) MsgIsZero() bool {
- return ((*z).Total == 0) && ((*z).Decimals == 0) && ((*z).DefaultFrozen == false) && ((*z).UnitName == "") && ((*z).AssetName == "") && ((*z).URL == "") && ((*z).MetadataHash == ([32]byte{})) && ((*z).Manager.MsgIsZero()) && ((*z).Reserve.MsgIsZero()) && ((*z).Freeze.MsgIsZero()) && ((*z).Clawback.MsgIsZero())
+ return ((*z).Total == 0) && ((*z).Decimals == 0) && ((*z).DefaultFrozen == false) && ((*z).UnitName == "") && ((*z).AssetName == "") && ((*z).URL == "") && ((*z).MetadataHash == ([MetadataHashLength]byte{})) && ((*z).Manager.MsgIsZero()) && ((*z).Reserve.MsgIsZero()) && ((*z).Freeze.MsgIsZero()) && ((*z).Clawback.MsgIsZero())
}
// MarshalMsg implements msgp.Marshaler
diff --git a/data/basics/userBalance.go b/data/basics/userBalance.go
index 4a5253e42..22f65490b 100644
--- a/data/basics/userBalance.go
+++ b/data/basics/userBalance.go
@@ -310,6 +310,9 @@ const (
// AppCreatable is the CreatableType corresponds to apps
AppCreatable CreatableType = 1
+
+ // MetadataHashLength is the number of bytes of the MetadataHash
+ MetadataHashLength int = 32
)
// CreatableLocator stores both the creator, whose balance record contains
@@ -361,7 +364,7 @@ type AssetParams struct {
// MetadataHash specifies a commitment to some unspecified asset
// metadata. The format of this metadata is up to the application.
- MetadataHash [32]byte `codec:"am"`
+ MetadataHash [MetadataHashLength]byte `codec:"am"`
// Manager specifies an account that is allowed to change the
// non-zero addresses in this AssetParams.
@@ -397,6 +400,16 @@ func MakeAccountData(status Status, algos MicroAlgos) AccountData {
return AccountData{Status: status, MicroAlgos: algos}
}
+// ClearOnlineState resets the account's fields to indicate that the account is an offline account
+func (u *AccountData) ClearOnlineState() {
+ u.Status = Offline
+ u.VoteFirstValid = Round(0)
+ u.VoteLastValid = Round(0)
+ u.VoteKeyDilution = 0
+ u.VoteID = crypto.OneTimeSignatureVerifier{}
+ u.SelectionID = crypto.VRFVerifier{}
+}
+
// Money returns the amount of MicroAlgos associated with the user's account
func (u AccountData) Money(proto config.ConsensusParams, rewardsLevel uint64) (money MicroAlgos, rewards MicroAlgos) {
e := u.WithUpdatedRewards(proto, rewardsLevel)
diff --git a/data/bookkeeping/block.go b/data/bookkeeping/block.go
index a60a9362c..bb9ae321b 100644
--- a/data/bookkeeping/block.go
+++ b/data/bookkeeping/block.go
@@ -125,6 +125,21 @@ type (
// for multiple types of certs.
//msgp:sort protocol.CompactCertType protocol.SortCompactCertType
CompactCert map[protocol.CompactCertType]CompactCertState `codec:"cc,allocbound=protocol.NumCompactCertTypes"`
+
+ // ParticipationUpdates contains the information needed to mark
+ // certain accounts offline because their participation keys expired
+ ParticipationUpdates
+ }
+
+ // ParticipationUpdates represents participation account data that
+ // needs to be checked/acted on by the network
+ ParticipationUpdates struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"`
+
+ // ExpiredParticipationAccounts contains a list of online accounts
+ // that needs to be converted to offline since their
+ // participation key expired.
+ ExpiredParticipationAccounts []basics.Address `codec:"partupdrmv,allocbound=config.MaxProposedExpiredOnlineAccounts"`
}
// RewardsState represents the global parameters controlling the rate
diff --git a/data/bookkeeping/msgp_gen.go b/data/bookkeeping/msgp_gen.go
index 8b88b8fbe..e7a810e3d 100644
--- a/data/bookkeeping/msgp_gen.go
+++ b/data/bookkeeping/msgp_gen.go
@@ -5,7 +5,9 @@ package bookkeeping
import (
"sort"
+ "github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/msgp/msgp"
)
@@ -59,6 +61,14 @@ import (
// |-----> (*) Msgsize
// |-----> (*) MsgIsZero
//
+// ParticipationUpdates
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
// RewardsState
// |-----> (*) MarshalMsg
// |-----> (*) CanMarshalMsg
@@ -80,108 +90,112 @@ import (
func (z *Block) MarshalMsg(b []byte) (o []byte) {
o = msgp.Require(b, z.Msgsize())
// omitempty: check for empty values
- zb0003Len := uint32(24)
- var zb0003Mask uint32 /* 27 bits */
+ zb0004Len := uint32(25)
+ var zb0004Mask uint32 /* 29 bits */
if len((*z).BlockHeader.CompactCert) == 0 {
- zb0003Len--
- zb0003Mask |= 0x8
+ zb0004Len--
+ zb0004Mask |= 0x10
}
if (*z).BlockHeader.RewardsState.RewardsLevel == 0 {
- zb0003Len--
- zb0003Mask |= 0x10
+ zb0004Len--
+ zb0004Mask |= 0x20
}
if (*z).BlockHeader.RewardsState.FeeSink.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x20
+ zb0004Len--
+ zb0004Mask |= 0x40
}
if (*z).BlockHeader.RewardsState.RewardsResidue == 0 {
- zb0003Len--
- zb0003Mask |= 0x40
+ zb0004Len--
+ zb0004Mask |= 0x80
}
if (*z).BlockHeader.GenesisID == "" {
- zb0003Len--
- zb0003Mask |= 0x80
+ zb0004Len--
+ zb0004Mask |= 0x100
}
if (*z).BlockHeader.GenesisHash.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x100
+ zb0004Len--
+ zb0004Mask |= 0x200
}
if (*z).BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x200
+ zb0004Len--
+ zb0004Mask |= 0x400
}
if (*z).BlockHeader.UpgradeState.NextProtocol.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x400
+ zb0004Len--
+ zb0004Mask |= 0x800
}
if (*z).BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x800
+ zb0004Len--
+ zb0004Mask |= 0x1000
}
if (*z).BlockHeader.UpgradeState.NextProtocolApprovals == 0 {
- zb0003Len--
- zb0003Mask |= 0x1000
+ zb0004Len--
+ zb0004Mask |= 0x2000
+ }
+ if len((*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x4000
}
if (*z).BlockHeader.Branch.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x2000
+ zb0004Len--
+ zb0004Mask |= 0x8000
}
if (*z).BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x4000
+ zb0004Len--
+ zb0004Mask |= 0x10000
}
if (*z).BlockHeader.RewardsState.RewardsRate == 0 {
- zb0003Len--
- zb0003Mask |= 0x8000
+ zb0004Len--
+ zb0004Mask |= 0x20000
}
if (*z).BlockHeader.Round.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x10000
+ zb0004Len--
+ zb0004Mask |= 0x40000
}
if (*z).BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x20000
+ zb0004Len--
+ zb0004Mask |= 0x80000
}
if (*z).BlockHeader.RewardsState.RewardsPool.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x40000
+ zb0004Len--
+ zb0004Mask |= 0x100000
}
if (*z).BlockHeader.Seed.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x80000
+ zb0004Len--
+ zb0004Mask |= 0x200000
}
if (*z).BlockHeader.TxnCounter == 0 {
- zb0003Len--
- zb0003Mask |= 0x100000
+ zb0004Len--
+ zb0004Mask |= 0x400000
}
if (*z).BlockHeader.TimeStamp == 0 {
- zb0003Len--
- zb0003Mask |= 0x200000
+ zb0004Len--
+ zb0004Mask |= 0x800000
}
if (*z).BlockHeader.TxnRoot.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x400000
+ zb0004Len--
+ zb0004Mask |= 0x1000000
}
if (*z).Payset.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x800000
+ zb0004Len--
+ zb0004Mask |= 0x2000000
}
if (*z).BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x1000000
+ zb0004Len--
+ zb0004Mask |= 0x4000000
}
if (*z).BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x2000000
+ zb0004Len--
+ zb0004Mask |= 0x8000000
}
if (*z).BlockHeader.UpgradeVote.UpgradeApprove == false {
- zb0003Len--
- zb0003Mask |= 0x4000000
+ zb0004Len--
+ zb0004Mask |= 0x10000000
}
- // variable map header, size zb0003Len
- o = msgp.AppendMapHeader(o, zb0003Len)
- if zb0003Len != 0 {
- if (zb0003Mask & 0x8) == 0 { // if not empty
+ // variable map header, size zb0004Len
+ o = msgp.AppendMapHeader(o, zb0004Len)
+ if zb0004Len != 0 {
+ if (zb0004Mask & 0x10) == 0 { // if not empty
// string "cc"
o = append(o, 0xa2, 0x63, 0x63)
if (*z).BlockHeader.CompactCert == nil {
@@ -201,117 +215,129 @@ func (z *Block) MarshalMsg(b []byte) (o []byte) {
o = zb0002.MarshalMsg(o)
}
}
- if (zb0003Mask & 0x10) == 0 { // if not empty
+ if (zb0004Mask & 0x20) == 0 { // if not empty
// string "earn"
o = append(o, 0xa4, 0x65, 0x61, 0x72, 0x6e)
o = msgp.AppendUint64(o, (*z).BlockHeader.RewardsState.RewardsLevel)
}
- if (zb0003Mask & 0x20) == 0 { // if not empty
+ if (zb0004Mask & 0x40) == 0 { // if not empty
// string "fees"
o = append(o, 0xa4, 0x66, 0x65, 0x65, 0x73)
o = (*z).BlockHeader.RewardsState.FeeSink.MarshalMsg(o)
}
- if (zb0003Mask & 0x40) == 0 { // if not empty
+ if (zb0004Mask & 0x80) == 0 { // if not empty
// string "frac"
o = append(o, 0xa4, 0x66, 0x72, 0x61, 0x63)
o = msgp.AppendUint64(o, (*z).BlockHeader.RewardsState.RewardsResidue)
}
- if (zb0003Mask & 0x80) == 0 { // if not empty
+ if (zb0004Mask & 0x100) == 0 { // if not empty
// string "gen"
o = append(o, 0xa3, 0x67, 0x65, 0x6e)
o = msgp.AppendString(o, (*z).BlockHeader.GenesisID)
}
- if (zb0003Mask & 0x100) == 0 { // if not empty
+ if (zb0004Mask & 0x200) == 0 { // if not empty
// string "gh"
o = append(o, 0xa2, 0x67, 0x68)
o = (*z).BlockHeader.GenesisHash.MarshalMsg(o)
}
- if (zb0003Mask & 0x200) == 0 { // if not empty
+ if (zb0004Mask & 0x400) == 0 { // if not empty
// string "nextbefore"
o = append(o, 0xaa, 0x6e, 0x65, 0x78, 0x74, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65)
o = (*z).BlockHeader.UpgradeState.NextProtocolVoteBefore.MarshalMsg(o)
}
- if (zb0003Mask & 0x400) == 0 { // if not empty
+ if (zb0004Mask & 0x800) == 0 { // if not empty
// string "nextproto"
o = append(o, 0xa9, 0x6e, 0x65, 0x78, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f)
o = (*z).BlockHeader.UpgradeState.NextProtocol.MarshalMsg(o)
}
- if (zb0003Mask & 0x800) == 0 { // if not empty
+ if (zb0004Mask & 0x1000) == 0 { // if not empty
// string "nextswitch"
o = append(o, 0xaa, 0x6e, 0x65, 0x78, 0x74, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68)
o = (*z).BlockHeader.UpgradeState.NextProtocolSwitchOn.MarshalMsg(o)
}
- if (zb0003Mask & 0x1000) == 0 { // if not empty
+ if (zb0004Mask & 0x2000) == 0 { // if not empty
// string "nextyes"
o = append(o, 0xa7, 0x6e, 0x65, 0x78, 0x74, 0x79, 0x65, 0x73)
o = msgp.AppendUint64(o, (*z).BlockHeader.UpgradeState.NextProtocolApprovals)
}
- if (zb0003Mask & 0x2000) == 0 { // if not empty
+ if (zb0004Mask & 0x4000) == 0 { // if not empty
+ // string "partupdrmv"
+ o = append(o, 0xaa, 0x70, 0x61, 0x72, 0x74, 0x75, 0x70, 0x64, 0x72, 0x6d, 0x76)
+ if (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts)))
+ }
+ for zb0003 := range (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ o = (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].MarshalMsg(o)
+ }
+ }
+ if (zb0004Mask & 0x8000) == 0 { // if not empty
// string "prev"
o = append(o, 0xa4, 0x70, 0x72, 0x65, 0x76)
o = (*z).BlockHeader.Branch.MarshalMsg(o)
}
- if (zb0003Mask & 0x4000) == 0 { // if not empty
+ if (zb0004Mask & 0x10000) == 0 { // if not empty
// string "proto"
o = append(o, 0xa5, 0x70, 0x72, 0x6f, 0x74, 0x6f)
o = (*z).BlockHeader.UpgradeState.CurrentProtocol.MarshalMsg(o)
}
- if (zb0003Mask & 0x8000) == 0 { // if not empty
+ if (zb0004Mask & 0x20000) == 0 { // if not empty
// string "rate"
o = append(o, 0xa4, 0x72, 0x61, 0x74, 0x65)
o = msgp.AppendUint64(o, (*z).BlockHeader.RewardsState.RewardsRate)
}
- if (zb0003Mask & 0x10000) == 0 { // if not empty
+ if (zb0004Mask & 0x40000) == 0 { // if not empty
// string "rnd"
o = append(o, 0xa3, 0x72, 0x6e, 0x64)
o = (*z).BlockHeader.Round.MarshalMsg(o)
}
- if (zb0003Mask & 0x20000) == 0 { // if not empty
+ if (zb0004Mask & 0x80000) == 0 { // if not empty
// string "rwcalr"
o = append(o, 0xa6, 0x72, 0x77, 0x63, 0x61, 0x6c, 0x72)
o = (*z).BlockHeader.RewardsState.RewardsRecalculationRound.MarshalMsg(o)
}
- if (zb0003Mask & 0x40000) == 0 { // if not empty
+ if (zb0004Mask & 0x100000) == 0 { // if not empty
// string "rwd"
o = append(o, 0xa3, 0x72, 0x77, 0x64)
o = (*z).BlockHeader.RewardsState.RewardsPool.MarshalMsg(o)
}
- if (zb0003Mask & 0x80000) == 0 { // if not empty
+ if (zb0004Mask & 0x200000) == 0 { // if not empty
// string "seed"
o = append(o, 0xa4, 0x73, 0x65, 0x65, 0x64)
o = (*z).BlockHeader.Seed.MarshalMsg(o)
}
- if (zb0003Mask & 0x100000) == 0 { // if not empty
+ if (zb0004Mask & 0x400000) == 0 { // if not empty
// string "tc"
o = append(o, 0xa2, 0x74, 0x63)
o = msgp.AppendUint64(o, (*z).BlockHeader.TxnCounter)
}
- if (zb0003Mask & 0x200000) == 0 { // if not empty
+ if (zb0004Mask & 0x800000) == 0 { // if not empty
// string "ts"
o = append(o, 0xa2, 0x74, 0x73)
o = msgp.AppendInt64(o, (*z).BlockHeader.TimeStamp)
}
- if (zb0003Mask & 0x400000) == 0 { // if not empty
+ if (zb0004Mask & 0x1000000) == 0 { // if not empty
// string "txn"
o = append(o, 0xa3, 0x74, 0x78, 0x6e)
o = (*z).BlockHeader.TxnRoot.MarshalMsg(o)
}
- if (zb0003Mask & 0x800000) == 0 { // if not empty
+ if (zb0004Mask & 0x2000000) == 0 { // if not empty
// string "txns"
o = append(o, 0xa4, 0x74, 0x78, 0x6e, 0x73)
o = (*z).Payset.MarshalMsg(o)
}
- if (zb0003Mask & 0x1000000) == 0 { // if not empty
+ if (zb0004Mask & 0x4000000) == 0 { // if not empty
// string "upgradedelay"
o = append(o, 0xac, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x64, 0x65, 0x6c, 0x61, 0x79)
o = (*z).BlockHeader.UpgradeVote.UpgradeDelay.MarshalMsg(o)
}
- if (zb0003Mask & 0x2000000) == 0 { // if not empty
+ if (zb0004Mask & 0x8000000) == 0 { // if not empty
// string "upgradeprop"
o = append(o, 0xab, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x70, 0x72, 0x6f, 0x70)
o = (*z).BlockHeader.UpgradeVote.UpgradePropose.MarshalMsg(o)
}
- if (zb0003Mask & 0x4000000) == 0 { // if not empty
+ if (zb0004Mask & 0x10000000) == 0 { // if not empty
// string "upgradeyes"
o = append(o, 0xaa, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x79, 0x65, 0x73)
o = msgp.AppendBool(o, (*z).BlockHeader.UpgradeVote.UpgradeApprove)
@@ -329,214 +355,214 @@ func (_ *Block) CanMarshalMsg(z interface{}) bool {
func (z *Block) UnmarshalMsg(bts []byte) (o []byte, err error) {
var field []byte
_ = field
- var zb0003 int
- var zb0004 bool
- zb0003, zb0004, bts, err = msgp.ReadMapHeaderBytes(bts)
+ var zb0004 int
+ var zb0005 bool
+ zb0004, zb0005, bts, err = msgp.ReadMapHeaderBytes(bts)
if _, ok := err.(msgp.TypeError); ok {
- zb0003, zb0004, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ zb0004, zb0005, bts, err = msgp.ReadArrayHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err)
return
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).BlockHeader.Round.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Round")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).BlockHeader.Branch.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Branch")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).BlockHeader.Seed.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Seed")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).BlockHeader.TxnRoot.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TxnRoot")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).BlockHeader.TimeStamp, bts, err = msgp.ReadInt64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TimeStamp")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).BlockHeader.GenesisID, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "GenesisID")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).BlockHeader.GenesisHash.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "GenesisHash")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).BlockHeader.RewardsState.FeeSink.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "FeeSink")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).BlockHeader.RewardsState.RewardsPool.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsPool")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).BlockHeader.RewardsState.RewardsLevel, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsLevel")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).BlockHeader.RewardsState.RewardsRate, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsRate")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).BlockHeader.RewardsState.RewardsResidue, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsResidue")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).BlockHeader.RewardsState.RewardsRecalculationRound.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsRecalculationRound")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).BlockHeader.UpgradeState.CurrentProtocol.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CurrentProtocol")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).BlockHeader.UpgradeState.NextProtocol.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocol")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).BlockHeader.UpgradeState.NextProtocolApprovals, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolApprovals")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).BlockHeader.UpgradeState.NextProtocolVoteBefore.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolVoteBefore")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).BlockHeader.UpgradeState.NextProtocolSwitchOn.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolSwitchOn")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).BlockHeader.UpgradeVote.UpgradePropose.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradePropose")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).BlockHeader.UpgradeVote.UpgradeDelay.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradeDelay")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).BlockHeader.UpgradeVote.UpgradeApprove, bts, err = msgp.ReadBoolBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradeApprove")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).BlockHeader.TxnCounter, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TxnCounter")
return
}
}
- if zb0003 > 0 {
- zb0003--
- var zb0005 int
- var zb0006 bool
- zb0005, zb0006, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if zb0004 > 0 {
+ zb0004--
+ var zb0006 int
+ var zb0007 bool
+ zb0006, zb0007, bts, err = msgp.ReadMapHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
return
}
- if zb0005 > protocol.NumCompactCertTypes {
- err = msgp.ErrOverflow(uint64(zb0005), uint64(protocol.NumCompactCertTypes))
+ if zb0006 > protocol.NumCompactCertTypes {
+ err = msgp.ErrOverflow(uint64(zb0006), uint64(protocol.NumCompactCertTypes))
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
return
}
- if zb0006 {
+ if zb0007 {
(*z).BlockHeader.CompactCert = nil
} else if (*z).BlockHeader.CompactCert == nil {
- (*z).BlockHeader.CompactCert = make(map[protocol.CompactCertType]CompactCertState, zb0005)
+ (*z).BlockHeader.CompactCert = make(map[protocol.CompactCertType]CompactCertState, zb0006)
}
- for zb0005 > 0 {
+ for zb0006 > 0 {
var zb0001 protocol.CompactCertType
var zb0002 CompactCertState
- zb0005--
+ zb0006--
bts, err = zb0001.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
@@ -550,16 +576,45 @@ func (z *Block) UnmarshalMsg(bts []byte) (o []byte, err error) {
(*z).BlockHeader.CompactCert[zb0001] = zb0002
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
+ var zb0008 int
+ var zb0009 bool
+ zb0008, zb0009, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0008 > config.MaxProposedExpiredOnlineAccounts {
+ err = msgp.ErrOverflow(uint64(zb0008), uint64(config.MaxProposedExpiredOnlineAccounts))
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0009 {
+ (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = nil
+ } else if (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts != nil && cap((*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) >= zb0008 {
+ (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = ((*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts)[:zb0008]
+ } else {
+ (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = make([]basics.Address, zb0008)
+ }
+ for zb0003 := range (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ bts, err = (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts", zb0003)
+ return
+ }
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Payset.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Payset")
return
}
}
- if zb0003 > 0 {
- err = msgp.ErrTooManyArrayFields(zb0003)
+ if zb0004 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0004)
if err != nil {
err = msgp.WrapError(err, "struct-from-array")
return
@@ -570,11 +625,11 @@ func (z *Block) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err)
return
}
- if zb0004 {
+ if zb0005 {
(*z) = Block{}
}
- for zb0003 > 0 {
- zb0003--
+ for zb0004 > 0 {
+ zb0004--
field, bts, err = msgp.ReadMapKeyZC(bts)
if err != nil {
err = msgp.WrapError(err)
@@ -714,27 +769,27 @@ func (z *Block) UnmarshalMsg(bts []byte) (o []byte, err error) {
return
}
case "cc":
- var zb0007 int
- var zb0008 bool
- zb0007, zb0008, bts, err = msgp.ReadMapHeaderBytes(bts)
+ var zb0010 int
+ var zb0011 bool
+ zb0010, zb0011, bts, err = msgp.ReadMapHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err, "CompactCert")
return
}
- if zb0007 > protocol.NumCompactCertTypes {
- err = msgp.ErrOverflow(uint64(zb0007), uint64(protocol.NumCompactCertTypes))
+ if zb0010 > protocol.NumCompactCertTypes {
+ err = msgp.ErrOverflow(uint64(zb0010), uint64(protocol.NumCompactCertTypes))
err = msgp.WrapError(err, "CompactCert")
return
}
- if zb0008 {
+ if zb0011 {
(*z).BlockHeader.CompactCert = nil
} else if (*z).BlockHeader.CompactCert == nil {
- (*z).BlockHeader.CompactCert = make(map[protocol.CompactCertType]CompactCertState, zb0007)
+ (*z).BlockHeader.CompactCert = make(map[protocol.CompactCertType]CompactCertState, zb0010)
}
- for zb0007 > 0 {
+ for zb0010 > 0 {
var zb0001 protocol.CompactCertType
var zb0002 CompactCertState
- zb0007--
+ zb0010--
bts, err = zb0001.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "CompactCert")
@@ -747,6 +802,33 @@ func (z *Block) UnmarshalMsg(bts []byte) (o []byte, err error) {
}
(*z).BlockHeader.CompactCert[zb0001] = zb0002
}
+ case "partupdrmv":
+ var zb0012 int
+ var zb0013 bool
+ zb0012, zb0013, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0012 > config.MaxProposedExpiredOnlineAccounts {
+ err = msgp.ErrOverflow(uint64(zb0012), uint64(config.MaxProposedExpiredOnlineAccounts))
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0013 {
+ (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = nil
+ } else if (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts != nil && cap((*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) >= zb0012 {
+ (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = ((*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts)[:zb0012]
+ } else {
+ (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts = make([]basics.Address, zb0012)
+ }
+ for zb0003 := range (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ bts, err = (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts", zb0003)
+ return
+ }
+ }
case "txns":
bts, err = (*z).Payset.UnmarshalMsg(bts)
if err != nil {
@@ -781,13 +863,17 @@ func (z *Block) Msgsize() (s int) {
s += 0 + zb0001.Msgsize() + zb0002.Msgsize()
}
}
+ s += 11 + msgp.ArrayHeaderSize
+ for zb0003 := range (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts {
+ s += (*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts[zb0003].Msgsize()
+ }
s += 5 + (*z).Payset.Msgsize()
return
}
// MsgIsZero returns whether this is a zero value
func (z *Block) MsgIsZero() bool {
- return ((*z).BlockHeader.Round.MsgIsZero()) && ((*z).BlockHeader.Branch.MsgIsZero()) && ((*z).BlockHeader.Seed.MsgIsZero()) && ((*z).BlockHeader.TxnRoot.MsgIsZero()) && ((*z).BlockHeader.TimeStamp == 0) && ((*z).BlockHeader.GenesisID == "") && ((*z).BlockHeader.GenesisHash.MsgIsZero()) && ((*z).BlockHeader.RewardsState.FeeSink.MsgIsZero()) && ((*z).BlockHeader.RewardsState.RewardsPool.MsgIsZero()) && ((*z).BlockHeader.RewardsState.RewardsLevel == 0) && ((*z).BlockHeader.RewardsState.RewardsRate == 0) && ((*z).BlockHeader.RewardsState.RewardsResidue == 0) && ((*z).BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).BlockHeader.UpgradeState.NextProtocol.MsgIsZero()) && ((*z).BlockHeader.UpgradeState.NextProtocolApprovals == 0) && ((*z).BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).BlockHeader.UpgradeVote.UpgradeApprove == false) && ((*z).BlockHeader.TxnCounter == 0) && (len((*z).BlockHeader.CompactCert) == 0) && ((*z).Payset.MsgIsZero())
+ return ((*z).BlockHeader.Round.MsgIsZero()) && ((*z).BlockHeader.Branch.MsgIsZero()) && ((*z).BlockHeader.Seed.MsgIsZero()) && ((*z).BlockHeader.TxnRoot.MsgIsZero()) && ((*z).BlockHeader.TimeStamp == 0) && ((*z).BlockHeader.GenesisID == "") && ((*z).BlockHeader.GenesisHash.MsgIsZero()) && ((*z).BlockHeader.RewardsState.FeeSink.MsgIsZero()) && ((*z).BlockHeader.RewardsState.RewardsPool.MsgIsZero()) && ((*z).BlockHeader.RewardsState.RewardsLevel == 0) && ((*z).BlockHeader.RewardsState.RewardsRate == 0) && ((*z).BlockHeader.RewardsState.RewardsResidue == 0) && ((*z).BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).BlockHeader.UpgradeState.NextProtocol.MsgIsZero()) && ((*z).BlockHeader.UpgradeState.NextProtocolApprovals == 0) && ((*z).BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).BlockHeader.UpgradeVote.UpgradeApprove == false) && ((*z).BlockHeader.TxnCounter == 0) && (len((*z).BlockHeader.CompactCert) == 0) && (len((*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) == 0) && ((*z).Payset.MsgIsZero())
}
// MarshalMsg implements msgp.Marshaler
@@ -822,104 +908,108 @@ func (z *BlockHash) MsgIsZero() bool {
func (z *BlockHeader) MarshalMsg(b []byte) (o []byte) {
o = msgp.Require(b, z.Msgsize())
// omitempty: check for empty values
- zb0003Len := uint32(23)
- var zb0003Mask uint32 /* 26 bits */
+ zb0004Len := uint32(24)
+ var zb0004Mask uint32 /* 28 bits */
if len((*z).CompactCert) == 0 {
- zb0003Len--
- zb0003Mask |= 0x8
+ zb0004Len--
+ zb0004Mask |= 0x10
}
if (*z).RewardsState.RewardsLevel == 0 {
- zb0003Len--
- zb0003Mask |= 0x10
+ zb0004Len--
+ zb0004Mask |= 0x20
}
if (*z).RewardsState.FeeSink.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x20
+ zb0004Len--
+ zb0004Mask |= 0x40
}
if (*z).RewardsState.RewardsResidue == 0 {
- zb0003Len--
- zb0003Mask |= 0x40
+ zb0004Len--
+ zb0004Mask |= 0x80
}
if (*z).GenesisID == "" {
- zb0003Len--
- zb0003Mask |= 0x80
+ zb0004Len--
+ zb0004Mask |= 0x100
}
if (*z).GenesisHash.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x100
+ zb0004Len--
+ zb0004Mask |= 0x200
}
if (*z).UpgradeState.NextProtocolVoteBefore.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x200
+ zb0004Len--
+ zb0004Mask |= 0x400
}
if (*z).UpgradeState.NextProtocol.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x400
+ zb0004Len--
+ zb0004Mask |= 0x800
}
if (*z).UpgradeState.NextProtocolSwitchOn.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x800
+ zb0004Len--
+ zb0004Mask |= 0x1000
}
if (*z).UpgradeState.NextProtocolApprovals == 0 {
- zb0003Len--
- zb0003Mask |= 0x1000
+ zb0004Len--
+ zb0004Mask |= 0x2000
+ }
+ if len((*z).ParticipationUpdates.ExpiredParticipationAccounts) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x4000
}
if (*z).Branch.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x2000
+ zb0004Len--
+ zb0004Mask |= 0x8000
}
if (*z).UpgradeState.CurrentProtocol.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x4000
+ zb0004Len--
+ zb0004Mask |= 0x10000
}
if (*z).RewardsState.RewardsRate == 0 {
- zb0003Len--
- zb0003Mask |= 0x8000
+ zb0004Len--
+ zb0004Mask |= 0x20000
}
if (*z).Round.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x10000
+ zb0004Len--
+ zb0004Mask |= 0x40000
}
if (*z).RewardsState.RewardsRecalculationRound.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x20000
+ zb0004Len--
+ zb0004Mask |= 0x80000
}
if (*z).RewardsState.RewardsPool.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x40000
+ zb0004Len--
+ zb0004Mask |= 0x100000
}
if (*z).Seed.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x80000
+ zb0004Len--
+ zb0004Mask |= 0x200000
}
if (*z).TxnCounter == 0 {
- zb0003Len--
- zb0003Mask |= 0x100000
+ zb0004Len--
+ zb0004Mask |= 0x400000
}
if (*z).TimeStamp == 0 {
- zb0003Len--
- zb0003Mask |= 0x200000
+ zb0004Len--
+ zb0004Mask |= 0x800000
}
if (*z).TxnRoot.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x400000
+ zb0004Len--
+ zb0004Mask |= 0x1000000
}
if (*z).UpgradeVote.UpgradeDelay.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x800000
+ zb0004Len--
+ zb0004Mask |= 0x2000000
}
if (*z).UpgradeVote.UpgradePropose.MsgIsZero() {
- zb0003Len--
- zb0003Mask |= 0x1000000
+ zb0004Len--
+ zb0004Mask |= 0x4000000
}
if (*z).UpgradeVote.UpgradeApprove == false {
- zb0003Len--
- zb0003Mask |= 0x2000000
+ zb0004Len--
+ zb0004Mask |= 0x8000000
}
- // variable map header, size zb0003Len
- o = msgp.AppendMapHeader(o, zb0003Len)
- if zb0003Len != 0 {
- if (zb0003Mask & 0x8) == 0 { // if not empty
+ // variable map header, size zb0004Len
+ o = msgp.AppendMapHeader(o, zb0004Len)
+ if zb0004Len != 0 {
+ if (zb0004Mask & 0x10) == 0 { // if not empty
// string "cc"
o = append(o, 0xa2, 0x63, 0x63)
if (*z).CompactCert == nil {
@@ -939,112 +1029,124 @@ func (z *BlockHeader) MarshalMsg(b []byte) (o []byte) {
o = zb0002.MarshalMsg(o)
}
}
- if (zb0003Mask & 0x10) == 0 { // if not empty
+ if (zb0004Mask & 0x20) == 0 { // if not empty
// string "earn"
o = append(o, 0xa4, 0x65, 0x61, 0x72, 0x6e)
o = msgp.AppendUint64(o, (*z).RewardsState.RewardsLevel)
}
- if (zb0003Mask & 0x20) == 0 { // if not empty
+ if (zb0004Mask & 0x40) == 0 { // if not empty
// string "fees"
o = append(o, 0xa4, 0x66, 0x65, 0x65, 0x73)
o = (*z).RewardsState.FeeSink.MarshalMsg(o)
}
- if (zb0003Mask & 0x40) == 0 { // if not empty
+ if (zb0004Mask & 0x80) == 0 { // if not empty
// string "frac"
o = append(o, 0xa4, 0x66, 0x72, 0x61, 0x63)
o = msgp.AppendUint64(o, (*z).RewardsState.RewardsResidue)
}
- if (zb0003Mask & 0x80) == 0 { // if not empty
+ if (zb0004Mask & 0x100) == 0 { // if not empty
// string "gen"
o = append(o, 0xa3, 0x67, 0x65, 0x6e)
o = msgp.AppendString(o, (*z).GenesisID)
}
- if (zb0003Mask & 0x100) == 0 { // if not empty
+ if (zb0004Mask & 0x200) == 0 { // if not empty
// string "gh"
o = append(o, 0xa2, 0x67, 0x68)
o = (*z).GenesisHash.MarshalMsg(o)
}
- if (zb0003Mask & 0x200) == 0 { // if not empty
+ if (zb0004Mask & 0x400) == 0 { // if not empty
// string "nextbefore"
o = append(o, 0xaa, 0x6e, 0x65, 0x78, 0x74, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65)
o = (*z).UpgradeState.NextProtocolVoteBefore.MarshalMsg(o)
}
- if (zb0003Mask & 0x400) == 0 { // if not empty
+ if (zb0004Mask & 0x800) == 0 { // if not empty
// string "nextproto"
o = append(o, 0xa9, 0x6e, 0x65, 0x78, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f)
o = (*z).UpgradeState.NextProtocol.MarshalMsg(o)
}
- if (zb0003Mask & 0x800) == 0 { // if not empty
+ if (zb0004Mask & 0x1000) == 0 { // if not empty
// string "nextswitch"
o = append(o, 0xaa, 0x6e, 0x65, 0x78, 0x74, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68)
o = (*z).UpgradeState.NextProtocolSwitchOn.MarshalMsg(o)
}
- if (zb0003Mask & 0x1000) == 0 { // if not empty
+ if (zb0004Mask & 0x2000) == 0 { // if not empty
// string "nextyes"
o = append(o, 0xa7, 0x6e, 0x65, 0x78, 0x74, 0x79, 0x65, 0x73)
o = msgp.AppendUint64(o, (*z).UpgradeState.NextProtocolApprovals)
}
- if (zb0003Mask & 0x2000) == 0 { // if not empty
+ if (zb0004Mask & 0x4000) == 0 { // if not empty
+ // string "partupdrmv"
+ o = append(o, 0xaa, 0x70, 0x61, 0x72, 0x74, 0x75, 0x70, 0x64, 0x72, 0x6d, 0x76)
+ if (*z).ParticipationUpdates.ExpiredParticipationAccounts == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).ParticipationUpdates.ExpiredParticipationAccounts)))
+ }
+ for zb0003 := range (*z).ParticipationUpdates.ExpiredParticipationAccounts {
+ o = (*z).ParticipationUpdates.ExpiredParticipationAccounts[zb0003].MarshalMsg(o)
+ }
+ }
+ if (zb0004Mask & 0x8000) == 0 { // if not empty
// string "prev"
o = append(o, 0xa4, 0x70, 0x72, 0x65, 0x76)
o = (*z).Branch.MarshalMsg(o)
}
- if (zb0003Mask & 0x4000) == 0 { // if not empty
+ if (zb0004Mask & 0x10000) == 0 { // if not empty
// string "proto"
o = append(o, 0xa5, 0x70, 0x72, 0x6f, 0x74, 0x6f)
o = (*z).UpgradeState.CurrentProtocol.MarshalMsg(o)
}
- if (zb0003Mask & 0x8000) == 0 { // if not empty
+ if (zb0004Mask & 0x20000) == 0 { // if not empty
// string "rate"
o = append(o, 0xa4, 0x72, 0x61, 0x74, 0x65)
o = msgp.AppendUint64(o, (*z).RewardsState.RewardsRate)
}
- if (zb0003Mask & 0x10000) == 0 { // if not empty
+ if (zb0004Mask & 0x40000) == 0 { // if not empty
// string "rnd"
o = append(o, 0xa3, 0x72, 0x6e, 0x64)
o = (*z).Round.MarshalMsg(o)
}
- if (zb0003Mask & 0x20000) == 0 { // if not empty
+ if (zb0004Mask & 0x80000) == 0 { // if not empty
// string "rwcalr"
o = append(o, 0xa6, 0x72, 0x77, 0x63, 0x61, 0x6c, 0x72)
o = (*z).RewardsState.RewardsRecalculationRound.MarshalMsg(o)
}
- if (zb0003Mask & 0x40000) == 0 { // if not empty
+ if (zb0004Mask & 0x100000) == 0 { // if not empty
// string "rwd"
o = append(o, 0xa3, 0x72, 0x77, 0x64)
o = (*z).RewardsState.RewardsPool.MarshalMsg(o)
}
- if (zb0003Mask & 0x80000) == 0 { // if not empty
+ if (zb0004Mask & 0x200000) == 0 { // if not empty
// string "seed"
o = append(o, 0xa4, 0x73, 0x65, 0x65, 0x64)
o = (*z).Seed.MarshalMsg(o)
}
- if (zb0003Mask & 0x100000) == 0 { // if not empty
+ if (zb0004Mask & 0x400000) == 0 { // if not empty
// string "tc"
o = append(o, 0xa2, 0x74, 0x63)
o = msgp.AppendUint64(o, (*z).TxnCounter)
}
- if (zb0003Mask & 0x200000) == 0 { // if not empty
+ if (zb0004Mask & 0x800000) == 0 { // if not empty
// string "ts"
o = append(o, 0xa2, 0x74, 0x73)
o = msgp.AppendInt64(o, (*z).TimeStamp)
}
- if (zb0003Mask & 0x400000) == 0 { // if not empty
+ if (zb0004Mask & 0x1000000) == 0 { // if not empty
// string "txn"
o = append(o, 0xa3, 0x74, 0x78, 0x6e)
o = (*z).TxnRoot.MarshalMsg(o)
}
- if (zb0003Mask & 0x800000) == 0 { // if not empty
+ if (zb0004Mask & 0x2000000) == 0 { // if not empty
// string "upgradedelay"
o = append(o, 0xac, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x64, 0x65, 0x6c, 0x61, 0x79)
o = (*z).UpgradeVote.UpgradeDelay.MarshalMsg(o)
}
- if (zb0003Mask & 0x1000000) == 0 { // if not empty
+ if (zb0004Mask & 0x4000000) == 0 { // if not empty
// string "upgradeprop"
o = append(o, 0xab, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x70, 0x72, 0x6f, 0x70)
o = (*z).UpgradeVote.UpgradePropose.MarshalMsg(o)
}
- if (zb0003Mask & 0x2000000) == 0 { // if not empty
+ if (zb0004Mask & 0x8000000) == 0 { // if not empty
// string "upgradeyes"
o = append(o, 0xaa, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x79, 0x65, 0x73)
o = msgp.AppendBool(o, (*z).UpgradeVote.UpgradeApprove)
@@ -1062,214 +1164,214 @@ func (_ *BlockHeader) CanMarshalMsg(z interface{}) bool {
func (z *BlockHeader) UnmarshalMsg(bts []byte) (o []byte, err error) {
var field []byte
_ = field
- var zb0003 int
- var zb0004 bool
- zb0003, zb0004, bts, err = msgp.ReadMapHeaderBytes(bts)
+ var zb0004 int
+ var zb0005 bool
+ zb0004, zb0005, bts, err = msgp.ReadMapHeaderBytes(bts)
if _, ok := err.(msgp.TypeError); ok {
- zb0003, zb0004, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ zb0004, zb0005, bts, err = msgp.ReadArrayHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err)
return
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Round.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Round")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Branch.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Branch")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).Seed.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "Seed")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).TxnRoot.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TxnRoot")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).TimeStamp, bts, err = msgp.ReadInt64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TimeStamp")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).GenesisID, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "GenesisID")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).GenesisHash.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "GenesisHash")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).RewardsState.FeeSink.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "FeeSink")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).RewardsState.RewardsPool.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsPool")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).RewardsState.RewardsLevel, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsLevel")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).RewardsState.RewardsRate, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsRate")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).RewardsState.RewardsResidue, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsResidue")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).RewardsState.RewardsRecalculationRound.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "RewardsRecalculationRound")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).UpgradeState.CurrentProtocol.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CurrentProtocol")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).UpgradeState.NextProtocol.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocol")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).UpgradeState.NextProtocolApprovals, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolApprovals")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).UpgradeState.NextProtocolVoteBefore.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolVoteBefore")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).UpgradeState.NextProtocolSwitchOn.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "NextProtocolSwitchOn")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).UpgradeVote.UpgradePropose.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradePropose")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
bts, err = (*z).UpgradeVote.UpgradeDelay.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradeDelay")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).UpgradeVote.UpgradeApprove, bts, err = msgp.ReadBoolBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "UpgradeApprove")
return
}
}
- if zb0003 > 0 {
- zb0003--
+ if zb0004 > 0 {
+ zb0004--
(*z).TxnCounter, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "TxnCounter")
return
}
}
- if zb0003 > 0 {
- zb0003--
- var zb0005 int
- var zb0006 bool
- zb0005, zb0006, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if zb0004 > 0 {
+ zb0004--
+ var zb0006 int
+ var zb0007 bool
+ zb0006, zb0007, bts, err = msgp.ReadMapHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
return
}
- if zb0005 > protocol.NumCompactCertTypes {
- err = msgp.ErrOverflow(uint64(zb0005), uint64(protocol.NumCompactCertTypes))
+ if zb0006 > protocol.NumCompactCertTypes {
+ err = msgp.ErrOverflow(uint64(zb0006), uint64(protocol.NumCompactCertTypes))
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
return
}
- if zb0006 {
+ if zb0007 {
(*z).CompactCert = nil
} else if (*z).CompactCert == nil {
- (*z).CompactCert = make(map[protocol.CompactCertType]CompactCertState, zb0005)
+ (*z).CompactCert = make(map[protocol.CompactCertType]CompactCertState, zb0006)
}
- for zb0005 > 0 {
+ for zb0006 > 0 {
var zb0001 protocol.CompactCertType
var zb0002 CompactCertState
- zb0005--
+ zb0006--
bts, err = zb0001.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "struct-from-array", "CompactCert")
@@ -1283,8 +1385,37 @@ func (z *BlockHeader) UnmarshalMsg(bts []byte) (o []byte, err error) {
(*z).CompactCert[zb0001] = zb0002
}
}
- if zb0003 > 0 {
- err = msgp.ErrTooManyArrayFields(zb0003)
+ if zb0004 > 0 {
+ zb0004--
+ var zb0008 int
+ var zb0009 bool
+ zb0008, zb0009, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0008 > config.MaxProposedExpiredOnlineAccounts {
+ err = msgp.ErrOverflow(uint64(zb0008), uint64(config.MaxProposedExpiredOnlineAccounts))
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0009 {
+ (*z).ParticipationUpdates.ExpiredParticipationAccounts = nil
+ } else if (*z).ParticipationUpdates.ExpiredParticipationAccounts != nil && cap((*z).ParticipationUpdates.ExpiredParticipationAccounts) >= zb0008 {
+ (*z).ParticipationUpdates.ExpiredParticipationAccounts = ((*z).ParticipationUpdates.ExpiredParticipationAccounts)[:zb0008]
+ } else {
+ (*z).ParticipationUpdates.ExpiredParticipationAccounts = make([]basics.Address, zb0008)
+ }
+ for zb0003 := range (*z).ParticipationUpdates.ExpiredParticipationAccounts {
+ bts, err = (*z).ParticipationUpdates.ExpiredParticipationAccounts[zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts", zb0003)
+ return
+ }
+ }
+ }
+ if zb0004 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0004)
if err != nil {
err = msgp.WrapError(err, "struct-from-array")
return
@@ -1295,11 +1426,11 @@ func (z *BlockHeader) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err)
return
}
- if zb0004 {
+ if zb0005 {
(*z) = BlockHeader{}
}
- for zb0003 > 0 {
- zb0003--
+ for zb0004 > 0 {
+ zb0004--
field, bts, err = msgp.ReadMapKeyZC(bts)
if err != nil {
err = msgp.WrapError(err)
@@ -1439,27 +1570,27 @@ func (z *BlockHeader) UnmarshalMsg(bts []byte) (o []byte, err error) {
return
}
case "cc":
- var zb0007 int
- var zb0008 bool
- zb0007, zb0008, bts, err = msgp.ReadMapHeaderBytes(bts)
+ var zb0010 int
+ var zb0011 bool
+ zb0010, zb0011, bts, err = msgp.ReadMapHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err, "CompactCert")
return
}
- if zb0007 > protocol.NumCompactCertTypes {
- err = msgp.ErrOverflow(uint64(zb0007), uint64(protocol.NumCompactCertTypes))
+ if zb0010 > protocol.NumCompactCertTypes {
+ err = msgp.ErrOverflow(uint64(zb0010), uint64(protocol.NumCompactCertTypes))
err = msgp.WrapError(err, "CompactCert")
return
}
- if zb0008 {
+ if zb0011 {
(*z).CompactCert = nil
} else if (*z).CompactCert == nil {
- (*z).CompactCert = make(map[protocol.CompactCertType]CompactCertState, zb0007)
+ (*z).CompactCert = make(map[protocol.CompactCertType]CompactCertState, zb0010)
}
- for zb0007 > 0 {
+ for zb0010 > 0 {
var zb0001 protocol.CompactCertType
var zb0002 CompactCertState
- zb0007--
+ zb0010--
bts, err = zb0001.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "CompactCert")
@@ -1472,6 +1603,33 @@ func (z *BlockHeader) UnmarshalMsg(bts []byte) (o []byte, err error) {
}
(*z).CompactCert[zb0001] = zb0002
}
+ case "partupdrmv":
+ var zb0012 int
+ var zb0013 bool
+ zb0012, zb0013, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0012 > config.MaxProposedExpiredOnlineAccounts {
+ err = msgp.ErrOverflow(uint64(zb0012), uint64(config.MaxProposedExpiredOnlineAccounts))
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0013 {
+ (*z).ParticipationUpdates.ExpiredParticipationAccounts = nil
+ } else if (*z).ParticipationUpdates.ExpiredParticipationAccounts != nil && cap((*z).ParticipationUpdates.ExpiredParticipationAccounts) >= zb0012 {
+ (*z).ParticipationUpdates.ExpiredParticipationAccounts = ((*z).ParticipationUpdates.ExpiredParticipationAccounts)[:zb0012]
+ } else {
+ (*z).ParticipationUpdates.ExpiredParticipationAccounts = make([]basics.Address, zb0012)
+ }
+ for zb0003 := range (*z).ParticipationUpdates.ExpiredParticipationAccounts {
+ bts, err = (*z).ParticipationUpdates.ExpiredParticipationAccounts[zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts", zb0003)
+ return
+ }
+ }
default:
err = msgp.ErrNoField(string(field))
if err != nil {
@@ -1500,12 +1658,16 @@ func (z *BlockHeader) Msgsize() (s int) {
s += 0 + zb0001.Msgsize() + zb0002.Msgsize()
}
}
+ s += 11 + msgp.ArrayHeaderSize
+ for zb0003 := range (*z).ParticipationUpdates.ExpiredParticipationAccounts {
+ s += (*z).ParticipationUpdates.ExpiredParticipationAccounts[zb0003].Msgsize()
+ }
return
}
// MsgIsZero returns whether this is a zero value
func (z *BlockHeader) MsgIsZero() bool {
- return ((*z).Round.MsgIsZero()) && ((*z).Branch.MsgIsZero()) && ((*z).Seed.MsgIsZero()) && ((*z).TxnRoot.MsgIsZero()) && ((*z).TimeStamp == 0) && ((*z).GenesisID == "") && ((*z).GenesisHash.MsgIsZero()) && ((*z).RewardsState.FeeSink.MsgIsZero()) && ((*z).RewardsState.RewardsPool.MsgIsZero()) && ((*z).RewardsState.RewardsLevel == 0) && ((*z).RewardsState.RewardsRate == 0) && ((*z).RewardsState.RewardsResidue == 0) && ((*z).RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).UpgradeState.NextProtocol.MsgIsZero()) && ((*z).UpgradeState.NextProtocolApprovals == 0) && ((*z).UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).UpgradeVote.UpgradeApprove == false) && ((*z).TxnCounter == 0) && (len((*z).CompactCert) == 0)
+ return ((*z).Round.MsgIsZero()) && ((*z).Branch.MsgIsZero()) && ((*z).Seed.MsgIsZero()) && ((*z).TxnRoot.MsgIsZero()) && ((*z).TimeStamp == 0) && ((*z).GenesisID == "") && ((*z).GenesisHash.MsgIsZero()) && ((*z).RewardsState.FeeSink.MsgIsZero()) && ((*z).RewardsState.RewardsPool.MsgIsZero()) && ((*z).RewardsState.RewardsLevel == 0) && ((*z).RewardsState.RewardsRate == 0) && ((*z).RewardsState.RewardsResidue == 0) && ((*z).RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).UpgradeState.NextProtocol.MsgIsZero()) && ((*z).UpgradeState.NextProtocolApprovals == 0) && ((*z).UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).UpgradeVote.UpgradeApprove == false) && ((*z).TxnCounter == 0) && (len((*z).CompactCert) == 0) && (len((*z).ParticipationUpdates.ExpiredParticipationAccounts) == 0)
}
// MarshalMsg implements msgp.Marshaler
@@ -2132,6 +2294,164 @@ func (z *GenesisAllocation) MsgIsZero() bool {
}
// MarshalMsg implements msgp.Marshaler
+func (z *ParticipationUpdates) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0002Len := uint32(1)
+ var zb0002Mask uint8 /* 2 bits */
+ if len((*z).ExpiredParticipationAccounts) == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x2
+ }
+ // variable map header, size zb0002Len
+ o = append(o, 0x80|uint8(zb0002Len))
+ if zb0002Len != 0 {
+ if (zb0002Mask & 0x2) == 0 { // if not empty
+ // string "partupdrmv"
+ o = append(o, 0xaa, 0x70, 0x61, 0x72, 0x74, 0x75, 0x70, 0x64, 0x72, 0x6d, 0x76)
+ if (*z).ExpiredParticipationAccounts == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).ExpiredParticipationAccounts)))
+ }
+ for zb0001 := range (*z).ExpiredParticipationAccounts {
+ o = (*z).ExpiredParticipationAccounts[zb0001].MarshalMsg(o)
+ }
+ }
+ }
+ return
+}
+
+func (_ *ParticipationUpdates) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*ParticipationUpdates)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *ParticipationUpdates) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0002 int
+ var zb0003 bool
+ zb0002, zb0003, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0002, zb0003, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 > 0 {
+ zb0002--
+ var zb0004 int
+ var zb0005 bool
+ zb0004, zb0005, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0004 > config.MaxProposedExpiredOnlineAccounts {
+ err = msgp.ErrOverflow(uint64(zb0004), uint64(config.MaxProposedExpiredOnlineAccounts))
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0005 {
+ (*z).ExpiredParticipationAccounts = nil
+ } else if (*z).ExpiredParticipationAccounts != nil && cap((*z).ExpiredParticipationAccounts) >= zb0004 {
+ (*z).ExpiredParticipationAccounts = ((*z).ExpiredParticipationAccounts)[:zb0004]
+ } else {
+ (*z).ExpiredParticipationAccounts = make([]basics.Address, zb0004)
+ }
+ for zb0001 := range (*z).ExpiredParticipationAccounts {
+ bts, err = (*z).ExpiredParticipationAccounts[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExpiredParticipationAccounts", zb0001)
+ return
+ }
+ }
+ }
+ if zb0002 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0002)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0003 {
+ (*z) = ParticipationUpdates{}
+ }
+ for zb0002 > 0 {
+ zb0002--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "partupdrmv":
+ var zb0006 int
+ var zb0007 bool
+ zb0006, zb0007, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0006 > config.MaxProposedExpiredOnlineAccounts {
+ err = msgp.ErrOverflow(uint64(zb0006), uint64(config.MaxProposedExpiredOnlineAccounts))
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts")
+ return
+ }
+ if zb0007 {
+ (*z).ExpiredParticipationAccounts = nil
+ } else if (*z).ExpiredParticipationAccounts != nil && cap((*z).ExpiredParticipationAccounts) >= zb0006 {
+ (*z).ExpiredParticipationAccounts = ((*z).ExpiredParticipationAccounts)[:zb0006]
+ } else {
+ (*z).ExpiredParticipationAccounts = make([]basics.Address, zb0006)
+ }
+ for zb0001 := range (*z).ExpiredParticipationAccounts {
+ bts, err = (*z).ExpiredParticipationAccounts[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExpiredParticipationAccounts", zb0001)
+ return
+ }
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *ParticipationUpdates) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*ParticipationUpdates)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *ParticipationUpdates) Msgsize() (s int) {
+ s = 1 + 11 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).ExpiredParticipationAccounts {
+ s += (*z).ExpiredParticipationAccounts[zb0001].Msgsize()
+ }
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *ParticipationUpdates) MsgIsZero() bool {
+ return (len((*z).ExpiredParticipationAccounts) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
func (z *RewardsState) MarshalMsg(b []byte) (o []byte) {
o = msgp.Require(b, z.Msgsize())
// omitempty: check for empty values
diff --git a/data/bookkeeping/msgp_gen_test.go b/data/bookkeeping/msgp_gen_test.go
index 44ff62e2d..8bad96593 100644
--- a/data/bookkeeping/msgp_gen_test.go
+++ b/data/bookkeeping/msgp_gen_test.go
@@ -312,6 +312,66 @@ func BenchmarkUnmarshalGenesisAllocation(b *testing.B) {
}
}
+func TestMarshalUnmarshalParticipationUpdates(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := ParticipationUpdates{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingParticipationUpdates(t *testing.T) {
+ protocol.RunEncodingTest(t, &ParticipationUpdates{})
+}
+
+func BenchmarkMarshalMsgParticipationUpdates(b *testing.B) {
+ v := ParticipationUpdates{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgParticipationUpdates(b *testing.B) {
+ v := ParticipationUpdates{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalParticipationUpdates(b *testing.B) {
+ v := ParticipationUpdates{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
func TestMarshalUnmarshalRewardsState(t *testing.T) {
partitiontest.PartitionTest(t)
v := RewardsState{}
diff --git a/data/pooldata/msgp_gen.go b/data/pooldata/msgp_gen.go
new file mode 100644
index 000000000..02a11cfa2
--- /dev/null
+++ b/data/pooldata/msgp_gen.go
@@ -0,0 +1,91 @@
+package pooldata
+
+// Code generated by github.com/algorand/msgp DO NOT EDIT.
+
+import (
+ "github.com/algorand/go-algorand/config"
+ "github.com/algorand/msgp/msgp"
+)
+
+// The following msgp objects are implemented in this file:
+// SignedTxnSlice
+// |-----> MarshalMsg
+// |-----> CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> Msgsize
+// |-----> MsgIsZero
+//
+
+// MarshalMsg implements msgp.Marshaler
+func (z SignedTxnSlice) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ if z == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len(z)))
+ }
+ for za0001 := range z {
+ o = z[za0001].MarshalMsg(o)
+ }
+ return
+}
+
+func (_ SignedTxnSlice) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(SignedTxnSlice)
+ if !ok {
+ _, ok = (z).(*SignedTxnSlice)
+ }
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *SignedTxnSlice) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var zb0002 int
+ var zb0003 bool
+ zb0002, zb0003, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 > config.MaxTxGroupSize {
+ err = msgp.ErrOverflow(uint64(zb0002), uint64(config.MaxTxGroupSize))
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0003 {
+ (*z) = nil
+ } else if (*z) != nil && cap((*z)) >= zb0002 {
+ (*z) = (*z)[:zb0002]
+ } else {
+ (*z) = make(SignedTxnSlice, zb0002)
+ }
+ for zb0001 := range *z {
+ bts, err = (*z)[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, zb0001)
+ return
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *SignedTxnSlice) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*SignedTxnSlice)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z SignedTxnSlice) Msgsize() (s int) {
+ s = msgp.ArrayHeaderSize
+ for za0001 := range z {
+ s += z[za0001].Msgsize()
+ }
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z SignedTxnSlice) MsgIsZero() bool {
+ return len(z) == 0
+}
diff --git a/data/pooldata/msgp_gen_test.go b/data/pooldata/msgp_gen_test.go
new file mode 100644
index 000000000..68ed008d0
--- /dev/null
+++ b/data/pooldata/msgp_gen_test.go
@@ -0,0 +1,73 @@
+// +build !skip_msgp_testing
+
+package pooldata
+
+// Code generated by github.com/algorand/msgp DO NOT EDIT.
+
+import (
+ "testing"
+
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/algorand/msgp/msgp"
+)
+
+func TestMarshalUnmarshalSignedTxnSlice(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := SignedTxnSlice{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingSignedTxnSlice(t *testing.T) {
+ protocol.RunEncodingTest(t, &SignedTxnSlice{})
+}
+
+func BenchmarkMarshalMsgSignedTxnSlice(b *testing.B) {
+ v := SignedTxnSlice{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgSignedTxnSlice(b *testing.B) {
+ v := SignedTxnSlice{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalSignedTxnSlice(b *testing.B) {
+ v := SignedTxnSlice{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
diff --git a/data/pooldata/signedTxGroup.go b/data/pooldata/signedTxGroup.go
new file mode 100644
index 000000000..fe4e1e24f
--- /dev/null
+++ b/data/pooldata/signedTxGroup.go
@@ -0,0 +1,63 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package pooldata
+
+import (
+ "math"
+
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/protocol"
+)
+
+// SignedTxGroup used as the in-memory representation of a signed transaction group.
+// unlike the plain array of signed transactions, this includes transaction origination and counter
+// used by the transaction pool and the transaction sync
+//msgp:ignore SignedTxGroup
+type SignedTxGroup struct {
+ // Transactions contains the signed transactions that are included in this transaction group.
+ Transactions SignedTxnSlice
+ // LocallyOriginated specify whether the trancation group was inroduced via the REST API or
+ // by the transaction sync.
+ LocallyOriginated bool
+ // GroupCounter is a monotonic increasing counter, that provides an identify for each transaction group.
+ // The transaction sync is using it as a way to scan the transactions group list more efficiently, as it
+ // can continue scanning the list from the place where it last stopped.
+ // GroupCounter is local, assigned when the group is first seen by the local transaction pool.
+ GroupCounter uint64
+ // GroupTransactionID is the hash of the entire transaction group.
+ GroupTransactionID transactions.Txid
+ // EncodedLength is the length, in bytes, of the messagepack encoding of all the transaction
+ // within this transaction group.
+ EncodedLength int
+}
+
+// SignedTxnSlice is a slice of SignedTxn(s), allowing us to
+// easily define the ID() function.
+//msgp:allocbound SignedTxnSlice config.MaxTxGroupSize
+type SignedTxnSlice []transactions.SignedTxn
+
+// ID calculate the hash of the signed transaction group.
+func (s SignedTxnSlice) ID() transactions.Txid {
+ enc := s.MarshalMsg(append(protocol.GetEncodingBuf(), []byte(protocol.TxGroup)...))
+ defer protocol.PutEncodingBuf(enc)
+ return transactions.Txid(crypto.Hash(enc))
+}
+
+// InvalidSignedTxGroupCounter is used to represent an invalid GroupCounter value. It's being used to indicate
+// the absence of an entry within a []SignedTxGroup with a particular GroupCounter value.
+const InvalidSignedTxGroupCounter = uint64(math.MaxUint64)
diff --git a/data/pools/transactionPool.go b/data/pools/transactionPool.go
index b4d1044b0..9477a380d 100644
--- a/data/pools/transactionPool.go
+++ b/data/pools/transactionPool.go
@@ -28,6 +28,7 @@ import (
"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
+ "github.com/algorand/go-algorand/data/pooldata"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/ledger"
"github.com/algorand/go-algorand/ledger/ledgercore"
@@ -53,6 +54,11 @@ type TransactionPool struct {
// with atomic operations which require 64 bit alignment on arm.
feePerByte uint64
+ // latestMeasuredDataExchangeRate is the average data exchange rate, as measured by the transaction sync.
+ // we use the latestMeasuredDataExchangeRate in order to determine the desired proposal size, so that it
+ // won't create undesired network bottlenecks.
+ latestMeasuredDataExchangeRate uint64
+
// const
logProcessBlockStats bool
logAssembleStats bool
@@ -75,18 +81,29 @@ type TransactionPool struct {
assemblyRound basics.Round
assemblyResults poolAsmResults
- // pendingMu protects pendingTxGroups and pendingTxids
- pendingMu deadlock.RWMutex
- pendingTxGroups [][]transactions.SignedTxn
- pendingTxids map[transactions.Txid]transactions.SignedTxn
+ // pendingMu protects pendingTxGroups, pendingTxids, pendingCounter and pendingLatestLocal
+ pendingMu deadlock.RWMutex
+ // pendingTxGroups is a slice of the pending transaction groups.
+ pendingTxGroups []pooldata.SignedTxGroup
+ // pendingTxids is a map of the pending *transaction ids* included in the pendingTxGroups array.
+ pendingTxids map[transactions.Txid]transactions.SignedTxn
+ // pendingCounter is a monotomic counter, indicating the next pending transaction group counter value.
+ pendingCounter uint64
+ // pendingLatestLocal is the value of the last transaction group counter which is associated with a transaction that was
+ // locally originated ( i.e. posted to this node via the REST API )
+ pendingLatestLocal uint64
// Calls to remember() add transactions to rememberedTxGroups and
// rememberedTxids. Calling rememberCommit() adds them to the
// pendingTxGroups and pendingTxids. This allows us to batch the
// changes in OnNewBlock() without preventing a concurrent call
- // to PendingTxGroups() or Verified().
- rememberedTxGroups [][]transactions.SignedTxn
+ // to PendingTxGroups().
+ rememberedTxGroups []pooldata.SignedTxGroup
rememberedTxids map[transactions.Txid]transactions.SignedTxn
+ // rememberedLatestLocal is the value of the last transaction group counter which is associated with a transaction that was
+ // locally originated ( i.e. posted to this node via the REST API ). This variable is used when OnNewBlock is called and
+ // we filter out the pending transaction through the evaluator.
+ rememberedLatestLocal uint64
log logging.Logger
}
@@ -147,6 +164,14 @@ const (
// duration it would take to execute the GenerateBlock() function
generateBlockBaseDuration = 2 * time.Millisecond
generateBlockTransactionDuration = 2155 * time.Nanosecond
+
+ // minMaxTxnBytesPerBlock is the minimal maximum block size that the evaluator would be asked to create, in case
+ // the local node doesn't have sufficient bandwidth to support higher throughputs.
+ // for example: a node that has a very low bandwidth of 10KB/s. If we will follow the block size calculations, we
+ // would get to an unrealistic block size of 20KB. This could be due to a temporary network bandwidth fluctuations
+ // or other measuring issue. In order to ensure we have some more realistic block sizes to
+ // work with, we clamp the block size to the range of [minMaxTxnBytesPerBlock .. proto.MaxTxnBytesPerBlock].
+ minMaxTxnBytesPerBlock = 100 * 1024
)
// ErrStaleBlockAssemblyRequest returned by AssembleBlock when requested block number is older than the current transaction pool round
@@ -157,6 +182,7 @@ var ErrStaleBlockAssemblyRequest = fmt.Errorf("AssembleBlock: requested block as
func (pool *TransactionPool) Reset() {
pool.pendingTxids = make(map[transactions.Txid]transactions.SignedTxn)
pool.pendingTxGroups = nil
+ pool.pendingLatestLocal = pooldata.InvalidSignedTxGroupCounter
pool.rememberedTxids = make(map[transactions.Txid]transactions.SignedTxn)
pool.rememberedTxGroups = nil
pool.expiredTxCount = make(map[basics.Round]int)
@@ -190,14 +216,15 @@ func (pool *TransactionPool) PendingTxIDs() []transactions.Txid {
}
// PendingTxGroups returns a list of transaction groups that should be proposed
-// in the next block, in order.
-func (pool *TransactionPool) PendingTxGroups() [][]transactions.SignedTxn {
+// in the next block, in order. As the second return value, it returns the transaction
+// group counter of the latest local generated transaction group.
+func (pool *TransactionPool) PendingTxGroups() ([]pooldata.SignedTxGroup, uint64) {
pool.pendingMu.RLock()
defer pool.pendingMu.RUnlock()
// note that this operation is safe for the sole reason that arrays in go are immutable.
// if the underlaying array need to be expanded, the actual underlaying array would need
// to be reallocated.
- return pool.pendingTxGroups
+ return pool.pendingTxGroups, pool.pendingLatestLocal
}
// pendingTxIDsCount returns the number of pending transaction ids that are still waiting
@@ -221,8 +248,26 @@ func (pool *TransactionPool) rememberCommit(flush bool) {
if flush {
pool.pendingTxGroups = pool.rememberedTxGroups
pool.pendingTxids = pool.rememberedTxids
+ pool.pendingLatestLocal = pool.rememberedLatestLocal
pool.ledger.VerifiedTransactionCache().UpdatePinned(pool.pendingTxids)
} else {
+ // update the GroupCounter on all the transaction groups we're going to add.
+ // this would ensure that each transaction group has a unique monotonic GroupCounter
+ encodingBuf := protocol.GetEncodingBuf()
+ for i, txGroup := range pool.rememberedTxGroups {
+ pool.pendingCounter++
+ txGroup.GroupCounter = pool.pendingCounter
+ txGroup.EncodedLength = 0
+ for _, txn := range txGroup.Transactions {
+ encodingBuf = encodingBuf[:0]
+ txGroup.EncodedLength += len(txn.MarshalMsg(encodingBuf))
+ }
+ pool.rememberedTxGroups[i] = txGroup
+ if txGroup.LocallyOriginated {
+ pool.pendingLatestLocal = txGroup.GroupCounter
+ }
+ }
+ protocol.PutEncodingBuf(encodingBuf)
pool.pendingTxGroups = append(pool.pendingTxGroups, pool.rememberedTxGroups...)
for txid, txn := range pool.rememberedTxids {
@@ -230,8 +275,15 @@ func (pool *TransactionPool) rememberCommit(flush bool) {
}
}
+ pool.resetRememberedTransactionGroups()
+}
+
+// resetRememberedTransactionGroups clears the remembered transaction groups.
+// The caller is assumed to be holding pool.mu.
+func (pool *TransactionPool) resetRememberedTransactionGroups() {
pool.rememberedTxGroups = nil
pool.rememberedTxids = make(map[transactions.Txid]transactions.SignedTxn)
+ pool.rememberedLatestLocal = pooldata.InvalidSignedTxGroupCounter
}
// PendingCount returns the number of transactions currently pending in the pool.
@@ -246,7 +298,7 @@ func (pool *TransactionPool) PendingCount() int {
func (pool *TransactionPool) pendingCountNoLock() int {
var count int
for _, txgroup := range pool.pendingTxGroups {
- count += len(txgroup)
+ count += len(txgroup.Transactions)
}
return count
}
@@ -310,12 +362,12 @@ func (pool *TransactionPool) computeFeePerByte() uint64 {
// checkSufficientFee take a set of signed transactions and verifies that each transaction has
// sufficient fee to get into the transaction pool
-func (pool *TransactionPool) checkSufficientFee(txgroup []transactions.SignedTxn) error {
+func (pool *TransactionPool) checkSufficientFee(txgroup pooldata.SignedTxGroup) error {
// Special case: the compact cert transaction, if issued from the
// special compact-cert-sender address, in a singleton group, pays
// no fee.
- if len(txgroup) == 1 {
- t := txgroup[0].Txn
+ if len(txgroup.Transactions) == 1 {
+ t := txgroup.Transactions[0].Txn
if t.Type == protocol.CompactCertTx && t.Sender == transactions.CompactCertSender && t.Fee.IsZero() {
return nil
}
@@ -324,7 +376,7 @@ func (pool *TransactionPool) checkSufficientFee(txgroup []transactions.SignedTxn
// get the current fee per byte
feePerByte := pool.computeFeePerByte()
- for _, t := range txgroup {
+ for _, t := range txgroup.Transactions {
feeThreshold := feePerByte * uint64(t.GetEncodedLength())
if t.Txn.Fee.Raw < feeThreshold {
return fmt.Errorf("fee %d below threshold %d (%d per byte * %d bytes)",
@@ -358,7 +410,7 @@ type poolIngestParams struct {
}
// remember attempts to add a transaction group to the pool.
-func (pool *TransactionPool) remember(txgroup []transactions.SignedTxn) error {
+func (pool *TransactionPool) remember(txgroup pooldata.SignedTxGroup) error {
params := poolIngestParams{
recomputing: false,
}
@@ -367,7 +419,7 @@ func (pool *TransactionPool) remember(txgroup []transactions.SignedTxn) error {
// add tries to add the transaction group to the pool, bypassing the fee
// priority checks.
-func (pool *TransactionPool) add(txgroup []transactions.SignedTxn, stats *telemetryspec.AssembleBlockMetrics) error {
+func (pool *TransactionPool) add(txgroup pooldata.SignedTxGroup, stats *telemetryspec.AssembleBlockMetrics) error {
params := poolIngestParams{
recomputing: true,
stats: stats,
@@ -380,7 +432,7 @@ func (pool *TransactionPool) add(txgroup []transactions.SignedTxn, stats *teleme
//
// ingest assumes that pool.mu is locked. It might release the lock
// while it waits for OnNewBlock() to be called.
-func (pool *TransactionPool) ingest(txgroup []transactions.SignedTxn, params poolIngestParams) error {
+func (pool *TransactionPool) ingest(txgroup pooldata.SignedTxGroup, params poolIngestParams) error {
if pool.pendingBlockEvaluator == nil {
return fmt.Errorf("TransactionPool.ingest: no pending block evaluator")
}
@@ -402,6 +454,10 @@ func (pool *TransactionPool) ingest(txgroup []transactions.SignedTxn, params poo
if err != nil {
return err
}
+
+ // since this is the first time the transaction was added to the transaction pool, it would
+ // be a good time now to figure the group's ID.
+ txgroup.GroupTransactionID = txgroup.Transactions.ID()
}
err := pool.addToPendingBlockEvaluator(txgroup, params.recomputing, params.stats)
@@ -410,22 +466,19 @@ func (pool *TransactionPool) ingest(txgroup []transactions.SignedTxn, params poo
}
pool.rememberedTxGroups = append(pool.rememberedTxGroups, txgroup)
- for _, t := range txgroup {
+ for _, t := range txgroup.Transactions {
pool.rememberedTxids[t.ID()] = t
}
- return nil
-}
-// RememberOne stores the provided transaction.
-// Precondition: Only RememberOne() properly-signed and well-formed transactions (i.e., ensure t.WellFormed())
-func (pool *TransactionPool) RememberOne(t transactions.SignedTxn) error {
- return pool.Remember([]transactions.SignedTxn{t})
+ return nil
}
// Remember stores the provided transaction group.
// Precondition: Only Remember() properly-signed and well-formed transactions (i.e., ensure t.WellFormed())
-func (pool *TransactionPool) Remember(txgroup []transactions.SignedTxn) error {
- if err := pool.checkPendingQueueSize(len(txgroup)); err != nil {
+// The function is called by the transaction handler ( i.e. txsync or gossip ) or by the node when
+// transaction is coming from a REST API call.
+func (pool *TransactionPool) Remember(txgroup pooldata.SignedTxGroup) error {
+ if err := pool.checkPendingQueueSize(len(txgroup.Transactions)); err != nil {
return err
}
@@ -441,6 +494,34 @@ func (pool *TransactionPool) Remember(txgroup []transactions.SignedTxn) error {
return nil
}
+// RememberArray stores the provided transaction group.
+// Precondition: Only RememberArray() properly-signed and well-formed transactions (i.e., ensure t.WellFormed())
+// The function is called by the transaction handler ( i.e. txsync )
+func (pool *TransactionPool) RememberArray(txgroups []pooldata.SignedTxGroup) error {
+ totalSize := 0
+ for _, txGroup := range txgroups {
+ totalSize += len(txGroup.Transactions)
+ }
+ if err := pool.checkPendingQueueSize(totalSize); err != nil {
+ return err
+ }
+
+ pool.mu.Lock()
+ defer pool.mu.Unlock()
+
+ for _, txGroup := range txgroups {
+ err := pool.remember(txGroup)
+ if err != nil {
+ // we need to explicitly clear the remembered transaction groups here, since we might have added the first one successfully and then failing on the second one.
+ pool.resetRememberedTransactionGroups()
+ return fmt.Errorf("TransactionPool.RememberArray: %w", err)
+ }
+ }
+
+ pool.rememberCommit(false)
+ return nil
+}
+
// Lookup returns the error associated with a transaction that used
// to be in the pool. If no status information is available (e.g., because
// it was too long ago, or the transaction committed successfully), then
@@ -544,9 +625,9 @@ func (pool *TransactionPool) isAssemblyTimedOut() bool {
return time.Now().After(pool.assemblyDeadline.Add(-generateBlockDuration))
}
-func (pool *TransactionPool) addToPendingBlockEvaluatorOnce(txgroup []transactions.SignedTxn, recomputing bool, stats *telemetryspec.AssembleBlockMetrics) error {
+func (pool *TransactionPool) addToPendingBlockEvaluatorOnce(txgroup pooldata.SignedTxGroup, recomputing bool, stats *telemetryspec.AssembleBlockMetrics) error {
r := pool.pendingBlockEvaluator.Round() + pool.numPendingWholeBlocks
- for _, tx := range txgroup {
+ for _, tx := range txgroup.Transactions {
if tx.Txn.LastValid < r {
return transactions.TxnDeadError{
Round: r,
@@ -556,7 +637,7 @@ func (pool *TransactionPool) addToPendingBlockEvaluatorOnce(txgroup []transactio
}
}
- txgroupad := transactions.WrapSignedTxnsWithAD(txgroup)
+ txgroupad := transactions.WrapSignedTxnsWithAD(txgroup.Transactions)
transactionGroupStartsTime := time.Time{}
if recomputing {
@@ -609,7 +690,7 @@ func (pool *TransactionPool) addToPendingBlockEvaluatorOnce(txgroup []transactio
return err
}
-func (pool *TransactionPool) addToPendingBlockEvaluator(txgroup []transactions.SignedTxn, recomputing bool, stats *telemetryspec.AssembleBlockMetrics) error {
+func (pool *TransactionPool) addToPendingBlockEvaluator(txgroup pooldata.SignedTxGroup, recomputing bool, stats *telemetryspec.AssembleBlockMetrics) error {
err := pool.addToPendingBlockEvaluatorOnce(txgroup, recomputing, stats)
if err == ledger.ErrNoSpace {
pool.numPendingWholeBlocks++
@@ -666,7 +747,7 @@ func (pool *TransactionPool) recomputeBlockEvaluator(committedTxIds map[transact
if hint < 0 || int(knownCommitted) < 0 {
hint = 0
}
- pool.pendingBlockEvaluator, err = pool.ledger.StartEvaluator(next.BlockHeader, hint)
+ pool.pendingBlockEvaluator, err = pool.ledger.StartEvaluator(next.BlockHeader, hint, pool.calculateMaxTxnBytesPerBlock(next.BlockHeader.CurrentProtocol))
if err != nil {
var nonSeqBlockEval ledgercore.ErrNonSequentialBlockEval
if errors.As(err, &nonSeqBlockEval) {
@@ -687,17 +768,17 @@ func (pool *TransactionPool) recomputeBlockEvaluator(committedTxIds map[transact
// Feed the transactions in order
for _, txgroup := range txgroups {
- if len(txgroup) == 0 {
+ if len(txgroup.Transactions) == 0 {
asmStats.InvalidCount++
continue
}
- if _, alreadyCommitted := committedTxIds[txgroup[0].ID()]; alreadyCommitted {
+ if _, alreadyCommitted := committedTxIds[txgroup.Transactions[0].ID()]; alreadyCommitted {
asmStats.EarlyCommittedCount++
continue
}
err := pool.add(txgroup, &asmStats)
if err != nil {
- for _, tx := range txgroup {
+ for _, tx := range txgroup.Transactions {
pool.statusCache.put(tx, err.Error())
}
@@ -717,6 +798,8 @@ func (pool *TransactionPool) recomputeBlockEvaluator(committedTxIds map[transact
stats.RemovedInvalidCount++
pool.log.Warnf("Cannot re-add pending transaction to pool: %v", err)
}
+ } else if txgroup.LocallyOriginated {
+ pool.rememberedLatestLocal = txgroup.GroupCounter
}
}
@@ -900,7 +983,7 @@ func (pool *TransactionPool) assembleEmptyBlock(round basics.Round) (assembled *
return nil, err
}
next := bookkeeping.MakeBlock(prev)
- blockEval, err := pool.ledger.StartEvaluator(next.BlockHeader, 0)
+ blockEval, err := pool.ledger.StartEvaluator(next.BlockHeader, 0, pool.calculateMaxTxnBytesPerBlock(next.BlockHeader.CurrentProtocol))
if err != nil {
var nonSeqBlockEval ledgercore.ErrNonSequentialBlockEval
if errors.As(err, &nonSeqBlockEval) {
@@ -916,6 +999,46 @@ func (pool *TransactionPool) assembleEmptyBlock(round basics.Round) (assembled *
return blockEval.GenerateBlock()
}
+// SetDataExchangeRate updates the data exchange rate this node is expected to have.
+func (pool *TransactionPool) SetDataExchangeRate(dataExchangeRate uint64) {
+ atomic.StoreUint64(&pool.latestMeasuredDataExchangeRate, dataExchangeRate)
+}
+
+// calculateMaxTxnBytesPerBlock computes the optimal block size for the current node, based
+// on it's effective network capabilities. This number is bound by the protocol MaxTxnBytesPerBlock.
+func (pool *TransactionPool) calculateMaxTxnBytesPerBlock(consensusVersion protocol.ConsensusVersion) int {
+ // get the latest data exchange rate we received from the transaction sync.
+ dataExchangeRate := atomic.LoadUint64(&pool.latestMeasuredDataExchangeRate)
+
+ // if we never received an update from the transaction sync connector about the data exchange rate,
+ // just let the evaluator use the consensus's default value.
+ if dataExchangeRate == 0 {
+ return 0
+ }
+
+ // get the consensus parameters for the given consensus version.
+ proto, ok := config.Consensus[consensusVersion]
+ if !ok {
+ // if we can't figure out the consensus version, just return 0.
+ return 0
+ }
+
+ // calculate the amount of data we can send in half of the agreement period.
+ halfMaxBlockSize := int(time.Duration(dataExchangeRate)*proto.AgreementFilterTimeoutPeriod0/time.Second) / 2
+
+ // if the amount of data is too high, bound it by the consensus parameters.
+ if halfMaxBlockSize > proto.MaxTxnBytesPerBlock {
+ return proto.MaxTxnBytesPerBlock
+ }
+
+ // if the amount of data is too low, use the low transaction bytes threshold.
+ if halfMaxBlockSize < minMaxTxnBytesPerBlock {
+ return minMaxTxnBytesPerBlock
+ }
+
+ return halfMaxBlockSize
+}
+
// AssembleDevModeBlock assemble a new block from the existing transaction pool. The pending evaluator is being
func (pool *TransactionPool) AssembleDevModeBlock() (assembled *ledger.ValidatedBlock, err error) {
pool.mu.Lock()
diff --git a/data/pools/transactionPool_test.go b/data/pools/transactionPool_test.go
index 59d81e888..f9ddb4b00 100644
--- a/data/pools/transactionPool_test.go
+++ b/data/pools/transactionPool_test.go
@@ -29,6 +29,7 @@ import (
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
+ "github.com/algorand/go-algorand/data/pooldata"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/data/transactions/logic"
"github.com/algorand/go-algorand/ledger"
@@ -55,6 +56,15 @@ type TestingT interface {
var minBalance = config.Consensus[protocol.ConsensusCurrentVersion].MinBalance
+// RememberOne stores the provided transaction.
+// Precondition: Only RememberOne() properly-signed and well-formed transactions (i.e., ensure t.WellFormed())
+func (pool *TransactionPool) RememberOne(t transactions.SignedTxn) error {
+ txgroup := pooldata.SignedTxGroup{
+ Transactions: []transactions.SignedTxn{t},
+ }
+ return pool.Remember(txgroup)
+}
+
func mockLedger(t TestingT, initAccounts map[basics.Address]basics.AccountData, proto protocol.ConsensusVersion) *ledger.Ledger {
var hash crypto.Digest
crypto.RandBytes(hash[:])
@@ -87,7 +97,7 @@ func mockLedger(t TestingT, initAccounts map[basics.Address]basics.AccountData,
const inMem = true
genesisInitState := ledger.InitState{Block: initBlock, Accounts: initAccounts, GenesisHash: hash}
cfg := config.GetDefaultLocal()
- cfg.Archival = true
+ cfg.Archival = false
l, err := ledger.OpenLedger(logging.Base(), fn, true, genesisInitState, cfg)
require.NoError(t, err)
return l
@@ -107,7 +117,7 @@ func newBlockEvaluator(t TestingT, l *ledger.Ledger) *ledger.BlockEvaluator {
require.NoError(t, err)
next := bookkeeping.MakeBlock(prev)
- eval, err := l.StartEvaluator(next.BlockHeader, 0)
+ eval, err := l.StartEvaluator(next.BlockHeader, 0, 0)
require.NoError(t, err)
return eval
@@ -558,7 +568,7 @@ func TestRememberForget(t *testing.T) {
}
}
- pending := transactionPool.PendingTxGroups()
+ pending, _ := transactionPool.PendingTxGroups()
numberOfTxns := numOfAccounts*numOfAccounts - numOfAccounts
require.Len(t, pending, numberOfTxns)
@@ -569,7 +579,7 @@ func TestRememberForget(t *testing.T) {
require.NoError(t, err)
transactionPool.OnNewBlock(blk.Block(), ledgercore.StateDelta{})
- pending = transactionPool.PendingTxGroups()
+ pending, _ = transactionPool.PendingTxGroups()
require.Len(t, pending, 0)
}
@@ -634,7 +644,7 @@ func TestCleanUp(t *testing.T) {
transactionPool.OnNewBlock(blk.Block(), ledgercore.StateDelta{})
}
- pending := transactionPool.PendingTxGroups()
+ pending, _ := transactionPool.PendingTxGroups()
require.Zero(t, len(pending))
require.Zero(t, transactionPool.NumExpired(4))
require.Equal(t, issuedTransactions, transactionPool.NumExpired(5))
@@ -708,7 +718,7 @@ func TestFixOverflowOnNewBlock(t *testing.T) {
}
}
}
- pending := transactionPool.PendingTxGroups()
+ pending, _ := transactionPool.PendingTxGroups()
require.Len(t, pending, savedTransactions)
secret := keypair()
@@ -744,7 +754,7 @@ func TestFixOverflowOnNewBlock(t *testing.T) {
transactionPool.OnNewBlock(block.Block(), ledgercore.StateDelta{})
- pending = transactionPool.PendingTxGroups()
+ pending, _ = transactionPool.PendingTxGroups()
// only one transaction is missing
require.Len(t, pending, savedTransactions-1)
}
@@ -852,7 +862,15 @@ func TestRemove(t *testing.T) {
}
signedTx := tx.Sign(secrets[0])
require.NoError(t, transactionPool.RememberOne(signedTx))
- require.Equal(t, transactionPool.PendingTxGroups(), [][]transactions.SignedTxn{{signedTx}})
+ pendingTxGroups, _ := transactionPool.PendingTxGroups()
+ require.Equal(t, []pooldata.SignedTxGroup{
+ {
+ Transactions: []transactions.SignedTxn{signedTx},
+ GroupCounter: 1,
+ GroupTransactionID: (pooldata.SignedTxnSlice{signedTx}).ID(),
+ EncodedLength: len(signedTx.MarshalMsg([]byte{})),
+ },
+ }, pendingTxGroups)
}
func TestLogicSigOK(t *testing.T) {
@@ -1238,7 +1256,7 @@ func TestTxPoolSizeLimits(t *testing.T) {
}
for groupSize := config.Consensus[protocol.ConsensusCurrentVersion].MaxTxGroupSize; groupSize > 0; groupSize-- {
- var txgroup []transactions.SignedTxn
+ var txgroup pooldata.SignedTxGroup
// fill the transaction group with groupSize transactions.
for i := 0; i < groupSize; i++ {
tx := transactions.Transaction{
@@ -1257,7 +1275,7 @@ func TestTxPoolSizeLimits(t *testing.T) {
},
}
signedTx := tx.Sign(secrets[0])
- txgroup = append(txgroup, signedTx)
+ txgroup.Transactions = append(txgroup.Transactions, signedTx)
uniqueTxID++
}
@@ -1267,7 +1285,7 @@ func TestTxPoolSizeLimits(t *testing.T) {
if groupSize > 1 {
// add a single transaction and ensure we succeed
// consume the transaction of allowed limit
- require.NoError(t, transactionPool.RememberOne(txgroup[0]))
+ require.NoError(t, transactionPool.RememberOne(txgroup.Transactions[0]))
}
}
}
diff --git a/data/transactions/application.go b/data/transactions/application.go
index 4588ed22f..1faef7998 100644
--- a/data/transactions/application.go
+++ b/data/transactions/application.go
@@ -23,29 +23,29 @@ import (
)
const (
- // encodedMaxApplicationArgs sets the allocation bound for the maximum
+ // EncodedMaxApplicationArgs sets the allocation bound for the maximum
// number of ApplicationArgs that a transaction decoded off of the wire
// can contain. Its value is verified against consensus parameters in
// TestEncodedAppTxnAllocationBounds
- encodedMaxApplicationArgs = 32
+ EncodedMaxApplicationArgs = 32
- // encodedMaxAccounts sets the allocation bound for the maximum number
+ // EncodedMaxAccounts sets the allocation bound for the maximum number
// of Accounts that a transaction decoded off of the wire can contain.
// Its value is verified against consensus parameters in
// TestEncodedAppTxnAllocationBounds
- encodedMaxAccounts = 32
+ EncodedMaxAccounts = 32
- // encodedMaxForeignApps sets the allocation bound for the maximum
+ // EncodedMaxForeignApps sets the allocation bound for the maximum
// number of ForeignApps that a transaction decoded off of the wire can
// contain. Its value is verified against consensus parameters in
// TestEncodedAppTxnAllocationBounds
- encodedMaxForeignApps = 32
+ EncodedMaxForeignApps = 32
- // encodedMaxForeignAssets sets the allocation bound for the maximum
+ // EncodedMaxForeignAssets sets the allocation bound for the maximum
// number of ForeignAssets that a transaction decoded off of the wire
// can contain. Its value is verified against consensus parameters in
// TestEncodedAppTxnAllocationBounds
- encodedMaxForeignAssets = 32
+ EncodedMaxForeignAssets = 32
)
// OnCompletion is an enum representing some layer 1 side effect that an
@@ -100,7 +100,7 @@ type ApplicationCallTxnFields struct {
// ApplicationArgs are arguments accessible to the executing
// ApprovalProgram or ClearStateProgram.
- ApplicationArgs [][]byte `codec:"apaa,allocbound=encodedMaxApplicationArgs"`
+ ApplicationArgs [][]byte `codec:"apaa,allocbound=EncodedMaxApplicationArgs"`
// Accounts are accounts whose balance records are accessible
// by the executing ApprovalProgram or ClearStateProgram. To
@@ -108,17 +108,17 @@ type ApplicationCallTxnFields struct {
// the sender, that account's address must be listed here (and
// since v4, the ForeignApp or ForeignAsset must also include
// the app or asset id).
- Accounts []basics.Address `codec:"apat,allocbound=encodedMaxAccounts"`
+ Accounts []basics.Address `codec:"apat,allocbound=EncodedMaxAccounts"`
// ForeignApps are application IDs for applications besides
// this one whose GlobalState (or Local, since v4) may be read
// by the executing ApprovalProgram or ClearStateProgram.
- ForeignApps []basics.AppIndex `codec:"apfa,allocbound=encodedMaxForeignApps"`
+ ForeignApps []basics.AppIndex `codec:"apfa,allocbound=EncodedMaxForeignApps"`
// ForeignAssets are asset IDs for assets whose AssetParams
// (and since v4, Holdings) may be read by the executing
// ApprovalProgram or ClearStateProgram.
- ForeignAssets []basics.AssetIndex `codec:"apas,allocbound=encodedMaxForeignAssets"`
+ ForeignAssets []basics.AssetIndex `codec:"apas,allocbound=EncodedMaxForeignAssets"`
// LocalStateSchema specifies the maximum number of each type that may
// appear in the local key/value store of users who opt in to this
diff --git a/data/transactions/application_test.go b/data/transactions/application_test.go
index 5d50d7126..28a48e4c4 100644
--- a/data/transactions/application_test.go
+++ b/data/transactions/application_test.go
@@ -103,16 +103,16 @@ func TestEncodedAppTxnAllocationBounds(t *testing.T) {
// ensure that all the supported protocols have value limits less or
// equal to their corresponding codec allocbounds
for protoVer, proto := range config.Consensus {
- if proto.MaxAppArgs > encodedMaxApplicationArgs {
+ if proto.MaxAppArgs > EncodedMaxApplicationArgs {
require.Failf(t, "proto.MaxAppArgs > encodedMaxApplicationArgs", "protocol version = %s", protoVer)
}
- if proto.MaxAppTxnAccounts > encodedMaxAccounts {
+ if proto.MaxAppTxnAccounts > EncodedMaxAccounts {
require.Failf(t, "proto.MaxAppTxnAccounts > encodedMaxAccounts", "protocol version = %s", protoVer)
}
- if proto.MaxAppTxnForeignApps > encodedMaxForeignApps {
+ if proto.MaxAppTxnForeignApps > EncodedMaxForeignApps {
require.Failf(t, "proto.MaxAppTxnForeignApps > encodedMaxForeignApps", "protocol version = %s", protoVer)
}
- if proto.MaxAppTxnForeignAssets > encodedMaxForeignAssets {
+ if proto.MaxAppTxnForeignAssets > EncodedMaxForeignAssets {
require.Failf(t, "proto.MaxAppTxnForeignAssets > encodedMaxForeignAssets", "protocol version = %s", protoVer)
}
}
diff --git a/data/transactions/logic/README.md b/data/transactions/logic/README.md
index 4ed8cacd7..6bdc19457 100644
--- a/data/transactions/logic/README.md
+++ b/data/transactions/logic/README.md
@@ -466,9 +466,10 @@ transaction types, are rejected by `itxn_submit`.
| Op | Description |
| --- | --- |
-| `itxn_begin` | begin preparation of a new inner transaction |
+| `itxn_begin` | begin preparation of a new inner transaction in a new transaction group |
+| `itxn_next` | begin preparation of a new inner transaction in the same transaction group |
| `itxn_field f` | set field F of the current inner transaction to X |
-| `itxn_submit` | execute the current inner transaction. Fail if 16 inner transactions have already been executed, or if the transaction itself fails. |
+| `itxn_submit` | execute the current inner transaction group. Fail if executing this group would exceed 16 total inner transactions, or if any transaction in the group fails. |
| `itxn f` | push field F of the last inner transaction to stack |
| `itxna f i` | push Ith value of the array field F of the last inner transaction to stack |
diff --git a/data/transactions/logic/TEAL_opcodes.md b/data/transactions/logic/TEAL_opcodes.md
index 9a28d3c7e..082f54553 100644
--- a/data/transactions/logic/TEAL_opcodes.md
+++ b/data/transactions/logic/TEAL_opcodes.md
@@ -1296,7 +1296,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xb1
- Pops: _None_
- Pushes: _None_
-- begin preparation of a new inner transaction
+- begin preparation of a new inner transaction in a new transaction group
- LogicSigVersion >= 5
- Mode: Application
@@ -1318,7 +1318,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xb3
- Pops: _None_
- Pushes: _None_
-- execute the current inner transaction. Fail if 16 inner transactions have already been executed, or if the transaction itself fails.
+- execute the current inner transaction group. Fail if executing this group would exceed 16 total inner transactions, or if any transaction in the group fails.
- LogicSigVersion >= 5
- Mode: Application
@@ -1342,6 +1342,15 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- LogicSigVersion >= 5
- Mode: Application
+## itxn_next
+
+- Opcode: 0xb6
+- Pops: _None_
+- Pushes: _None_
+- begin preparation of a new inner transaction in the same transaction group
+- LogicSigVersion >= 6
+- Mode: Application
+
## txnas f
- Opcode: 0xc0 {uint8 transaction field index}
diff --git a/data/transactions/logic/assembler_test.go b/data/transactions/logic/assembler_test.go
index bc61b83b2..d3963017e 100644
--- a/data/transactions/logic/assembler_test.go
+++ b/data/transactions/logic/assembler_test.go
@@ -134,7 +134,7 @@ intc 1
mulw
`
-const v2Nonsense = `
+const v2Nonsense = v1Nonsense + `
dup2
pop
pop
@@ -219,7 +219,7 @@ txn FreezeAssetAccount
txn FreezeAssetFrozen
`
-const v3Nonsense = `
+const v3Nonsense = v2Nonsense + `
assert
min_balance
int 0x031337 // get bit 1, negate it, put it back
@@ -248,7 +248,7 @@ pushbytes "john"
// Keep in mind, only use existing int and byte constants, or else use
// push* instead. The idea is to not cause the *cblocks to change.
-const v4Nonsense = `
+const v4Nonsense = v3Nonsense + `
int 1
pushint 2000
int 0
@@ -294,7 +294,7 @@ gaids
int 100
`
-const v5Nonsense = `
+const v5Nonsense = v4Nonsense + `
app_params_get AppExtraProgramPages
cover 1
uncover 1
@@ -342,12 +342,17 @@ ecdsa_pk_recover Secp256k1
itxna Logs 3
`
+const v6Nonsense = v5Nonsense + `
+itxn_next
+`
+
var nonsense = map[uint64]string{
1: v1Nonsense,
- 2: v1Nonsense + v2Nonsense,
- 3: v1Nonsense + v2Nonsense + v3Nonsense,
- 4: v1Nonsense + v2Nonsense + v3Nonsense + v4Nonsense,
- 5: v1Nonsense + v2Nonsense + v3Nonsense + v4Nonsense + v5Nonsense,
+ 2: v2Nonsense,
+ 3: v3Nonsense,
+ 4: v4Nonsense,
+ 5: v5Nonsense,
+ 6: v6Nonsense,
}
var compiled = map[uint64]string{
@@ -356,6 +361,7 @@ var compiled = map[uint64]string{
3: "032008b7a60cf8acd19181cf959a12f8acd19181cf951af8acd19181cf15f8acd191810f01020026050212340c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d024242047465737400320032013202320328292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e0102222324252104082209240a220b230c240d250e230f23102311231223132314181b1c2b171615400003290349483403350222231d4a484848482a50512a63222352410003420000432105602105612105270463484821052b62482b642b65484821052b2106662b21056721072b682b692107210570004848210771004848361c0037001a0031183119311b311d311e311f3120210721051e312131223123312431253126312731283129312a312b312c312d312e312f4478222105531421055427042106552105082106564c4d4b02210538212106391c0081e80780046a6f686e",
4: "042004010200b7a60c26040242420c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f23102311231223132314181b1c28171615400003290349483403350222231d4a484848482a50512a632223524100034200004322602261222b634848222862482864286548482228236628226724286828692422700048482471004848361c0037001a0031183119311b311d311e311f312024221e312131223123312431253126312731283129312a312b312c312d312e312f44782522531422542b2355220823564c4d4b0222382123391c0081e80780046a6f686e2281d00f24231f880003420001892223902291922394239593a0a1a2a3a4a5a6a7a8a9aaabacadae23af3a00003b003c003d8164",
5: "052004010002b7a60c26050242420c68656c6c6f20776f726c6421070123456789abcd208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292b0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f23102311231223132314181b1c28171615400003290349483403350222231d4a484848482b50512a632223524100034200004322602261222704634848222862482864286548482228246628226723286828692322700048482371004848361c0037001a0031183119311b311d311e311f312023221e312131223123312431253126312731283129312a312b312c312d312e312f447825225314225427042455220824564c4d4b0222382124391c0081e80780046a6f686e2281d00f23241f880003420001892224902291922494249593a0a1a2a3a4a5a6a7a8a9aaabacadae24af3a00003b003c003d816472064e014f012a57000823810858235b235a2359b03139330039b1b200b322c01a23c1001a2323c21a23c3233e233f8120af06002a494905002a49490700b53a03",
+ 6: "062004010002b7a60c26050242420c68656c6c6f20776f726c6421070123456789abcd208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292b0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f23102311231223132314181b1c28171615400003290349483403350222231d4a484848482b50512a632223524100034200004322602261222704634848222862482864286548482228246628226723286828692322700048482371004848361c0037001a0031183119311b311d311e311f312023221e312131223123312431253126312731283129312a312b312c312d312e312f447825225314225427042455220824564c4d4b0222382124391c0081e80780046a6f686e2281d00f23241f880003420001892224902291922494249593a0a1a2a3a4a5a6a7a8a9aaabacadae24af3a00003b003c003d816472064e014f012a57000823810858235b235a2359b03139330039b1b200b322c01a23c1001a2323c21a23c3233e233f8120af06002a494905002a49490700b53a03b6",
}
func pseudoOp(opcode string) bool {
@@ -381,6 +387,7 @@ func TestAssemble(t *testing.T) {
// This doesn't have to be a sensible program to run, it just has to compile.
t.Parallel()
+ require.Equal(t, LogicVersion, len(nonsense))
for v := uint64(2); v <= AssemblerMaxVersion; v++ {
t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) {
for _, spec := range OpSpecs {
@@ -1374,12 +1381,6 @@ func TestAssembleDisassembleCycle(t *testing.T) {
// Disassembly won't necessarily perfectly recreate the source text, but assembling the result of Disassemble() should be the same program bytes.
t.Parallel()
- tests := map[uint64]string{
- 1: v1Nonsense,
- 2: v1Nonsense + v2Nonsense,
- 3: v1Nonsense + v2Nonsense + v3Nonsense,
- }
-
// This confirms that each program compiles to the same bytes
// (except the leading version indicator), when compiled under
// original version, unspecified version (so it should pick up
@@ -1388,7 +1389,8 @@ func TestAssembleDisassembleCycle(t *testing.T) {
// optimizations in later versions that change the bytecode
// emitted. But currently it is, so we test it for now to
// catch any suprises.
- for v, source := range tests {
+ require.Equal(t, LogicVersion, len(nonsense))
+ for v, source := range nonsense {
t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) {
ops := testProg(t, source, v)
t2, err := Disassemble(ops.Program)
diff --git a/data/transactions/logic/doc.go b/data/transactions/logic/doc.go
index 0c9c6f8fc..98e757f8b 100644
--- a/data/transactions/logic/doc.go
+++ b/data/transactions/logic/doc.go
@@ -169,9 +169,10 @@ var opDocByName = map[string]string{
"b~": "X with all bits inverted",
"log": "write bytes to log state of the current application",
- "itxn_begin": "begin preparation of a new inner transaction",
+ "itxn_begin": "begin preparation of a new inner transaction in a new transaction group",
+ "itxn_next": "begin preparation of a new inner transaction in the same transaction group",
"itxn_field": "set field F of the current inner transaction to X",
- "itxn_submit": "execute the current inner transaction. Fail if 16 inner transactions have already been executed, or if the transaction itself fails.",
+ "itxn_submit": "execute the current inner transaction group. Fail if executing this group would exceed 16 total inner transactions, or if any transaction in the group fails.",
}
// OpDoc returns a description of the op
@@ -300,7 +301,7 @@ var OpGroups = map[string][]string{
"Loading Values": {"intcblock", "intc", "intc_0", "intc_1", "intc_2", "intc_3", "pushint", "bytecblock", "bytec", "bytec_0", "bytec_1", "bytec_2", "bytec_3", "pushbytes", "bzero", "arg", "arg_0", "arg_1", "arg_2", "arg_3", "args", "txn", "gtxn", "txna", "txnas", "gtxna", "gtxnas", "gtxns", "gtxnsa", "gtxnsas", "global", "load", "loads", "store", "stores", "gload", "gloads", "gaid", "gaids"},
"Flow Control": {"err", "bnz", "bz", "b", "return", "pop", "dup", "dup2", "dig", "cover", "uncover", "swap", "select", "assert", "callsub", "retsub"},
"State Access": {"balance", "min_balance", "app_opted_in", "app_local_get", "app_local_get_ex", "app_global_get", "app_global_get_ex", "app_local_put", "app_global_put", "app_local_del", "app_global_del", "asset_holding_get", "asset_params_get", "app_params_get", "log"},
- "Inner Transactions": {"itxn_begin", "itxn_field", "itxn_submit", "itxn", "itxna"},
+ "Inner Transactions": {"itxn_begin", "itxn_next", "itxn_field", "itxn_submit", "itxn", "itxna"},
}
// OpCost indicates the cost of an operation over the range of
diff --git a/data/transactions/logic/eval.go b/data/transactions/logic/eval.go
index aa2744ddc..9a2530f36 100644
--- a/data/transactions/logic/eval.go
+++ b/data/transactions/logic/eval.go
@@ -349,8 +349,8 @@ type EvalContext struct {
version uint64
scratch scratchSpace
- subtxn *transactions.SignedTxn // place to build for itxn_submit
- // The transactions Performed() and their effects
+ subtxns []transactions.SignedTxn // place to build for itxn_submit
+ // Previous transactions Performed() and their effects
InnerTxns []transactions.SignedTxnWithAD
cost int // cost incurred so far
@@ -3676,33 +3676,68 @@ func authorizedSender(cx *EvalContext, addr basics.Address) bool {
return appAddr == authorizer
}
-func opTxBegin(cx *EvalContext) {
- if cx.subtxn != nil {
- cx.err = errors.New("itxn_begin without itxn_submit")
- return
- }
- // Start fresh
- cx.subtxn = &transactions.SignedTxn{}
- // Fill in defaults.
+// addInnerTxn appends a fresh SignedTxn to subtxns, populated with reasonable
+// defaults.
+func addInnerTxn(cx *EvalContext) error {
addr, err := cx.getApplicationAddress()
if err != nil {
- cx.err = err
- return
+ return err
}
- fee := cx.Proto.MinTxnFee
- if cx.FeeCredit != nil {
- // Use credit to shrink the fee, but don't change FeeCredit
- // here, because they might never itxn_submit, or they might
- // change the fee. Do it in itxn_submit.
- fee = basics.SubSaturate(fee, *cx.FeeCredit)
+ // For compatibility with v5, in which failures only occurred in the submit,
+ // we only fail here if we are OVER the MaxInnerTransactions limit. Thus
+ // this allows construction of one more Inner than is actually allowed, and
+ // will fail in submit. (But we do want the check here, so this can't become
+ // unbounded.) The MaxTxGroupSize check can be, and is, precise.
+ if len(cx.InnerTxns)+len(cx.subtxns) > cx.Proto.MaxInnerTransactions ||
+ len(cx.subtxns) >= cx.Proto.MaxTxGroupSize {
+ return errors.New("attempt to create too many inner transactions")
}
- cx.subtxn.Txn.Header = transactions.Header{
- Sender: addr, // Default, to simplify usage
+
+ stxn := transactions.SignedTxn{}
+
+ groupFee := basics.MulSaturate(cx.Proto.MinTxnFee, uint64(len(cx.subtxns)+1))
+ groupPaid := uint64(0)
+ for _, ptxn := range cx.subtxns {
+ groupPaid = basics.AddSaturate(groupPaid, ptxn.Txn.Fee.Raw)
+ }
+
+ fee := uint64(0)
+ if groupPaid < groupFee {
+ fee = groupFee - groupPaid
+
+ if cx.FeeCredit != nil {
+ // Use credit to shrink the default populated fee, but don't change
+ // FeeCredit here, because they might never itxn_submit, or they
+ // might change the fee. Do it in itxn_submit.
+ fee = basics.SubSaturate(fee, *cx.FeeCredit)
+ }
+ }
+
+ stxn.Txn.Header = transactions.Header{
+ Sender: addr,
Fee: basics.MicroAlgos{Raw: fee},
FirstValid: cx.Txn.Txn.FirstValid,
LastValid: cx.Txn.Txn.LastValid,
}
+ cx.subtxns = append(cx.subtxns, stxn)
+ return nil
+}
+
+func opTxBegin(cx *EvalContext) {
+ if len(cx.subtxns) > 0 {
+ cx.err = errors.New("itxn_begin without itxn_submit")
+ return
+ }
+ cx.err = addInnerTxn(cx)
+}
+
+func opTxNext(cx *EvalContext) {
+ if len(cx.subtxns) == 0 {
+ cx.err = errors.New("itxn_next without itxn_begin")
+ return
+ }
+ cx.err = addInnerTxn(cx)
}
// availableAccount is used instead of accountReference for more recent opcodes
@@ -3741,11 +3776,12 @@ func (cx *EvalContext) stackIntoTxnField(sv stackValue, fs txnFieldSpec, txn *tr
err = fmt.Errorf("Type arg not a byte array")
return
}
- txType, ok := innerTxnTypes[string(sv.Bytes)]
- if ok {
- txn.Type = txType
+ txType := string(sv.Bytes)
+ ver, ok := innerTxnTypes[txType]
+ if ok && ver <= cx.version {
+ txn.Type = protocol.TxType(txType)
} else {
- err = fmt.Errorf("%s is not a valid Type for itxn_field", sv.Bytes)
+ err = fmt.Errorf("%s is not a valid Type for itxn_field", txType)
}
case TypeEnum:
var i uint64
@@ -3755,9 +3791,9 @@ func (cx *EvalContext) stackIntoTxnField(sv stackValue, fs txnFieldSpec, txn *tr
}
// i != 0 is so that the error reports 0 instead of Unknown
if i != 0 && i < uint64(len(TxnTypeNames)) {
- txType, ok := innerTxnTypes[TxnTypeNames[i]]
- if ok {
- txn.Type = txType
+ ver, ok := innerTxnTypes[TxnTypeNames[i]]
+ if ok && ver <= cx.version {
+ txn.Type = protocol.TxType(TxnTypeNames[i])
} else {
err = fmt.Errorf("%s is not a valid Type for itxn_field", TxnTypeNames[i])
}
@@ -3768,14 +3804,48 @@ func (cx *EvalContext) stackIntoTxnField(sv stackValue, fs txnFieldSpec, txn *tr
txn.Sender, err = cx.availableAccount(sv)
case Fee:
txn.Fee.Raw, err = sv.uint()
- // FirstValid, LastValid unsettable: no motivation
- // Note unsettable: would be strange, as this "Note" would not end up "chain-visible"
+ // FirstValid, LastValid unsettable: little motivation (maybe a app call
+ // wants to inspect?) If we set, make sure they are legal, both for current
+ // round, and separation by MaxLifetime (check lifetime in submit, not here)
+ case Note:
+ if len(sv.Bytes) > cx.Proto.MaxTxnNoteBytes {
+ err = fmt.Errorf("%s may not exceed %d bytes", fs.field, cx.Proto.MaxTxnNoteBytes)
+ } else {
+ txn.Note = make([]byte, len(sv.Bytes))
+ copy(txn.Note[:], sv.Bytes)
+ }
// GenesisID, GenesisHash unsettable: surely makes no sense
// Group unsettable: Can't make groups from AVM (yet?)
// Lease unsettable: This seems potentially useful.
- // RekeyTo unsettable: Feels dangerous for first release.
- // KeyReg not allowed yet, so no fields settable
+ case RekeyTo:
+ txn.RekeyTo, err = sv.address()
+
+ // KeyReg
+ case VotePK:
+ if len(sv.Bytes) != 32 {
+ err = fmt.Errorf("%s must be 32 bytes", fs.field)
+ } else {
+ copy(txn.VotePK[:], sv.Bytes)
+ }
+ case SelectionPK:
+ if len(sv.Bytes) != 32 {
+ err = fmt.Errorf("%s must be 32 bytes", fs.field)
+ } else {
+ copy(txn.SelectionPK[:], sv.Bytes)
+ }
+ case VoteFirst:
+ var round uint64
+ round, err = sv.uint()
+ txn.VoteFirst = basics.Round(round)
+ case VoteLast:
+ var round uint64
+ round, err = sv.uint()
+ txn.VoteLast = basics.Round(round)
+ case VoteKeyDilution:
+ txn.VoteKeyDilution, err = sv.uint()
+ case Nonparticipation:
+ txn.Nonparticipation, err = sv.bool()
// Payment
case Receiver:
@@ -3820,7 +3890,7 @@ func (cx *EvalContext) stackIntoTxnField(sv stackValue, fs txnFieldSpec, txn *tr
txn.AssetParams.URL, err = sv.string(cx.Proto.MaxAssetURLBytes)
case ConfigAssetMetadataHash:
if len(sv.Bytes) != 32 {
- err = fmt.Errorf("ConfigAssetMetadataHash must be 32 bytes")
+ err = fmt.Errorf("%s must be 32 bytes", fs.field)
} else {
copy(txn.AssetParams.MetadataHash[:], sv.Bytes)
}
@@ -3849,7 +3919,8 @@ func (cx *EvalContext) stackIntoTxnField(sv stackValue, fs txnFieldSpec, txn *tr
}
func opTxField(cx *EvalContext) {
- if cx.subtxn == nil {
+ itx := len(cx.subtxns) - 1
+ if itx < 0 {
cx.err = errors.New("itxn_field without itxn_begin")
return
}
@@ -3857,10 +3928,11 @@ func opTxField(cx *EvalContext) {
field := TxnField(cx.program[cx.pc+1])
fs, ok := txnFieldSpecByField[field]
if !ok || fs.itxVersion == 0 || fs.itxVersion > cx.version {
- cx.err = fmt.Errorf("invalid itxn_field field %d", field)
+ cx.err = fmt.Errorf("invalid itxn_field %s", field)
+ return
}
sv := cx.stack[last]
- cx.err = cx.stackIntoTxnField(sv, fs, &cx.subtxn.Txn)
+ cx.err = cx.stackIntoTxnField(sv, fs, &cx.subtxns[itx].Txn)
cx.stack = cx.stack[:last] // pop
}
@@ -3870,71 +3942,95 @@ func opTxSubmit(cx *EvalContext) {
return
}
- if cx.subtxn == nil {
- cx.err = errors.New("itxn_submit without itxn_begin")
+ // Should never trigger, since itxn_next checks these too.
+ if len(cx.InnerTxns)+len(cx.subtxns) > cx.Proto.MaxInnerTransactions ||
+ len(cx.subtxns) > cx.Proto.MaxTxGroupSize {
+ cx.err = errors.New("too many inner transactions")
return
}
- if len(cx.InnerTxns) >= cx.Proto.MaxInnerTransactions {
- cx.err = errors.New("itxn_submit with MaxInnerTransactions")
+ if len(cx.subtxns) == 0 {
+ cx.err = errors.New("itxn_submit without itxn_begin")
return
}
- // Error out on anything unusual. Allow pay, axfer.
- switch cx.subtxn.Txn.Type {
- case protocol.PaymentTx, protocol.AssetTransferTx, protocol.AssetConfigTx, protocol.AssetFreezeTx:
- // only pay, axfer, acfg, afrz for now
- default:
- cx.err = fmt.Errorf("Invalid inner transaction type %#v", cx.subtxn.Txn.Type)
- return
+ // Check fees across the group first. Allows fee pooling in inner groups.
+ groupFee := basics.MulSaturate(cx.Proto.MinTxnFee, uint64(len(cx.subtxns)))
+ groupPaid := uint64(0)
+ for _, ptxn := range cx.subtxns {
+ groupPaid = basics.AddSaturate(groupPaid, ptxn.Txn.Fee.Raw)
}
-
- // The goal is to follow the same invariants used by the
- // transaction pool. Namely that any transaction that makes it
- // to Perform (which is equivalent to eval.applyTransaction)
- // is authorized, and WellFormed.
- if !authorizedSender(cx, cx.subtxn.Txn.Sender) {
- cx.err = fmt.Errorf("unauthorized")
- return
+ if groupPaid < groupFee {
+ // See if the FeeCredit is enough to cover the shortfall
+ shortfall := groupFee - groupPaid
+ if cx.FeeCredit == nil || *cx.FeeCredit < shortfall {
+ cx.err = fmt.Errorf("fee too small %#v", cx.subtxns)
+ return
+ }
+ *cx.FeeCredit -= shortfall
+ } else {
+ overpay := groupPaid - groupFee
+ if cx.FeeCredit == nil {
+ cx.FeeCredit = new(uint64)
+ }
+ *cx.FeeCredit = basics.AddSaturate(*cx.FeeCredit, overpay)
}
- // Recall that WellFormed does not care about individual
- // transaction fees because of fee pooling. So we check below.
- cx.err = cx.subtxn.Txn.WellFormed(*cx.Specials, *cx.Proto)
- if cx.err != nil {
- return
- }
+ for itx := range cx.subtxns {
+ // The goal is to follow the same invariants used by the
+ // transaction pool. Namely that any transaction that makes it
+ // to Perform (which is equivalent to eval.applyTransaction)
+ // is authorized, and WellFormed.
+ if !authorizedSender(cx, cx.subtxns[itx].Txn.Sender) {
+ cx.err = fmt.Errorf("unauthorized")
+ return
+ }
- paid := cx.subtxn.Txn.Fee.Raw
- if paid >= cx.Proto.MinTxnFee {
- // Over paying - accumulate into FeeCredit
- overpaid := paid - cx.Proto.MinTxnFee
- if cx.FeeCredit == nil {
- cx.FeeCredit = new(uint64)
+ // Recall that WellFormed does not care about individual
+ // transaction fees because of fee pooling. So we check below.
+ cx.err = cx.subtxns[itx].Txn.WellFormed(*cx.Specials, *cx.Proto)
+ if cx.err != nil {
+ return
}
- *cx.FeeCredit = basics.AddSaturate(*cx.FeeCredit, overpaid)
- } else {
- underpaid := cx.Proto.MinTxnFee - paid
- // Try to pay with FeeCredit, else fail.
- if cx.FeeCredit != nil && *cx.FeeCredit >= underpaid {
- *cx.FeeCredit -= underpaid
- } else {
- // We allow changing the fee. One pattern might be for an
- // app to unilaterally set its Fee to 0. The idea would be
- // that other transactions were supposed to overpay.
- cx.err = fmt.Errorf("fee too small")
+
+ ad, err := cx.Ledger.Perform(&cx.subtxns[itx].Txn, *cx.Specials)
+ if err != nil {
+ cx.err = err
return
}
+
+ cx.InnerTxns = append(cx.InnerTxns, transactions.SignedTxnWithAD{
+ SignedTxn: cx.subtxns[itx],
+ ApplyData: ad,
+ })
}
+ cx.subtxns = nil
+}
- ad, err := cx.Ledger.Perform(&cx.subtxn.Txn, *cx.Specials)
+// PcDetails return PC and disassembled instructions at PC up to 2 opcodes back
+func (cx *EvalContext) PcDetails() (pc int, dis string) {
+ const maxNumAdditionalOpcodes = 2
+ text, ds, err := disassembleInstrumented(cx.program, nil)
if err != nil {
- cx.err = err
- return
+ return cx.pc, dis
+ }
+
+ for i := 0; i < len(ds.pcOffset); i++ {
+ if ds.pcOffset[i].PC == cx.pc {
+ start := 0
+ if i >= maxNumAdditionalOpcodes {
+ start = i - maxNumAdditionalOpcodes
+ }
+
+ startTextPos := ds.pcOffset[start].Offset
+ endTextPos := len(text)
+ if i+1 < len(ds.pcOffset) {
+ endTextPos = ds.pcOffset[i+1].Offset
+ }
+
+ dis = text[startTextPos:endTextPos]
+ break
+ }
}
- cx.InnerTxns = append(cx.InnerTxns, transactions.SignedTxnWithAD{
- SignedTxn: *cx.subtxn,
- ApplyData: ad,
- })
- cx.subtxn = nil
+ return cx.pc, dis
}
diff --git a/data/transactions/logic/evalAppTxn_test.go b/data/transactions/logic/evalAppTxn_test.go
index 693e1e82e..b24e10fc2 100644
--- a/data/transactions/logic/evalAppTxn_test.go
+++ b/data/transactions/logic/evalAppTxn_test.go
@@ -25,11 +25,18 @@ import (
"github.com/stretchr/testify/require"
)
-func TestActionTypes(t *testing.T) {
+func TestInnerTypesV5(t *testing.T) {
+ v5, _ := makeSampleEnvWithVersion(5)
+ // not alllowed in v5
+ testApp(t, "itxn_begin; byte \"keyreg\"; itxn_field Type; itxn_submit; int 1;", v5, "keyreg is not a valid Type for itxn_field")
+ testApp(t, "itxn_begin; int keyreg; itxn_field TypeEnum; itxn_submit; int 1;", v5, "keyreg is not a valid Type for itxn_field")
+}
+
+func TestCurrentInnerTypes(t *testing.T) {
ep, ledger := makeSampleEnv()
testApp(t, "itxn_submit; int 1;", ep, "itxn_submit without itxn_begin")
testApp(t, "int pay; itxn_field TypeEnum; itxn_submit; int 1;", ep, "itxn_field without itxn_begin")
- testApp(t, "itxn_begin; itxn_submit; int 1;", ep, "Invalid inner transaction type")
+ testApp(t, "itxn_begin; itxn_submit; int 1;", ep, "unknown tx type")
// bad type
testApp(t, "itxn_begin; byte \"pya\"; itxn_field Type; itxn_submit; int 1;", ep, "pya is not a valid Type")
// mixed up the int form for the byte form
@@ -37,11 +44,9 @@ func TestActionTypes(t *testing.T) {
// or vice versa
testApp(t, obfuscate("itxn_begin; byte \"pay\"; itxn_field TypeEnum; itxn_submit; int 1;"), ep, "not a uint64")
- // good types, not alllowed yet
- testApp(t, "itxn_begin; byte \"keyreg\"; itxn_field Type; itxn_submit; int 1;", ep, "keyreg is not a valid Type for itxn_field")
+ // good types, not allowed yet
testApp(t, "itxn_begin; byte \"appl\"; itxn_field Type; itxn_submit; int 1;", ep, "appl is not a valid Type for itxn_field")
// same, as enums
- testApp(t, "itxn_begin; int keyreg; itxn_field TypeEnum; itxn_submit; int 1;", ep, "keyreg is not a valid Type for itxn_field")
testApp(t, "itxn_begin; int appl; itxn_field TypeEnum; itxn_submit; int 1;", ep, "appl is not a valid Type for itxn_field")
testApp(t, "itxn_begin; int 42; itxn_field TypeEnum; itxn_submit; int 1;", ep, "42 is not a valid TypeEnum")
testApp(t, "itxn_begin; int 0; itxn_field TypeEnum; itxn_submit; int 1;", ep, "0 is not a valid TypeEnum")
@@ -58,6 +63,10 @@ func TestActionTypes(t *testing.T) {
testApp(t, "itxn_begin; int acfg; itxn_field TypeEnum; itxn_submit; int 1;", ep, "insufficient balance")
testApp(t, "itxn_begin; int afrz; itxn_field TypeEnum; itxn_submit; int 1;", ep, "insufficient balance")
+ // alllowed since v6
+ testApp(t, "itxn_begin; byte \"keyreg\"; itxn_field Type; itxn_submit; int 1;", ep, "insufficient balance")
+ testApp(t, "itxn_begin; int keyreg; itxn_field TypeEnum; itxn_submit; int 1;", ep, "insufficient balance")
+
// Establish 888 as the app id, and fund it.
ledger.NewApp(ep.Txn.Txn.Receiver, 888, basics.AppParams{})
ledger.NewAccount(basics.AppIndex(888).Address(), 200000)
@@ -220,6 +229,30 @@ func TestRekeyPay(t *testing.T) {
// See explanation in logicLedger's Perform()
}
+func TestRekeyBack(t *testing.T) {
+ payAndUnkey := `
+ itxn_begin
+ itxn_field Amount
+ itxn_field Receiver
+ itxn_field Sender
+ int pay
+ itxn_field TypeEnum
+ txn Sender
+ itxn_field RekeyTo
+ itxn_submit
+`
+
+ ep, ledger := makeSampleEnv()
+ ledger.NewApp(ep.Txn.Txn.Receiver, 888, basics.AppParams{})
+ testApp(t, "txn Sender; balance; int 0; ==;", ep)
+ testApp(t, "txn Sender; txn Accounts 1; int 100"+payAndUnkey, ep, "unauthorized")
+ ledger.NewAccount(ep.Txn.Txn.Sender, 120+3*ep.Proto.MinTxnFee)
+ ledger.Rekey(ep.Txn.Txn.Sender, basics.AppIndex(888).Address())
+ testApp(t, "txn Sender; txn Accounts 1; int 100"+payAndUnkey+"; int 1", ep)
+ // now rekeyed back to original
+ testApp(t, "txn Sender; txn Accounts 1; int 100"+payAndUnkey, ep, "unauthorized")
+}
+
func TestDefaultSender(t *testing.T) {
pay := `
itxn_begin
@@ -320,7 +353,7 @@ func TestExtraFields(t *testing.T) {
"non-zero fields for type axfer")
}
-func TestBadField(t *testing.T) {
+func TestBadFieldV5(t *testing.T) {
pay := `
itxn_begin
int 7; itxn_field AssetAmount;
@@ -334,12 +367,34 @@ func TestBadField(t *testing.T) {
itxn_submit
`
- ep, ledger := makeSampleEnv()
+ ep, ledger := makeSampleEnvWithVersion(5)
ledger.NewApp(ep.Txn.Txn.Receiver, 888, basics.AppParams{})
testApp(t, "global CurrentApplicationAddress; txn Accounts 1; int 100"+pay, ep,
"invalid itxn_field RekeyTo")
}
+func TestBadField(t *testing.T) {
+ pay := `
+ itxn_begin
+ int 7; itxn_field AssetAmount;
+ itxn_field Amount
+ itxn_field Receiver
+ itxn_field Sender
+ int pay
+ itxn_field TypeEnum
+ txn Receiver
+ itxn_field RekeyTo // ALLOWED, since v6
+ int 10
+ itxn_field FirstValid // NOT ALLOWED
+ itxn_submit
+`
+
+ ep, ledger := makeSampleEnv()
+ ledger.NewApp(ep.Txn.Txn.Receiver, 888, basics.AppParams{})
+ testApp(t, "global CurrentApplicationAddress; txn Accounts 1; int 100"+pay, ep,
+ "invalid itxn_field FirstValid")
+}
+
func TestNumInner(t *testing.T) {
pay := `
itxn_begin
@@ -360,7 +415,7 @@ func TestNumInner(t *testing.T) {
testApp(t, pay+pay+pay+";int 1", ep)
testApp(t, pay+pay+pay+pay+";int 1", ep)
// In the sample proto, MaxInnerTransactions = 4
- testApp(t, pay+pay+pay+pay+pay+";int 1", ep, "itxn_submit with MaxInnerTransactions")
+ testApp(t, pay+pay+pay+pay+pay+";int 1", ep, "too many inner transactions")
}
func TestAssetCreate(t *testing.T) {
@@ -434,3 +489,94 @@ func TestAssetFreeze(t *testing.T) {
require.NoError(t, err)
require.Equal(t, false, holding.Frozen)
}
+
+func TestFieldSetting(t *testing.T) {
+ ep, ledger := makeSampleEnv()
+ ledger.NewApp(ep.Txn.Txn.Receiver, 888, basics.AppParams{})
+ ledger.NewAccount(ledger.ApplicationID().Address(), 10*defaultEvalProto().MinTxnFee)
+ testApp(t, "itxn_begin; int 500; bzero; itxn_field Note; int 1", ep)
+ testApp(t, "itxn_begin; int 501; bzero; itxn_field Note; int 1", ep,
+ "Note may not exceed")
+
+ testApp(t, "itxn_begin; int 32; bzero; itxn_field VotePK; int 1", ep)
+ testApp(t, "itxn_begin; int 31; bzero; itxn_field VotePK; int 1", ep,
+ "VotePK must be 32")
+
+ testApp(t, "itxn_begin; int 32; bzero; itxn_field SelectionPK; int 1", ep)
+ testApp(t, "itxn_begin; int 33; bzero; itxn_field SelectionPK; int 1", ep,
+ "SelectionPK must be 32")
+
+ testApp(t, "itxn_begin; int 32; bzero; itxn_field RekeyTo; int 1", ep)
+ testApp(t, "itxn_begin; int 31; bzero; itxn_field RekeyTo; int 1", ep,
+ "not an address")
+
+ testApp(t, "itxn_begin; int 6; bzero; itxn_field ConfigAssetUnitName; int 1", ep)
+ testApp(t, "itxn_begin; int 7; bzero; itxn_field ConfigAssetUnitName; int 1", ep,
+ "value is too long")
+
+ testApp(t, "itxn_begin; int 12; bzero; itxn_field ConfigAssetName; int 1", ep)
+ testApp(t, "itxn_begin; int 13; bzero; itxn_field ConfigAssetName; int 1", ep,
+ "value is too long")
+}
+
+func TestInnerGroup(t *testing.T) {
+ ep, ledger := makeSampleEnv()
+ ledger.NewApp(ep.Txn.Txn.Receiver, 888, basics.AppParams{})
+ // Need both fees and both payments
+ ledger.NewAccount(ledger.ApplicationID().Address(), 999+2*defaultEvalProto().MinTxnFee)
+ pay := `
+int pay; itxn_field TypeEnum;
+int 500; itxn_field Amount;
+txn Sender; itxn_field Receiver;
+`
+ testApp(t, "itxn_begin"+pay+"itxn_next"+pay+"itxn_submit; int 1", ep,
+ "insufficient balance")
+
+ // NewAccount overwrites the existing balance
+ ledger.NewAccount(ledger.ApplicationID().Address(), 1000+2*defaultEvalProto().MinTxnFee)
+ testApp(t, "itxn_begin"+pay+"itxn_next"+pay+"itxn_submit; int 1", ep)
+}
+
+func TestInnerFeePooling(t *testing.T) {
+ ep, ledger := makeSampleEnv()
+ ledger.NewApp(ep.Txn.Txn.Receiver, 888, basics.AppParams{})
+ ledger.NewAccount(ledger.ApplicationID().Address(), 50_000)
+ pay := `
+int pay; itxn_field TypeEnum;
+int 500; itxn_field Amount;
+txn Sender; itxn_field Receiver;
+`
+ // Force the first fee to 3, but the second will default to 2*fee-3 = 2002-3
+ testApp(t, "itxn_begin"+
+ pay+
+ "int 3; itxn_field Fee;"+
+ "itxn_next"+
+ pay+
+ "itxn_submit; itxn Fee; int 1999; ==", ep)
+
+ // Same first, but force the second too low
+ testApp(t, "itxn_begin"+
+ pay+
+ "int 3; itxn_field Fee;"+
+ "itxn_next"+
+ pay+
+ "int 1998; itxn_field Fee;"+
+ "itxn_submit; int 1", ep, "fee too small")
+
+ // Overpay in first itxn, the second will default to less
+ testApp(t, "itxn_begin"+
+ pay+
+ "int 2000; itxn_field Fee;"+
+ "itxn_next"+
+ pay+
+ "itxn_submit; itxn Fee; int 2; ==", ep)
+
+ // Same first, but force the second too low
+ testApp(t, "itxn_begin"+
+ pay+
+ "int 2000; itxn_field Fee;"+
+ "itxn_next"+
+ pay+
+ "int 1; itxn_field Fee;"+
+ "itxn_submit; itxn Fee; int 1", ep, "fee too small")
+}
diff --git a/data/transactions/logic/evalStateful_test.go b/data/transactions/logic/evalStateful_test.go
index f270bd541..5a212629c 100644
--- a/data/transactions/logic/evalStateful_test.go
+++ b/data/transactions/logic/evalStateful_test.go
@@ -2493,7 +2493,7 @@ func TestPooledAppCallsVerifyOp(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
- source := `#pragma version 5
+ source := `
global CurrentApplicationID
pop
byte 0x01
diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go
index 3e1fe56af..74b9f931c 100644
--- a/data/transactions/logic/eval_test.go
+++ b/data/transactions/logic/eval_test.go
@@ -64,6 +64,7 @@ func defaultEvalProtoWithVersion(version uint64) config.ConsensusParams {
SchemaBytesMinBalance: 1005,
MaxInnerTransactions: 4,
+ MaxTxGroupSize: 8,
// With the addition of itxn_field, itxn_submit, which rely on
// machinery outside logic package for validity checking, we
@@ -73,6 +74,14 @@ func defaultEvalProtoWithVersion(version uint64) config.ConsensusParams {
MaxAssetUnitNameBytes: 6,
MaxAssetURLBytes: 32,
MaxAssetDecimals: 4,
+ SupportRekeying: true,
+ MaxTxnNoteBytes: 500,
+ EnableFeePooling: true,
+
+ // Chosen to be different from one another and from normal proto
+ MaxAppTxnAccounts: 3,
+ MaxAppTxnForeignApps: 5,
+ MaxAppTxnForeignAssets: 6,
}
}
@@ -999,6 +1008,10 @@ byte 0x0706000000000000000000000000000000000000000000000000000000000000
&&
`
+const globalV6TestProgram = globalV5TestProgram + `
+// No new globals in v6
+`
+
func TestGlobal(t *testing.T) {
partitiontest.PartitionTest(t)
@@ -1028,6 +1041,10 @@ func TestGlobal(t *testing.T) {
GroupID, globalV5TestProgram,
EvalStateful, CheckStateful,
},
+ 6: {
+ GroupID, globalV6TestProgram,
+ EvalStateful, CheckStateful,
+ },
}
// tests keys are versions so they must be in a range 1..AssemblerMaxVersion plus zero version
require.LessOrEqual(t, len(tests), AssemblerMaxVersion+1)
@@ -1439,6 +1456,12 @@ assert
int 1
`
+const testTxnProgramTextV6 = testTxnProgramTextV5 + `
+assert
+
+int 1
+`
+
func makeSampleTxn() transactions.SignedTxn {
var txn transactions.SignedTxn
copy(txn.Txn.Sender[:], []byte("aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00"))
@@ -1526,7 +1549,7 @@ func TestTxn(t *testing.T) {
t.Parallel()
for i, txnField := range TxnFieldNames {
fs := txnFieldSpecByField[TxnField(i)]
- if !fs.effects && !strings.Contains(testTxnProgramTextV5, txnField) {
+ if !fs.effects && !strings.Contains(testTxnProgramTextV6, txnField) {
if txnField != FirstValidTime.String() {
t.Errorf("TestTxn missing field %v", txnField)
}
@@ -1539,6 +1562,7 @@ func TestTxn(t *testing.T) {
3: testTxnProgramTextV3,
4: testTxnProgramTextV4,
5: testTxnProgramTextV5,
+ 6: testTxnProgramTextV6,
}
clearOps := testProg(t, "int 1", 1)
@@ -1823,11 +1847,15 @@ gtxn 0 Sender
&&
`
+ gtxnTextV6 := gtxnTextV5 + `
+`
+
tests := map[uint64]string{
1: gtxnTextV1,
2: gtxnTextV2,
4: gtxnTextV4,
5: gtxnTextV5,
+ 6: gtxnTextV6,
}
for v, source := range tests {
@@ -4842,3 +4870,42 @@ func TestLog(t *testing.T) {
require.False(t, pass)
}
}
+
+func TestPcDetails(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ var tests = []struct {
+ source string
+ pc int
+ det string
+ }{
+ {"int 1; int 2; -", 5, "pushint 1\npushint 2\n-\n"},
+ {"int 1; err", 3, "pushint 1\nerr\n"},
+ {"int 1; dup; int 2; -; +", 6, "dup\npushint 2\n-\n"},
+ {"b end; end:", 4, ""},
+ }
+ for i, test := range tests {
+ t.Run(fmt.Sprintf("i=%d", i), func(t *testing.T) {
+ ops := testProg(t, test.source, LogicVersion)
+ txn := makeSampleTxn()
+ txgroup := makeSampleTxnGroup(txn)
+ txn.Lsig.Logic = ops.Program
+ sb := strings.Builder{}
+ ep := defaultEvalParams(&sb, &txn)
+ ep.TxnGroup = txgroup
+
+ var cx EvalContext
+ cx.EvalParams = ep
+ cx.runModeFlags = runModeSignature
+
+ pass, err := eval(ops.Program, &cx)
+ require.Error(t, err)
+ require.False(t, pass)
+
+ pc, det := cx.PcDetails()
+ require.Equal(t, test.pc, pc)
+ require.Equal(t, test.det, det)
+ })
+ }
+}
diff --git a/data/transactions/logic/fields.go b/data/transactions/logic/fields.go
index 32d29fd85..68ae0f12f 100644
--- a/data/transactions/logic/fields.go
+++ b/data/transactions/logic/fields.go
@@ -197,16 +197,16 @@ var txnFieldSpecs = []txnFieldSpec{
{FirstValid, StackUint64, 0, 0, false},
{FirstValidTime, StackUint64, 0, 0, false},
{LastValid, StackUint64, 0, 0, false},
- {Note, StackBytes, 0, 0, false},
+ {Note, StackBytes, 0, 6, false},
{Lease, StackBytes, 0, 0, false},
{Receiver, StackBytes, 0, 5, false},
{Amount, StackUint64, 0, 5, false},
{CloseRemainderTo, StackBytes, 0, 5, false},
- {VotePK, StackBytes, 0, 0, false},
- {SelectionPK, StackBytes, 0, 0, false},
- {VoteFirst, StackUint64, 0, 0, false},
- {VoteLast, StackUint64, 0, 0, false},
- {VoteKeyDilution, StackUint64, 0, 0, false},
+ {VotePK, StackBytes, 0, 6, false},
+ {SelectionPK, StackBytes, 0, 6, false},
+ {VoteFirst, StackUint64, 0, 6, false},
+ {VoteLast, StackUint64, 0, 6, false},
+ {VoteKeyDilution, StackUint64, 0, 6, false},
{Type, StackBytes, 0, 5, false},
{TypeEnum, StackUint64, 0, 5, false},
{XferAsset, StackUint64, 0, 5, false},
@@ -224,7 +224,7 @@ var txnFieldSpecs = []txnFieldSpec{
{NumAccounts, StackUint64, 2, 0, false},
{ApprovalProgram, StackBytes, 2, 0, false},
{ClearStateProgram, StackBytes, 2, 0, false},
- {RekeyTo, StackBytes, 2, 0, false},
+ {RekeyTo, StackBytes, 2, 6, false},
{ConfigAsset, StackUint64, 2, 5, false},
{ConfigAssetTotal, StackUint64, 2, 5, false},
{ConfigAssetDecimals, StackUint64, 2, 5, false},
@@ -249,7 +249,7 @@ var txnFieldSpecs = []txnFieldSpec{
{LocalNumUint, StackUint64, 3, 0, false},
{LocalNumByteSlice, StackUint64, 3, 0, false},
{ExtraProgramPages, StackUint64, 4, 0, false},
- {Nonparticipation, StackUint64, 5, 0, false},
+ {Nonparticipation, StackUint64, 5, 6, false},
{Logs, StackBytes, 5, 5, true},
{NumLogs, StackUint64, 5, 5, true},
@@ -279,11 +279,12 @@ var txnaFieldSpecByField = map[TxnField]txnFieldSpec{
Logs: {Logs, StackBytes, 5, 5, true},
}
-var innerTxnTypes = map[string]protocol.TxType{
- string(protocol.PaymentTx): protocol.PaymentTx,
- string(protocol.AssetTransferTx): protocol.AssetTransferTx,
- string(protocol.AssetConfigTx): protocol.AssetConfigTx,
- string(protocol.AssetFreezeTx): protocol.AssetFreezeTx,
+var innerTxnTypes = map[string]uint64{
+ string(protocol.PaymentTx): 5,
+ string(protocol.KeyRegistrationTx): 6,
+ string(protocol.AssetTransferTx): 5,
+ string(protocol.AssetConfigTx): 5,
+ string(protocol.AssetFreezeTx): 5,
}
// TxnTypeNames is the values of Txn.Type in enum order
@@ -638,7 +639,7 @@ func init() {
txnFieldSpecByField = make(map[TxnField]txnFieldSpec, len(TxnFieldNames))
for i, s := range txnFieldSpecs {
if int(s.field) != i {
- panic("txnFieldTypePairs disjoint with TxnField enum")
+ panic("txnFieldSpecs disjoint with TxnField enum")
}
TxnFieldTypes[i] = s.ftype
txnFieldSpecByField[s.field] = s
@@ -654,8 +655,11 @@ func init() {
}
GlobalFieldTypes = make([]StackType, len(GlobalFieldNames))
globalFieldSpecByField = make(map[GlobalField]globalFieldSpec, len(GlobalFieldNames))
- for _, s := range globalFieldSpecs {
- GlobalFieldTypes[int(s.field)] = s.ftype
+ for i, s := range globalFieldSpecs {
+ if int(s.field) != i {
+ panic("globalFieldSpecs disjoint with GlobalField enum")
+ }
+ GlobalFieldTypes[i] = s.ftype
globalFieldSpecByField[s.field] = s
}
globalFieldSpecByName = make(gfNameSpecMap, len(GlobalFieldNames))
diff --git a/data/transactions/logic/opcodes.go b/data/transactions/logic/opcodes.go
index d45dd25fb..604db789a 100644
--- a/data/transactions/logic/opcodes.go
+++ b/data/transactions/logic/opcodes.go
@@ -21,7 +21,7 @@ import (
)
// LogicVersion defines default assembler and max eval versions
-const LogicVersion = 5
+const LogicVersion = 6
// rekeyingEnabledVersion is the version of TEAL where RekeyTo functionality
// was enabled. This is important to remember so that old TEAL accounts cannot
@@ -317,6 +317,7 @@ var OpSpecs = []OpSpec{
{0xb3, "itxn_submit", opTxSubmit, asmDefault, disDefault, nil, nil, 5, runModeApplication, opDefault},
{0xb4, "itxn", opItxn, asmItxn, disTxn, nil, oneAny, 5, runModeApplication, immediates("f")},
{0xb5, "itxna", opItxna, asmItxna, disTxna, nil, oneAny, 5, runModeApplication, immediates("f", "i")},
+ {0xb6, "itxn_next", opTxNext, asmDefault, disDefault, nil, nil, 6, runModeApplication, opDefault},
// Dynamic indexing
{0xc0, "txnas", opTxnas, assembleTxnas, disTxn, oneInt, oneAny, 5, modeAny, immediates("f")},
diff --git a/data/transactions/logictest/ledger.go b/data/transactions/logictest/ledger.go
index 5d75b210f..51ed94124 100644
--- a/data/transactions/logictest/ledger.go
+++ b/data/transactions/logictest/ledger.go
@@ -549,6 +549,23 @@ func (l *Ledger) move(from basics.Address, to basics.Address, amount uint64) err
return nil
}
+func (l *Ledger) rekey(tx *transactions.Transaction) error {
+ // rekeying: update br.auth to tx.RekeyTo if provided
+ if (tx.RekeyTo != basics.Address{}) {
+ br, ok := l.balances[tx.Sender]
+ if !ok {
+ return fmt.Errorf("no account")
+ }
+ if tx.RekeyTo == tx.Sender {
+ br.auth = basics.Address{}
+ } else {
+ br.auth = tx.RekeyTo
+ }
+ l.balances[tx.Sender] = br
+ }
+ return nil
+}
+
func (l *Ledger) pay(from basics.Address, pay transactions.PaymentTxnFields) error {
err := l.move(from, pay.Receiver, pay.Amount.Raw)
if err != nil {
@@ -706,6 +723,12 @@ func (l *Ledger) Perform(txn *transactions.Transaction, spec transactions.Specia
if err != nil {
return ad, err
}
+
+ err = l.rekey(txn)
+ if err != nil {
+ return ad, err
+ }
+
switch txn.Type {
case protocol.PaymentTx:
err = l.pay(txn.Sender, txn.PaymentTxnFields)
diff --git a/data/transactions/msgp_gen.go b/data/transactions/msgp_gen.go
index 009de07b5..218c86fa2 100644
--- a/data/transactions/msgp_gen.go
+++ b/data/transactions/msgp_gen.go
@@ -360,8 +360,8 @@ func (z *ApplicationCallTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error
err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs")
return
}
- if zb0008 > encodedMaxApplicationArgs {
- err = msgp.ErrOverflow(uint64(zb0008), uint64(encodedMaxApplicationArgs))
+ if zb0008 > EncodedMaxApplicationArgs {
+ err = msgp.ErrOverflow(uint64(zb0008), uint64(EncodedMaxApplicationArgs))
err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs")
return
}
@@ -389,8 +389,8 @@ func (z *ApplicationCallTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error
err = msgp.WrapError(err, "struct-from-array", "Accounts")
return
}
- if zb0010 > encodedMaxAccounts {
- err = msgp.ErrOverflow(uint64(zb0010), uint64(encodedMaxAccounts))
+ if zb0010 > EncodedMaxAccounts {
+ err = msgp.ErrOverflow(uint64(zb0010), uint64(EncodedMaxAccounts))
err = msgp.WrapError(err, "struct-from-array", "Accounts")
return
}
@@ -418,8 +418,8 @@ func (z *ApplicationCallTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error
err = msgp.WrapError(err, "struct-from-array", "ForeignApps")
return
}
- if zb0012 > encodedMaxForeignApps {
- err = msgp.ErrOverflow(uint64(zb0012), uint64(encodedMaxForeignApps))
+ if zb0012 > EncodedMaxForeignApps {
+ err = msgp.ErrOverflow(uint64(zb0012), uint64(EncodedMaxForeignApps))
err = msgp.WrapError(err, "struct-from-array", "ForeignApps")
return
}
@@ -447,8 +447,8 @@ func (z *ApplicationCallTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error
err = msgp.WrapError(err, "struct-from-array", "ForeignAssets")
return
}
- if zb0014 > encodedMaxForeignAssets {
- err = msgp.ErrOverflow(uint64(zb0014), uint64(encodedMaxForeignAssets))
+ if zb0014 > EncodedMaxForeignAssets {
+ err = msgp.ErrOverflow(uint64(zb0014), uint64(EncodedMaxForeignAssets))
err = msgp.WrapError(err, "struct-from-array", "ForeignAssets")
return
}
@@ -574,8 +574,8 @@ func (z *ApplicationCallTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error
err = msgp.WrapError(err, "ApplicationArgs")
return
}
- if zb0019 > encodedMaxApplicationArgs {
- err = msgp.ErrOverflow(uint64(zb0019), uint64(encodedMaxApplicationArgs))
+ if zb0019 > EncodedMaxApplicationArgs {
+ err = msgp.ErrOverflow(uint64(zb0019), uint64(EncodedMaxApplicationArgs))
err = msgp.WrapError(err, "ApplicationArgs")
return
}
@@ -601,8 +601,8 @@ func (z *ApplicationCallTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error
err = msgp.WrapError(err, "Accounts")
return
}
- if zb0021 > encodedMaxAccounts {
- err = msgp.ErrOverflow(uint64(zb0021), uint64(encodedMaxAccounts))
+ if zb0021 > EncodedMaxAccounts {
+ err = msgp.ErrOverflow(uint64(zb0021), uint64(EncodedMaxAccounts))
err = msgp.WrapError(err, "Accounts")
return
}
@@ -628,8 +628,8 @@ func (z *ApplicationCallTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error
err = msgp.WrapError(err, "ForeignApps")
return
}
- if zb0023 > encodedMaxForeignApps {
- err = msgp.ErrOverflow(uint64(zb0023), uint64(encodedMaxForeignApps))
+ if zb0023 > EncodedMaxForeignApps {
+ err = msgp.ErrOverflow(uint64(zb0023), uint64(EncodedMaxForeignApps))
err = msgp.WrapError(err, "ForeignApps")
return
}
@@ -655,8 +655,8 @@ func (z *ApplicationCallTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error
err = msgp.WrapError(err, "ForeignAssets")
return
}
- if zb0025 > encodedMaxForeignAssets {
- err = msgp.ErrOverflow(uint64(zb0025), uint64(encodedMaxForeignAssets))
+ if zb0025 > EncodedMaxForeignAssets {
+ err = msgp.ErrOverflow(uint64(zb0025), uint64(EncodedMaxForeignAssets))
err = msgp.WrapError(err, "ForeignAssets")
return
}
@@ -2056,7 +2056,7 @@ func (z *Header) MarshalMsg(b []byte) (o []byte) {
zb0002Len--
zb0002Mask |= 0x40
}
- if (*z).Lease == ([32]byte{}) {
+ if (*z).Lease == ([LeaseByteLength]byte{}) {
zb0002Len--
zb0002Mask |= 0x80
}
@@ -2350,13 +2350,13 @@ func (_ *Header) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *Header) Msgsize() (s int) {
- s = 1 + 4 + (*z).Sender.Msgsize() + 4 + (*z).Fee.Msgsize() + 3 + (*z).FirstValid.Msgsize() + 3 + (*z).LastValid.Msgsize() + 5 + msgp.BytesPrefixSize + len((*z).Note) + 4 + msgp.StringPrefixSize + len((*z).GenesisID) + 3 + (*z).GenesisHash.Msgsize() + 4 + (*z).Group.Msgsize() + 3 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 6 + (*z).RekeyTo.Msgsize()
+ s = 1 + 4 + (*z).Sender.Msgsize() + 4 + (*z).Fee.Msgsize() + 3 + (*z).FirstValid.Msgsize() + 3 + (*z).LastValid.Msgsize() + 5 + msgp.BytesPrefixSize + len((*z).Note) + 4 + msgp.StringPrefixSize + len((*z).GenesisID) + 3 + (*z).GenesisHash.Msgsize() + 4 + (*z).Group.Msgsize() + 3 + msgp.ArrayHeaderSize + (LeaseByteLength * (msgp.ByteSize)) + 6 + (*z).RekeyTo.Msgsize()
return
}
// MsgIsZero returns whether this is a zero value
func (z *Header) MsgIsZero() bool {
- return ((*z).Sender.MsgIsZero()) && ((*z).Fee.MsgIsZero()) && ((*z).FirstValid.MsgIsZero()) && ((*z).LastValid.MsgIsZero()) && (len((*z).Note) == 0) && ((*z).GenesisID == "") && ((*z).GenesisHash.MsgIsZero()) && ((*z).Group.MsgIsZero()) && ((*z).Lease == ([32]byte{})) && ((*z).RekeyTo.MsgIsZero())
+ return ((*z).Sender.MsgIsZero()) && ((*z).Fee.MsgIsZero()) && ((*z).FirstValid.MsgIsZero()) && ((*z).LastValid.MsgIsZero()) && (len((*z).Note) == 0) && ((*z).GenesisID == "") && ((*z).GenesisHash.MsgIsZero()) && ((*z).Group.MsgIsZero()) && ((*z).Lease == ([LeaseByteLength]byte{})) && ((*z).RekeyTo.MsgIsZero())
}
// MarshalMsg implements msgp.Marshaler
@@ -4302,7 +4302,7 @@ func (z *Transaction) MarshalMsg(b []byte) (o []byte) {
zb0006Len--
zb0006Mask |= 0x8000000000
}
- if (*z).Header.Lease == ([32]byte{}) {
+ if (*z).Header.Lease == ([LeaseByteLength]byte{}) {
zb0006Len--
zb0006Mask |= 0x10000000000
}
@@ -4906,8 +4906,8 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs")
return
}
- if zb0010 > encodedMaxApplicationArgs {
- err = msgp.ErrOverflow(uint64(zb0010), uint64(encodedMaxApplicationArgs))
+ if zb0010 > EncodedMaxApplicationArgs {
+ err = msgp.ErrOverflow(uint64(zb0010), uint64(EncodedMaxApplicationArgs))
err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs")
return
}
@@ -4935,8 +4935,8 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "struct-from-array", "Accounts")
return
}
- if zb0012 > encodedMaxAccounts {
- err = msgp.ErrOverflow(uint64(zb0012), uint64(encodedMaxAccounts))
+ if zb0012 > EncodedMaxAccounts {
+ err = msgp.ErrOverflow(uint64(zb0012), uint64(EncodedMaxAccounts))
err = msgp.WrapError(err, "struct-from-array", "Accounts")
return
}
@@ -4964,8 +4964,8 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "struct-from-array", "ForeignApps")
return
}
- if zb0014 > encodedMaxForeignApps {
- err = msgp.ErrOverflow(uint64(zb0014), uint64(encodedMaxForeignApps))
+ if zb0014 > EncodedMaxForeignApps {
+ err = msgp.ErrOverflow(uint64(zb0014), uint64(EncodedMaxForeignApps))
err = msgp.WrapError(err, "struct-from-array", "ForeignApps")
return
}
@@ -4993,8 +4993,8 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "struct-from-array", "ForeignAssets")
return
}
- if zb0016 > encodedMaxForeignAssets {
- err = msgp.ErrOverflow(uint64(zb0016), uint64(encodedMaxForeignAssets))
+ if zb0016 > EncodedMaxForeignAssets {
+ err = msgp.ErrOverflow(uint64(zb0016), uint64(EncodedMaxForeignAssets))
err = msgp.WrapError(err, "struct-from-array", "ForeignAssets")
return
}
@@ -5334,8 +5334,8 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "ApplicationArgs")
return
}
- if zb0022 > encodedMaxApplicationArgs {
- err = msgp.ErrOverflow(uint64(zb0022), uint64(encodedMaxApplicationArgs))
+ if zb0022 > EncodedMaxApplicationArgs {
+ err = msgp.ErrOverflow(uint64(zb0022), uint64(EncodedMaxApplicationArgs))
err = msgp.WrapError(err, "ApplicationArgs")
return
}
@@ -5361,8 +5361,8 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "Accounts")
return
}
- if zb0024 > encodedMaxAccounts {
- err = msgp.ErrOverflow(uint64(zb0024), uint64(encodedMaxAccounts))
+ if zb0024 > EncodedMaxAccounts {
+ err = msgp.ErrOverflow(uint64(zb0024), uint64(EncodedMaxAccounts))
err = msgp.WrapError(err, "Accounts")
return
}
@@ -5388,8 +5388,8 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "ForeignApps")
return
}
- if zb0026 > encodedMaxForeignApps {
- err = msgp.ErrOverflow(uint64(zb0026), uint64(encodedMaxForeignApps))
+ if zb0026 > EncodedMaxForeignApps {
+ err = msgp.ErrOverflow(uint64(zb0026), uint64(EncodedMaxForeignApps))
err = msgp.WrapError(err, "ForeignApps")
return
}
@@ -5415,8 +5415,8 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "ForeignAssets")
return
}
- if zb0028 > encodedMaxForeignAssets {
- err = msgp.ErrOverflow(uint64(zb0028), uint64(encodedMaxForeignAssets))
+ if zb0028 > EncodedMaxForeignAssets {
+ err = msgp.ErrOverflow(uint64(zb0028), uint64(EncodedMaxForeignAssets))
err = msgp.WrapError(err, "ForeignAssets")
return
}
@@ -5522,7 +5522,7 @@ func (_ *Transaction) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *Transaction) Msgsize() (s int) {
- s = 3 + 5 + (*z).Type.Msgsize() + 4 + (*z).Header.Sender.Msgsize() + 4 + (*z).Header.Fee.Msgsize() + 3 + (*z).Header.FirstValid.Msgsize() + 3 + (*z).Header.LastValid.Msgsize() + 5 + msgp.BytesPrefixSize + len((*z).Header.Note) + 4 + msgp.StringPrefixSize + len((*z).Header.GenesisID) + 3 + (*z).Header.GenesisHash.Msgsize() + 4 + (*z).Header.Group.Msgsize() + 3 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 6 + (*z).Header.RekeyTo.Msgsize() + 8 + (*z).KeyregTxnFields.VotePK.Msgsize() + 7 + (*z).KeyregTxnFields.SelectionPK.Msgsize() + 8 + (*z).KeyregTxnFields.VoteFirst.Msgsize() + 8 + (*z).KeyregTxnFields.VoteLast.Msgsize() + 7 + msgp.Uint64Size + 8 + msgp.BoolSize + 4 + (*z).PaymentTxnFields.Receiver.Msgsize() + 4 + (*z).PaymentTxnFields.Amount.Msgsize() + 6 + (*z).PaymentTxnFields.CloseRemainderTo.Msgsize() + 5 + (*z).AssetConfigTxnFields.ConfigAsset.Msgsize() + 5 + (*z).AssetConfigTxnFields.AssetParams.Msgsize() + 5 + (*z).AssetTransferTxnFields.XferAsset.Msgsize() + 5 + msgp.Uint64Size + 5 + (*z).AssetTransferTxnFields.AssetSender.Msgsize() + 5 + (*z).AssetTransferTxnFields.AssetReceiver.Msgsize() + 7 + (*z).AssetTransferTxnFields.AssetCloseTo.Msgsize() + 5 + (*z).AssetFreezeTxnFields.FreezeAccount.Msgsize() + 5 + (*z).AssetFreezeTxnFields.FreezeAsset.Msgsize() + 5 + msgp.BoolSize + 5 + (*z).ApplicationCallTxnFields.ApplicationID.Msgsize() + 5 + msgp.Uint64Size + 5 + msgp.ArrayHeaderSize
+ s = 3 + 5 + (*z).Type.Msgsize() + 4 + (*z).Header.Sender.Msgsize() + 4 + (*z).Header.Fee.Msgsize() + 3 + (*z).Header.FirstValid.Msgsize() + 3 + (*z).Header.LastValid.Msgsize() + 5 + msgp.BytesPrefixSize + len((*z).Header.Note) + 4 + msgp.StringPrefixSize + len((*z).Header.GenesisID) + 3 + (*z).Header.GenesisHash.Msgsize() + 4 + (*z).Header.Group.Msgsize() + 3 + msgp.ArrayHeaderSize + (LeaseByteLength * (msgp.ByteSize)) + 6 + (*z).Header.RekeyTo.Msgsize() + 8 + (*z).KeyregTxnFields.VotePK.Msgsize() + 7 + (*z).KeyregTxnFields.SelectionPK.Msgsize() + 8 + (*z).KeyregTxnFields.VoteFirst.Msgsize() + 8 + (*z).KeyregTxnFields.VoteLast.Msgsize() + 7 + msgp.Uint64Size + 8 + msgp.BoolSize + 4 + (*z).PaymentTxnFields.Receiver.Msgsize() + 4 + (*z).PaymentTxnFields.Amount.Msgsize() + 6 + (*z).PaymentTxnFields.CloseRemainderTo.Msgsize() + 5 + (*z).AssetConfigTxnFields.ConfigAsset.Msgsize() + 5 + (*z).AssetConfigTxnFields.AssetParams.Msgsize() + 5 + (*z).AssetTransferTxnFields.XferAsset.Msgsize() + 5 + msgp.Uint64Size + 5 + (*z).AssetTransferTxnFields.AssetSender.Msgsize() + 5 + (*z).AssetTransferTxnFields.AssetReceiver.Msgsize() + 7 + (*z).AssetTransferTxnFields.AssetCloseTo.Msgsize() + 5 + (*z).AssetFreezeTxnFields.FreezeAccount.Msgsize() + 5 + (*z).AssetFreezeTxnFields.FreezeAsset.Msgsize() + 5 + msgp.BoolSize + 5 + (*z).ApplicationCallTxnFields.ApplicationID.Msgsize() + 5 + msgp.Uint64Size + 5 + msgp.ArrayHeaderSize
for zb0002 := range (*z).ApplicationCallTxnFields.ApplicationArgs {
s += msgp.BytesPrefixSize + len((*z).ApplicationCallTxnFields.ApplicationArgs[zb0002])
}
@@ -5544,7 +5544,7 @@ func (z *Transaction) Msgsize() (s int) {
// MsgIsZero returns whether this is a zero value
func (z *Transaction) MsgIsZero() bool {
- return ((*z).Type.MsgIsZero()) && ((*z).Header.Sender.MsgIsZero()) && ((*z).Header.Fee.MsgIsZero()) && ((*z).Header.FirstValid.MsgIsZero()) && ((*z).Header.LastValid.MsgIsZero()) && (len((*z).Header.Note) == 0) && ((*z).Header.GenesisID == "") && ((*z).Header.GenesisHash.MsgIsZero()) && ((*z).Header.Group.MsgIsZero()) && ((*z).Header.Lease == ([32]byte{})) && ((*z).Header.RekeyTo.MsgIsZero()) && ((*z).KeyregTxnFields.VotePK.MsgIsZero()) && ((*z).KeyregTxnFields.SelectionPK.MsgIsZero()) && ((*z).KeyregTxnFields.VoteFirst.MsgIsZero()) && ((*z).KeyregTxnFields.VoteLast.MsgIsZero()) && ((*z).KeyregTxnFields.VoteKeyDilution == 0) && ((*z).KeyregTxnFields.Nonparticipation == false) && ((*z).PaymentTxnFields.Receiver.MsgIsZero()) && ((*z).PaymentTxnFields.Amount.MsgIsZero()) && ((*z).PaymentTxnFields.CloseRemainderTo.MsgIsZero()) && ((*z).AssetConfigTxnFields.ConfigAsset.MsgIsZero()) && ((*z).AssetConfigTxnFields.AssetParams.MsgIsZero()) && ((*z).AssetTransferTxnFields.XferAsset.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetAmount == 0) && ((*z).AssetTransferTxnFields.AssetSender.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetReceiver.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetCloseTo.MsgIsZero()) && ((*z).AssetFreezeTxnFields.FreezeAccount.MsgIsZero()) && ((*z).AssetFreezeTxnFields.FreezeAsset.MsgIsZero()) && ((*z).AssetFreezeTxnFields.AssetFrozen == false) && ((*z).ApplicationCallTxnFields.ApplicationID.MsgIsZero()) && ((*z).ApplicationCallTxnFields.OnCompletion == 0) && (len((*z).ApplicationCallTxnFields.ApplicationArgs) == 0) && (len((*z).ApplicationCallTxnFields.Accounts) == 0) && (len((*z).ApplicationCallTxnFields.ForeignApps) == 0) && (len((*z).ApplicationCallTxnFields.ForeignAssets) == 0) && ((*z).ApplicationCallTxnFields.LocalStateSchema.MsgIsZero()) && ((*z).ApplicationCallTxnFields.GlobalStateSchema.MsgIsZero()) && (len((*z).ApplicationCallTxnFields.ApprovalProgram) == 0) && (len((*z).ApplicationCallTxnFields.ClearStateProgram) == 0) && ((*z).ApplicationCallTxnFields.ExtraProgramPages == 0) && ((*z).CompactCertTxnFields.CertRound.MsgIsZero()) && ((*z).CompactCertTxnFields.CertType.MsgIsZero()) && ((*z).CompactCertTxnFields.Cert.MsgIsZero())
+ return ((*z).Type.MsgIsZero()) && ((*z).Header.Sender.MsgIsZero()) && ((*z).Header.Fee.MsgIsZero()) && ((*z).Header.FirstValid.MsgIsZero()) && ((*z).Header.LastValid.MsgIsZero()) && (len((*z).Header.Note) == 0) && ((*z).Header.GenesisID == "") && ((*z).Header.GenesisHash.MsgIsZero()) && ((*z).Header.Group.MsgIsZero()) && ((*z).Header.Lease == ([LeaseByteLength]byte{})) && ((*z).Header.RekeyTo.MsgIsZero()) && ((*z).KeyregTxnFields.VotePK.MsgIsZero()) && ((*z).KeyregTxnFields.SelectionPK.MsgIsZero()) && ((*z).KeyregTxnFields.VoteFirst.MsgIsZero()) && ((*z).KeyregTxnFields.VoteLast.MsgIsZero()) && ((*z).KeyregTxnFields.VoteKeyDilution == 0) && ((*z).KeyregTxnFields.Nonparticipation == false) && ((*z).PaymentTxnFields.Receiver.MsgIsZero()) && ((*z).PaymentTxnFields.Amount.MsgIsZero()) && ((*z).PaymentTxnFields.CloseRemainderTo.MsgIsZero()) && ((*z).AssetConfigTxnFields.ConfigAsset.MsgIsZero()) && ((*z).AssetConfigTxnFields.AssetParams.MsgIsZero()) && ((*z).AssetTransferTxnFields.XferAsset.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetAmount == 0) && ((*z).AssetTransferTxnFields.AssetSender.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetReceiver.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetCloseTo.MsgIsZero()) && ((*z).AssetFreezeTxnFields.FreezeAccount.MsgIsZero()) && ((*z).AssetFreezeTxnFields.FreezeAsset.MsgIsZero()) && ((*z).AssetFreezeTxnFields.AssetFrozen == false) && ((*z).ApplicationCallTxnFields.ApplicationID.MsgIsZero()) && ((*z).ApplicationCallTxnFields.OnCompletion == 0) && (len((*z).ApplicationCallTxnFields.ApplicationArgs) == 0) && (len((*z).ApplicationCallTxnFields.Accounts) == 0) && (len((*z).ApplicationCallTxnFields.ForeignApps) == 0) && (len((*z).ApplicationCallTxnFields.ForeignAssets) == 0) && ((*z).ApplicationCallTxnFields.LocalStateSchema.MsgIsZero()) && ((*z).ApplicationCallTxnFields.GlobalStateSchema.MsgIsZero()) && (len((*z).ApplicationCallTxnFields.ApprovalProgram) == 0) && (len((*z).ApplicationCallTxnFields.ClearStateProgram) == 0) && ((*z).ApplicationCallTxnFields.ExtraProgramPages == 0) && ((*z).CompactCertTxnFields.CertRound.MsgIsZero()) && ((*z).CompactCertTxnFields.CertType.MsgIsZero()) && ((*z).CompactCertTxnFields.Cert.MsgIsZero())
}
// MarshalMsg implements msgp.Marshaler
diff --git a/data/transactions/transaction.go b/data/transactions/transaction.go
index fb356bb04..baf40a312 100644
--- a/data/transactions/transaction.go
+++ b/data/transactions/transaction.go
@@ -29,6 +29,9 @@ import (
// Txid is a hash used to uniquely identify individual transactions
type Txid crypto.Digest
+// LeaseByteLength is the byte length of a lease
+const LeaseByteLength = int(32)
+
// String converts txid to a pretty-printable string
func (txid Txid) String() string {
return fmt.Sprintf("%v", crypto.Digest(txid))
@@ -69,7 +72,7 @@ type Header struct {
// lease identified by the (Sender, Lease) pair of the transaction until
// the LastValid round passes. While this transaction possesses the
// lease, no other transaction specifying this lease can be confirmed.
- Lease [32]byte `codec:"lx"`
+ Lease [LeaseByteLength]byte `codec:"lx"`
// RekeyTo, if nonzero, sets the sender's AuthAddr to the given address
// If the RekeyTo address is the sender's actual address, the AuthAddr is set to zero
diff --git a/data/transactions/verify/verifiedTxnCache.go b/data/transactions/verify/verifiedTxnCache.go
index 0c9bbe2c0..2e228c4fc 100644
--- a/data/transactions/verify/verifiedTxnCache.go
+++ b/data/transactions/verify/verifiedTxnCache.go
@@ -21,6 +21,7 @@ import (
"github.com/algorand/go-deadlock"
+ "github.com/algorand/go-algorand/data/pooldata"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/data/transactions/logic"
"github.com/algorand/go-algorand/protocol"
@@ -67,6 +68,8 @@ type VerifiedTransactionCache interface {
UpdatePinned(pinnedTxns map[transactions.Txid]transactions.SignedTxn) error
// Pin function would mark the given transaction group as pinned.
Pin(txgroup []transactions.SignedTxn) error
+ // PinGroups function would mark the given transaction groups as pinned.
+ PinGroups(txgroups []pooldata.SignedTxGroup) error
}
// verifiedTransactionCache provides an implementation of the VerifiedTransactionCache interface
@@ -206,6 +209,25 @@ func (v *verifiedTransactionCache) UpdatePinned(pinnedTxns map[transactions.Txid
func (v *verifiedTransactionCache) Pin(txgroup []transactions.SignedTxn) (err error) {
v.bucketsLock.Lock()
defer v.bucketsLock.Unlock()
+ return v.pin(txgroup)
+}
+
+// PinGroups function would mark the given transaction groups as pinned.
+func (v *verifiedTransactionCache) PinGroups(txgroups []pooldata.SignedTxGroup) error {
+ v.bucketsLock.Lock()
+ defer v.bucketsLock.Unlock()
+ var outError error
+ for _, txgroup := range txgroups {
+ err := v.pin(txgroup.Transactions)
+ if err != nil {
+ outError = err
+ }
+ }
+ return outError
+}
+
+// Pin sets a given transaction group as pinned items, after they have already been verified.
+func (v *verifiedTransactionCache) pin(txgroup []transactions.SignedTxn) (err error) {
transactionMissing := false
if len(v.pinned)+len(txgroup) > maxPinnedEntries {
// reaching this number likely means that we have an issue not removing entries from the pinned map.
@@ -283,6 +305,10 @@ func (v *mockedCache) UpdatePinned(pinnedTxns map[transactions.Txid]transactions
return nil
}
+func (v *mockedCache) PinGroups(txgroups []pooldata.SignedTxGroup) error {
+ return nil
+}
+
func (v *mockedCache) Pin(txgroup []transactions.SignedTxn) (err error) {
return nil
}
diff --git a/data/txHandler.go b/data/txHandler.go
index fa8bf250b..4a6087aff 100644
--- a/data/txHandler.go
+++ b/data/txHandler.go
@@ -25,9 +25,11 @@ import (
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/bookkeeping"
+ "github.com/algorand/go-algorand/data/pooldata"
"github.com/algorand/go-algorand/data/pools"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/data/transactions/verify"
+ "github.com/algorand/go-algorand/ledger/ledgercore"
"github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/network"
"github.com/algorand/go-algorand/protocol"
@@ -175,7 +177,7 @@ func (handler *TxHandler) postprocessCheckedTxn(wi *txBacklogMsg) {
verifiedTxGroup := wi.unverifiedTxGroup
// save the transaction, if it has high enough fee and not already in the cache
- err := handler.txPool.Remember(verifiedTxGroup)
+ err := handler.txPool.Remember(pooldata.SignedTxGroup{Transactions: verifiedTxGroup})
if err != nil {
logging.Base().Debugf("could not remember tx: %v", err)
return
@@ -263,12 +265,6 @@ func (handler *TxHandler) processIncomingTxn(rawmsg network.IncomingMessage) net
// Note that this also checks the consistency of the transaction's group hash,
// which is required for safe transaction signature caching behavior.
func (handler *TxHandler) checkAlreadyCommitted(tx *txBacklogMsg) (processingDone bool) {
- txids := make([]transactions.Txid, len(tx.unverifiedTxGroup))
- for i := range tx.unverifiedTxGroup {
- txids[i] = tx.unverifiedTxGroup[i].ID()
- }
- logging.Base().Debugf("got a tx group with IDs %v", txids)
-
// do a quick test to check that this transaction could potentially be committed, to reject dup pending transactions
err := handler.txPool.Test(tx.unverifiedTxGroup)
if err != nil {
@@ -278,12 +274,12 @@ func (handler *TxHandler) checkAlreadyCommitted(tx *txBacklogMsg) (processingDon
return false
}
-func (handler *TxHandler) processDecoded(unverifiedTxGroup []transactions.SignedTxn) (outmsg network.OutgoingMessage, processingDone bool) {
+func (handler *TxHandler) processDecoded(unverifiedTxGroup []transactions.SignedTxn) (disconnect bool) {
tx := &txBacklogMsg{
unverifiedTxGroup: unverifiedTxGroup,
}
if handler.checkAlreadyCommitted(tx) {
- return network.OutgoingMessage{}, true
+ return false
}
// build the transaction verification context
@@ -291,7 +287,7 @@ func (handler *TxHandler) processDecoded(unverifiedTxGroup []transactions.Signed
latestHdr, err := handler.ledger.BlockHdr(latest)
if err != nil {
logging.Base().Warnf("Could not get header for previous block %v: %v", latest, err)
- return network.OutgoingMessage{}, true
+ return false
}
unverifiedTxnGroups := bookkeeping.SignedTxnsToGroups(unverifiedTxGroup)
@@ -299,7 +295,7 @@ func (handler *TxHandler) processDecoded(unverifiedTxGroup []transactions.Signed
if err != nil {
// transaction is invalid
logging.Base().Warnf("One or more transactions were malformed: %v", err)
- return network.OutgoingMessage{Action: network.Disconnect}, true
+ return true
}
// at this point, we've verified the transaction group,
@@ -307,10 +303,10 @@ func (handler *TxHandler) processDecoded(unverifiedTxGroup []transactions.Signed
verifiedTxGroup := unverifiedTxGroup
// save the transaction, if it has high enough fee and not already in the cache
- err = handler.txPool.Remember(verifiedTxGroup)
+ err = handler.txPool.Remember(pooldata.SignedTxGroup{Transactions: verifiedTxGroup})
if err != nil {
logging.Base().Debugf("could not remember tx: %v", err)
- return network.OutgoingMessage{}, true
+ return false
}
// if we remembered without any error ( i.e. txpool wasn't full ), then we should pin these transactions.
@@ -319,7 +315,98 @@ func (handler *TxHandler) processDecoded(unverifiedTxGroup []transactions.Signed
logging.Base().Warnf("unable to pin transaction: %v", err)
}
- return network.OutgoingMessage{}, false
+ return false
+}
+
+// filterAlreadyCommitted scan the list of signed transaction groups, and filter out the ones that have already been included,
+// or that should not be added to the transaction pool.
+// the resulting slice is using the *same* underlying array as the input slice, and the caller must ensure that this would not
+// cause issue on the caller side. The hasError describe whether any of the removed transacation groups was
+// removed for a reason *other* than being duplicate ( for instance, malformed transaction )
+func (handler *TxHandler) filterAlreadyCommitted(unverifiedTxGroups []pooldata.SignedTxGroup) (filteredGroups []pooldata.SignedTxGroup, hasError bool) {
+ remainedTxnsGroupOffset := 0
+ for idx, utxng := range unverifiedTxGroups {
+ err := handler.txPool.Test(utxng.Transactions)
+ switch err.(type) {
+ case nil:
+ // no error was generated.
+ if remainedTxnsGroupOffset != idx {
+ unverifiedTxGroups[remainedTxnsGroupOffset] = utxng
+ }
+ remainedTxnsGroupOffset++
+ case *ledgercore.TransactionInLedgerError:
+ // this is a duplicate transaction group.
+ default:
+ // some non-duplicate error was reported on this group.
+ hasError = true
+ }
+ }
+ return unverifiedTxGroups[:remainedTxnsGroupOffset], hasError
+}
+
+// processDecodedArray receives a slice of transaction groups and attempt to add them to the transaction pool.
+// The processDecodedArray returns whether the node should be disconnecting from the source of these transactions ( in case a malicious transaction is found )
+// as well as whether all the provided transactions were included in the transaction pool or committed.
+func (handler *TxHandler) processDecodedArray(unverifiedTxGroups []pooldata.SignedTxGroup) (disconnect, allTransactionIncluded bool) {
+ var hasError bool
+ unverifiedTxGroups, hasError = handler.filterAlreadyCommitted(unverifiedTxGroups)
+
+ if len(unverifiedTxGroups) == 0 {
+ return false, !hasError
+ }
+
+ // build the transaction verification context
+ latest := handler.ledger.Latest()
+ latestHdr, err := handler.ledger.BlockHdr(latest)
+ if err != nil {
+ // being unable to retrieve the last's block header is not something a working node is expected to expirience ( ever ).
+ logging.Base().Errorf("Could not get header for previous block %d: %v", latest, err)
+ // returning a disconnect=true, would not fix the problem for the local node, but would force the remote node to pick a different
+ // relay, which ( hopefully ! ) would not have the same issue as this one.
+ return true, false
+ }
+
+ unverifiedTxnGroups := make([][]transactions.SignedTxn, len(unverifiedTxGroups))
+ for i, unverifiedGroup := range unverifiedTxGroups {
+ unverifiedTxnGroups[i] = unverifiedGroup.Transactions
+ }
+
+ err = verify.PaysetGroups(context.Background(), unverifiedTxnGroups, latestHdr, handler.txVerificationPool, handler.ledger.VerifiedTransactionCache())
+ if err != nil {
+ // transaction is invalid
+ logging.Base().Warnf("One or more transactions were malformed: %v", err)
+ return true, false
+ }
+
+ // at this point, we've verified the transaction group,
+ // so we can safely treat the transaction as a verified transaction.
+ verifiedTxGroups := unverifiedTxGroups
+
+ // before calling RememberArray we should reallocate the individual remaining
+ // signed transactions - these transactions were allocated in bulk by the
+ // transaction sync. By re-allocating the backing storage, we would allow the
+ // original backing storage ( which includes transactions that won't go into the
+ // transaction pool ) to be garbge collected.
+ for i, group := range verifiedTxGroups {
+ copiedTransactions := make(pooldata.SignedTxnSlice, len(group.Transactions))
+ copy(copiedTransactions, group.Transactions)
+ verifiedTxGroups[i].Transactions = copiedTransactions
+ }
+
+ // save the transaction, if it has high enough fee and not already in the cache
+ err = handler.txPool.RememberArray(verifiedTxGroups)
+ if err != nil {
+ logging.Base().Debugf("could not remember tx: %v", err)
+ return false, false
+ }
+
+ // if we remembered without any error ( i.e. txpool wasn't full ), then we should pin these transactions.
+ err = handler.ledger.VerifiedTransactionCache().PinGroups(verifiedTxGroups)
+ if err != nil {
+ logging.Base().Warnf("unable to pin transaction: %v", err)
+ }
+
+ return false, !hasError
}
// SolicitedTxHandler handles messages received through channels other than the gossip network.
@@ -328,19 +415,136 @@ type SolicitedTxHandler interface {
Handle(txgroup []transactions.SignedTxn) error
}
+type solicitedTxHandler struct {
+ txHandler *TxHandler
+}
+
// SolicitedTxHandler converts a transaction handler to a SolicitedTxHandler
func (handler *TxHandler) SolicitedTxHandler() SolicitedTxHandler {
return &solicitedTxHandler{txHandler: handler}
}
-type solicitedTxHandler struct {
- txHandler *TxHandler
-}
-
func (handler *solicitedTxHandler) Handle(txgroup []transactions.SignedTxn) error {
- outmsg, _ := handler.txHandler.processDecoded(txgroup)
- if outmsg.Action == network.Disconnect {
+ disconnect := handler.txHandler.processDecoded(txgroup)
+ if disconnect {
return fmt.Errorf("invalid transaction")
}
return nil
}
+
+// SolicitedAsyncTxHandler handles slices of transaction groups received from the transaction sync.
+// It provides a non-blocking queueing for the processing of these transaction groups, which allows
+// the single-threaded transaction sync to keep processing other messages.
+type SolicitedAsyncTxHandler interface {
+ // HandleTransactionGroups enqueues the given slice of transaction groups that came from the given network peer with
+ // the given message sequence number. The provided acknowledgement channel provides a feedback for the transaction sync
+ // that the entire transaction group slice was added ( or already included ) within the transaction pool. The method
+ // return true if it's able to enqueue the processing task, or false if it's unable to enqueue the processing task.
+ HandleTransactionGroups(networkPeer interface{}, ackCh chan uint64, messageSeq uint64, groups []pooldata.SignedTxGroup) bool
+ Start()
+ Stop()
+}
+
+type solicitedAsyncTxHandler struct {
+ txHandler *TxHandler
+ backlogGroups chan *txGroups
+ stopped sync.WaitGroup
+ stopCtxFunc context.CancelFunc
+ // skipNextBacklogWarning is used to avoid repeated backlog full warning messages.
+ skipNextBacklogWarning bool
+}
+
+type txGroups struct {
+ // the network package opaque network peer
+ networkPeer interface{}
+ // the feedback channel, in case we've successfully added the transaction groups to the transaction pool.
+ ackCh chan uint64
+ // the message sequence number, which would be written back to the feedback channel
+ messageSeq uint64
+ // the transactions groups slice
+ txGroups []pooldata.SignedTxGroup
+}
+
+// SolicitedAsyncTxHandler converts a transaction handler to a SolicitedTxHandler
+func (handler *TxHandler) SolicitedAsyncTxHandler() SolicitedAsyncTxHandler {
+ return &solicitedAsyncTxHandler{
+ txHandler: handler,
+ backlogGroups: make(chan *txGroups, txBacklogSize),
+ skipNextBacklogWarning: false,
+ }
+}
+
+// HandleTransactionGroups implements the solicitedAsyncTxHandler.HandleTransactionGroups interface.
+// It enqueues the given slice of transaction groups that came from the given network peer with
+// the given message sequence number. The provided acknowledgement channel provides a feedback for the transaction sync
+// that the entire transaction group slice was added ( or already included ) within the transaction pool. The method
+// return true if it's able to enqueue the processing task, or false if it's unable to enqueue the processing task.
+func (handler *solicitedAsyncTxHandler) HandleTransactionGroups(networkPeer interface{}, ackCh chan uint64, messageSeq uint64, groups []pooldata.SignedTxGroup) (enqueued bool) {
+ select {
+ case handler.backlogGroups <- &txGroups{networkPeer: networkPeer, txGroups: groups, ackCh: ackCh, messageSeq: messageSeq}:
+ // reset the skipNextBacklogWarning once the number of pending items on the backlogGroups channels goes to
+ // less than half of it's capacity.
+ if handler.skipNextBacklogWarning && (len(handler.backlogGroups)*2 < cap(handler.backlogGroups)) {
+ handler.skipNextBacklogWarning = false
+ }
+ enqueued = true
+ default:
+ if !handler.skipNextBacklogWarning {
+ logging.Base().Warnf("solicitedAsyncTxHandler exhusted groups backlog")
+ handler.skipNextBacklogWarning = true
+ }
+ // if we failed here we want to increase the corresponding metric. It might suggest that we
+ // want to increase the queue size.
+ transactionMessagesDroppedFromBacklog.Inc(nil)
+ }
+ return
+}
+
+func (handler *solicitedAsyncTxHandler) Start() {
+ if handler.stopCtxFunc == nil {
+ var ctx context.Context
+ ctx, handler.stopCtxFunc = context.WithCancel(context.Background())
+ handler.stopped.Add(1)
+ go handler.loop(ctx)
+ }
+}
+
+func (handler *solicitedAsyncTxHandler) Stop() {
+ if handler.stopCtxFunc != nil {
+ handler.stopCtxFunc()
+ handler.stopped.Wait()
+ handler.stopCtxFunc = nil
+ }
+}
+
+func (handler *solicitedAsyncTxHandler) loop(ctx context.Context) {
+ defer handler.stopped.Done()
+ var groups *txGroups
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case groups = <-handler.backlogGroups:
+ }
+ disconnect, allTransactionsIncluded := handler.txHandler.processDecodedArray(groups.txGroups)
+ if disconnect {
+ handler.txHandler.net.Disconnect(groups.networkPeer)
+ handler.txHandler.net.RequestConnectOutgoing(false, make(chan struct{}))
+ transactionMessagesDroppedFromPool.Inc(nil)
+ } else if allTransactionsIncluded {
+ select {
+ case groups.ackCh <- groups.messageSeq:
+ // all good, write was successful.
+ default:
+ // unable to write since channel was full - log this:
+ logging.Base().Warnf("solicitedAsyncTxHandler was unable to ack transaction groups inclusion since the acknowledgement channel was full")
+ }
+ // we've processed this message, so increase the counter.
+ transactionMessagesHandled.Inc(nil)
+ } else {
+ transactionMessagesDroppedFromPool.Inc(nil)
+ }
+ // clear out the groups; that would allow the GC to collect the group's memory allocations while we wait for the next task.
+ *groups = txGroups{}
+ }
+}
diff --git a/data/txHandler_test.go b/data/txHandler_test.go
index a53d83163..ad3bbc833 100644
--- a/data/txHandler_test.go
+++ b/data/txHandler_test.go
@@ -29,19 +29,18 @@ import (
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
+ "github.com/algorand/go-algorand/data/pooldata"
"github.com/algorand/go-algorand/data/pools"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/test/partitiontest"
"github.com/algorand/go-algorand/util/execpool"
)
-func BenchmarkTxHandlerProcessDecoded(b *testing.B) {
- b.StopTimer()
- b.ResetTimer()
- const numRounds = 10
+func makeTestingTransactionPoolAndLedger(tb testing.TB, N int) (*pools.TransactionPool, *Ledger, []*crypto.SignatureSecrets, []basics.Address) {
const numUsers = 100
- log := logging.TestingLog(b)
+ log := logging.TestingLog(tb)
secrets := make([]*crypto.SignatureSecrets, numUsers)
addresses := make([]basics.Address, numUsers)
@@ -62,20 +61,25 @@ func BenchmarkTxHandlerProcessDecoded(b *testing.B) {
MicroAlgos: basics.MicroAlgos{Raw: config.Consensus[protocol.ConsensusCurrentVersion].MinBalance},
}
- require.Equal(b, len(genesis), numUsers+1)
+ require.Equal(tb, len(genesis), numUsers+1)
genBal := bookkeeping.MakeGenesisBalances(genesis, sinkAddr, poolAddr)
- ledgerName := fmt.Sprintf("%s-mem-%d", b.Name(), b.N)
+ ledgerName := fmt.Sprintf("%s-mem-%d", tb.Name(), N)
const inMem = true
cfg := config.GetDefaultLocal()
cfg.Archival = true
ledger, err := LoadLedger(log, ledgerName, inMem, protocol.ConsensusCurrentVersion, genBal, genesisID, genesisHash, nil, cfg)
- require.NoError(b, err)
-
- l := ledger
+ require.NoError(tb, err)
cfg.TxPoolSize = 20000
cfg.EnableProcessBlockStats = false
- tp := pools.MakeTransactionPool(l.Ledger, cfg, logging.Base())
+ tp := pools.MakeTransactionPool(ledger.Ledger, cfg, logging.Base())
+ return tp, ledger, secrets, addresses
+}
+
+func BenchmarkTxHandlerProcessDecoded(b *testing.B) {
+ const numUsers = 100
+ tp, l, secrets, addresses := makeTestingTransactionPoolAndLedger(b, b.N)
+ defer l.Close()
signedTransactions := make([]transactions.SignedTxn, 0, b.N)
for i := 0; i < b.N/numUsers; i++ {
for u := 0; u < numUsers; u++ {
@@ -100,19 +104,17 @@ func BenchmarkTxHandlerProcessDecoded(b *testing.B) {
}
backlogPool := execpool.MakeBacklog(nil, 0, execpool.LowPriority, nil)
txHandler := MakeTxHandler(tp, l, &mocks.MockNetwork{}, "", crypto.Digest{}, backlogPool)
- b.StartTimer()
+ b.ResetTimer()
for _, signedTxn := range signedTransactions {
txHandler.processDecoded([]transactions.SignedTxn{signedTxn})
}
}
func BenchmarkTimeAfter(b *testing.B) {
- b.StopTimer()
- b.ResetTimer()
deadline := time.Now().Add(5 * time.Second)
after := 0
before := 0
- b.StartTimer()
+ b.ResetTimer()
for i := 0; i < b.N; i++ {
if time.Now().After(deadline) {
after++
@@ -121,3 +123,143 @@ func BenchmarkTimeAfter(b *testing.B) {
}
}
}
+func TestFilterAlreadyCommitted(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ const numUsers = 100
+ tp, l, secrets, addresses := makeTestingTransactionPoolAndLedger(t, 1)
+ defer l.Close()
+ signedTransactions := make([]transactions.SignedTxn, 0, 100)
+
+ for u := 0; u < numUsers; u++ {
+ // generate transactions
+ tx := transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: addresses[u],
+ Fee: basics.MicroAlgos{Raw: proto.MinTxnFee * 2},
+ FirstValid: 0,
+ LastValid: basics.Round(proto.MaxTxnLife),
+ GenesisHash: l.GenesisHash(),
+ Note: make([]byte, 2),
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: addresses[(u+1)%numUsers],
+ Amount: basics.MicroAlgos{Raw: mockBalancesMinBalance + (rand.Uint64() % 10000)},
+ },
+ }
+ signedTx := tx.Sign(secrets[u])
+ signedTransactions = append(signedTransactions, signedTx)
+ }
+
+ backlogPool := execpool.MakeBacklog(nil, 0, execpool.LowPriority, nil)
+ txHandler := MakeTxHandler(tp, l, &mocks.MockNetwork{}, "", crypto.Digest{}, backlogPool)
+
+ // add the first 10 transactions to the pool.
+ for i := 0; i < 10; i++ {
+ tp.Remember(pooldata.SignedTxGroup{Transactions: []transactions.SignedTxn{signedTransactions[i]}})
+ }
+
+ allNew := []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[10:11],
+ },
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[11:12],
+ },
+ }
+ allNewRef := []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[10:11],
+ },
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[11:12],
+ },
+ }
+ allNewTransactions, allNewNonDupFilteredGroups := txHandler.filterAlreadyCommitted(allNew)
+ require.Equal(t, allNewRef, allNewTransactions)
+ require.False(t, allNewNonDupFilteredGroups)
+
+ firstTxDup := []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ Transactions: []transactions.SignedTxn{signedTransactions[1]},
+ },
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[11:12],
+ },
+ }
+ firstTxExpectedOutput := []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[11:12],
+ },
+ }
+ firstTxDupTransactions, firstTxDupNonDupFilteredGroups := txHandler.filterAlreadyCommitted(firstTxDup)
+ require.Equal(t, firstTxExpectedOutput, firstTxDupTransactions)
+ require.False(t, firstTxDupNonDupFilteredGroups)
+
+ lastTxDup := []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[11:12],
+ },
+ pooldata.SignedTxGroup{
+ Transactions: []transactions.SignedTxn{signedTransactions[1]},
+ },
+ }
+ lastTxExpectedOutput := []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[11:12],
+ },
+ }
+ lastTxDupTransactions, lastTxDupNonDupFilteredGroups := txHandler.filterAlreadyCommitted(lastTxDup)
+ require.Equal(t, lastTxExpectedOutput, lastTxDupTransactions)
+ require.False(t, lastTxDupNonDupFilteredGroups)
+
+ midTxDup := []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[10:11],
+ },
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[11:12],
+ },
+ pooldata.SignedTxGroup{
+ Transactions: []transactions.SignedTxn{signedTransactions[1]},
+ },
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[13:14],
+ },
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[14:15],
+ },
+ pooldata.SignedTxGroup{
+ Transactions: []transactions.SignedTxn{signedTransactions[2]},
+ },
+ pooldata.SignedTxGroup{
+ Transactions: []transactions.SignedTxn{signedTransactions[3]},
+ },
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[15:16],
+ },
+ }
+ midTxDupExpectedOutput := []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[10:11],
+ },
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[11:12],
+ },
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[13:14],
+ },
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[14:15],
+ },
+ pooldata.SignedTxGroup{
+ Transactions: signedTransactions[15:16],
+ },
+ }
+ midTxDupTransactions, midTxDupNonDupFilteredGroups := txHandler.filterAlreadyCommitted(midTxDup)
+ require.Equal(t, midTxDupExpectedOutput, midTxDupTransactions)
+ require.False(t, midTxDupNonDupFilteredGroups)
+
+ return
+}
diff --git a/go.mod b/go.mod
index 1feb160f8..2ecfb9903 100644
--- a/go.mod
+++ b/go.mod
@@ -9,6 +9,7 @@ require (
github.com/algorand/msgp v1.1.48
github.com/algorand/oapi-codegen v1.3.5-algorand5
github.com/algorand/websocket v1.4.2
+ github.com/algorand/xorfilter v0.2.0
github.com/aws/aws-sdk-go v1.16.5
github.com/chrismcguire/gobberish v0.0.0-20150821175641-1d8adb509a0e
github.com/cpuguy83/go-md2man v1.0.8 // indirect
diff --git a/go.sum b/go.sum
index 723fd7e94..c5e86d8ce 100644
--- a/go.sum
+++ b/go.sum
@@ -12,13 +12,14 @@ github.com/algorand/oapi-codegen v1.3.5-algorand5 h1:y576Ca2/guQddQrQA7dtL5KcOx5
github.com/algorand/oapi-codegen v1.3.5-algorand5/go.mod h1:/k0Ywn0lnt92uBMyE+yiRf/Wo3/chxHHsAfenD09EbY=
github.com/algorand/websocket v1.4.2 h1:zMB7ukz+c7tcef8rVqmKQTv6KQtxXtCFuiAqKaE7n9I=
github.com/algorand/websocket v1.4.2/go.mod h1:0nFSn+xppw/GZS9hgWPS3b8/4FcA3Pj7XQxm+wqHGx8=
+github.com/algorand/xorfilter v0.2.0 h1:YC31ANxdZ2jmtbwqv1+USskVSqjkeiRZcQGc6//ro9Q=
+github.com/algorand/xorfilter v0.2.0/go.mod h1:f5cJsYrFbJhXkbjnV4odJB44np05/PvwvdBnABnQoUs=
github.com/aws/aws-sdk-go v1.16.5 h1:NVxzZXIuwX828VcJrpNxxWjur1tlOBISdMdDdHIKHcc=
github.com/aws/aws-sdk-go v1.16.5/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/chrismcguire/gobberish v0.0.0-20150821175641-1d8adb509a0e h1:CHPYEbz71w8DqJ7DRIq+MXyCQsdibK08vdcQTY4ufas=
github.com/chrismcguire/gobberish v0.0.0-20150821175641-1d8adb509a0e/go.mod h1:6Xhs0ZlsRjXLIiSMLKafbZxML/j30pg9Z1priLuha5s=
github.com/cpuguy83/go-md2man v1.0.8 h1:DwoNytLphI8hzS2Af4D0dfaEaiSq2bN05mEm4R6vf8M=
github.com/cpuguy83/go-md2man v1.0.8/go.mod h1:N6JayAiVKtlHSnuTCeuLSQVs75hb8q+dYQLjr7cDsKY=
-github.com/cyberdelia/templates v0.0.0-20191230040416-20a325f050d4 h1:Fphwr1XDjkTR/KFbrrkLfY6D2CEOlHqFGomQQrxcHFs=
github.com/cyberdelia/templates v0.0.0-20191230040416-20a325f050d4/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -31,7 +32,6 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/gen2brain/beeep v0.0.0-20180718162406-4e430518395f h1:eyHMPp7tXlBMF8PZHdsL89G0ehuRNflu7zKUeoQjcJ0=
github.com/gen2brain/beeep v0.0.0-20180718162406-4e430518395f/go.mod h1:GprdPCZglWh5OMcIDpeKBxuUJI+fEDOTVUfxZeda4zo=
@@ -40,33 +40,24 @@ github.com/getkin/kin-openapi v0.22.0 h1:J5IFyKd/5yuB6AZAgwK0CMBKnabWcmkowtsl6bR
github.com/getkin/kin-openapi v0.22.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/go-chi/chi v4.1.1+incompatible h1:MmTgB0R8Bt/jccxp+t6S/1VGIKdJw5J74CK/c9tTfA4=
github.com/go-chi/chi v4.1.1+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
-github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/godbus/dbus v0.0.0-20181101234600-2ff6f7ffd60f h1:zlOR3rOlPAVvtfuxGKoghCmop5B0TRyu/ZieziZuGiM=
github.com/godbus/dbus v0.0.0-20181101234600-2ff6f7ffd60f/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/gofrs/flock v0.7.0 h1:pGFUjl501gafK9HBt1VGL1KCOd/YhIooID+xgyJCf3g=
github.com/gofrs/flock v0.7.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
-github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
-github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
-github.com/gopherjs/gopherwasm v1.0.1 h1:Gmj9RMDjh+P9EFzzQltoCtjAxR5mUkaJqaNPfeaNe2I=
github.com/gopherjs/gopherwasm v1.0.1/go.mod h1:SkZ8z7CWBz5VXbhJel8TxCmAcsQqzgWGR/8nMhyhZSI=
-github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/gorilla/schema v1.0.2 h1:sAgNfOcNYvdDSrzGHVy9nzCQahG+qmsg+nE8dK85QRA=
github.com/gorilla/schema v1.0.2/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
-github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -80,22 +71,17 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGi
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
-github.com/labstack/echo/v4 v4.1.16 h1:8swiwjE5Jkai3RPfZoahp8kjVCRNq+y7Q0hPji2Kz0o=
github.com/labstack/echo/v4 v4.1.16/go.mod h1:awO+5TzAjvL8XpibdsfXxPgHr+orhtXZJZIQCVjogKI=
github.com/labstack/echo/v4 v4.1.17 h1:PQIBaRplyRy3OjwILGkPg89JRtH2x5bssi59G2EL3fo=
github.com/labstack/echo/v4 v4.1.17/go.mod h1:Tn2yRQL/UclUalpb5rPdXDevbkJ+lp/2svdyFBg6CHQ=
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
-github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/matryer/moq v0.0.0-20200310130814-7721994d1b54 h1:p8zN0Xu28xyEkPpqLbFXAnjdgBVvTJCpfOtoDf/+/RQ=
github.com/matryer/moq v0.0.0-20200310130814-7721994d1b54/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
@@ -108,9 +94,7 @@ github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK86
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/miekg/dns v1.1.27 h1:aEH/kqUzUxGJ/UHcEKdJY+ugH6WEzsEBBSPa8zuy1aM=
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
github.com/olivere/elastic v6.2.14+incompatible h1:k+KadwNP/dkXE0/eu+T6otk1+5fe0tEpPyQJ4XVm5i8=
github.com/olivere/elastic v6.2.14+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8=
@@ -136,16 +120,13 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31 h1:OXcKh35JaYsGMRzpvFkLv/MEyPuL49CThT1pZ8aSml4=
github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
-github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4=
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
@@ -158,7 +139,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
-golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
@@ -171,7 +151,6 @@ golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOL
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -187,7 +166,6 @@ golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f h1:Fqb3ao1hUmOR3GkUOg/Y+BadLwykBIzs5q8Ez2SbHyc=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -199,17 +177,13 @@ golang.org/x/tools v0.0.0-20200423205358-59e73619c742 h1:9OGWpORUXvk8AsaBJlpzzDx
golang.org/x/tools v0.0.0-20200423205358-59e73619c742/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/sohlich/elogrus.v3 v3.0.0-20180410122755-1fa29e2f2009 h1:q/fZgS8MMadqFFGa8WL4Oyz+TmjiZfi8UrzWhTl8d5w=
gopkg.in/sohlich/elogrus.v3 v3.0.0-20180410122755-1fa29e2f2009/go.mod h1:O0bY1e/dSoxMYZYTHP0SWKxG5EWLEvKR9/cOjWPPMKU=
-gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 h1:MZF6J7CV6s/h0HBkfqebrYfKCVEo5iN+wzE4QhV3Evo=
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2/go.mod h1:s1Sn2yZos05Qfs7NKt867Xe18emOmtsO3eAKbDaon0o=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/installer/config.json.example b/installer/config.json.example
index 42b6361bd..aa80a6dad 100644
--- a/installer/config.json.example
+++ b/installer/config.json.example
@@ -1,5 +1,5 @@
{
- "Version": 16,
+ "Version": 17,
"AccountUpdatesStatsInterval": 5000000000,
"AccountsRebuildSynchronousMode": 1,
"AnnounceParticipationKey": true,
@@ -44,11 +44,13 @@
"EnableProfiler": false,
"EnableRequestLogger": false,
"EnableTopAccountsReporting": false,
+ "EnableVerbosedTransactionSyncLogging": false,
"EndpointAddress": "127.0.0.1:0",
"FallbackDNSResolverAddress": "",
+ "ForceFetchTransactions": false,
"ForceRelayMessages": false,
"GossipFanout": 4,
- "IncomingConnectionsLimit": 10000,
+ "IncomingConnectionsLimit": 800,
"IncomingMessageFilterBucketCount": 5,
"IncomingMessageFilterBucketSize": 512,
"IsIndexerActive": false,
@@ -82,6 +84,8 @@
"TLSCertFile": "",
"TLSKeyFile": "",
"TelemetryToLog": true,
+ "TransactionSyncDataExchangeRate": 0,
+ "TransactionSyncSignificantMessageThreshold": 0,
"TxPoolExponentialIncreaseFactor": 2,
"TxPoolSize": 15000,
"TxSyncIntervalSeconds": 60,
diff --git a/ledger/README.md b/ledger/README.md
index 37d6baed7..04c088e4c 100644
--- a/ledger/README.md
+++ b/ledger/README.md
@@ -124,13 +124,13 @@ three functions:
- Construct a new block, based on a pool of potential transactions
and rewards, that will be valid. This is done by using
- the `Ledger.StartEvaluator(hdr, txcache)` method. This returns a
- `BlockEvaluator`, which can then accept tentative transactions
+ the `Ledger.StartEvaluator(hdr, paysetHint, maxTxnBytesPerBlock)` method.
+ This returns a `BlockEvaluator`, which can then accept tentative transactions
and rewards (using `BlockEvaluator.Transaction()` and
`BlockEvaluator.Reward()`). The caller can finalize the block by
- calling `BlockEvaluator.GenerateBlock()`. `txcache` represents a
- cache of previously verified transactions, to avoid repeated checking
- of transaction signatures.
+ calling `BlockEvaluator.GenerateBlock()`. `paysetHint` provides a hint
+ to the evaluator for the upcoming number of transactions. `maxTxnBytesPerBlock`
+ allows the evaluator to adjust the size of the block dynamically.
- Validate a block. This is done by calling `Ledger.Validate(block, txcache)`.
Under the covers, it executes the same logic using a `BlockEvaluator`.
diff --git a/ledger/appcow.go b/ledger/appcow.go
index 30c481d05..c5f20454e 100644
--- a/ledger/appcow.go
+++ b/ledger/appcow.go
@@ -484,7 +484,12 @@ func (cb *roundCowState) StatefulEval(params logic.EvalParams, aidx basics.AppIn
var cx *logic.EvalContext
pass, cx, err = logic.EvalStatefulCx(program, params)
if err != nil {
- return false, transactions.EvalDelta{}, ledgercore.LogicEvalError{Err: err}
+ var details string
+ if cx != nil {
+ pc, det := cx.PcDetails()
+ details = fmt.Sprintf("pc=%d, opcodes=%s", pc, det)
+ }
+ return false, transactions.EvalDelta{}, ledgercore.LogicEvalError{Err: err, Details: details}
}
// If program passed, build our eval delta, and commit to state changes
diff --git a/ledger/applications.go b/ledger/applications.go
index 9b3cb27b4..5d4e8c3b7 100644
--- a/ledger/applications.go
+++ b/ledger/applications.go
@@ -273,6 +273,11 @@ func (al *logicLedger) Perform(tx *transactions.Transaction, spec transactions.S
return ad, err
}
+ err = apply.Rekey(balances, tx)
+ if err != nil {
+ return ad, err
+ }
+
// compared to eval.transaction() it may seem strange that we
// increment the transaction count *before* transaction
// processing, rather than after. But we need to account for the
@@ -287,12 +292,18 @@ func (al *logicLedger) Perform(tx *transactions.Transaction, spec transactions.S
switch tx.Type {
case protocol.PaymentTx:
err = apply.Payment(tx.PaymentTxnFields, tx.Header, balances, spec, &ad)
- case protocol.AssetTransferTx:
- err = apply.AssetTransfer(tx.AssetTransferTxnFields, tx.Header, balances, spec, &ad)
+
+ case protocol.KeyRegistrationTx:
+ err = apply.Keyreg(tx.KeyregTxnFields, tx.Header, balances, spec, &ad, al.Round())
+
case protocol.AssetConfigTx:
err = apply.AssetConfig(tx.AssetConfigTxnFields, tx.Header, balances, spec, &ad, al.cow.txnCounter())
+
+ case protocol.AssetTransferTx:
+ err = apply.AssetTransfer(tx.AssetTransferTxnFields, tx.Header, balances, spec, &ad)
case protocol.AssetFreezeTx:
err = apply.AssetFreeze(tx.AssetFreezeTxnFields, tx.Header, balances, spec, &ad)
+
default:
err = fmt.Errorf("%s tx in AVM", tx.Type)
}
diff --git a/ledger/apply/apply.go b/ledger/apply/apply.go
index 988ae8cb9..f6a91ed8e 100644
--- a/ledger/apply/apply.go
+++ b/ledger/apply/apply.go
@@ -64,3 +64,26 @@ type Balances interface {
// to a ConsensusParams. This returns those parameters.
ConsensusParams() config.ConsensusParams
}
+
+// Rekey updates tx.Sender's AuthAddr to tx.RekeyTo, if provided
+func Rekey(balances Balances, tx *transactions.Transaction) error {
+ if (tx.RekeyTo != basics.Address{}) {
+ acct, err := balances.Get(tx.Sender, false)
+ if err != nil {
+ return err
+ }
+ // Special case: rekeying to the account's actual address just sets acct.AuthAddr to 0
+ // This saves 32 bytes in your balance record if you want to go back to using your original key
+ if tx.RekeyTo == tx.Sender {
+ acct.AuthAddr = basics.Address{}
+ } else {
+ acct.AuthAddr = tx.RekeyTo
+ }
+
+ err = balances.Put(tx.Sender, acct)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/ledger/apptxn_test.go b/ledger/apptxn_test.go
index 5527b385e..800668af9 100644
--- a/ledger/apptxn_test.go
+++ b/ledger/apptxn_test.go
@@ -984,3 +984,202 @@ func TestAsaDuringInit(t *testing.T) {
asaIndex := vb.blk.Payset[1].EvalDelta.InnerTxns[0].ConfigAsset
require.Equal(t, basics.AssetIndex(3), asaIndex)
}
+
+func TestRekey(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ genBalances, addrs, _ := newTestGenesis()
+ l := newTestLedger(t, genBalances)
+ defer l.Close()
+
+ app := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
+ itxn_begin
+ int pay
+ itxn_field TypeEnum
+ int 1
+ itxn_field Amount
+ global CurrentApplicationAddress
+ itxn_field Receiver
+ int 31
+ bzero
+ byte 0x01
+ concat
+ itxn_field RekeyTo
+ itxn_submit
+`),
+ }
+
+ eval := l.nextBlock(t)
+ eval.txns(t, &app)
+ vb := l.endBlock(t, eval)
+ appIndex := vb.blk.Payset[0].ApplicationID
+ require.Equal(t, basics.AppIndex(1), appIndex)
+
+ fund := txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: appIndex.Address(),
+ Amount: 1_000_000,
+ }
+ rekey := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[1],
+ ApplicationID: appIndex,
+ }
+ eval = l.nextBlock(t)
+ eval.txns(t, &fund, &rekey)
+ eval.txn(t, rekey.Noted("2"), "unauthorized")
+ l.endBlock(t, eval)
+
+}
+
+func TestNote(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ genBalances, addrs, _ := newTestGenesis()
+ l := newTestLedger(t, genBalances)
+ defer l.Close()
+
+ app := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
+ itxn_begin
+ int pay
+ itxn_field TypeEnum
+ int 0
+ itxn_field Amount
+ global CurrentApplicationAddress
+ itxn_field Receiver
+ byte "abcdefghijklmnopqrstuvwxyz01234567890"
+ itxn_field Note
+ itxn_submit
+`),
+ }
+
+ eval := l.nextBlock(t)
+ eval.txns(t, &app)
+ vb := l.endBlock(t, eval)
+ appIndex := vb.blk.Payset[0].ApplicationID
+ require.Equal(t, basics.AppIndex(1), appIndex)
+
+ fund := txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: appIndex.Address(),
+ Amount: 1_000_000,
+ }
+ note := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[1],
+ ApplicationID: appIndex,
+ }
+ eval = l.nextBlock(t)
+ eval.txns(t, &fund, &note)
+ vb = l.endBlock(t, eval)
+ alphabet := vb.blk.Payset[1].EvalDelta.InnerTxns[0].Txn.Note
+ require.Equal(t, "abcdefghijklmnopqrstuvwxyz01234567890", string(alphabet))
+}
+
+func TestKeyreg(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ genBalances, addrs, _ := newTestGenesis()
+ l := newTestLedger(t, genBalances)
+ defer l.Close()
+
+ app := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
+ txn ApplicationArgs 0
+ byte "pay"
+ ==
+ bz nonpart
+ itxn_begin
+ int pay
+ itxn_field TypeEnum
+ int 1
+ itxn_field Amount
+ txn Sender
+ itxn_field Receiver
+ itxn_submit
+ int 1
+ return
+nonpart:
+ itxn_begin
+ int keyreg
+ itxn_field TypeEnum
+ int 1
+ itxn_field Nonparticipation
+ itxn_submit
+`),
+ }
+
+ // Create the app
+ eval := l.nextBlock(t)
+ eval.txns(t, &app)
+ vb := l.endBlock(t, eval)
+ appIndex := vb.blk.Payset[0].ApplicationID
+ require.Equal(t, basics.AppIndex(1), appIndex)
+
+ // Give the app a lot of money
+ fund := txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: appIndex.Address(),
+ Amount: 1_000_000_000,
+ }
+ eval = l.nextBlock(t)
+ eval.txn(t, &fund)
+ vb = l.endBlock(t, eval)
+
+ require.Equal(t, 1_000_000_000, int(l.micros(t, appIndex.Address())))
+
+ // Build up Residue in RewardsState so it's ready to pay
+ for i := 1; i < 10; i++ {
+ eval := l.nextBlock(t)
+ l.endBlock(t, eval)
+ }
+
+ // pay a little
+ pay := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApplicationID: appIndex,
+ ApplicationArgs: [][]byte{[]byte("pay")},
+ }
+ eval = l.nextBlock(t)
+ eval.txn(t, &pay)
+ l.endBlock(t, eval)
+ // 2000 was earned in rewards (- 1000 fee, -1 pay)
+ require.Equal(t, 1_000_000_999, int(l.micros(t, appIndex.Address())))
+
+ // Go nonpart
+ nonpart := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApplicationID: appIndex,
+ ApplicationArgs: [][]byte{[]byte("nonpart")},
+ }
+ eval = l.nextBlock(t)
+ eval.txn(t, &nonpart)
+ l.endBlock(t, eval)
+ require.Equal(t, 999_999_999, int(l.micros(t, appIndex.Address())))
+
+ // Build up Residue in RewardsState so it's ready to pay AGAIN
+ // But expect no rewards
+ for i := 1; i < 100; i++ {
+ eval := l.nextBlock(t)
+ l.endBlock(t, eval)
+ }
+ eval = l.nextBlock(t)
+ eval.txn(t, pay.Noted("again"))
+ eval.txn(t, nonpart.Noted("again"), "cannot change online/offline")
+ l.endBlock(t, eval)
+ // Ppaid fee and 1. Did not get rewards
+ require.Equal(t, 999_998_998, int(l.micros(t, appIndex.Address())))
+}
diff --git a/ledger/eval.go b/ledger/eval.go
index 9bb9947c2..7b239d3cf 100644
--- a/ledger/eval.go
+++ b/ledger/eval.go
@@ -388,9 +388,10 @@ type BlockEvaluator struct {
proto config.ConsensusParams
genesisHash crypto.Digest
- block bookkeeping.Block
- blockTxBytes int
- specials transactions.SpecialAddresses
+ block bookkeeping.Block
+ blockTxBytes int
+ specials transactions.SpecialAddresses
+ maxTxnBytesPerBlock int
blockGenerated bool // prevent repeated GenerateBlock calls
@@ -415,17 +416,25 @@ type ledgerForCowBase interface {
// StartEvaluator creates a BlockEvaluator, given a ledger and a block header
// of the block that the caller is planning to evaluate. If the length of the
// payset being evaluated is known in advance, a paysetHint >= 0 can be
-// passed, avoiding unnecessary payset slice growth.
-func (l *Ledger) StartEvaluator(hdr bookkeeping.BlockHeader, paysetHint int) (*BlockEvaluator, error) {
+// passed, avoiding unnecessary payset slice growth. The optional maxTxnBytesPerBlock parameter
+// provides a cap on the size of a single generated block size, when a non-zero value is passed.
+// If a value of zero or less is passed to maxTxnBytesPerBlock, the consensus MaxTxnBytesPerBlock would
+// be used instead.
+func (l *Ledger) StartEvaluator(hdr bookkeeping.BlockHeader, paysetHint, maxTxnBytesPerBlock int) (*BlockEvaluator, error) {
proto, ok := config.Consensus[hdr.CurrentProtocol]
if !ok {
return nil, protocol.Error(hdr.CurrentProtocol)
}
- return startEvaluator(l, hdr, proto, paysetHint, true, true)
+ return startEvaluator(l, hdr, proto, paysetHint, true, true, maxTxnBytesPerBlock)
}
-func startEvaluator(l ledgerForEvaluator, hdr bookkeeping.BlockHeader, proto config.ConsensusParams, paysetHint int, validate bool, generate bool) (*BlockEvaluator, error) {
+func startEvaluator(l ledgerForEvaluator, hdr bookkeeping.BlockHeader, proto config.ConsensusParams, paysetHint int, validate bool, generate bool, maxTxnBytesPerBlock int) (*BlockEvaluator, error) {
+ // if the caller did not provide a valid block size limit, default to the consensus params defaults.
+ if maxTxnBytesPerBlock <= 0 || maxTxnBytesPerBlock > proto.MaxTxnBytesPerBlock {
+ maxTxnBytesPerBlock = proto.MaxTxnBytesPerBlock
+ }
+
if hdr.Round == 0 {
return nil, ErrRoundZero
}
@@ -457,9 +466,10 @@ func startEvaluator(l ledgerForEvaluator, hdr bookkeeping.BlockHeader, proto con
FeeSink: hdr.FeeSink,
RewardsPool: hdr.RewardsPool,
},
- proto: proto,
- genesisHash: l.GenesisHash(),
- l: l,
+ proto: proto,
+ genesisHash: l.GenesisHash(),
+ l: l,
+ maxTxnBytesPerBlock: maxTxnBytesPerBlock,
}
// Preallocate space for the payset so that we don't have to
@@ -788,7 +798,7 @@ func (eval *BlockEvaluator) transactionGroup(txgroup []transactions.SignedTxnWit
if eval.validate {
groupTxBytes += txib.GetEncodedLength()
- if eval.blockTxBytes+groupTxBytes > eval.proto.MaxTxnBytesPerBlock {
+ if eval.blockTxBytes+groupTxBytes > eval.maxTxnBytesPerBlock {
return ErrNoSpace
}
}
@@ -964,25 +974,9 @@ func (eval *BlockEvaluator) applyTransaction(tx transactions.Transaction, balanc
return
}
- // rekeying: update balrecord.AuthAddr to tx.RekeyTo if provided
- if (tx.RekeyTo != basics.Address{}) {
- var acct basics.AccountData
- acct, err = balances.Get(tx.Sender, false)
- if err != nil {
- return
- }
- // Special case: rekeying to the account's actual address just sets acct.AuthAddr to 0
- // This saves 32 bytes in your balance record if you want to go back to using your original key
- if tx.RekeyTo == tx.Sender {
- acct.AuthAddr = basics.Address{}
- } else {
- acct.AuthAddr = tx.RekeyTo
- }
-
- err = balances.Put(tx.Sender, acct)
- if err != nil {
- return
- }
+ err = apply.Rekey(balances, &tx)
+ if err != nil {
+ return
}
switch tx.Type {
@@ -1069,6 +1063,8 @@ func (eval *BlockEvaluator) endOfBlock() error {
eval.block.TxnCounter = 0
}
+ eval.generateExpiredOnlineAccountsList()
+
if eval.proto.CompactCertRounds > 0 {
var basicCompactCert bookkeeping.CompactCertState
basicCompactCert.CompactCertVoters, basicCompactCert.CompactCertVotersTotal, err = eval.compactCertVotersAndTotal()
@@ -1083,6 +1079,137 @@ func (eval *BlockEvaluator) endOfBlock() error {
}
}
+ err := eval.validateExpiredOnlineAccounts()
+ if err != nil {
+ return err
+ }
+
+ err = eval.resetExpiredOnlineAccountsParticipationKeys()
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// generateExpiredOnlineAccountsList creates the list of the expired participation accounts by traversing over the
+// modified accounts in the state deltas and testing if any of them needs to be reset.
+func (eval *BlockEvaluator) generateExpiredOnlineAccountsList() {
+ if !eval.generate {
+ return
+ }
+ // We are going to find the list of modified accounts and the
+ // current round that is being evaluated.
+ // Then we are going to go through each modified account and
+ // see if it meets the criteria for adding it to the expired
+ // participation accounts list.
+ modifiedAccounts := eval.state.mods.Accts.ModifiedAccounts()
+ currentRound := eval.Round()
+
+ expectedMaxNumberOfExpiredAccounts := eval.proto.MaxProposedExpiredOnlineAccounts
+
+ for i := 0; i < len(modifiedAccounts) && len(eval.block.ParticipationUpdates.ExpiredParticipationAccounts) < expectedMaxNumberOfExpiredAccounts; i++ {
+ accountAddr := modifiedAccounts[i]
+ acctDelta, found := eval.state.mods.Accts.Get(accountAddr)
+ if !found {
+ continue
+ }
+
+ // true if the account is online
+ isOnline := acctDelta.Status == basics.Online
+ // true if the accounts last valid round has passed
+ pastCurrentRound := acctDelta.VoteLastValid < currentRound
+
+ if isOnline && pastCurrentRound {
+ eval.block.ParticipationUpdates.ExpiredParticipationAccounts = append(
+ eval.block.ParticipationUpdates.ExpiredParticipationAccounts,
+ accountAddr,
+ )
+ }
+ }
+}
+
+// validateExpiredOnlineAccounts tests the expired online accounts specified in ExpiredParticipationAccounts, and verify
+// that they have all expired and need to be reset.
+func (eval *BlockEvaluator) validateExpiredOnlineAccounts() error {
+ if !eval.validate {
+ return nil
+ }
+ expectedMaxNumberOfExpiredAccounts := eval.proto.MaxProposedExpiredOnlineAccounts
+ lengthOfExpiredParticipationAccounts := len(eval.block.ParticipationUpdates.ExpiredParticipationAccounts)
+
+ // If the length of the array is strictly greater than our max then we have an error.
+ // This works when the expected number of accounts is zero (i.e. it is disabled) as well
+ if lengthOfExpiredParticipationAccounts > expectedMaxNumberOfExpiredAccounts {
+ return fmt.Errorf("length of expired accounts (%d) was greater than expected (%d)",
+ lengthOfExpiredParticipationAccounts, expectedMaxNumberOfExpiredAccounts)
+ }
+
+ // For security reasons, we need to make sure that all addresses in the expired participation accounts
+ // are unique. We make this map to keep track of previously seen address
+ addressSet := make(map[basics.Address]bool, lengthOfExpiredParticipationAccounts)
+
+ // Validate that all expired accounts meet the current criteria
+ currentRound := eval.Round()
+ for _, accountAddr := range eval.block.ParticipationUpdates.ExpiredParticipationAccounts {
+
+ if _, exists := addressSet[accountAddr]; exists {
+ // We shouldn't have duplicate addresses...
+ return fmt.Errorf("duplicate address found: %v", accountAddr)
+ }
+
+ // Record that we have seen this address
+ addressSet[accountAddr] = true
+
+ acctData, err := eval.state.lookup(accountAddr)
+ if err != nil {
+ return fmt.Errorf("endOfBlock was unable to retrieve account %v : %w", accountAddr, err)
+ }
+
+ // true if the account is online
+ isOnline := acctData.Status == basics.Online
+ // true if the accounts last valid round has passed
+ pastCurrentRound := acctData.VoteLastValid < currentRound
+
+ if !isOnline {
+ return fmt.Errorf("endOfBlock found %v was not online but %v", accountAddr, acctData.Status)
+ }
+
+ if !pastCurrentRound {
+ return fmt.Errorf("endOfBlock found %v round (%d) was not less than current round (%d)", accountAddr, acctData.VoteLastValid, currentRound)
+ }
+ }
+ return nil
+}
+
+// resetExpiredOnlineAccountsParticipationKeys after all transactions and rewards are processed, modify the accounts so that their status is offline
+func (eval *BlockEvaluator) resetExpiredOnlineAccountsParticipationKeys() error {
+
+ expectedMaxNumberOfExpiredAccounts := eval.proto.MaxProposedExpiredOnlineAccounts
+ lengthOfExpiredParticipationAccounts := len(eval.block.ParticipationUpdates.ExpiredParticipationAccounts)
+
+ // If the length of the array is strictly greater than our max then we have an error.
+ // This works when the expected number of accounts is zero (i.e. it is disabled) as well
+ if lengthOfExpiredParticipationAccounts > expectedMaxNumberOfExpiredAccounts {
+ return fmt.Errorf("length of expired accounts (%d) was greater than expected (%d)",
+ lengthOfExpiredParticipationAccounts, expectedMaxNumberOfExpiredAccounts)
+ }
+
+ for _, accountAddr := range eval.block.ParticipationUpdates.ExpiredParticipationAccounts {
+ acctData, err := eval.state.lookup(accountAddr)
+ if err != nil {
+ return fmt.Errorf("resetExpiredOnlineAccountsParticipationKeys was unable to retrieve account %v : %w", accountAddr, err)
+ }
+
+ // Reset the appropriate account data
+ acctData.ClearOnlineState()
+
+ // Update the account information
+ err = eval.state.Put(accountAddr, acctData)
+ if err != nil {
+ return err
+ }
+ }
return nil
}
@@ -1125,6 +1252,7 @@ func (eval *BlockEvaluator) finalValidation() error {
return fmt.Errorf("CompactCertType %d unexpected", ccType)
}
}
+
}
return eval.state.CalculateTotals()
@@ -1223,8 +1351,7 @@ func eval(ctx context.Context, l ledgerForEvaluator, blk bookkeeping.Block, vali
return ledgercore.StateDelta{}, protocol.Error(blk.BlockHeader.CurrentProtocol)
}
- eval, err := startEvaluator(
- l, blk.BlockHeader, proto, len(blk.Payset), validate, false)
+ eval, err := startEvaluator(l, blk.BlockHeader, proto, len(blk.Payset), validate, false, 0)
if err != nil {
return ledgercore.StateDelta{}, err
}
diff --git a/ledger/evalIndexer.go b/ledger/evalIndexer.go
index 002b7c84b..b0d6aaf16 100644
--- a/ledger/evalIndexer.go
+++ b/ledger/evalIndexer.go
@@ -162,7 +162,7 @@ func EvalForIndexer(il indexerLedgerForEval, block *bookkeeping.Block, proto con
ilc := makeIndexerLedgerConnector(il, block.GenesisHash(), block.Round()-1)
eval, err := startEvaluator(
- ilc, block.BlockHeader, proto, len(block.Payset), false, false)
+ ilc, block.BlockHeader, proto, len(block.Payset), false, false, 0)
if err != nil {
return ledgercore.StateDelta{}, []transactions.SignedTxnInBlock{},
fmt.Errorf("EvalForIndexer() err: %w", err)
diff --git a/ledger/evalIndexer_test.go b/ledger/evalIndexer_test.go
index 977070275..fd8175044 100644
--- a/ledger/evalIndexer_test.go
+++ b/ledger/evalIndexer_test.go
@@ -228,3 +228,69 @@ func TestSaveResourcesInCowBase(t *testing.T) {
require.False(t, found)
}
}
+
+// TestEvalForIndexerForExpiredAccounts tests that the EvalForIndexer function will correctly mark accounts offline
+func TestEvalForIndexerForExpiredAccounts(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ genesisBalances, addrs, _ := newTestGenesis()
+
+ var genHash crypto.Digest
+ crypto.RandBytes(genHash[:])
+ block, err := bookkeeping.MakeGenesisBlock(protocol.ConsensusFuture,
+ genesisBalances, "test", genHash)
+
+ dbName := fmt.Sprintf("%s", t.Name())
+ cfg := config.GetDefaultLocal()
+ cfg.Archival = true
+ l, err := OpenLedger(logging.Base(), dbName, true, InitState{
+ Block: block,
+ Accounts: genesisBalances.Balances,
+ GenesisHash: genHash,
+ }, cfg)
+ require.NoError(t, err)
+ defer l.Close()
+
+ proto := config.Consensus[protocol.ConsensusFuture]
+
+ block = bookkeeping.MakeBlock(block.BlockHeader)
+
+ il := indexerLedgerForEvalImpl{
+ l: l,
+ latestRound: 0,
+ }
+
+ _, _, err = EvalForIndexer(il, &block, proto, EvalForIndexerResources{})
+ require.NoError(t, err)
+
+ badBlock := block
+ // First validate that bad block is fine if we dont touch it...
+ _, _, err = EvalForIndexer(il, &badBlock, proto, EvalForIndexerResources{})
+ require.NoError(t, err)
+
+ // Introduce an unknown address, but this time the Eval function is called with parameters that
+ // don't necessarily mean that this will cause an error. Just that an empty address will be added
+ badBlock.ExpiredParticipationAccounts = append(badBlock.ExpiredParticipationAccounts, basics.Address{123})
+
+ _, _, err = EvalForIndexer(il, &badBlock, proto, EvalForIndexerResources{})
+ require.NoError(t, err)
+
+ badBlock = block
+
+ // Now we add way too many accounts which will cause resetExpiredOnlineAccountsParticipationKeys() to fail
+ addressToCopy := addrs[0]
+
+ for i := 0; i < proto.MaxProposedExpiredOnlineAccounts+1; i++ {
+ badBlock.ExpiredParticipationAccounts = append(badBlock.ExpiredParticipationAccounts, addressToCopy)
+ }
+
+ _, _, err = EvalForIndexer(il, &badBlock, proto, EvalForIndexerResources{})
+ require.Error(t, err)
+
+ // Sanity Check
+
+ badBlock = block
+
+ _, _, err = EvalForIndexer(il, &badBlock, proto, EvalForIndexerResources{})
+ require.NoError(t, err)
+}
diff --git a/ledger/eval_test.go b/ledger/eval_test.go
index b71e37d52..8b23b3278 100644
--- a/ledger/eval_test.go
+++ b/ledger/eval_test.go
@@ -42,6 +42,7 @@ import (
"github.com/algorand/go-algorand/data/bookkeeping"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/data/transactions/logic"
+ "github.com/algorand/go-algorand/data/transactions/verify"
"github.com/algorand/go-algorand/data/txntest"
"github.com/algorand/go-algorand/ledger/ledgercore"
"github.com/algorand/go-algorand/logging"
@@ -73,7 +74,7 @@ func TestBlockEvaluator(t *testing.T) {
defer l.Close()
newBlock := bookkeeping.MakeBlock(genesisInitState.Block.BlockHeader)
- eval, err := l.StartEvaluator(newBlock.BlockHeader, 0)
+ eval, err := l.StartEvaluator(newBlock.BlockHeader, 0, 0)
require.Equal(t, eval.specials.FeeSink, testSinkAddr)
require.NoError(t, err)
@@ -286,7 +287,7 @@ func TestRekeying(t *testing.T) {
// So the ValidatedBlock that comes out isn't necessarily actually a valid block. We'll call Validate ourselves.
newBlock := bookkeeping.MakeBlock(genesisInitState.Block.BlockHeader)
- eval, err := l.StartEvaluator(newBlock.BlockHeader, 0)
+ eval, err := l.StartEvaluator(newBlock.BlockHeader, 0, 0)
require.NoError(t, err)
for _, stxn := range stxns {
@@ -462,7 +463,7 @@ func testEvalAppGroup(t *testing.T, schema basics.StateSchema) (*BlockEvaluator,
defer l.Close()
newBlock := bookkeeping.MakeBlock(genesisInitState.Block.BlockHeader)
- eval, err := l.StartEvaluator(newBlock.BlockHeader, 0)
+ eval, err := l.StartEvaluator(newBlock.BlockHeader, 0, 0)
require.NoError(t, err)
eval.validate = true
eval.generate = false
@@ -578,6 +579,9 @@ func testEvalAppPoolingGroup(t *testing.T, schema basics.StateSchema, approvalPr
defer l.Close()
eval := l.nextBlock(t)
+ eval.validate = true
+ eval.generate = false
+
eval.proto = config.Consensus[consensusVersion]
appcall1 := txntest.Txn{
@@ -927,7 +931,7 @@ func benchmarkBlockEvaluator(b *testing.B, inMem bool, withCrypto bool, proto pr
}
newBlock := bookkeeping.MakeBlock(genesisInitState.Block.BlockHeader)
- bev, err := l.StartEvaluator(newBlock.BlockHeader, 0)
+ bev, err := l.StartEvaluator(newBlock.BlockHeader, 0, 0)
require.NoError(b, err)
genHash := genesisInitState.Block.BlockHeader.GenesisHash
@@ -966,7 +970,7 @@ func benchmarkBlockEvaluator(b *testing.B, inMem bool, withCrypto bool, proto pr
require.NoError(b, err)
}
newBlock = bookkeeping.MakeBlock(validatedBlock.blk.BlockHeader)
- bev, err = l.StartEvaluator(newBlock.BlockHeader, 0)
+ bev, err = l.StartEvaluator(newBlock.BlockHeader, 0, 0)
require.NoError(b, err)
numBlocks++
}
@@ -989,7 +993,7 @@ func benchmarkBlockEvaluator(b *testing.B, inMem bool, withCrypto bool, proto pr
wg.Wait()
newBlock = bookkeeping.MakeBlock(validatedBlock.blk.BlockHeader)
- bev, err = l.StartEvaluator(newBlock.BlockHeader, 0)
+ bev, err = l.StartEvaluator(newBlock.BlockHeader, 0, 0)
require.NoError(b, err)
}
@@ -1190,7 +1194,7 @@ func testnetFixupExecution(t *testing.T, headerRound basics.Round, poolBonus uin
defer l.Close()
newBlock := bookkeeping.MakeBlock(genesisInitState.Block.BlockHeader)
- eval, err := l.StartEvaluator(newBlock.BlockHeader, 0)
+ eval, err := l.StartEvaluator(newBlock.BlockHeader, 0, 0)
require.NoError(t, err)
// won't work before funding bank
@@ -1408,7 +1412,7 @@ func (ledger *Ledger) nextBlock(t testing.TB) *BlockEvaluator {
require.NoError(t, err)
nextHdr := bookkeeping.MakeBlock(hdr).BlockHeader
- eval, err := ledger.StartEvaluator(nextHdr, 0)
+ eval, err := ledger.StartEvaluator(nextHdr, 0, 0)
require.NoError(t, err)
return eval
}
@@ -1929,3 +1933,317 @@ func TestCowBaseCreatorsCache(t *testing.T) {
}
}
}
+
+// TestEvalFunctionForExpiredAccounts tests that the eval function will correctly mark accounts as offline
+func TestEvalFunctionForExpiredAccounts(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ genesisInitState, addrs, keys := genesisWithProto(10, protocol.ConsensusFuture)
+
+ sendAddr := addrs[0]
+ recvAddr := addrs[1]
+
+ // the last round that the recvAddr is valid for
+ recvAddrLastValidRound := basics.Round(2)
+
+ // the target round we want to advance the evaluator to
+ targetRound := basics.Round(4)
+
+ // Set all to online except the sending address
+ for _, addr := range addrs {
+ if addr == sendAddr {
+ continue
+ }
+ tmp := genesisInitState.Accounts[addr]
+ tmp.Status = basics.Online
+ genesisInitState.Accounts[addr] = tmp
+ }
+
+ // Choose recvAddr to have a last valid round less than genesis block round
+ {
+ tmp := genesisInitState.Accounts[recvAddr]
+ tmp.VoteLastValid = recvAddrLastValidRound
+ genesisInitState.Accounts[recvAddr] = tmp
+ }
+
+ dbName := fmt.Sprintf("%s.%d", t.Name(), crypto.RandUint64())
+ const inMem = true
+ cfg := config.GetDefaultLocal()
+ l, err := OpenLedger(logging.Base(), dbName, inMem, genesisInitState, cfg)
+ require.NoError(t, err)
+ defer l.Close()
+
+ newBlock := bookkeeping.MakeBlock(genesisInitState.Block.BlockHeader)
+
+ blkEval, err := l.StartEvaluator(newBlock.BlockHeader, 0, 0)
+
+ // Advance the evaluator a couple rounds...
+ for i := uint64(0); i < uint64(targetRound); i++ {
+ l.endBlock(t, blkEval)
+ blkEval = l.nextBlock(t)
+ }
+
+ require.Greater(t, uint64(blkEval.Round()), uint64(recvAddrLastValidRound))
+
+ genHash := genesisInitState.Block.BlockHeader.GenesisHash
+ txn := transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: sendAddr,
+ Fee: minFee,
+ FirstValid: newBlock.Round(),
+ LastValid: blkEval.Round(),
+ GenesisHash: genHash,
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: recvAddr,
+ Amount: basics.MicroAlgos{Raw: 100},
+ },
+ }
+
+ st := txn.Sign(keys[0])
+ err = blkEval.Transaction(st, transactions.ApplyData{})
+ require.NoError(t, err)
+
+ // Make sure we validate our block as well
+ blkEval.validate = true
+
+ validatedBlock, err := blkEval.GenerateBlock()
+ require.NoError(t, err)
+
+ _, err = eval(context.Background(), l, validatedBlock.blk, false, nil, nil)
+ require.NoError(t, err)
+
+ badBlock := *validatedBlock
+
+ // First validate that bad block is fine if we dont touch it...
+ _, err = eval(context.Background(), l, badBlock.blk, true, verify.GetMockedCache(true), nil)
+ require.NoError(t, err)
+
+ badBlock = *validatedBlock
+
+ // Introduce an unknown address to introduce an error
+ badBlock.blk.ExpiredParticipationAccounts = append(badBlock.blk.ExpiredParticipationAccounts, basics.Address{1})
+
+ _, err = eval(context.Background(), l, badBlock.blk, true, verify.GetMockedCache(true), nil)
+ require.Error(t, err)
+
+ badBlock = *validatedBlock
+
+ addressToCopy := badBlock.blk.ExpiredParticipationAccounts[0]
+
+ // Add more than the expected number of accounts
+
+ for i := 0; i < blkEval.proto.MaxProposedExpiredOnlineAccounts+1; i++ {
+ badBlock.blk.ExpiredParticipationAccounts = append(badBlock.blk.ExpiredParticipationAccounts, addressToCopy)
+ }
+
+ _, err = eval(context.Background(), l, badBlock.blk, true, verify.GetMockedCache(true), nil)
+ require.Error(t, err)
+
+ badBlock = *validatedBlock
+
+ // Duplicate an address
+ badBlock.blk.ExpiredParticipationAccounts = append(badBlock.blk.ExpiredParticipationAccounts, badBlock.blk.ExpiredParticipationAccounts[0])
+
+ _, err = eval(context.Background(), l, badBlock.blk, true, verify.GetMockedCache(true), nil)
+ require.Error(t, err)
+
+ badBlock = *validatedBlock
+ // sanity check that bad block is being actually copied and not just the pointer
+ _, err = eval(context.Background(), l, badBlock.blk, true, verify.GetMockedCache(true), nil)
+ require.NoError(t, err)
+
+}
+
+type failRoundCowParent struct {
+ roundCowBase
+}
+
+func (p *failRoundCowParent) lookup(basics.Address) (basics.AccountData, error) {
+ return basics.AccountData{}, fmt.Errorf("disk I/O fail (on purpose)")
+}
+
+// TestExpiredAccountGenerationWithDiskFailure tests edge cases where disk failures can lead to ledger look up failures
+func TestExpiredAccountGenerationWithDiskFailure(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ genesisInitState, addrs, keys := genesisWithProto(10, protocol.ConsensusFuture)
+
+ sendAddr := addrs[0]
+ recvAddr := addrs[1]
+
+ // the last round that the recvAddr is valid for
+ recvAddrLastValidRound := basics.Round(10)
+
+ // the target round we want to advance the evaluator to
+ targetRound := basics.Round(4)
+
+ // Set all to online except the sending address
+ for _, addr := range addrs {
+ if addr == sendAddr {
+ continue
+ }
+ tmp := genesisInitState.Accounts[addr]
+ tmp.Status = basics.Online
+ genesisInitState.Accounts[addr] = tmp
+ }
+
+ // Choose recvAddr to have a last valid round less than genesis block round
+ {
+ tmp := genesisInitState.Accounts[recvAddr]
+ tmp.VoteLastValid = recvAddrLastValidRound
+ genesisInitState.Accounts[recvAddr] = tmp
+ }
+
+ dbName := fmt.Sprintf("%s.%d", t.Name(), crypto.RandUint64())
+ const inMem = true
+ cfg := config.GetDefaultLocal()
+ l, err := OpenLedger(logging.Base(), dbName, inMem, genesisInitState, cfg)
+ require.NoError(t, err)
+ defer l.Close()
+
+ newBlock := bookkeeping.MakeBlock(genesisInitState.Block.BlockHeader)
+
+ eval, err := l.StartEvaluator(newBlock.BlockHeader, 0, 0)
+
+ // Advance the evaluator a couple rounds...
+ for i := uint64(0); i < uint64(targetRound); i++ {
+ l.endBlock(t, eval)
+ eval = l.nextBlock(t)
+ }
+
+ genHash := genesisInitState.Block.BlockHeader.GenesisHash
+ txn := transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: sendAddr,
+ Fee: minFee,
+ FirstValid: newBlock.Round(),
+ LastValid: eval.Round(),
+ GenesisHash: genHash,
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: recvAddr,
+ Amount: basics.MicroAlgos{Raw: 100},
+ },
+ }
+
+ st := txn.Sign(keys[0])
+ err = eval.Transaction(st, transactions.ApplyData{})
+ require.NoError(t, err)
+
+ eval.validate = true
+ eval.generate = false
+
+ eval.block.ExpiredParticipationAccounts = append(eval.block.ExpiredParticipationAccounts, recvAddr)
+
+ err = eval.endOfBlock()
+ require.Error(t, err)
+
+ eval.block.ExpiredParticipationAccounts = []basics.Address{
+ basics.Address{},
+ }
+ eval.state.mods.Accts = ledgercore.AccountDeltas{}
+ eval.state.lookupParent = &failRoundCowParent{}
+ err = eval.endOfBlock()
+ require.Error(t, err)
+
+ err = eval.resetExpiredOnlineAccountsParticipationKeys()
+ require.Error(t, err)
+
+}
+
+// TestExpiredAccountGeneration test that expired accounts are added to a block header and validated
+func TestExpiredAccountGeneration(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ genesisInitState, addrs, keys := genesisWithProto(10, protocol.ConsensusFuture)
+
+ sendAddr := addrs[0]
+ recvAddr := addrs[1]
+
+ // the last round that the recvAddr is valid for
+ recvAddrLastValidRound := basics.Round(2)
+
+ // the target round we want to advance the evaluator to
+ targetRound := basics.Round(4)
+
+ // Set all to online except the sending address
+ for _, addr := range addrs {
+ if addr == sendAddr {
+ continue
+ }
+ tmp := genesisInitState.Accounts[addr]
+ tmp.Status = basics.Online
+ genesisInitState.Accounts[addr] = tmp
+ }
+
+ // Choose recvAddr to have a last valid round less than genesis block round
+ {
+ tmp := genesisInitState.Accounts[recvAddr]
+ tmp.VoteLastValid = recvAddrLastValidRound
+ genesisInitState.Accounts[recvAddr] = tmp
+ }
+
+ dbName := fmt.Sprintf("%s.%d", t.Name(), crypto.RandUint64())
+ const inMem = true
+ cfg := config.GetDefaultLocal()
+ l, err := OpenLedger(logging.Base(), dbName, inMem, genesisInitState, cfg)
+ require.NoError(t, err)
+ defer l.Close()
+
+ newBlock := bookkeeping.MakeBlock(genesisInitState.Block.BlockHeader)
+
+ eval, err := l.StartEvaluator(newBlock.BlockHeader, 0, 0)
+
+ // Advance the evaluator a couple rounds...
+ for i := uint64(0); i < uint64(targetRound); i++ {
+ l.endBlock(t, eval)
+ eval = l.nextBlock(t)
+ }
+
+ require.Greater(t, uint64(eval.Round()), uint64(recvAddrLastValidRound))
+
+ genHash := genesisInitState.Block.BlockHeader.GenesisHash
+ txn := transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: sendAddr,
+ Fee: minFee,
+ FirstValid: newBlock.Round(),
+ LastValid: eval.Round(),
+ GenesisHash: genHash,
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: recvAddr,
+ Amount: basics.MicroAlgos{Raw: 100},
+ },
+ }
+
+ st := txn.Sign(keys[0])
+ err = eval.Transaction(st, transactions.ApplyData{})
+ require.NoError(t, err)
+
+ // Make sure we validate our block as well
+ eval.validate = true
+
+ validatedBlock, err := eval.GenerateBlock()
+ require.NoError(t, err)
+
+ listOfExpiredAccounts := validatedBlock.Block().ParticipationUpdates.ExpiredParticipationAccounts
+
+ require.Equal(t, 1, len(listOfExpiredAccounts))
+ expiredAccount := listOfExpiredAccounts[0]
+ require.Equal(t, expiredAccount, recvAddr)
+
+ recvAcct, err := eval.state.lookup(recvAddr)
+ require.NoError(t, err)
+ require.Equal(t, recvAcct.Status, basics.Offline)
+ require.Equal(t, recvAcct.VoteFirstValid, basics.Round(0))
+ require.Equal(t, recvAcct.VoteLastValid, basics.Round(0))
+ require.Equal(t, recvAcct.VoteKeyDilution, uint64(0))
+ require.Equal(t, recvAcct.VoteID, crypto.OneTimeSignatureVerifier{})
+ require.Equal(t, recvAcct.SelectionID, crypto.VRFVerifier{})
+
+}
diff --git a/ledger/ledger_perf_test.go b/ledger/ledger_perf_test.go
index b1b2244b4..c29652b38 100644
--- a/ledger/ledger_perf_test.go
+++ b/ledger/ledger_perf_test.go
@@ -206,7 +206,7 @@ func benchmarkFullBlocks(params testParams, b *testing.B) {
prev, err := l0.BlockHdr(basics.Round(i))
require.NoError(b, err)
newBlk := bookkeeping.MakeBlock(prev)
- eval, err := l0.StartEvaluator(newBlk.BlockHeader, 5000)
+ eval, err := l0.StartEvaluator(newBlk.BlockHeader, 5000, 0)
require.NoError(b, err)
// build a payset
diff --git a/ledger/ledgercore/error.go b/ledger/ledgercore/error.go
index c0e02b195..c54c6173c 100644
--- a/ledger/ledgercore/error.go
+++ b/ledger/ledgercore/error.go
@@ -79,12 +79,17 @@ func (err ErrNoEntry) Error() string {
// LogicEvalError indicates TEAL evaluation failure
type LogicEvalError struct {
- Err error
+ Err error
+ Details string
}
// Error satisfies builtin interface `error`
func (err LogicEvalError) Error() string {
- return fmt.Sprintf("logic eval error: %v", err.Err)
+ msg := fmt.Sprintf("logic eval error: %v", err.Err)
+ if len(err.Details) > 0 {
+ msg = fmt.Sprintf("%s. Details: %s", msg, err.Details)
+ }
+ return msg
}
// ErrNonSequentialBlockEval provides feedback when the evaluator cannot be created for
diff --git a/logging/telemetryspec/metric.go b/logging/telemetryspec/metric.go
index 349d3f972..2e87502fd 100644
--- a/logging/telemetryspec/metric.go
+++ b/logging/telemetryspec/metric.go
@@ -83,6 +83,67 @@ func (m AssembleBlockMetrics) Identifier() Metric {
return assembleBlockMetricsIdentifier
}
+// the identifier for the transaction sync profiling metrics.
+const transactionSyncProfilingMetricsIdentifier Metric = "SyncProfile"
+
+// TransactionSyncProfilingMetrics is the profiling metrics of the recent transaction sync activity
+type TransactionSyncProfilingMetrics struct {
+ // total number of operations
+ TotalOps uint64
+ // number of idle operations
+ IdleOps uint64
+ // number of transaction pool changes operations
+ TransactionPoolChangedOps uint64
+ // number of new rounds operations
+ NewRoundOps uint64
+ // number of peer state changes operations
+ PeerStateOps uint64
+ // number of incoming messages operations
+ IncomingMsgOps uint64
+ // number of outgoing message operations
+ OutgoingMsgOps uint64
+ // number of next offsets message operations
+ NextOffsetOps uint64
+ // number of times transaction sync was retrieving the transaction groups from the transaction pool
+ GetTxnGroupsOps uint64
+ // number of times the transaction sync was assembling messages
+ AssembleMessageOps uint64
+ // number of times the transaction sync was creating bloom filters
+ MakeBloomFilterOps uint64
+ // number of times the transaction sync was selecting pending transactions out of existing pool
+ SelectPendingTransactionsOps uint64
+
+ // total duration of this profiling session
+ TotalDuration time.Duration
+ // percent of time the transaction sync was idle
+ IdlePercent float64
+ // percent of time the transaction sync was processing transaction pool changes
+ TransactionPoolChangedPercent float64
+ // percent of time the transaction sync was processing new rounds
+ NewRoundPercent float64
+ // percent of time the transaction sync was processing peer state changes
+ PeerStatePercent float64
+ // percent of time the transaction sync was processing incoming messages
+ IncomingMsgPercent float64
+ // percent of time the transaction sync was processing outgoing messages
+ OutgoingMsgPercent float64
+ // percent of time the transaction sync was processing next offset messages
+ NextOffsetPercent float64
+ // percent of time the transaction sync was collecting next set of transaction groups from the transaction pool
+ GetTxnGroupsPercent float64
+ // percent of time the transaction sync was assembling messages
+ AssembleMessagePercent float64
+ // percent of time the transaction sync was creating bloom filter
+ MakeBloomFilterPercent float64
+ // percent of time the transaction sync was selecting transaction to be sent
+ SelectPendingTransactionsPercent float64
+}
+
+// Identifier implements the required MetricDetails interface, retrieving the Identifier for this set of metrics.
+func (m TransactionSyncProfilingMetrics) Identifier() Metric {
+ return transactionSyncProfilingMetricsIdentifier
+}
+
//-------------------------------------------------------
// ProcessBlock
diff --git a/network/ping.go b/network/ping.go
index 064bb5ff9..02915b49f 100644
--- a/network/ping.go
+++ b/network/ping.go
@@ -36,7 +36,7 @@ func pingHandler(message IncomingMessage) OutgoingMessage {
copy(mbytes, tbytes)
copy(mbytes[len(tbytes):], message.Data)
var digest crypto.Digest // leave blank, ping message too short
- peer.writeNonBlock(context.Background(), mbytes, false, digest, time.Now())
+ peer.writeNonBlock(context.Background(), mbytes, false, digest, time.Now(), nil)
return OutgoingMessage{}
}
diff --git a/network/wsNetwork.go b/network/wsNetwork.go
index ace79c5b0..666f6a21a 100644
--- a/network/wsNetwork.go
+++ b/network/wsNetwork.go
@@ -54,7 +54,11 @@ import (
)
const incomingThreads = 20
-const messageFilterSize = 5000 // messages greater than that size may be blocked by incoming/outgoing filter
+
+// messageFilterSize is the threshold beyond we send a request to the other peer to avoid sending us a message with that particular hash.
+// typically, this is beneficial for proposal messages, which tends to be large and uniform across the network. Non-uniform messages, such
+// as the transaction sync messages should not included in this filter.
+const messageFilterSize = 200000
// httpServerReadHeaderTimeout is the amount of time allowed to read
// request headers. The connection's read deadline is reset
@@ -220,6 +224,9 @@ type IncomingMessage struct {
Err error
Net GossipNode
+ // Sequence is the sequence number of the message for the specific tag and peer
+ Sequence uint64
+
// Received is time.Time.UnixNano()
Received int64
@@ -425,6 +432,9 @@ func (wn *WebsocketNetwork) Address() (string, bool) {
parsedURL := url.URL{Scheme: wn.scheme}
var connected bool
if wn.listener == nil {
+ if wn.config.NetAddress == "" {
+ parsedURL.Scheme = ""
+ }
parsedURL.Host = wn.config.NetAddress
connected = false
} else {
@@ -1134,7 +1144,7 @@ func (wn *WebsocketNetwork) ServeHTTP(response http.ResponseWriter, request *htt
// We are careful to encode this prior to starting the server to avoid needing 'messagesOfInterestMu' here.
if wn.messagesOfInterestEnc != nil {
- err = peer.Unicast(wn.ctx, wn.messagesOfInterestEnc, protocol.MsgOfInterestTag)
+ err = peer.Unicast(wn.ctx, wn.messagesOfInterestEnc, protocol.MsgOfInterestTag, nil)
if err != nil {
wn.log.Infof("ws send msgOfInterest: %v", err)
}
@@ -1416,7 +1426,7 @@ func (wn *WebsocketNetwork) innerBroadcast(request broadcastRequest, prio bool,
if peer == request.except {
continue
}
- ok := peer.writeNonBlockMsgs(request.ctx, data, prio, digests, request.enqueueTime)
+ ok := peer.writeNonBlockMsgs(request.ctx, data, prio, digests, request.enqueueTime, nil)
if ok {
sentMessageCount++
continue
@@ -1866,14 +1876,15 @@ const ProtocolVersionHeader = "X-Algorand-Version"
const ProtocolAcceptVersionHeader = "X-Algorand-Accept-Version"
// SupportedProtocolVersions contains the list of supported protocol versions by this node ( in order of preference ).
-var SupportedProtocolVersions = []string{"2.1"}
+var SupportedProtocolVersions = []string{"3.0", "2.1"}
// ProtocolVersion is the current version attached to the ProtocolVersionHeader header
/* Version history:
* 1 Catchup service over websocket connections with unicast messages between peers
* 2.1 Introduced topic key/data pairs and enabled services over the gossip connections
+ * 3.0 Introduced new transaction gossiping protocol
*/
-const ProtocolVersion = "2.1"
+const ProtocolVersion = "3.0"
// TelemetryIDHeader HTTP header for telemetry-id for logging
const TelemetryIDHeader = "X-Algorand-TelId"
@@ -2139,7 +2150,7 @@ func (wn *WebsocketNetwork) tryConnect(addr, gossipAddr string) {
resp := wn.prioScheme.MakePrioResponse(challenge)
if resp != nil {
mbytes := append([]byte(protocol.NetPrioResponseTag), resp...)
- sent := peer.writeNonBlock(context.Background(), mbytes, true, crypto.Digest{}, time.Now())
+ sent := peer.writeNonBlock(context.Background(), mbytes, true, crypto.Digest{}, time.Now(), nil)
if !sent {
wn.log.With("remote", addr).With("local", localAddr).Warnf("could not send priority response to %v", addr)
}
diff --git a/network/wsNetwork_test.go b/network/wsNetwork_test.go
index d1d719b36..6571f5b9e 100644
--- a/network/wsNetwork_test.go
+++ b/network/wsNetwork_test.go
@@ -238,7 +238,7 @@ func TestWebsocketNetworkBasic(t *testing.T) {
defer func() { t.Log("stopping B"); netB.Stop(); t.Log("B done") }()
counter := newMessageCounter(t, 2)
counterDone := counter.done
- netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: counter}})
+ netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.AgreementVoteTag, MessageHandler: counter}})
readyTimeout := time.NewTimer(2 * time.Second)
waitReady(t, netA, readyTimeout.C)
@@ -246,8 +246,8 @@ func TestWebsocketNetworkBasic(t *testing.T) {
waitReady(t, netB, readyTimeout.C)
t.Log("b ready")
- netA.Broadcast(context.Background(), protocol.TxnTag, []byte("foo"), false, nil)
- netA.Broadcast(context.Background(), protocol.TxnTag, []byte("bar"), false, nil)
+ netA.Broadcast(context.Background(), protocol.AgreementVoteTag, []byte("foo"), false, nil)
+ netA.Broadcast(context.Background(), protocol.AgreementVoteTag, []byte("bar"), false, nil)
select {
case <-counterDone:
@@ -274,7 +274,7 @@ func TestWebsocketNetworkUnicast(t *testing.T) {
defer func() { t.Log("stopping B"); netB.Stop(); t.Log("B done") }()
counter := newMessageCounter(t, 2)
counterDone := counter.done
- netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: counter}})
+ netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.AgreementVoteTag, MessageHandler: counter}})
readyTimeout := time.NewTimer(2 * time.Second)
waitReady(t, netA, readyTimeout.C)
@@ -285,9 +285,9 @@ func TestWebsocketNetworkUnicast(t *testing.T) {
require.Equal(t, 1, len(netA.peers))
require.Equal(t, 1, len(netA.GetPeers(PeersConnectedIn)))
peerB := netA.peers[0]
- err := peerB.Unicast(context.Background(), []byte("foo"), protocol.TxnTag)
+ err := peerB.Unicast(context.Background(), []byte("foo"), protocol.AgreementVoteTag, nil)
assert.NoError(t, err)
- err = peerB.Unicast(context.Background(), []byte("bar"), protocol.TxnTag)
+ err = peerB.Unicast(context.Background(), []byte("bar"), protocol.AgreementVoteTag, nil)
assert.NoError(t, err)
select {
@@ -353,7 +353,7 @@ func TestWebsocketNetworkArray(t *testing.T) {
defer func() { t.Log("stopping B"); netB.Stop(); t.Log("B done") }()
counter := newMessageCounter(t, 3)
counterDone := counter.done
- netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: counter}})
+ netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.AgreementVoteTag, MessageHandler: counter}})
readyTimeout := time.NewTimer(2 * time.Second)
waitReady(t, netA, readyTimeout.C)
@@ -361,7 +361,7 @@ func TestWebsocketNetworkArray(t *testing.T) {
waitReady(t, netB, readyTimeout.C)
t.Log("b ready")
- tags := []protocol.Tag{protocol.TxnTag, protocol.TxnTag, protocol.TxnTag}
+ tags := []protocol.Tag{protocol.AgreementVoteTag, protocol.AgreementVoteTag, protocol.AgreementVoteTag}
data := [][]byte{[]byte("foo"), []byte("bar"), []byte("algo")}
netA.BroadcastArray(context.Background(), tags, data, false, nil)
@@ -390,7 +390,7 @@ func TestWebsocketNetworkCancel(t *testing.T) {
defer func() { t.Log("stopping B"); netB.Stop(); t.Log("B done") }()
counter := newMessageCounter(t, 100)
counterDone := counter.done
- netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: counter}})
+ netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.AgreementVoteTag, MessageHandler: counter}})
readyTimeout := time.NewTimer(2 * time.Second)
waitReady(t, netA, readyTimeout.C)
@@ -401,8 +401,8 @@ func TestWebsocketNetworkCancel(t *testing.T) {
tags := make([]protocol.Tag, 100)
data := make([][]byte, 100)
for i := range data {
- tags[i] = protocol.TxnTag
- data[i] = []byte(string(rune(i)))
+ tags[i] = protocol.AgreementVoteTag
+ data[i] = []byte(fmt.Sprintf("%d", i))
}
ctx, cancel := context.WithCancel(context.Background())
@@ -438,7 +438,7 @@ func TestWebsocketNetworkCancel(t *testing.T) {
mbytes := make([]byte, len(tbytes)+len(msg))
copy(mbytes, tbytes)
copy(mbytes[len(tbytes):], msg)
- msgs = append(msgs, sendMessage{data: mbytes, enqueued: time.Now(), peerEnqueued: enqueueTime, hash: crypto.Hash(mbytes), ctx: context.Background()})
+ msgs = append(msgs, sendMessage{data: mbytes, enqueued: time.Now(), peerEnqueued: enqueueTime, ctx: context.Background()})
}
msgs[50].ctx = ctx
@@ -476,7 +476,7 @@ func TestWebsocketNetworkNoAddress(t *testing.T) {
defer func() { t.Log("stopping B"); netB.Stop(); t.Log("B done") }()
counter := newMessageCounter(t, 2)
counterDone := counter.done
- netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: counter}})
+ netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.AgreementVoteTag, MessageHandler: counter}})
readyTimeout := time.NewTimer(2 * time.Second)
waitReady(t, netA, readyTimeout.C)
@@ -484,8 +484,8 @@ func TestWebsocketNetworkNoAddress(t *testing.T) {
waitReady(t, netB, readyTimeout.C)
t.Log("b ready")
- netA.Broadcast(context.Background(), protocol.TxnTag, []byte("foo"), false, nil)
- netA.Broadcast(context.Background(), protocol.TxnTag, []byte("bar"), false, nil)
+ netA.Broadcast(context.Background(), protocol.AgreementVoteTag, []byte("foo"), false, nil)
+ netA.Broadcast(context.Background(), protocol.AgreementVoteTag, []byte("bar"), false, nil)
select {
case <-counterDone:
@@ -508,7 +508,7 @@ func lineNetwork(t *testing.T, numNodes int) (nodes []*WebsocketNetwork, counter
addrPrev, postListen := nodes[i-1].Address()
require.True(t, postListen)
nodes[i].phonebook.ReplacePeerList([]string{addrPrev}, "default", PhoneBookEntryRelayRole)
- nodes[i].RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: &counters[i]}})
+ nodes[i].RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.AgreementVoteTag, MessageHandler: &counters[i]}})
}
nodes[i].Start()
counters[i].t = t
@@ -565,7 +565,7 @@ func TestLineNetwork(t *testing.T) {
sendTime := time.Now().UnixNano()
var timeblob [8]byte
binary.LittleEndian.PutUint64(timeblob[:], uint64(sendTime))
- nodes[0].Broadcast(context.Background(), protocol.TxnTag, timeblob[:], true, nil)
+ nodes[0].Broadcast(context.Background(), protocol.AgreementVoteTag, timeblob[:], true, nil)
}
select {
case <-counterDone:
@@ -786,71 +786,124 @@ func avgSendBufferHighPrioLength(wn *WebsocketNetwork) float64 {
return float64(sum) / float64(len(wn.peers))
}
-// TestSlowOutboundPeer tests what happens when one outbound peer is slow and the rest are fine. Current logic is to disconnect the one slow peer when its outbound channel is full.
-//
-// This is a deeply invasive test that reaches into the guts of WebsocketNetwork and wsPeer. If the implementation chainges consider throwing away or totally reimplementing this test.
+// TestSlowOutboundPeer tests what happens when one outbound peer is slow and the rest are fine.
func TestSlowOutboundPeer(t *testing.T) {
partitiontest.PartitionTest(t)
- t.Skip() // todo - update this test to reflect the new implementation.
- xtag := protocol.ProposalPayloadTag
+ nodeA := makeTestWebsocketNode(t)
+ nodeA.config.GossipFanout = 0
+ nodeA.Start()
+ defer nodeA.Stop()
+
+ addrA, postListenA := nodeA.Address()
+ require.True(t, postListenA)
+
+ nodeB := makeTestWebsocketNode(t)
+ nodeB.config.GossipFanout = 0
+ nodeB.Start()
+ defer nodeB.Stop()
+
+ addrB, postListenB := nodeB.Address()
+ require.True(t, postListenB)
+
node := makeTestWebsocketNode(t)
- destPeers := make([]wsPeer, 5)
- for i := range destPeers {
- destPeers[i].closing = make(chan struct{})
- destPeers[i].net = node
- destPeers[i].sendBufferHighPrio = make(chan sendMessages, sendBufferLength)
- destPeers[i].sendBufferBulk = make(chan sendMessages, sendBufferLength)
- destPeers[i].conn = &nopConnSingleton
- destPeers[i].rootURL = fmt.Sprintf("fake %d", i)
- node.addPeer(&destPeers[i])
- }
+ node.config.GossipFanout = 2
+ dl := eventsDetailsLogger{Logger: logging.TestingLog(t), eventReceived: make(chan interface{}, 100), eventIdentifier: telemetryspec.DisconnectPeerEvent}
+ node.log = dl
+
+ node.phonebook.ReplacePeerList([]string{addrA, addrB}, "default", PhoneBookEntryRelayRole)
node.Start()
- tctx, cf := context.WithTimeout(context.Background(), 5*time.Second)
- for i := 0; i < sendBufferLength; i++ {
- t.Logf("broadcast %d", i)
- sent := node.Broadcast(tctx, xtag, []byte{byte(i)}, true, nil)
- require.NoError(t, sent)
+ defer node.Stop()
+
+ msg := make([]byte, 100)
+ rand.Read(msg)
+
+ muHandleA := deadlock.Mutex{}
+ numHandledA := 0
+ waitMessageArriveHandlerA := func(msg IncomingMessage) (out OutgoingMessage) {
+ muHandleA.Lock()
+ defer muHandleA.Unlock()
+ numHandledA++
+ return
}
- cf()
- ok := false
- for i := 0; i < 10; i++ {
- time.Sleep(time.Millisecond)
- aoql := avgSendBufferHighPrioLength(node)
- if aoql == sendBufferLength {
- ok = true
- break
- }
- t.Logf("node.avgOutboundQueueLength() %f", aoql)
+ nodeA.RegisterHandlers([]TaggedMessageHandler{
+ {
+ Tag: protocol.AgreementVoteTag,
+ MessageHandler: HandlerFunc(waitMessageArriveHandlerA),
+ }})
+
+ muHandleB := deadlock.Mutex{}
+ numHandledB := 0
+ waitMessageArriveHandlerB := func(msg IncomingMessage) (out OutgoingMessage) {
+ muHandleB.Lock()
+ defer muHandleB.Unlock()
+ numHandledB++
+ return
}
- require.True(t, ok)
- for p := range destPeers {
- if p == 0 {
- continue
+ nodeB.RegisterHandlers([]TaggedMessageHandler{
+ {
+ Tag: protocol.AgreementVoteTag,
+ MessageHandler: HandlerFunc(waitMessageArriveHandlerB),
+ }})
+
+ readyTimeout := time.NewTimer(2 * time.Second)
+ waitReady(t, node, readyTimeout.C)
+ require.Equal(t, 2, len(node.peers))
+
+ callback := func(enqueued bool, sequenceNumber uint64) error {
+ time.Sleep(2 * maxMessageQueueDuration)
+ return nil
+ }
+
+ rand.Read(msg)
+ x := 0
+MAINLOOP:
+ for ; x < 1000; x++ {
+ select {
+ case eventDetails := <-dl.eventReceived:
+ switch disconnectPeerEventDetails := eventDetails.(type) {
+ case telemetryspec.DisconnectPeerEventDetails:
+ require.Equal(t, string(disconnectSlowConn), disconnectPeerEventDetails.Reason)
+ default:
+ require.FailNow(t, "Unexpected event was send : %v", eventDetails)
+ }
+ break MAINLOOP
+ default:
}
- for j := 0; j < sendBufferLength; j++ {
- // throw away a message as if sent
- <-destPeers[p].sendBufferHighPrio
+
+ node.Broadcast(context.Background(), protocol.AgreementVoteTag, msg, true, nil)
+ if x == 0 {
+ node.peers[0].Unicast(context.Background(), msg, protocol.AgreementVoteTag, callback)
}
+ time.Sleep(200 * time.Millisecond)
}
- aoql := avgSendBufferHighPrioLength(node)
- if aoql > (sendBufferLength / 2) {
- t.Fatalf("avgOutboundQueueLength=%f wanted <%f", aoql, sendBufferLength/2.0)
- return
- }
- // it shouldn't have closed for just sitting on the limit of full
- require.False(t, peerIsClosed(&destPeers[0]))
- // function context just to contain defer cf()
- func() {
- timeout, cf := context.WithTimeout(context.Background(), time.Second)
- defer cf()
- sent := node.Broadcast(timeout, xtag, []byte{byte(42)}, true, nil)
- assert.NoError(t, sent)
- }()
+ require.Less(t, x, 1000)
- // and now with the rest of the peers well and this one slow, we closed the slow one
- require.True(t, peerIsClosed(&destPeers[0]))
+ maxNumHandled := 0
+ minNumHandled := 0
+ for i := 0; i < 10; i++ {
+ muHandleA.Lock()
+ a := numHandledA
+ muHandleA.Unlock()
+
+ muHandleB.Lock()
+ b := numHandledB
+ muHandleB.Unlock()
+
+ maxNumHandled = b
+ minNumHandled = a
+ if maxNumHandled < a {
+ maxNumHandled = a
+ minNumHandled = b
+ }
+ if maxNumHandled == x {
+ break
+ }
+ time.Sleep(100 * time.Millisecond)
+ }
+ require.Equal(t, maxNumHandled, x)
+ require.Less(t, minNumHandled, x/2)
}
func makeTestFilterWebsocketNode(t *testing.T, nodename string) *WebsocketNetwork {
@@ -1038,7 +1091,7 @@ func BenchmarkWebsocketNetworkBasic(t *testing.B) {
defer func() { t.Log("stopping B"); netB.Stop(); t.Log("B done") }()
returns := make(chan uint64, 100)
bhandler := benchmarkHandler{returns}
- netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: &bhandler}})
+ netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.AgreementVoteTag, MessageHandler: &bhandler}})
readyTimeout := time.NewTimer(2 * time.Second)
waitReady(t, netA, readyTimeout.C)
@@ -1061,7 +1114,7 @@ func BenchmarkWebsocketNetworkBasic(t *testing.B) {
}
msg := make([]byte, msgSize)
binary.LittleEndian.PutUint64(msg, uint64(i))
- err := netA.Broadcast(context.Background(), protocol.TxnTag, msg, true, nil)
+ err := netA.Broadcast(context.Background(), protocol.AgreementVoteTag, msg, true, nil)
if err != nil {
t.Errorf("error on broadcast: %v", err)
return
@@ -1163,7 +1216,7 @@ func TestWebsocketNetworkPrioLimit(t *testing.T) {
netB.config.GossipFanout = 1
netB.config.NetAddress = ""
netB.phonebook.ReplacePeerList([]string{addrA}, "default", PhoneBookEntryRelayRole)
- netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: counterB}})
+ netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.AgreementVoteTag, MessageHandler: counterB}})
netB.Start()
defer func() { t.Log("stopping B"); netB.Stop(); t.Log("B done") }()
@@ -1177,7 +1230,7 @@ func TestWebsocketNetworkPrioLimit(t *testing.T) {
netC.config.GossipFanout = 1
netC.config.NetAddress = ""
netC.phonebook.ReplacePeerList([]string{addrA}, "default", PhoneBookEntryRelayRole)
- netC.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: counterC}})
+ netC.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.AgreementVoteTag, MessageHandler: counterC}})
netC.Start()
defer func() { t.Log("stopping C"); netC.Stop(); t.Log("C done") }()
@@ -1201,7 +1254,7 @@ func TestWebsocketNetworkPrioLimit(t *testing.T) {
waitReady(t, netA, time.After(time.Second))
firstPeer := netA.peers[0]
- netA.Broadcast(context.Background(), protocol.TxnTag, nil, true, nil)
+ netA.Broadcast(context.Background(), protocol.AgreementVoteTag, nil, true, nil)
failed := false
select {
@@ -1391,7 +1444,7 @@ func TestDelayedMessageDrop(t *testing.T) {
defer func() { t.Log("stopping B"); netB.Stop(); t.Log("B done") }()
counter := newMessageCounter(t, 5)
counterDone := counter.done
- netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: counter}})
+ netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.AgreementVoteTag, MessageHandler: counter}})
readyTimeout := time.NewTimer(2 * time.Second)
waitReady(t, netA, readyTimeout.C)
@@ -1399,7 +1452,7 @@ func TestDelayedMessageDrop(t *testing.T) {
currentTime := time.Now()
for i := 0; i < 10; i++ {
- err := netA.broadcastWithTimestamp(protocol.TxnTag, []byte("foo"), currentTime.Add(time.Hour*time.Duration(i-5)))
+ err := netA.broadcastWithTimestamp(protocol.AgreementVoteTag, []byte("foo"), currentTime.Add(time.Hour*time.Duration(i-5)))
require.NoErrorf(t, err, "No error was expected")
}
@@ -1494,7 +1547,7 @@ func TestForceMessageRelaying(t *testing.T) {
counter := newMessageCounter(t, 5)
counterDone := counter.done
- netA.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: counter}})
+ netA.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.AgreementVoteTag, MessageHandler: counter}})
netA.Start()
addrA, postListen := netA.Address()
require.Truef(t, postListen, "Listening network failed to start")
@@ -1521,9 +1574,9 @@ func TestForceMessageRelaying(t *testing.T) {
// send 5 messages from both netB and netC to netA
for i := 0; i < 5; i++ {
- err := netB.Relay(context.Background(), protocol.TxnTag, []byte{1, 2, 3}, true, nil)
+ err := netB.Relay(context.Background(), protocol.AgreementVoteTag, []byte{1, 2, 3}, true, nil)
require.NoError(t, err)
- err = netC.Relay(context.Background(), protocol.TxnTag, []byte{1, 2, 3}, true, nil)
+ err = netC.Relay(context.Background(), protocol.AgreementVoteTag, []byte{1, 2, 3}, true, nil)
require.NoError(t, err)
}
@@ -1539,13 +1592,13 @@ func TestForceMessageRelaying(t *testing.T) {
netA.ClearHandlers()
counter = newMessageCounter(t, 10)
counterDone = counter.done
- netA.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: counter}})
+ netA.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.AgreementVoteTag, MessageHandler: counter}})
// hack the relayMessages on the netB so that it would start sending messages.
netB.relayMessages = true
// send additional 10 messages from netB
for i := 0; i < 10; i++ {
- err := netB.Relay(context.Background(), protocol.TxnTag, []byte{1, 2, 3}, true, nil)
+ err := netB.Relay(context.Background(), protocol.AgreementVoteTag, []byte{1, 2, 3}, true, nil)
require.NoError(t, err)
}
@@ -1768,7 +1821,7 @@ func TestWebsocketNetworkMessageOfInterest(t *testing.T) {
// send 5 messages of few types.
for i := 0; i < 5; i++ {
netA.Broadcast(context.Background(), protocol.AgreementVoteTag, []byte{0, 1, 2, 3, 4}, true, nil)
- netA.Broadcast(context.Background(), protocol.TxnTag, []byte{0, 1, 2, 3, 4}, true, nil)
+ netA.Broadcast(context.Background(), protocol.CompactCertSigTag, []byte{0, 1, 2, 3, 4}, true, nil)
netA.Broadcast(context.Background(), protocol.ProposalPayloadTag, []byte{0, 1, 2, 3, 4}, true, nil)
netA.Broadcast(context.Background(), protocol.VoteBundleTag, []byte{0, 1, 2, 3, 4}, true, nil)
}
@@ -1866,7 +1919,7 @@ func TestWebsocketDisconnection(t *testing.T) {
case eventDetails := <-dl.eventReceived:
switch disconnectPeerEventDetails := eventDetails.(type) {
case telemetryspec.DisconnectPeerEventDetails:
- require.Equal(t, disconnectPeerEventDetails.Reason, string(disconnectRequestReceived))
+ require.Equal(t, string(disconnectRequestReceived), disconnectPeerEventDetails.Reason)
default:
require.FailNow(t, "Unexpected event was send : %v", eventDetails)
}
@@ -2002,7 +2055,7 @@ func BenchmarkVariableTransactionMessageBlockSizes(t *testing.B) {
// register all the handlers.
taggedHandlersA := []TaggedMessageHandler{
{
- Tag: protocol.TxnTag,
+ Tag: protocol.AgreementVoteTag,
MessageHandler: HandlerFunc(msgHandlerA),
},
}
@@ -2026,7 +2079,7 @@ func BenchmarkVariableTransactionMessageBlockSizes(t *testing.B) {
t.ResetTimer()
startTime := time.Now()
for i := 0; i < t.N/txnCount; i++ {
- netB.Broadcast(context.Background(), protocol.TxnTag, dataBuffer, true, nil)
+ netB.Broadcast(context.Background(), protocol.AgreementVoteTag, dataBuffer, true, nil)
<-msgProcessed
}
deltaTime := time.Now().Sub(startTime)
diff --git a/network/wsPeer.go b/network/wsPeer.go
index f9e5e1dc1..75e7a9633 100644
--- a/network/wsPeer.go
+++ b/network/wsPeer.go
@@ -76,10 +76,10 @@ var defaultSendMessageTags = map[protocol.Tag]bool{
protocol.ProposalPayloadTag: true,
protocol.TopicMsgRespTag: true,
protocol.MsgOfInterestTag: true,
- protocol.TxnTag: true,
protocol.UniCatchupReqTag: true,
protocol.UniEnsBlockReqTag: true,
protocol.VoteBundleTag: true,
+ protocol.Txn2Tag: true,
}
// interface allows substituting debug implementation for *websocket.Conn
@@ -94,10 +94,10 @@ type wsPeerWebsocketConn interface {
type sendMessage struct {
data []byte
- enqueued time.Time // the time at which the message was first generated
- peerEnqueued time.Time // the time at which the peer was attempting to enqueue the message
- msgTags map[protocol.Tag]bool // when msgTags is specified ( i.e. non-nil ), the send goroutine is to replace the message tag filter with this one. No data would be accompanied to this message.
- hash crypto.Digest
+ enqueued time.Time // the time at which the message was first generated
+ peerEnqueued time.Time // the time at which the peer was attempting to enqueue the message
+ msgTags map[protocol.Tag]bool // when msgTags is specified ( i.e. non-nil ), the send goroutine is to replace the message tag filter with this one. No data would be accompanied to this message.
+ callback UnicastWebsocketMessageStateCallback // when non-nil, the callback function would be called after entry would be placed on the outgoing websocket queue
ctx context.Context
}
@@ -122,6 +122,7 @@ const disconnectLeastPerformingPeer disconnectReason = "LeastPerformingPeer"
const disconnectCliqueResolve disconnectReason = "CliqueResolving"
const disconnectRequestReceived disconnectReason = "DisconnectRequest"
const disconnectStaleWrite disconnectReason = "DisconnectStaleWrite"
+const disconnectClientCallback disconnectReason = "ClientCallback"
// Response is the structure holding the response from the server
type Response struct {
@@ -222,6 +223,9 @@ type wsPeer struct {
// clientDataStoreMu synchronizes access to clientDataStore
clientDataStoreMu deadlock.Mutex
+
+ // outgoingMessageCounters counts the number of messages send for each tag. It allows us to use implicit message counting.
+ outgoingMessageCounters map[protocol.Tag]uint64
}
// HTTPPeer is what the opaque Peer might be.
@@ -231,16 +235,21 @@ type HTTPPeer interface {
GetHTTPClient() *http.Client
}
+// UnicastWebsocketMessageStateCallback provide asyncrounious feedback for the sequence number of a message
+// if the caller return an error, the network peer would disconnect
+type UnicastWebsocketMessageStateCallback func(enqueued bool, sequenceNumber uint64) error
+
// UnicastPeer is another possible interface for the opaque Peer.
// It is possible that we can only initiate a connection to a peer over websockets.
type UnicastPeer interface {
GetAddress() string
// Unicast sends the given bytes to this specific peer. Does not wait for message to be sent.
- Unicast(ctx context.Context, data []byte, tag protocol.Tag) error
+ Unicast(ctx context.Context, data []byte, tag protocol.Tag, callback UnicastWebsocketMessageStateCallback) error
// Version returns the matching version from network.SupportedProtocolVersions
Version() string
Request(ctx context.Context, tag Tag, topics Topics) (resp *Response, e error)
Respond(ctx context.Context, reqMsg IncomingMessage, topics Topics) (e error)
+ IsOutgoing() bool
}
// Create a wsPeerCore object
@@ -270,9 +279,15 @@ func (wp *wsPeer) Version() string {
return wp.version
}
+// IsOutgoing returns true if the connection is an outgoing connection or false if it the connection
+// is an incoming connection.
+func (wp *wsPeer) IsOutgoing() bool {
+ return wp.outgoing
+}
+
// Unicast sends the given bytes to this specific peer. Does not wait for message to be sent.
// (Implements UnicastPeer)
-func (wp *wsPeer) Unicast(ctx context.Context, msg []byte, tag protocol.Tag) error {
+func (wp *wsPeer) Unicast(ctx context.Context, msg []byte, tag protocol.Tag, callback UnicastWebsocketMessageStateCallback) error {
var err error
tbytes := []byte(tag)
@@ -284,7 +299,7 @@ func (wp *wsPeer) Unicast(ctx context.Context, msg []byte, tag protocol.Tag) err
digest = crypto.Hash(mbytes)
}
- ok := wp.writeNonBlock(ctx, mbytes, false, digest, time.Now())
+ ok := wp.writeNonBlock(ctx, mbytes, false, digest, time.Now(), callback)
if !ok {
networkBroadcastsDropped.Inc(nil)
err = fmt.Errorf("wsPeer failed to unicast: %v", wp.GetAddress())
@@ -337,6 +352,7 @@ func (wp *wsPeer) init(config config.Local, sendBufferLength int) {
wp.responseChannels = make(map[uint64]chan *Response)
wp.sendMessageTag = defaultSendMessageTags
wp.clientDataStore = make(map[string]interface{})
+ wp.outgoingMessageCounters = make(map[protocol.Tag]uint64)
// processed is a channel that messageHandlerThread writes to
// when it's done with one of our messages, so that we can queue
@@ -351,6 +367,17 @@ func (wp *wsPeer) init(config config.Local, sendBufferLength int) {
wp.outgoingMsgFilter = makeMessageFilter(config.OutgoingMessageFilterBucketCount, config.OutgoingMessageFilterBucketSize)
}
+ // if we're on an older version, then add the old style transaction message to the send messages tag.
+ // once we deprecate old style transaction sending, this part can go away.
+ if wp.version != "3.0" {
+ txSendMsgTags := make(map[protocol.Tag]bool)
+ for tag := range wp.sendMessageTag {
+ txSendMsgTags[tag] = true
+ }
+ txSendMsgTags[protocol.TxnTag] = true
+ wp.sendMessageTag = txSendMsgTags
+ }
+
wp.wg.Add(2)
go wp.readLoop()
go wp.writeLoop()
@@ -383,6 +410,7 @@ func (wp *wsPeer) readLoop() {
}()
wp.conn.SetReadLimit(maxMessageLength)
slurper := MakeLimitedReaderSlurper(averageMessageLength, maxMessageLength)
+ sequenceCounters := make(map[protocol.Tag]uint64)
for {
msg := IncomingMessage{}
mtype, reader, err := wp.conn.NextReader()
@@ -428,6 +456,8 @@ func (wp *wsPeer) readLoop() {
networkReceivedBytesByTag.Add(string(tag[:]), uint64(len(msg.Data)+2))
networkMessageReceivedByTag.Add(string(tag[:]), 1)
msg.Sender = wp
+ msg.Sequence = sequenceCounters[msg.Tag]
+ sequenceCounters[msg.Tag] = msg.Sequence + 1
// for outgoing connections, we want to notify the connection monitor that we've received
// a message. The connection monitor would update it's statistics accordingly.
@@ -581,6 +611,12 @@ func (wp *wsPeer) writeLoopSendMsg(msg sendMessage) disconnectReason {
if len(msg.data) > maxMessageLength {
wp.net.log.Errorf("trying to send a message longer than we would receive: %d > %d tag=%s", len(msg.data), maxMessageLength, string(msg.data[0:2]))
// just drop it, don't break the connection
+ if msg.callback != nil {
+ // let the callback know that the message was not sent.
+ if nil != msg.callback(false, 0) {
+ return disconnectClientCallback
+ }
+ }
return disconnectReasonNone
}
if msg.msgTags != nil {
@@ -593,6 +629,12 @@ func (wp *wsPeer) writeLoopSendMsg(msg sendMessage) disconnectReason {
tag := protocol.Tag(msg.data[:2])
if !wp.sendMessageTag[tag] {
// the peer isn't interested in this message.
+ if msg.callback != nil {
+ // let the callback know that the message was not sent.
+ if nil != msg.callback(false, 0) {
+ return disconnectClientCallback
+ }
+ }
return disconnectReasonNone
}
@@ -601,6 +643,12 @@ func (wp *wsPeer) writeLoopSendMsg(msg sendMessage) disconnectReason {
if msgWaitDuration > maxMessageQueueDuration {
wp.net.log.Warnf("peer stale enqueued message %dms", msgWaitDuration.Nanoseconds()/1000000)
networkConnectionsDroppedTotal.Inc(map[string]string{"reason": "stale message"})
+ if msg.callback != nil {
+ // let the callback know that the message was not sent.
+ if nil != msg.callback(false, 0) {
+ return disconnectClientCallback
+ }
+ }
return disconnectStaleWrite
}
atomic.StoreInt64(&wp.intermittentOutgoingMessageEnqueueTime, msg.enqueued.UnixNano())
@@ -611,6 +659,12 @@ func (wp *wsPeer) writeLoopSendMsg(msg sendMessage) disconnectReason {
wp.net.log.Warn("peer write error ", err)
networkConnectionsDroppedTotal.Inc(map[string]string{"reason": "write err"})
}
+ if msg.callback != nil {
+ // let the callback know that the message was not sent.
+ if nil != msg.callback(false, 0) {
+ return disconnectClientCallback
+ }
+ }
return disconnectWriteError
}
atomic.StoreInt64(&wp.lastPacketTime, time.Now().UnixNano())
@@ -619,6 +673,16 @@ func (wp *wsPeer) writeLoopSendMsg(msg sendMessage) disconnectReason {
networkMessageSentTotal.AddUint64(1, nil)
networkMessageSentByTag.Add(string(tag), 1)
networkMessageQueueMicrosTotal.AddUint64(uint64(time.Now().Sub(msg.peerEnqueued).Nanoseconds()/1000), nil)
+
+ if msg.callback != nil {
+ // for performance reasons, we count messages only for messages that request a callback. we might want to revisit this
+ // in the future.
+ seq := wp.outgoingMessageCounters[tag]
+ if nil != msg.callback(true, seq) {
+ return disconnectClientCallback
+ }
+ wp.outgoingMessageCounters[tag] = seq + 1
+ }
return disconnectReasonNone
}
@@ -661,16 +725,16 @@ func (wp *wsPeer) writeLoopCleanup(reason disconnectReason) {
wp.wg.Done()
}
-func (wp *wsPeer) writeNonBlock(ctx context.Context, data []byte, highPrio bool, digest crypto.Digest, msgEnqueueTime time.Time) bool {
+func (wp *wsPeer) writeNonBlock(ctx context.Context, data []byte, highPrio bool, digest crypto.Digest, msgEnqueueTime time.Time, callback UnicastWebsocketMessageStateCallback) bool {
msgs := make([][]byte, 1, 1)
digests := make([]crypto.Digest, 1, 1)
msgs[0] = data
digests[0] = digest
- return wp.writeNonBlockMsgs(ctx, msgs, highPrio, digests, msgEnqueueTime)
+ return wp.writeNonBlockMsgs(ctx, msgs, highPrio, digests, msgEnqueueTime, callback)
}
// return true if enqueued/sent
-func (wp *wsPeer) writeNonBlockMsgs(ctx context.Context, data [][]byte, highPrio bool, digest []crypto.Digest, msgEnqueueTime time.Time) bool {
+func (wp *wsPeer) writeNonBlockMsgs(ctx context.Context, data [][]byte, highPrio bool, digest []crypto.Digest, msgEnqueueTime time.Time, callback UnicastWebsocketMessageStateCallback) bool {
includeIndices := make([]int, 0, len(data))
for i := range data {
if wp.outgoingMsgFilter != nil && len(data[i]) > messageFilterSize && wp.outgoingMsgFilter.CheckDigest(digest[i], false, false) {
@@ -692,7 +756,7 @@ func (wp *wsPeer) writeNonBlockMsgs(ctx context.Context, data [][]byte, highPrio
msgs := make([]sendMessage, 0, len(includeIndices))
enqueueTime := time.Now()
for _, index := range includeIndices {
- msgs = append(msgs, sendMessage{data: data[index], enqueued: msgEnqueueTime, peerEnqueued: enqueueTime, hash: digest[index], ctx: ctx})
+ msgs = append(msgs, sendMessage{data: data[index], enqueued: msgEnqueueTime, peerEnqueued: enqueueTime, ctx: ctx, callback: callback})
}
if highPrio {
@@ -726,7 +790,7 @@ func (wp *wsPeer) sendPing() bool {
copy(mbytes, tagBytes)
crypto.RandBytes(mbytes[len(tagBytes):])
wp.pingData = mbytes[len(tagBytes):]
- sent := wp.writeNonBlock(context.Background(), mbytes, false, crypto.Digest{}, time.Now())
+ sent := wp.writeNonBlock(context.Background(), mbytes, false, crypto.Digest{}, time.Now(), nil) // todo : we might want to use the callback function to figure a more precise sending time.
if sent {
wp.pingInFlight = true
diff --git a/node/assemble_test.go b/node/assemble_test.go
index f094c8dd9..937b039db 100644
--- a/node/assemble_test.go
+++ b/node/assemble_test.go
@@ -30,6 +30,7 @@ import (
"github.com/algorand/go-algorand/data"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
+ "github.com/algorand/go-algorand/data/pooldata"
"github.com/algorand/go-algorand/data/pools"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/logging"
@@ -132,7 +133,8 @@ func BenchmarkAssembleBlock(b *testing.B) {
if okcount == 0 {
worstTxID = signedTx.ID()
}
- err := tp.Remember([]transactions.SignedTxn{signedTx})
+
+ err := tp.Remember(pooldata.SignedTxGroup{Transactions: []transactions.SignedTxn{signedTx}})
if err != nil {
errcount++
b.Logf("(%d/%d) could not send [%d] %s -> [%d] %s: %s", errcount, okcount, sourcei, addresses[sourcei], desti, addresses[desti], err)
diff --git a/node/node.go b/node/node.go
index b43393e67..62256b348 100644
--- a/node/node.go
+++ b/node/node.go
@@ -38,6 +38,7 @@ import (
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
"github.com/algorand/go-algorand/data/committee"
+ "github.com/algorand/go-algorand/data/pooldata"
"github.com/algorand/go-algorand/data/pools"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/data/transactions/verify"
@@ -49,6 +50,7 @@ import (
"github.com/algorand/go-algorand/node/indexer"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/rpcs"
+ "github.com/algorand/go-algorand/txnsync"
"github.com/algorand/go-algorand/util/db"
"github.com/algorand/go-algorand/util/execpool"
"github.com/algorand/go-algorand/util/metrics"
@@ -106,6 +108,7 @@ type AlgorandFullNode struct {
blockService *rpcs.BlockService
ledgerService *rpcs.LedgerService
txPoolSyncerService *rpcs.TxSyncer
+ txnSyncService *txnsync.Service
indexer *indexer.Indexer
@@ -133,6 +136,8 @@ type AlgorandFullNode struct {
tracer messagetracer.MessageTracer
compactCert *compactcert.Worker
+
+ txnSyncConnector *transactionSyncNodeConnector
}
// TxnWithStatus represents information about a single transaction,
@@ -210,15 +215,6 @@ func MakeFull(log logging.Logger, rootDir string, cfg config.Local, phonebookAdd
node.transactionPool = pools.MakeTransactionPool(node.ledger.Ledger, cfg, node.log)
- blockListeners := []ledger.BlockListener{
- node.transactionPool,
- node,
- }
-
- if node.config.EnableTopAccountsReporting {
- blockListeners = append(blockListeners, &accountListener)
- }
- node.ledger.RegisterBlockListeners(blockListeners)
node.txHandler = data.MakeTxHandler(node.transactionPool, node.ledger, node.net, node.genesisID, node.genesisHash, node.lowPriorityCryptoVerificationPool)
// Indexer setup
@@ -267,6 +263,8 @@ func MakeFull(log logging.Logger, rootDir string, cfg config.Local, phonebookAdd
node.catchupBlockAuth = blockAuthenticatorImpl{Ledger: node.ledger, AsyncVoteVerifier: agreement.MakeAsyncVoteVerifier(node.lowPriorityCryptoVerificationPool)}
node.catchupService = catchup.MakeService(node.log, node.config, p2pNode, node.ledger, node.catchupBlockAuth, agreementLedger.UnmatchedPendingCertificates, node.lowPriorityCryptoVerificationPool)
node.txPoolSyncerService = rpcs.MakeTxSyncer(node.transactionPool, node.net, node.txHandler.SolicitedTxHandler(), time.Duration(cfg.TxSyncIntervalSeconds)*time.Second, time.Duration(cfg.TxSyncTimeoutSeconds)*time.Second, cfg.TxSyncServeResponseSize)
+ node.txnSyncConnector = makeTransactionSyncNodeConnector(node)
+ node.txnSyncService = txnsync.MakeTransactionSyncService(node.log, node.txnSyncConnector, cfg.NetAddress != "", node.genesisID, node.genesisHash, node.config, node.lowPriorityCryptoVerificationPool)
err = node.loadParticipationKeys()
if err != nil {
@@ -300,6 +298,17 @@ func MakeFull(log logging.Logger, rootDir string, cfg config.Local, phonebookAdd
}
node.compactCert = compactcert.NewWorker(compactCertAccess, node.log, node.accountManager, node.ledger.Ledger, node.net, node)
+ blockListeners := []ledger.BlockListener{
+ node.txnSyncConnector,
+ node.transactionPool,
+ node,
+ }
+
+ if node.config.EnableTopAccountsReporting {
+ blockListeners = append(blockListeners, &accountListener)
+ }
+ node.ledger.RegisterBlockListeners(blockListeners)
+
return node, err
}
@@ -370,9 +379,12 @@ func (node *AlgorandFullNode) Start() {
node.txPoolSyncerService.Start(node.catchupService.InitialSyncDone)
node.blockService.Start()
node.ledgerService.Start()
- node.txHandler.Start()
node.compactCert.Start()
+ node.txnSyncService.Start()
+ node.txnSyncConnector.start()
+
startNetwork()
+
// start indexer
if idx, err := node.Indexer(); err == nil {
err := idx.Start()
@@ -439,7 +451,8 @@ func (node *AlgorandFullNode) Stop() {
if node.catchpointCatchupService != nil {
node.catchpointCatchupService.Stop()
} else {
- node.txHandler.Stop()
+ node.txnSyncService.Stop()
+ node.txnSyncConnector.stop()
node.agreementService.Shutdown()
node.catchupService.Stop()
node.txPoolSyncerService.Stop()
@@ -515,7 +528,7 @@ func (node *AlgorandFullNode) BroadcastSignedTxGroup(txgroup []transactions.Sign
return err
}
- err = node.transactionPool.Remember(txgroup)
+ err = node.transactionPool.Remember(pooldata.SignedTxGroup{Transactions: txgroup, LocallyOriginated: true})
if err != nil {
node.log.Infof("rejected by local pool: %v - transaction group was %+v", err, txgroup)
return err
@@ -526,6 +539,8 @@ func (node *AlgorandFullNode) BroadcastSignedTxGroup(txgroup []transactions.Sign
logging.Base().Infof("unable to pin transaction: %v", err)
}
+ node.txnSyncConnector.onNewTransactionPoolEntry(node.transactionPool.PendingCount())
+
var enc []byte
var txids []transactions.Txid
for _, tx := range txgroup {
@@ -740,7 +755,12 @@ func (node *AlgorandFullNode) SuggestedFee() basics.MicroAlgos {
// GetPendingTxnsFromPool returns a snapshot of every pending transactions from the node's transaction pool in a slice.
// Transactions are sorted in decreasing order. If no transactions, returns an empty slice.
func (node *AlgorandFullNode) GetPendingTxnsFromPool() ([]transactions.SignedTxn, error) {
- return bookkeeping.SignedTxnGroupsFlatten(node.transactionPool.PendingTxGroups()), nil
+ poolGroups, _ := node.transactionPool.PendingTxGroups()
+ txnGroups := make([][]transactions.SignedTxn, len(poolGroups))
+ for i := range txnGroups {
+ txnGroups[i] = poolGroups[i].Transactions
+ }
+ return bookkeeping.SignedTxnGroupsFlatten(txnGroups), nil
}
// Reload participation keys from disk periodically
@@ -842,10 +862,17 @@ func (node *AlgorandFullNode) IsArchival() bool {
}
// OnNewBlock implements the BlockListener interface so we're notified after each block is written to the ledger
+// The method is being called *after* the transaction pool received it's OnNewBlock call.
func (node *AlgorandFullNode) OnNewBlock(block bookkeeping.Block, delta ledgercore.StateDelta) {
- if node.ledger.Latest() > block.Round() {
+ blkRound := block.Round()
+ if node.ledger.Latest() > blkRound {
return
}
+
+ // the transaction pool already updated its transactions (dumping out old and invalid transactions). At this point,
+ // we need to let the txnsync know about the size of the transaction pool.
+ node.txnSyncConnector.onNewTransactionPoolEntry(node.transactionPool.PendingCount())
+
node.syncStatusMu.Lock()
node.lastRoundTimestamp = time.Now()
node.hasSyncedSinceStartup = true
@@ -1013,7 +1040,8 @@ func (node *AlgorandFullNode) SetCatchpointCatchupMode(catchpointCatchupMode boo
node.waitMonitoringRoutines()
}()
node.net.ClearHandlers()
- node.txHandler.Stop()
+ node.txnSyncConnector.stop()
+ node.txnSyncService.Stop()
node.agreementService.Shutdown()
node.catchupService.Stop()
node.txPoolSyncerService.Stop()
@@ -1037,7 +1065,8 @@ func (node *AlgorandFullNode) SetCatchpointCatchupMode(catchpointCatchupMode boo
node.txPoolSyncerService.Start(node.catchupService.InitialSyncDone)
node.blockService.Start()
node.ledgerService.Start()
- node.txHandler.Start()
+ node.txnSyncService.Start()
+ node.txnSyncConnector.start()
// start indexer
if idx, err := node.Indexer(); err == nil {
diff --git a/node/txnSyncConn.go b/node/txnSyncConn.go
new file mode 100644
index 000000000..1a88b7998
--- /dev/null
+++ b/node/txnSyncConn.go
@@ -0,0 +1,240 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+// Package node is the Algorand node itself, with functions exposed to the frontend
+package node
+
+import (
+ "context"
+ "time"
+
+ "github.com/algorand/go-algorand/data"
+ "github.com/algorand/go-algorand/data/bookkeeping"
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/ledger/ledgercore"
+ "github.com/algorand/go-algorand/network"
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/txnsync"
+ "github.com/algorand/go-algorand/util/timers"
+)
+
+// txnsyncPeerDataKey is the key name by which we're going to store the
+// transaction sync internal data object inside the network peer.
+const txnsyncPeerDataKey = "txsync"
+
+// transactionSyncNodeConnector implements the txnsync.NodeConnector interface, allowing the
+// transaction sync communicate with the node and it's child objects.
+type transactionSyncNodeConnector struct {
+ node *AlgorandFullNode
+ eventsCh chan txnsync.Event
+ clock timers.WallClock
+ messageHandler txnsync.IncomingMessageHandler
+ txHandler data.SolicitedAsyncTxHandler
+ openStateCh chan struct{}
+}
+
+func makeTransactionSyncNodeConnector(node *AlgorandFullNode) *transactionSyncNodeConnector {
+ return &transactionSyncNodeConnector{
+ node: node,
+ eventsCh: make(chan txnsync.Event, 1),
+ clock: timers.MakeMonotonicClock(time.Now()),
+ txHandler: node.txHandler.SolicitedAsyncTxHandler(),
+ openStateCh: make(chan struct{}),
+ }
+}
+
+func (tsnc *transactionSyncNodeConnector) Events() <-chan txnsync.Event {
+ return tsnc.eventsCh
+}
+
+// GetCurrentRoundSettings is called when the txsync is starting up, proving
+// round information.
+func (tsnc *transactionSyncNodeConnector) GetCurrentRoundSettings() txnsync.RoundSettings {
+ round := tsnc.node.ledger.Latest()
+ return txnsync.RoundSettings{
+ Round: round,
+ FetchTransactions: tsnc.node.config.ForceFetchTransactions || tsnc.node.accountManager.HasLiveKeys(round, round),
+ }
+}
+
+// NotifyMonitor is used for testing purposes only, and can remain(almost) empty on production code.
+func (tsnc *transactionSyncNodeConnector) NotifyMonitor() chan struct{} {
+ return tsnc.openStateCh
+}
+
+func (tsnc *transactionSyncNodeConnector) Random(upperBound uint64) uint64 {
+ return tsnc.node.Uint64() % upperBound
+}
+
+func (tsnc *transactionSyncNodeConnector) Clock() timers.WallClock {
+ return tsnc.clock
+}
+
+func (tsnc *transactionSyncNodeConnector) GetPeer(networkPeer interface{}) txnsync.PeerInfo {
+ unicastPeer := networkPeer.(network.UnicastPeer)
+ if unicastPeer == nil {
+ return txnsync.PeerInfo{}
+ }
+
+ peerData := tsnc.node.net.GetPeerData(networkPeer, txnsyncPeerDataKey)
+ if peerData == nil {
+ return txnsync.PeerInfo{
+ IsOutgoing: unicastPeer.IsOutgoing(),
+ NetworkPeer: unicastPeer,
+ }
+ }
+ return txnsync.PeerInfo{
+ IsOutgoing: unicastPeer.IsOutgoing(),
+ NetworkPeer: unicastPeer,
+ TxnSyncPeer: peerData.(*txnsync.Peer),
+ }
+}
+
+func (tsnc *transactionSyncNodeConnector) GetPeers() (peersInfo []txnsync.PeerInfo) {
+ networkPeers := tsnc.node.net.GetPeers(network.PeersConnectedOut, network.PeersConnectedIn)
+ peersInfo = make([]txnsync.PeerInfo, len(networkPeers))
+ k := 0
+ for i := range networkPeers {
+ unicastPeer := networkPeers[i].(network.UnicastPeer)
+ if unicastPeer == nil {
+ continue
+ }
+ // check version.
+ if unicastPeer.Version() != "3.0" {
+ continue
+ }
+ peersInfo[k].IsOutgoing = unicastPeer.IsOutgoing()
+ peersInfo[k].NetworkPeer = networkPeers[i]
+ peerData := tsnc.node.net.GetPeerData(networkPeers[i], txnsyncPeerDataKey)
+ if peerData != nil {
+ peersInfo[k].TxnSyncPeer = peerData.(*txnsync.Peer)
+ }
+ k++
+ }
+
+ return peersInfo[:k]
+}
+
+func (tsnc *transactionSyncNodeConnector) UpdatePeers(txnsyncPeers []*txnsync.Peer, netPeers []interface{}, averageDataExchangeRate uint64) {
+ for i, netPeer := range netPeers {
+ tsnc.node.net.SetPeerData(netPeer, txnsyncPeerDataKey, txnsyncPeers[i])
+ }
+ // The average peers data exchange rate has been updated.
+ if averageDataExchangeRate > 0 {
+ // update the transaction pool with the latest peers data exchange rate.
+ tsnc.node.transactionPool.SetDataExchangeRate(averageDataExchangeRate)
+ }
+}
+
+func (tsnc *transactionSyncNodeConnector) SendPeerMessage(netPeer interface{}, msg []byte, callback txnsync.SendMessageCallback) {
+ unicastPeer := netPeer.(network.UnicastPeer)
+ if unicastPeer == nil {
+ return
+ }
+
+ // this might return an error to the network package callback routine. Returning an error signal the network package
+ // that we want to disconnect from this peer. This aligns with the transaction sync txnsync.SendMessageCallback function
+ // behaviour.
+ if err := unicastPeer.Unicast(context.Background(), msg, protocol.Txn2Tag, network.UnicastWebsocketMessageStateCallback(callback)); err != nil {
+ if callbackErr := callback(false, 0); callbackErr != nil {
+ // disconnect from peer - the transaction sync wasn't able to process message sending confirmation
+ tsnc.node.net.Disconnect(unicastPeer)
+ }
+ }
+}
+
+// GetPendingTransactionGroups is called by the transaction sync when it needs to look into the transaction
+// pool and get the updated set of pending transactions. The second returned argument is the latest locally originated
+// group counter within the given transaction groups list. If there is no group that is locally originated, the expected
+// value is InvalidSignedTxGroupCounter.
+func (tsnc *transactionSyncNodeConnector) GetPendingTransactionGroups() ([]pooldata.SignedTxGroup, uint64) {
+ return tsnc.node.transactionPool.PendingTxGroups()
+}
+
+func (tsnc *transactionSyncNodeConnector) onNewTransactionPoolEntry(transactionPoolSize int) {
+ select {
+ case tsnc.eventsCh <- txnsync.MakeTransactionPoolChangeEvent(transactionPoolSize, false):
+ default:
+ }
+}
+
+// OnNewBlock receives a notification that we've moved to a new round from the ledger.
+// This notification would be received before the transaction pool get a similar notification, due
+// the ordering of the block notifier registration.
+func (tsnc *transactionSyncNodeConnector) OnNewBlock(block bookkeeping.Block, delta ledgercore.StateDelta) {
+ blkRound := block.Round()
+
+ fetchTransactions := tsnc.node.config.ForceFetchTransactions || tsnc.node.accountManager.HasLiveKeys(blkRound, blkRound)
+ // if this is a relay, then we always want to fetch transactions, regardless if we have participation keys.
+ if tsnc.node.config.NetAddress != "" {
+ fetchTransactions = true
+ }
+
+ select {
+ case tsnc.eventsCh <- txnsync.MakeNewRoundEvent(blkRound, fetchTransactions):
+ default:
+ }
+
+}
+
+func (tsnc *transactionSyncNodeConnector) start() {
+ tsnc.txHandler.Start()
+ tsnc.messageHandler = tsnc.node.txnSyncService.GetIncomingMessageHandler()
+ handlers := []network.TaggedMessageHandler{
+ {Tag: protocol.Txn2Tag, MessageHandler: tsnc},
+ }
+ tsnc.node.net.RegisterHandlers(handlers)
+}
+
+func (tsnc *transactionSyncNodeConnector) Handle(raw network.IncomingMessage) network.OutgoingMessage {
+ unicastPeer := raw.Sender.(network.UnicastPeer)
+ if unicastPeer != nil {
+ // check version.
+ if unicastPeer.Version() != "3.0" {
+ return network.OutgoingMessage{
+ Action: network.Ignore,
+ }
+ }
+ }
+ var peer *txnsync.Peer
+ peerData := tsnc.node.net.GetPeerData(raw.Sender, txnsyncPeerDataKey)
+ if peerData != nil {
+ peer = peerData.(*txnsync.Peer)
+ }
+
+ err := tsnc.messageHandler(raw.Sender, peer, raw.Data, raw.Sequence)
+ if err != nil {
+ return network.OutgoingMessage{
+ Action: network.Disconnect,
+ }
+ }
+ return network.OutgoingMessage{
+ Action: network.Ignore,
+ }
+}
+
+func (tsnc *transactionSyncNodeConnector) stop() {
+ tsnc.txHandler.Stop()
+}
+
+func (tsnc *transactionSyncNodeConnector) IncomingTransactionGroups(peer *txnsync.Peer, messageSeq uint64, txGroups []pooldata.SignedTxGroup) (transactionPoolSize int) {
+ if tsnc.txHandler.HandleTransactionGroups(peer.GetNetworkPeer(), peer.GetTransactionPoolAckChannel(), messageSeq, txGroups) {
+ transactionPoolSize = tsnc.node.transactionPool.PendingCount()
+ } else {
+ transactionPoolSize = -1
+ }
+ return
+}
diff --git a/protocol/tags.go b/protocol/tags.go
index 0cab25628..070460c1a 100644
--- a/protocol/tags.go
+++ b/protocol/tags.go
@@ -41,4 +41,5 @@ const (
//UniEnsBlockResTag Tag = "US" was used for wsfetcherservice
//UniCatchupResTag Tag = "UT" was used for wsfetcherservice
VoteBundleTag Tag = "VB"
+ Txn2Tag Tag = "tx"
)
diff --git a/protocol/txntype.go b/protocol/txntype.go
index 919c576d4..8f6129139 100644
--- a/protocol/txntype.go
+++ b/protocol/txntype.go
@@ -47,3 +47,15 @@ const (
// UnknownTx signals an error
UnknownTx TxType = "unknown"
)
+
+// TxnTypes is an array containing all the defined transaction types
+var TxnTypes = []TxType{
+ PaymentTx,
+ KeyRegistrationTx,
+ AssetConfigTx,
+ AssetTransferTx,
+ AssetFreezeTx,
+ ApplicationCallTx,
+ CompactCertTx,
+ UnknownTx,
+}
diff --git a/rpcs/blockService_test.go b/rpcs/blockService_test.go
index a48217b13..5b16ae87b 100644
--- a/rpcs/blockService_test.go
+++ b/rpcs/blockService_test.go
@@ -44,11 +44,14 @@ type mockUnicastPeer struct {
func (mup *mockUnicastPeer) GetAddress() string {
return ""
}
-func (mup *mockUnicastPeer) Unicast(ctx context.Context, data []byte, tag protocol.Tag) error {
+func (mup *mockUnicastPeer) Unicast(ctx context.Context, msg []byte, tag protocol.Tag, callback network.UnicastWebsocketMessageStateCallback) error {
return nil
}
func (mup *mockUnicastPeer) Version() string {
- return "2.1"
+ return network.ProtocolVersion
+}
+func (mup *mockUnicastPeer) IsOutgoing() bool {
+ return false
}
func (mup *mockUnicastPeer) Request(ctx context.Context, tag network.Tag, topics network.Topics) (resp *network.Response, e error) {
return nil, nil
diff --git a/rpcs/txService.go b/rpcs/txService.go
index df08114c6..9201f96e2 100644
--- a/rpcs/txService.go
+++ b/rpcs/txService.go
@@ -194,7 +194,11 @@ func (txs *TxService) updateTxCache() (pendingTxGroups [][]transactions.SignedTx
// The txs.pool.PendingTxGroups() function allocates a new array on every call. That means that the old
// array ( if being used ) is still valid. There is no risk of data race here since
// the txs.pendingTxGroups is a slice (hence a pointer to the array) and not the array itself.
- txs.pendingTxGroups = txs.pool.PendingTxGroups()
+ pendingSignedTxGroups, _ := txs.pool.PendingTxGroups()
+ txs.pendingTxGroups = make([][]transactions.SignedTxn, len(pendingSignedTxGroups))
+ for i := range txs.pendingTxGroups {
+ txs.pendingTxGroups[i] = pendingSignedTxGroups[i].Transactions
+ }
txs.lastUpdate = currentUnixTime
}
return txs.pendingTxGroups
diff --git a/rpcs/txSyncer.go b/rpcs/txSyncer.go
index 0290d82a6..4d9f344f1 100644
--- a/rpcs/txSyncer.go
+++ b/rpcs/txSyncer.go
@@ -23,6 +23,7 @@ import (
"time"
"github.com/algorand/go-algorand/data"
+ "github.com/algorand/go-algorand/data/pooldata"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/network"
@@ -32,7 +33,7 @@ import (
// PendingTxAggregate is a container of pending transactions
type PendingTxAggregate interface {
PendingTxIDs() []transactions.Txid
- PendingTxGroups() [][]transactions.SignedTxn
+ PendingTxGroups() ([]pooldata.SignedTxGroup, uint64)
}
// TxSyncClient abstracts sync-ing pending transactions from a peer.
diff --git a/rpcs/txSyncer_test.go b/rpcs/txSyncer_test.go
index 9b89fda1b..c9a0d274f 100644
--- a/rpcs/txSyncer_test.go
+++ b/rpcs/txSyncer_test.go
@@ -32,6 +32,7 @@ import (
"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/bookkeeping"
+ "github.com/algorand/go-algorand/data/pooldata"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/network"
@@ -75,8 +76,16 @@ func (mock mockPendingTxAggregate) PendingTxIDs() []transactions.Txid {
}
return ids
}
-func (mock mockPendingTxAggregate) PendingTxGroups() [][]transactions.SignedTxn {
- return bookkeeping.SignedTxnsToGroups(mock.txns)
+func makeSignedTxGroup(source [][]transactions.SignedTxn) (result []pooldata.SignedTxGroup) {
+ result = make([]pooldata.SignedTxGroup, len(source))
+ for i := range source {
+ result[i].Transactions = source[i]
+ }
+ return
+}
+
+func (mock mockPendingTxAggregate) PendingTxGroups() ([]pooldata.SignedTxGroup, uint64) {
+ return makeSignedTxGroup(bookkeeping.SignedTxnsToGroups(mock.txns)), pooldata.InvalidSignedTxGroupCounter
}
type mockHandler struct {
@@ -97,7 +106,7 @@ type mockRunner struct {
done chan *rpc.Call
failWithNil bool
failWithError bool
- txgroups [][]transactions.SignedTxn
+ txgroups []pooldata.SignedTxGroup
}
type mockRPCClient struct {
@@ -128,7 +137,11 @@ func (client *mockRPCClient) Sync(ctx context.Context, bloom *bloom.Filter) (txg
if client.client.failWithError {
return nil, errors.New("failing call")
}
- return client.client.txgroups, nil
+ txgroups = make([][]transactions.SignedTxn, len(client.client.txgroups))
+ for i := range txgroups {
+ txgroups[i] = client.client.txgroups[i].Transactions
+ }
+ return txgroups, nil
}
// network.HTTPPeer interface
@@ -168,7 +181,8 @@ func TestSyncFromClient(t *testing.T) {
clientPool := makeMockPendingTxAggregate(2)
serverPool := makeMockPendingTxAggregate(1)
- runner := mockRunner{failWithNil: false, failWithError: false, txgroups: serverPool.PendingTxGroups()[len(serverPool.PendingTxGroups())-1:], done: make(chan *rpc.Call)}
+ serverTxGroups, _ := serverPool.PendingTxGroups()
+ runner := mockRunner{failWithNil: false, failWithError: false, txgroups: serverTxGroups[len(serverTxGroups)-1:], done: make(chan *rpc.Call)}
client := mockRPCClient{client: &runner, log: logging.TestingLog(t)}
clientAgg := mockClientAggregator{peers: []network.Peer{&client}}
handler := mockHandler{}
@@ -183,7 +197,8 @@ func TestSyncFromUnsupportedClient(t *testing.T) {
partitiontest.PartitionTest(t)
pool := makeMockPendingTxAggregate(3)
- runner := mockRunner{failWithNil: true, failWithError: false, txgroups: pool.PendingTxGroups()[len(pool.PendingTxGroups())-1:], done: make(chan *rpc.Call)}
+ poolTxGroups, _ := pool.PendingTxGroups()
+ runner := mockRunner{failWithNil: true, failWithError: false, txgroups: poolTxGroups[len(poolTxGroups)-1:], done: make(chan *rpc.Call)}
client := mockRPCClient{client: &runner, log: logging.TestingLog(t)}
clientAgg := mockClientAggregator{peers: []network.Peer{&client}}
handler := mockHandler{}
@@ -198,7 +213,8 @@ func TestSyncFromClientAndQuit(t *testing.T) {
partitiontest.PartitionTest(t)
pool := makeMockPendingTxAggregate(3)
- runner := mockRunner{failWithNil: false, failWithError: false, txgroups: pool.PendingTxGroups()[len(pool.PendingTxGroups())-1:], done: make(chan *rpc.Call)}
+ poolTxGroups, _ := pool.PendingTxGroups()
+ runner := mockRunner{failWithNil: false, failWithError: false, txgroups: poolTxGroups[len(poolTxGroups)-1:], done: make(chan *rpc.Call)}
client := mockRPCClient{client: &runner, log: logging.TestingLog(t)}
clientAgg := mockClientAggregator{peers: []network.Peer{&client}}
handler := mockHandler{}
@@ -213,7 +229,8 @@ func TestSyncFromClientAndError(t *testing.T) {
partitiontest.PartitionTest(t)
pool := makeMockPendingTxAggregate(3)
- runner := mockRunner{failWithNil: false, failWithError: true, txgroups: pool.PendingTxGroups()[len(pool.PendingTxGroups())-1:], done: make(chan *rpc.Call)}
+ poolTxGroups, _ := pool.PendingTxGroups()
+ runner := mockRunner{failWithNil: false, failWithError: true, txgroups: poolTxGroups[len(poolTxGroups)-1:], done: make(chan *rpc.Call)}
client := mockRPCClient{client: &runner, log: logging.TestingLog(t)}
clientAgg := mockClientAggregator{peers: []network.Peer{&client}}
handler := mockHandler{}
@@ -227,7 +244,8 @@ func TestSyncFromClientAndTimeout(t *testing.T) {
partitiontest.PartitionTest(t)
pool := makeMockPendingTxAggregate(3)
- runner := mockRunner{failWithNil: false, failWithError: false, txgroups: pool.PendingTxGroups()[len(pool.PendingTxGroups())-1:], done: make(chan *rpc.Call)}
+ poolTxGroups, _ := pool.PendingTxGroups()
+ runner := mockRunner{failWithNil: false, failWithError: false, txgroups: poolTxGroups[len(poolTxGroups)-1:], done: make(chan *rpc.Call)}
client := mockRPCClient{client: &runner, log: logging.TestingLog(t)}
clientAgg := mockClientAggregator{peers: []network.Peer{&client}}
handler := mockHandler{}
@@ -248,7 +266,8 @@ func TestSync(t *testing.T) {
nodeA.start()
nodeAURL := nodeA.rootURL()
- runner := mockRunner{failWithNil: false, failWithError: false, txgroups: pool.PendingTxGroups()[len(pool.PendingTxGroups())-1:], done: make(chan *rpc.Call)}
+ poolTxGroups, _ := pool.PendingTxGroups()
+ runner := mockRunner{failWithNil: false, failWithError: false, txgroups: poolTxGroups[len(poolTxGroups)-1:], done: make(chan *rpc.Call)}
client := mockRPCClient{client: &runner, rootURL: nodeAURL, log: logging.TestingLog(t)}
clientAgg := mockClientAggregator{peers: []network.Peer{&client}}
handler := mockHandler{}
@@ -283,7 +302,8 @@ func TestStartAndStop(t *testing.T) {
nodeA.start()
nodeAURL := nodeA.rootURL()
- runner := mockRunner{failWithNil: false, failWithError: false, txgroups: pool.PendingTxGroups()[len(pool.PendingTxGroups())-1:], done: make(chan *rpc.Call)}
+ poolTxGroups, _ := pool.PendingTxGroups()
+ runner := mockRunner{failWithNil: false, failWithError: false, txgroups: poolTxGroups[len(poolTxGroups)-1:], done: make(chan *rpc.Call)}
client := mockRPCClient{client: &runner, rootURL: nodeAURL, log: logging.TestingLog(t)}
clientAgg := mockClientAggregator{peers: []network.Peer{&client}}
handler := mockHandler{}
@@ -320,7 +340,8 @@ func TestStartAndQuit(t *testing.T) {
partitiontest.PartitionTest(t)
pool := makeMockPendingTxAggregate(3)
- runner := mockRunner{failWithNil: false, failWithError: false, txgroups: pool.PendingTxGroups()[len(pool.PendingTxGroups())-1:], done: make(chan *rpc.Call)}
+ poolTxGroups, _ := pool.PendingTxGroups()
+ runner := mockRunner{failWithNil: false, failWithError: false, txgroups: poolTxGroups[len(poolTxGroups)-1:], done: make(chan *rpc.Call)}
client := mockRPCClient{client: &runner, log: logging.TestingLog(t)}
clientAgg := mockClientAggregator{peers: []network.Peer{&client}}
handler := mockHandler{}
diff --git a/test/e2e-go/cli/goal/expect/goalNodeTest.exp b/test/e2e-go/cli/goal/expect/goalNodeTest.exp
index efab678f1..d1af42d77 100644
--- a/test/e2e-go/cli/goal/expect/goalNodeTest.exp
+++ b/test/e2e-go/cli/goal/expect/goalNodeTest.exp
@@ -53,22 +53,35 @@ if { [catch {
# Stop node
::AlgorandGoal::StopNode $TEST_PRIMARY_NODE_DIR
+ set WAIT_FOR_EOF 0
# Try stopping the node again, should fail
spawn goal node stop -d $TEST_PRIMARY_NODE_DIR
expect {
timeout { close; ::AlgorandGoal::Abort "Goal Node Stop did not fail as expected" }
- "^Cannot kill node: no running node in directory '*'" {puts "Node failed successfully"; close}
- eof { close; ::AlgorandGoal::Abort "Goal Node Stop did not fail as expected" }
+ "^Cannot kill node: no running node in directory '*'" {puts "Node failed to stop, as expected"; set WAIT_FOR_EOF 1; exp_continue }
+ eof {
+ if {$WAIT_FOR_EOF == 0} {
+ close;
+ ::AlgorandGoal::Abort "Goal Node Stop did not fail as expected"
+ }
+ set WAIT_FOR_EOF 0
+ }
}
- #Try stopping node in invalid directory, should fail
+ # Try stopping node in invalid directory, should fail
spawn goal node stop -d ''
expect {
timeout { close; ::AlgorandGoal::Abort "Goal Node Fail did not fail as expected" }
- "^Cannot kill node: the provided directory '*' does not exist" {puts "Node failed successfully"; close}
- eof { close; ::AlgorandGoal::Abort "Goal Node Stop did not fail as expected" }
+ "^Cannot kill node: the provided directory '*' does not exist" {puts "Node failed to start on an invalid directory, as expected"; set WAIT_FOR_EOF 1; exp_continue }
+ eof {
+ if {$WAIT_FOR_EOF == 0} {
+ close;
+ ::AlgorandGoal::Abort "Goal Node Stop did not fail as expected"
+ }
+ set WAIT_FOR_EOF 0
+ }
}
-
+
# "break" the node by replacing it's ledger data files with "broken" ones.
lassign [exec find $TEST_PRIMARY_NODE_DIR -name "ledger.tracker.sqlite"] PRIMARY_TRACKER_DATABASE_FILE
exec find $TEST_PRIMARY_NODE_DIR -name "ledger.tracker.sqlite*" -delete
diff --git a/test/e2e-go/features/participation/participationExpiration_test.go b/test/e2e-go/features/participation/participationExpiration_test.go
new file mode 100644
index 000000000..8c56ed5c0
--- /dev/null
+++ b/test/e2e-go/features/participation/participationExpiration_test.go
@@ -0,0 +1,172 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package participation
+
+import (
+ "path/filepath"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/test/framework/fixtures"
+ "github.com/algorand/go-algorand/test/partitiontest"
+)
+
+func testExpirationAccounts(t *testing.T, fixture *fixtures.RestClientFixture, finalStatus basics.Status, protocolCheck string) {
+
+ a := require.New(fixtures.SynchronizedTest(t))
+ pClient := fixture.GetLibGoalClientForNamedNode("Primary")
+
+ sClient := fixture.GetLibGoalClientForNamedNode("Secondary")
+ sWH, err := sClient.GetUnencryptedWalletHandle()
+ a.NoError(err)
+ sAccount, err := sClient.GenerateAddress(sWH)
+ a.NoError(err)
+
+ // send money to new account from some other account in the template, so that account can go online
+ accountList, err := fixture.GetWalletsSortedByBalance()
+ a.NoError(err)
+ richAccount := accountList[0].Address
+ _, initialRound := fixture.GetBalanceAndRound(richAccount)
+
+ minTxnFee, minAcctBalance, err := fixture.MinFeeAndBalance(initialRound)
+ a.NoError(err)
+
+ transactionFee := minTxnFee
+ amountToSendInitial := 5 * minAcctBalance
+ fixture.SendMoneyAndWait(initialRound, amountToSendInitial, transactionFee, richAccount, sAccount, "")
+ amt, err := sClient.GetBalance(sAccount)
+ a.NoError(err)
+ sNodeStatus, err := sClient.Status()
+ a.NoError(err)
+ seededRound := sNodeStatus.LastRound
+ a.Equal(amountToSendInitial, amt)
+
+ newAccountStatus, err := pClient.AccountInformation(sAccount)
+ a.NoError(err)
+ a.Equal(basics.Offline.String(), newAccountStatus.Status)
+
+ // account adds part key
+ partKeyFirstValid := uint64(0)
+ partKeyValidityPeriod := uint64(10)
+ partKeyLastValid := partKeyFirstValid + partKeyValidityPeriod
+ partkeyResponse, _, err := sClient.GenParticipationKeys(sAccount, partKeyFirstValid, partKeyLastValid, 0)
+ a.NoError(err)
+ a.Equal(sAccount, partkeyResponse.Parent.String())
+ // account uses part key to go online
+ goOnlineTx, err := sClient.MakeUnsignedGoOnlineTx(sAccount, &partkeyResponse, 0, 0, transactionFee, [32]byte{})
+ a.NoError(err)
+ a.Equal(sAccount, goOnlineTx.Src().String())
+ onlineTxID, err := sClient.SignAndBroadcastTransaction(sWH, nil, goOnlineTx)
+ a.NoError(err)
+
+ fixture.AssertValidTxid(onlineTxID)
+ maxRoundsToWaitForTxnConfirm := uint64(3)
+ fixture.WaitForTxnConfirmation(seededRound+maxRoundsToWaitForTxnConfirm, sAccount, onlineTxID)
+ sNodeStatus, _ = sClient.Status()
+ newAccountStatus, err = pClient.AccountInformation(sAccount)
+ a.NoError(err)
+ a.Equal(basics.Online.String(), newAccountStatus.Status)
+ sAccountData, err := sClient.AccountData(sAccount)
+ a.NoError(err)
+
+ lastValidRound := sAccountData.VoteLastValid
+
+ a.Equal(basics.Round(10), lastValidRound)
+
+ // We want to wait until we get to one round past the last valid round
+ err = fixture.WaitForRoundWithTimeout(uint64(lastValidRound) + 1)
+ newAccountStatus, err = pClient.AccountInformation(sAccount)
+ a.NoError(err)
+
+ // The account should be online still...
+ a.Equal(basics.Online.String(), newAccountStatus.Status)
+
+ // Now we want to send a transaction to the account and test that
+ // it was taken offline after we sent it something
+
+ amt, err = sClient.GetBalance(sAccount)
+ a.NoError(err)
+
+ _, initialRound = fixture.GetBalanceAndRound(richAccount)
+
+ blk, err := sClient.Block(initialRound)
+ a.NoError(err)
+ a.Equal(blk.CurrentProtocol, protocolCheck)
+
+ fixture.SendMoneyAndWait(initialRound, amountToSendInitial, transactionFee, richAccount, sAccount, "")
+
+ newAmt, err := sClient.GetBalance(sAccount)
+ a.NoError(err)
+
+ a.Greater(newAmt, amt)
+
+ err = fixture.WaitForRoundWithTimeout(uint64(initialRound) + 3)
+
+ newAccountStatus, err = pClient.AccountInformation(sAccount)
+ a.NoError(err)
+
+ // The account should be equal to the target status now
+ a.Equal(finalStatus.String(), newAccountStatus.Status)
+}
+
+// TestParticipationAccountsExpirationFuture tests that sending a transaction to an account with
+// its last valid round being less than the current round will turn it offline. This test will only
+// work when the consensus protocol enables it (in this case the future protocol)
+func TestParticipationAccountsExpirationFuture(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ if testing.Short() {
+ t.Skip()
+ }
+
+ t.Parallel()
+
+ var fixture fixtures.RestClientFixture
+
+ fixture.SetupNoStart(t, filepath.Join("nettemplates", "TwoNodesExpiredOfflineVFuture.json"))
+
+ fixture.Start()
+ defer fixture.Shutdown()
+
+ testExpirationAccounts(t, &fixture, basics.Offline, "future")
+}
+
+// TestParticipationAccountsExpirationNonFuture tests that sending a transaction to an account with
+// its last valid round being less than the current round will NOT turn it offline. This tests that
+// when the consensus protocol is less than the required version, it will not turn nodes offline
+func TestParticipationAccountsExpirationNonFuture(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ if testing.Short() {
+ t.Skip()
+ }
+
+ t.Parallel()
+
+ var fixture fixtures.RestClientFixture
+
+ // V29 is the version before participation key expiration checking was enabled
+ fixture.SetupNoStart(t, filepath.Join("nettemplates", "TwoNodesExpiredOfflineV29.json"))
+
+ fixture.Start()
+ defer fixture.Shutdown()
+
+ testExpirationAccounts(t, &fixture, basics.Online, string(protocol.ConsensusV29))
+}
diff --git a/test/e2e-go/features/partitionRecovery/partitionRecovery_test.go b/test/e2e-go/features/partitionRecovery/partitionRecovery_test.go
index d686ed798..3ec2c323d 100644
--- a/test/e2e-go/features/partitionRecovery/partitionRecovery_test.go
+++ b/test/e2e-go/features/partitionRecovery/partitionRecovery_test.go
@@ -23,6 +23,7 @@ import (
"github.com/stretchr/testify/require"
+ "github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/test/framework/fixtures"
"github.com/algorand/go-algorand/test/partitiontest"
)
@@ -244,7 +245,16 @@ func TestPartitionHalfOffline(t *testing.T) {
// Start all but 10% of stake and verify we recover
var fixture fixtures.RestClientFixture
- fixture.Setup(t, filepath.Join("nettemplates", "TenNodesDistributedMultiWallet.json"))
+ fixture.SetupNoStart(t, filepath.Join("nettemplates", "TenNodesDistributedMultiWallet.json"))
+ for _, nodeDir := range fixture.NodeDataDirs() {
+ cfg, err := config.LoadConfigFromDisk(nodeDir)
+ a.NoError(err)
+ // adjust the refresh interval for one hour, so that we won't be reloading the participation key during this test.
+ cfg.ParticipationKeysRefreshInterval = time.Hour
+ cfg.SaveToDisk(nodeDir)
+ }
+ fixture.Start()
+
defer fixture.Shutdown()
// Get the 1st node (with Node1-3 wallets) so we can wait until it has reached the target round
diff --git a/test/e2e-go/features/transactions/messageRate_test.go b/test/e2e-go/features/transactions/messageRate_test.go
new file mode 100644
index 000000000..ac0394e64
--- /dev/null
+++ b/test/e2e-go/features/transactions/messageRate_test.go
@@ -0,0 +1,248 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package transactions
+
+import (
+ "bufio"
+ "context"
+ "fmt"
+ "io/ioutil"
+ "math"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/account"
+ "github.com/algorand/go-algorand/libgoal"
+ "github.com/algorand/go-algorand/test/framework/fixtures"
+ "github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/algorand/go-algorand/util/db"
+)
+
+// this test checks that the txsync outgoing message rate
+// varies according to the transaction rate
+func TestMessageRateChangesWithTxnRate(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ if _, present := os.LookupEnv("GORACE"); present {
+ t.Skip("Skipping MessageRateChangesWithTxnRate test when race mode is enabled")
+ }
+ a := require.New(fixtures.SynchronizedTest(t))
+ txnRates := []uint{50, 300, 800, 1200}
+ if testing.Short() {
+ txnRates = []uint{50, 300}
+ }
+ prevMsgRate := 0.0
+ for _, txnRate := range txnRates {
+ avgTps, msgRate := testMessageRateChangesWithTxnRate(t, filepath.Join("nettemplates", "OneNodeTwoRelays.json"), txnRate, a)
+ fmt.Printf("Message rate: %f Previous Message Rate: %f \nExpected Transaction rate: %f Actual Transaction rate: %f\n", msgRate, prevMsgRate, float64(txnRate), avgTps)
+ aErrorMessage := fmt.Sprintf("TxSync message rate not monotonic for txn rate: %d", txnRate)
+ a.GreaterOrEqual(msgRate, prevMsgRate, aErrorMessage)
+ prevMsgRate = msgRate
+ }
+
+}
+
+func throttleTransactionRate(startTime time.Time, txnRate uint, sentSoFar uint) float64 {
+ timeDelta := time.Since(startTime)
+ currentTps := float64(sentSoFar) / timeDelta.Seconds()
+ if currentTps > float64(txnRate) {
+ sleepDuration := float64(sentSoFar)/float64(txnRate) - timeDelta.Seconds()
+ sleepTime := time.Duration(int64(math.Round(sleepDuration*1000))) * time.Millisecond
+ time.Sleep(sleepTime)
+ currentTps = float64(sentSoFar) / (sleepDuration + timeDelta.Seconds())
+ }
+ return currentTps
+}
+
+func testMessageRateChangesWithTxnRate(t *testing.T, templatePath string, txnRate uint, a *require.Assertions) (avgTps, msgRate float64) {
+ var fixture fixtures.RestClientFixture
+ fixture.SetupNoStart(t, templatePath)
+ nodeDataDir, err := fixture.GetNodeDir("Node")
+ a.NoError(err)
+ cfg, err := config.LoadConfigFromDisk(nodeDataDir)
+ a.NoError(err)
+ cfg.EnableVerbosedTransactionSyncLogging = true
+ cfg.SaveToDisk(nodeDataDir)
+ fixture.Start()
+
+ defer fixture.Shutdown()
+
+ client := fixture.GetLibGoalClientForNamedNode("Node")
+ accountsList, err := fixture.GetNodeWalletsSortedByBalance(client.DataDir())
+ a.NoError(err)
+ account := accountsList[0].Address
+ clientAlgod := fixture.GetAlgodClientForController(fixture.GetNodeControllerForDataDir(nodeDataDir))
+
+ // get the node account's secret key
+ secretKey, err := fetchSecretKey(client, nodeDataDir)
+ a.NoError(err)
+ signatureSecrets, err := crypto.SecretKeyToSignatureSecrets(secretKey)
+ a.NoError(err)
+
+ // build the path for the primary node's log file
+ logPath := filepath.Join(nodeDataDir, "node.log")
+
+ // Get the relay's gossip port
+ r1, err := fixture.GetNodeController("Relay1")
+ a.NoError(err)
+ listeningURLRaw, err := r1.GetListeningAddress()
+ a.NoError(err)
+ listeningURL := strings.Split(listeningURLRaw, "//")[1]
+
+ errChan := make(chan error)
+ resetChan := make(chan bool)
+ msgRateChan := make(chan float64)
+ ctx, stopParsing := context.WithCancel(context.Background())
+ defer stopParsing()
+
+ go parseLog(ctx, logPath, listeningURL, errChan, msgRateChan, resetChan)
+
+ // get the min transaction fee
+ minTxnFee, _, err := fixture.CurrentMinFeeAndBalance()
+ a.NoError(err)
+ transactionFee := minTxnFee * 1000 * 253
+
+ startTime := time.Now()
+ txnSentCount := uint(0)
+
+ for {
+ // send txns at txnRate for 30s
+ timeSinceStart := time.Since(startTime)
+ if timeSinceStart > 30*time.Second {
+ break
+ }
+
+ tx, err := client.ConstructPayment(account, account, transactionFee, 0, GenerateRandomBytes(8), "", [32]byte{}, 0, 0)
+ a.NoError(err)
+ signedTxn := tx.Sign(signatureSecrets)
+
+ _, err = clientAlgod.SendRawTransaction(signedTxn)
+ a.NoError(err, "Unable to send raw txn")
+
+ txnSentCount++
+
+ avgTps = throttleTransactionRate(startTime, txnRate, txnSentCount)
+ }
+
+ // send reset on resetChan to signal the parseLog goroutine to send the msgRate and reset its counters
+ resetChan <- true
+
+ select {
+ case err := <-errChan:
+ a.Error(err)
+ case msgRate = <-msgRateChan:
+ break
+ }
+ return
+}
+
+// parseLog continuously monitors the log for txnsync messages sent to filterAddress
+// resetChan is used to signal it to send results on msgRate chan
+// and reset its internal counters
+// errChan is used to propagate errors if any
+func parseLog(ctx context.Context, logPath string, filterAddress string, errChan chan error, msgRateChan chan float64, resetChan chan bool) {
+ file, err := os.Open(logPath)
+ if err != nil {
+ errChan <- err
+ return
+ }
+ defer file.Close()
+
+ messageCount := 0
+ var firstTimestamp, lastTimestamp time.Time
+ firstTimestamp = time.Now()
+
+ scanner := bufio.NewScanner(file)
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case <-resetChan:
+ lastTimestamp = time.Now()
+ msgRate := float64(messageCount) / float64(lastTimestamp.Sub(firstTimestamp)) * float64(time.Second)
+ msgRateChan <- msgRate
+ messageCount = 0
+ firstTimestamp = time.Now()
+ continue
+ default:
+ }
+ scanned := scanner.Scan()
+ if !scanned {
+ if err := scanner.Err(); err != nil {
+ errChan <- err
+ return
+ }
+ time.Sleep(100 * time.Millisecond)
+ scanner = bufio.NewScanner(file)
+ continue
+ }
+
+ line := scanner.Text()
+ // look for txnsync messages sent to `filterAddress`
+ if strings.Contains(line, "Outgoing Txsync") && strings.Contains(line, filterAddress) {
+ messageCount++
+ }
+ }
+}
+
+func fetchSecretKey(client libgoal.Client, dataDir string) (crypto.PrivateKey, error) {
+ secretKey := crypto.PrivateKey{}
+ genID, err := client.GenesisID()
+ if err != nil {
+ return secretKey, err
+ }
+
+ keyDir := filepath.Join(dataDir, genID)
+ files, err := ioutil.ReadDir(keyDir)
+ if err != nil {
+ return secretKey, err
+ }
+
+ // For each of these files
+ for _, info := range files {
+ var handle db.Accessor
+
+ filename := info.Name()
+
+ // If it isn't a key file we care about, skip it
+ if config.IsRootKeyFilename(filename) {
+ handle, err = db.MakeAccessor(filepath.Join(keyDir, filename), true, false)
+ if err != nil {
+ // Couldn't open it, skip it
+ continue
+ }
+
+ // Fetch an account.Root from the database
+ root, err := account.RestoreRoot(handle)
+ if err != nil {
+ return secretKey, err
+ }
+
+ secretKey = crypto.PrivateKey(root.Secrets().SK)
+ break
+ }
+
+ }
+
+ return secretKey, nil
+}
diff --git a/test/e2e-go/features/transactions/txnsync_test.go b/test/e2e-go/features/transactions/txnsync_test.go
new file mode 100644
index 000000000..ee373ea5e
--- /dev/null
+++ b/test/e2e-go/features/transactions/txnsync_test.go
@@ -0,0 +1,376 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package transactions
+
+import (
+ "context"
+ "fmt"
+ "math"
+ "path/filepath"
+ "testing"
+ "time"
+
+ "github.com/algorand/go-deadlock"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/libgoal"
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/test/framework/fixtures"
+ "github.com/algorand/go-algorand/test/partitiontest"
+)
+
+// This test sets up a network with 2 nodes and 2 relays.
+// The two nodes send payment transactions.
+
+// For each transaction, the test checks if the relays and the nodes
+// (including the node that originated the transaction) have the
+// transaction in the pool (i.e. the transactionInfo.ConfirmedRound ==
+// 0).
+
+// The tests needs to check for the transactions in the pool fast
+// enough before they get evicted from the pool to the block.
+
+// To achieve this, it sends transactions during the first half of the
+// round period, to give the test enough time to check for the
+// transactions.
+func TestTxnSync(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ maxNumberOfSends := 1200
+ maxRate := 1000 // txn/sec
+ if testing.Short() {
+ maxNumberOfSends = 300
+ }
+ templatePath := filepath.Join("nettemplates", "TwoNodes50EachWithTwoRelays.json")
+
+ var fixture fixtures.RestClientFixture
+
+ roundTime := time.Duration(8 * 1000 * time.Millisecond)
+
+ proto, ok := config.Consensus[protocol.ConsensusCurrentVersion]
+ require.True(t, ok)
+ proto.AgreementFilterTimeoutPeriod0 = roundTime
+ proto.AgreementFilterTimeout = roundTime
+ fixture.SetConsensus(config.ConsensusProtocols{protocol.ConsensusCurrentVersion: proto})
+
+ fixture.Setup(t, templatePath)
+ defer fixture.Shutdown()
+
+ node1 := fixture.GetLibGoalClientForNamedNode("Node1")
+ node2 := fixture.GetLibGoalClientForNamedNode("Node2")
+ relay1 := fixture.GetLibGoalClientForNamedNode("Relay1")
+ relay2 := fixture.GetLibGoalClientForNamedNode("Relay2")
+
+ n1chan := make(chan string, maxNumberOfSends*2)
+ n2chan := make(chan string, maxNumberOfSends*2)
+ r1chan := make(chan string, maxNumberOfSends*2)
+ r2chan := make(chan string, maxNumberOfSends*2)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ account1List, err := fixture.GetNodeWalletsSortedByBalance(node1.DataDir())
+ require.NoError(t, err)
+ account1 := account1List[0].Address
+
+ account2List, err := fixture.GetNodeWalletsSortedByBalance(node2.DataDir())
+ require.NoError(t, err)
+ account2 := account2List[0].Address
+
+ ttn1 := transactionTracker{
+ t: t,
+ ctx: ctx,
+ client: &node1,
+ othersToVerify: []chan string{n2chan, r1chan, r2chan, n1chan},
+ selfToVerify: n1chan,
+ pendingVerification: make(map[string]bool),
+ account1: account1,
+ account2: account2,
+ name: "node1",
+ cancelFunc: cancel,
+ }
+
+ ttn2 := transactionTracker{
+ t: t,
+ ctx: ctx,
+ client: &node2,
+ othersToVerify: []chan string{n1chan, r1chan, r2chan, n2chan},
+ selfToVerify: n2chan,
+ pendingVerification: make(map[string]bool),
+ account1: account1,
+ account2: account2,
+ name: "node2",
+ cancelFunc: cancel,
+ }
+
+ ttr1 := transactionTracker{
+ t: t,
+ ctx: ctx,
+ client: &relay1,
+ othersToVerify: []chan string{n1chan, n2chan, r2chan, r1chan},
+ selfToVerify: r1chan,
+ pendingVerification: make(map[string]bool),
+ account1: account1,
+ account2: account2,
+ name: "relay1",
+ cancelFunc: cancel,
+ }
+
+ ttr2 := transactionTracker{
+ t: t,
+ ctx: ctx,
+ client: &relay2,
+ othersToVerify: []chan string{n1chan, n2chan, r1chan, r2chan},
+ selfToVerify: r2chan,
+ pendingVerification: make(map[string]bool),
+ account1: account1,
+ account2: account2,
+ name: "relay2",
+ cancelFunc: cancel,
+ }
+
+ minTxnFee, minAcctBalance, err := fixture.CurrentMinFeeAndBalance()
+ require.NoError(t, err)
+
+ transactionFee := minTxnFee * 1000
+ amount1 := minAcctBalance / uint64(maxNumberOfSends)
+ amount2 := minAcctBalance / uint64(maxNumberOfSends)
+
+ defer ttn1.terminate()
+ defer ttn2.terminate()
+ defer ttr1.terminate()
+ defer ttr2.terminate()
+
+ defer cancel()
+
+ go ttn1.passTxnsToVeirfy()
+ go ttn2.passTxnsToVeirfy()
+ go ttr1.passTxnsToVeirfy()
+ go ttr2.passTxnsToVeirfy()
+
+ go ttn1.checkAll()
+ go ttn2.checkAll()
+ go ttr1.checkAll()
+ go ttr2.checkAll()
+
+ // wait for the 1st round
+ nextRound := uint64(1)
+ err = fixture.ClientWaitForRound(fixture.AlgodClient, nextRound, 20*roundTime)
+ require.NoError(t, err)
+ nextRound++
+
+ st := time.Now()
+ timeout := time.NewTimer(roundTime / 2)
+
+ for i := 0; i < maxNumberOfSends; i++ {
+
+ select {
+ case <-ctx.Done():
+ require.True(t, false, "Context canceled due to an error at iteration %d", i)
+ return
+ case <-timeout.C:
+ // Send the transactions only during the first half of the round
+ // Wait for the next round, and stop sending transactions after the first half
+ err = fixture.ClientWaitForRound(fixture.AlgodClient, nextRound, 10*roundTime)
+ require.NoError(t, err)
+ fmt.Printf("Round %d\n", int(nextRound))
+ nextRound++
+ timeout = time.NewTimer(roundTime / 2)
+ default:
+ }
+ throttleRate(st, maxRate, i*2)
+ tx1, err := node1.SendPaymentFromUnencryptedWallet(account1, account2, transactionFee, amount1, GenerateRandomBytes(8))
+ require.NoError(t, err, "Failed to send transaction on iteration %d", i)
+ ttn1.addTransactionToVerify(tx1.ID().String())
+
+ tx2, err := node2.SendPaymentFromUnencryptedWallet(account2, account1, transactionFee, amount2, GenerateRandomBytes(8))
+ require.NoError(t, err, "Failed to send transaction on iteration %d", i)
+ ttn2.addTransactionToVerify(tx2.ID().String())
+ if i%100 == 0 {
+ fmt.Printf("txn sent %d / %d\n", i, maxNumberOfSends)
+ }
+ }
+ close(ttn1.selfToVerify)
+ close(ttn2.selfToVerify)
+ close(ttr1.selfToVerify)
+ close(ttr2.selfToVerify)
+
+ // wait until all channels are empty for max 50 seconds
+ for x := 0; x < 250; x++ {
+ select {
+ case <-ctx.Done():
+ require.True(t, false, "Context canceled due to an error")
+ default:
+ }
+
+ if ttn1.channelsAreEmpty() {
+ break
+ }
+ time.Sleep(200 * time.Millisecond)
+ if x%10 == 0 {
+ fmt.Printf("waiting for channel flushing [%d %d %d %d] %d / %d\n", len(n1chan), len(n2chan), len(r1chan), len(r2chan), x, 250)
+ }
+ }
+ require.True(t, ttn1.channelsAreEmpty())
+
+ unprocessed := 0
+ maxWait := 100
+ for x := 0; x < maxWait; x++ {
+ select {
+ case <-ctx.Done():
+ require.True(t, false, "Context canceled due to an error")
+ default:
+ }
+ ttn1.mu.Lock()
+ unprocessed = len(ttn1.pendingVerification)
+ ttn1.mu.Unlock()
+
+ ttn2.mu.Lock()
+ unprocessed += len(ttn2.pendingVerification)
+ ttn2.mu.Unlock()
+
+ ttr1.mu.Lock()
+ unprocessed += len(ttr1.pendingVerification)
+ ttr1.mu.Unlock()
+
+ ttr2.mu.Lock()
+ unprocessed += len(ttr2.pendingVerification)
+ ttr2.mu.Unlock()
+
+ if unprocessed == 0 {
+ break
+ }
+ time.Sleep(200 * time.Millisecond)
+ if x%10 == 0 {
+ fmt.Printf("waiting for pending verificaitons [%d] %d / %d\n", unprocessed, x, maxWait)
+ }
+ }
+ require.Equal(t, 0, unprocessed, "missing %d transactions", unprocessed)
+}
+
+type transactionTracker struct {
+ t *testing.T
+ ctx context.Context
+ mu deadlock.Mutex
+ client *libgoal.Client
+ othersToVerify []chan string
+ selfToVerify chan string
+ pendingVerification map[string]bool
+ account1 string
+ account2 string
+ name string
+ cancelFunc context.CancelFunc
+}
+
+// Adds the transaction to the channels of the nodes intended to receive the transaction
+// This should not block to maintain the transaction rate. Hence, the channel is large enough.
+func (tt *transactionTracker) addTransactionToVerify(transactionID string) {
+ for _, c := range tt.othersToVerify {
+ select {
+ case <-tt.ctx.Done():
+ return
+ case c <- transactionID:
+ }
+ }
+}
+
+func (tt *transactionTracker) passTxnsToVeirfy() {
+ for tid := range tt.selfToVerify {
+ select {
+ case <-tt.ctx.Done():
+ return
+ default:
+ }
+
+ tt.mu.Lock()
+ tt.pendingVerification[tid] = true
+ tt.mu.Unlock()
+ }
+}
+
+func (tt *transactionTracker) checkAll() {
+ for {
+ select {
+ case <-tt.ctx.Done():
+ return
+ case _, more := <-tt.selfToVerify:
+ tt.mu.Lock()
+ if !more && len(tt.pendingVerification) == 0 {
+ tt.mu.Unlock()
+ return
+ }
+ tt.mu.Unlock()
+ default:
+ }
+ transactions, err := tt.client.GetPendingTransactionsByAddress(tt.account1, 1000000)
+ if err != nil {
+ tt.cancelFunc()
+ require.NoError(tt.t, err)
+ }
+
+ for _, transactionInfo := range transactions.TruncatedTxns.Transactions {
+ tt.mu.Lock()
+ if _, ok := tt.pendingVerification[transactionInfo.TxID]; ok {
+ delete(tt.pendingVerification, transactionInfo.TxID)
+ }
+ tt.mu.Unlock()
+ }
+
+ transactions, err = tt.client.GetPendingTransactionsByAddress(tt.account2, 1000000)
+ if err != nil {
+ tt.cancelFunc()
+ require.NoError(tt.t, err)
+ }
+
+ for _, transactionInfo := range transactions.TruncatedTxns.Transactions {
+ tt.mu.Lock()
+ if _, ok := tt.pendingVerification[transactionInfo.TxID]; ok {
+ delete(tt.pendingVerification, transactionInfo.TxID)
+ }
+ tt.mu.Unlock()
+ }
+ time.Sleep(time.Second)
+ }
+}
+
+func (tt *transactionTracker) terminate() {
+ tt.mu.Lock()
+ defer tt.mu.Unlock()
+ require.Equal(tt.t, 0, len(tt.pendingVerification), "%s is missing %d transactions", tt.name, len(tt.pendingVerification))
+}
+
+// Retruns true if all the associated channels are empty
+func (tt *transactionTracker) channelsAreEmpty() bool {
+ for _, c := range tt.othersToVerify {
+ if len(c) > 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// throttle transaction rate
+func throttleRate(startTime time.Time, targetRate int, total int) {
+ localTimeDelta := time.Now().Sub(startTime)
+ currentTps := float64(total) / localTimeDelta.Seconds()
+ if currentTps > float64(targetRate) {
+ sleepSec := float64(total)/float64(targetRate) - localTimeDelta.Seconds()
+ sleepTime := time.Duration(int64(math.Round(sleepSec*1000))) * time.Millisecond
+ time.Sleep(sleepTime)
+ }
+}
diff --git a/test/scripts/e2e_subs/app-assets.sh b/test/scripts/e2e_subs/app-assets.sh
index 65fd5e927..8b1fa6f5d 100755
--- a/test/scripts/e2e_subs/app-assets.sh
+++ b/test/scripts/e2e_subs/app-assets.sh
@@ -26,15 +26,15 @@ ACCOUNT=$(${gcmd} account list|awk '{ print $3 }')
# Create a smaller account so rewards won't change balances.
SMALL=$(${gcmd} account new | awk '{ print $6 }')
# Under one algo receives no rewards
-${gcmd} clerk send -a 1000000 -f "$ACCOUNT" -t "$SMALL"
+${gcmd} clerk send -a 999000 -f "$ACCOUNT" -t "$SMALL"
function balance {
acct=$1; shift
goal account balance -a "$acct" | awk '{print $1}'
}
-[ "$(balance "$ACCOUNT")" = 999998999000 ]
-[ "$(balance "$SMALL")" = 1000000 ]
+[ "$(balance "$ACCOUNT")" = 999999000000 ]
+[ "$(balance "$SMALL")" = 999000 ]
function created_assets {
acct=$1;
@@ -62,7 +62,7 @@ function assets {
}
APPID=$(${gcmd} app create --creator "${SMALL}" --approval-prog=${TEAL}/assets-escrow.teal --global-byteslices 4 --global-ints 0 --local-byteslices 0 --local-ints 1 --clear-prog=${TEAL}/approve-all.teal | grep Created | awk '{ print $6 }')
-[ "$(balance "$SMALL")" = 999000 ] # 1000 fee
+[ "$(balance "$SMALL")" = 998000 ] # 1000 fee
function appl {
method=$1; shift
@@ -81,7 +81,6 @@ function asset-id {
}
APPACCT=$(python -c "import algosdk.encoding as e; print(e.encode_address(e.checksum(b'appID'+($APPID).to_bytes(8, 'big'))))")
-[ "$(balance "$SMALL")" = 999000 ] # 1000 fee
function asset-create {
amount=$1; shift
@@ -116,15 +115,15 @@ function sign {
TXID=$(${gcmd} app optin --app-id "$APPID" --from "${SMALL}" | app-txid)
# Rest succeeds, no stray inner-txn array
[ "$(rest "/v2/transactions/pending/$TXID" | jq '.["inner-txn"]')" == null ]
-[ "$(balance "$SMALL")" = 998000 ] # 1000 fee
+[ "$(balance "$SMALL")" = 997000 ] # 1000 fee
ASSETID=$(asset-create 1000000 --name "e2e" --unitname "e" | asset-id)
-[ "$(balance "$SMALL")" = 997000 ] # 1000 fee
+[ "$(balance "$SMALL")" = 996000 ] # 1000 fee
-${gcmd} clerk send -a 1000000 -f "$ACCOUNT" -t "$APPACCT"
+${gcmd} clerk send -a 999000 -f "$ACCOUNT" -t "$APPACCT"
appl "optin():void" --foreign-asset="$ASSETID" --from="$SMALL"
-[ "$(balance "$APPACCT")" = 999000 ] # 1000 fee
-[ "$(balance "$SMALL")" = 996000 ]
+[ "$(balance "$APPACCT")" = 998000 ] # 1000 fee
+[ "$(balance "$SMALL")" = 995000 ]
appl "deposit():void" -o "$T/deposit.tx" --from="$SMALL"
asset-deposit 1000 $ASSETID -o "$T/axfer1.tx"
@@ -136,8 +135,8 @@ ${gcmd} clerk rawsend -f "$T/group.stx"
[ "$(asset_bal "$SMALL")" = 999000 ] # asset balance
[ "$(asset_ids "$APPACCT")" = $ASSETID ]
[ "$(asset_bal "$APPACCT")" = 1000 ]
-[ "$(balance "$SMALL")" = 994000 ] # 2 fees
-[ "$(balance "$APPACCT")" = 999000 ]
+[ "$(balance "$SMALL")" = 993000 ] # 2 fees
+[ "$(balance "$APPACCT")" = 998000 ]
# Withdraw 100 in app. Confirm that inner txn is visible to transaction API.
TXID=$(appl "withdraw(uint64):void" --app-arg="int:100" --foreign-asset="$ASSETID" --from="$SMALL" | app-txid)
@@ -151,31 +150,31 @@ rest "/v2/blocks/$ROUND" | jq .block.txns[0].dt.itx
[ "$(asset_bal "$SMALL")" = 999100 ] # 100 asset withdrawn
[ "$(asset_bal "$APPACCT")" = 900 ] # 100 asset withdrawn
-[ "$(balance "$SMALL")" = 993000 ] # 1 fee
-[ "$(balance "$APPACCT")" = 998000 ] # fee paid by app
+[ "$(balance "$SMALL")" = 992000 ] # 1 fee
+[ "$(balance "$APPACCT")" = 997000 ] # fee paid by app
appl "withdraw(uint64):void" --app-arg="int:100" --foreign-asset="$ASSETID" --fee 2000 --from="$SMALL"
[ "$(asset_bal "$SMALL")" = 999200 ] # 100 asset withdrawn
-[ "$(balance "$SMALL")" = 991000 ] # 2000 fee
+[ "$(balance "$SMALL")" = 990000 ] # 2000 fee
[ "$(asset_bal "$APPACCT")" = 800 ] # 100 asset withdrawn
-[ "$(balance "$APPACCT")" = 998000 ] # fee credit used
+[ "$(balance "$APPACCT")" = 997000 ] # fee credit used
# Try to withdraw too much
appl "withdraw(uint64):void" --app-arg="int:1000" --foreign-asset="$ASSETID" --from="$SMALL" && exit 1
[ "$(asset_bal "$SMALL")" = 999200 ] # no change
[ "$(asset_bal "$APPACCT")" = 800 ] # no change
-[ "$(balance "$SMALL")" = 991000 ]
-[ "$(balance "$APPACCT")" = 998000 ]
+[ "$(balance "$SMALL")" = 990000 ]
+[ "$(balance "$APPACCT")" = 997000 ]
# Show that it works AT exact asset balance
appl "withdraw(uint64):void" --app-arg="int:800" --foreign-asset="$ASSETID" --from="$SMALL"
[ "$(asset_bal "$SMALL")" = 1000000 ]
[ "$(asset_bal "$APPACCT")" = 0 ]
-[ "$(balance "$SMALL")" = 990000 ]
-[ "$(balance "$APPACCT")" = 997000 ]
+[ "$(balance "$SMALL")" = 989000 ]
+[ "$(balance "$APPACCT")" = 996000 ]
USER=$(${gcmd} account new | awk '{ print $6 }') #new account
-${gcmd} clerk send -a 1000000 -f "$ACCOUNT" -t "$USER" #fund account
+${gcmd} clerk send -a 999000 -f "$ACCOUNT" -t "$USER" #fund account
asset-optin -f "$USER" -t "$USER" --assetid "$ASSETID" #opt in to asset
# SET $USER as clawback address
${gcmd} asset config --manager $SMALL --assetid $ASSETID --new-clawback $USER
@@ -190,7 +189,7 @@ ${gcmd} clerk send --from "$USER" --to "$USER" -a 0 --rekey-to "$APPACCT"
${gcmd} asset send -f "$SMALL" -t "$USER" -a "1000" --assetid "$ASSETID" --clawback "$USER" && exit 1
USER2=$(${gcmd} account new | awk '{ print $6 }') #new account
-${gcmd} clerk send -a 1000000 -f "$ACCOUNT" -t "$USER2" #fund account
+${gcmd} clerk send -a 999000 -f "$ACCOUNT" -t "$USER2" #fund account
asset-optin -f "$USER2" -t "$USER2" --assetid "$ASSETID" #opt in to asset
# set $APPACCT as clawback address on asset
${gcmd} asset config --manager $SMALL --assetid $ASSETID --new-clawback $APPACCT
diff --git a/test/scripts/e2e_subs/app-group.py b/test/scripts/e2e_subs/app-group.py
new file mode 100755
index 000000000..738e1cb79
--- /dev/null
+++ b/test/scripts/e2e_subs/app-group.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+
+import os
+import sys
+from goal import Goal
+
+from datetime import datetime
+
+stamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+print(f"{os.path.basename(sys.argv[0])} start {stamp}")
+
+goal = Goal(sys.argv[1], autosend=True)
+
+joe = goal.new_account()
+
+txinfo, err = goal.pay(goal.account, joe, amt=500_000)
+assert not err, err
+
+# Turn off rewards for precise balance checking
+txinfo, err = goal.keyreg(joe, nonpart=True)
+assert not err, err
+joeb = goal.balance(joe)
+
+teal = """
+#pragma version 6
+ txn ApplicationID
+ bz end
+ // Pay the sender and Accounts[1]. Force the second fee to default high
+ itxn_begin
+ int pay
+ itxn_field TypeEnum
+
+ txn Sender
+ itxn_field Receiver
+
+ int 5
+ itxn_field Amount
+
+ int 0
+ itxn_field Fee // No fee, so 2nd fee is doubled
+
+ itxn_next
+
+ int pay
+ itxn_field TypeEnum
+
+ txn Accounts 1
+ itxn_field Receiver
+
+ int 5
+ itxn_field Amount
+
+ itxn_submit
+
+ itxn Fee
+ int 2000
+ ==
+ assert
+
+end:
+ int 1
+"""
+
+txinfo, err = goal.app_create(joe, goal.assemble(teal))
+assert not err, err
+app_id = txinfo['application-index']
+assert app_id
+
+# Fund the app account
+txinfo, err = goal.pay(goal.account, goal.app_address(app_id), amt=400_000)
+assert not err, err
+
+
+txinfo, err = goal.app_call(joe, app_id, accounts=[goal.account])
+assert not err, err
+
+print(f"{os.path.basename(sys.argv[0])} OK {stamp}")
diff --git a/test/scripts/e2e_subs/app-rekey.py b/test/scripts/e2e_subs/app-rekey.py
new file mode 100755
index 000000000..94bfcd22a
--- /dev/null
+++ b/test/scripts/e2e_subs/app-rekey.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+
+import os
+import sys
+from goal import Goal
+
+from datetime import datetime
+
+stamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+print(f"{os.path.basename(sys.argv[0])} start {stamp}")
+
+goal = Goal(sys.argv[1], autosend=True)
+
+joe = goal.new_account()
+flo = goal.new_account()
+
+txinfo, err = goal.pay(goal.account, joe, amt=500_000)
+assert not err, err
+
+# Turn off rewards for precise balance checking
+txinfo, err = goal.keyreg(joe, nonpart=True)
+assert not err, err
+joeb = goal.balance(joe)
+
+txinfo, err = goal.pay(goal.account, flo, amt=500_000)
+assert not err, err
+
+teal = """
+#pragma version 6
+ txn ApplicationID
+ bz end
+ // Use the rekeyed account to make a payment, and give it back
+ itxn_begin
+ int pay
+ itxn_field TypeEnum
+
+ txn Accounts 1
+ itxn_field Sender
+
+ txn Accounts 0
+ itxn_field Receiver
+
+ int 5
+ itxn_field Amount
+
+ txn Accounts 1
+ itxn_field RekeyTo
+ itxn_submit
+
+end:
+ int 1
+"""
+
+txinfo, err = goal.app_create(joe, goal.assemble(teal))
+assert not err, err
+joeb = joeb-1000
+app_id = txinfo['application-index']
+assert app_id
+
+app_addr = goal.app_address(app_id)
+# flo rekeys her account to the app, app spends from it, then rekeys it back
+txinfo, err = goal.pay(flo, joe, amt=1, rekey_to=app_addr)
+assert not err, err
+assert goal.balance(joe) == joeb+1, goal.balance(joe)
+
+# can no longer spend
+txinfo, err = goal.pay(flo, joe, amt=1)
+assert err
+assert goal.balance(joe) == joeb+1, goal.balance(joe)
+
+txinfo, err = goal.app_call(joe, app_id, accounts=[flo])
+assert not err, err
+joeb = joeb-1000
+assert goal.balance(joe) == joeb+6, goal.balance(joe)
+
+# can spend again
+txinfo, err = goal.pay(flo, joe, amt=1)
+assert not err, err
+assert goal.balance(joe) == joeb+7, goal.balance(joe)
+
+print(f"{os.path.basename(sys.argv[0])} OK {stamp}")
diff --git a/test/scripts/e2e_subs/example.py b/test/scripts/e2e_subs/example.py
index 4685f5739..cc7acda2c 100755
--- a/test/scripts/e2e_subs/example.py
+++ b/test/scripts/e2e_subs/example.py
@@ -5,6 +5,10 @@ import sys
from goal import Goal
import algosdk.future.transaction as txn
+from datetime import datetime
+
+stamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+print(f"{os.path.basename(sys.argv[0])} start {stamp}")
goal = Goal(sys.argv[1])
@@ -13,8 +17,8 @@ flo = goal.new_account()
# Pays
-pay = goal.pay(goal.account, receiver=joe, amt=10000)
-txid, err = goal.send(pay)
+pay = goal.pay(goal.account, receiver=joe, amt=10000) # under min balance
+txid, err = goal.send(pay, confirm=False) # errors early
assert err
pay = goal.pay(goal.account, receiver=joe, amt=500_000)
@@ -65,7 +69,7 @@ assert goal.holding(joe, gold)[1]
# App create
teal = "test/scripts/e2e_subs/tealprogs"
approval = goal.assemble(os.path.join(teal, "app-escrow.teal"))
-yes = goal.assemble("#pragma version 2\nint 28") # 28 is just to uniquify
+yes = goal.assemble("#pragma version 2\nint 28") # 28 is just to uniquify
create = goal.appl(flo, 0,
local_schema=(1, 0),
global_schema=(0, 4),
@@ -118,3 +122,6 @@ spend = goal.sign_with_program(spend, yes)
txinfo, err = goal.send(spend)
assert not err, err
assert goal.balance(goal.logic_address(yes)) == 107_000, goal.balance(goal.logic_address(yes))
+
+stamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+print(f"{os.path.basename(sys.argv[0])} OK {stamp}")
diff --git a/test/scripts/e2e_subs/goal/goal.py b/test/scripts/e2e_subs/goal/goal.py
index 4982d06ca..921d2c3ea 100755
--- a/test/scripts/e2e_subs/goal/goal.py
+++ b/test/scripts/e2e_subs/goal/goal.py
@@ -56,6 +56,7 @@ class Goal:
algod_address=None,
kmd_token=None,
kmd_address=None,
+ autosend=None,
):
self.algod = None
self.kmd = None
@@ -84,6 +85,8 @@ class Goal:
# txns easily, even without kmd.
self.internal_wallet = {}
+ self.autosend = autosend
+
def open_algod(self, algodata, algod_address=None):
if algod_address:
algod_token = algodata
@@ -197,12 +200,12 @@ class Goal:
"""
print(f"Waiting for block {block}.")
s = self.algod.status()
- last_round = s['last-round']
+ last_round = s["last-round"]
while last_round < block:
wait_block = min(block, last_round + 3)
print(f" waiting for {last_round}...")
s = self.algod.status_after_block(wait_block)
- last_round = s['last-round']
+ last_round = s["last-round"]
return s
def new_account(self):
@@ -215,31 +218,53 @@ class Goal:
assert len(key) == 88, key
self.internal_wallet[address] = key
- def pay(self, sender, receiver, amt: int, **kwargs):
+ def finish(self, tx, send):
+ if send is None:
+ send = self.autosend
+ if send:
+ return self.send(tx, confirm=True)
+ return tx
+
+ def keyreg(self, sender, votekey=None, selkey=None, votefst=None,
+ votelst=None, votekd=None,
+ send=None, **kwargs):
params = self.algod.suggested_params()
- return txn.PaymentTxn(sender, params, receiver, amt, **kwargs)
+ tx = txn.KeyregTxn(sender, params,
+ votekey, selkey, votefst, votelst, votekd,
+ **kwargs)
+ return self.finish(tx, send)
- def acfg(self, sender, **kwargs):
+ def pay(self, sender, receiver, amt: int, send=None, **kwargs):
params = self.algod.suggested_params()
- return txn.AssetConfigTxn(
+ tx = txn.PaymentTxn(sender, params, receiver, amt, **kwargs)
+ return self.finish(tx, send)
+
+ def acfg(self, sender, send=None, **kwargs):
+ params = self.algod.suggested_params()
+ tx = txn.AssetConfigTxn(
sender, params, **kwargs, strict_empty_address_check=False
)
+ return self.finish(tx, send)
def asset_create(self, sender, **kwargs):
assert not kwargs.pop("index", None)
return self.acfg(sender, **kwargs)
- def axfer(self, sender, receiver, amt: int, index: int, **kwargs):
+ def axfer(self, sender, receiver, amt: int, index: int, send=None, **kwargs):
params = self.algod.suggested_params()
- return txn.AssetTransferTxn(sender, params, receiver, amt, index, **kwargs)
+ tx = txn.AssetTransferTxn(
+ sender, params, receiver, amt, index, **kwargs
+ )
+ return self.finish(tx, send)
def asset_optin(self, sender, index: int, **kwargs):
assert not kwargs.pop("receiver", None)
return self.axfer(sender, sender, 0, index, **kwargs)
- def afrz(self, sender, index: int, target, frozen, **kwargs):
+ def afrz(self, sender, index: int, target, frozen, send=None, **kwargs):
params = self.algod.suggested_params()
- return txn.AssetFreezeTxn(sender, params, index, target, frozen, **kwargs)
+ tx = txn.AssetFreezeTxn(sender, params, index, target, frozen, **kwargs)
+ return self.finish(tx, send)
def coerce_schema(self, values):
if not values:
@@ -248,11 +273,12 @@ class Goal:
return values
return txn.StateSchema(num_uints=values[0], num_byte_slices=values[1])
- def appl(self, sender, index: int, on_complete=txn.OnComplete.NoOpOC, **kwargs):
+ def appl(self, sender, index: int, on_complete=txn.OnComplete.NoOpOC,
+ send=None, **kwargs):
params = self.algod.suggested_params()
local_schema = self.coerce_schema(kwargs.pop("local_schema", None))
global_schema = self.coerce_schema(kwargs.pop("global_schema", None))
- return txn.ApplicationCallTxn(
+ tx = txn.ApplicationCallTxn(
sender,
params,
index,
@@ -261,6 +287,7 @@ class Goal:
global_schema=global_schema,
**kwargs,
)
+ return self.finish(tx, send)
def app_create(
self,
@@ -326,7 +353,7 @@ class Goal:
def assemble_with_rest(self, source):
compile_response = self.algod.compile(source)
- return base64.b64decode(compile_response['result'])
+ return base64.b64decode(compile_response["result"])
def app_info(self, index: int) -> dict:
return self.algod.application_info(index)["params"]
diff --git a/test/testdata/configs/config-v17.json b/test/testdata/configs/config-v17.json
new file mode 100644
index 000000000..aa80a6dad
--- /dev/null
+++ b/test/testdata/configs/config-v17.json
@@ -0,0 +1,96 @@
+{
+ "Version": 17,
+ "AccountUpdatesStatsInterval": 5000000000,
+ "AccountsRebuildSynchronousMode": 1,
+ "AnnounceParticipationKey": true,
+ "Archival": false,
+ "BaseLoggerDebugLevel": 4,
+ "BlockServiceCustomFallbackEndpoints": "",
+ "BroadcastConnectionsLimit": -1,
+ "CadaverSizeTarget": 1073741824,
+ "CatchpointFileHistoryLength": 365,
+ "CatchpointInterval": 10000,
+ "CatchpointTracking": 0,
+ "CatchupBlockDownloadRetryAttempts": 1000,
+ "CatchupBlockValidateMode": 0,
+ "CatchupFailurePeerRefreshRate": 10,
+ "CatchupGossipBlockFetchTimeoutSec": 4,
+ "CatchupHTTPBlockFetchTimeoutSec": 4,
+ "CatchupLedgerDownloadRetryAttempts": 50,
+ "CatchupParallelBlocks": 16,
+ "ConnectionsRateLimitingCount": 60,
+ "ConnectionsRateLimitingWindowSeconds": 1,
+ "DNSBootstrapID": "<network>.algorand.network",
+ "DNSSecurityFlags": 1,
+ "DeadlockDetection": 0,
+ "DisableLocalhostConnectionRateLimit": true,
+ "DisableNetworking": false,
+ "DisableOutgoingConnectionThrottling": false,
+ "EnableAccountUpdatesStats": false,
+ "EnableAgreementReporting": false,
+ "EnableAgreementTimeMetrics": false,
+ "EnableAssembleStats": false,
+ "EnableBlockService": false,
+ "EnableBlockServiceFallbackToArchiver": true,
+ "EnableCatchupFromArchiveServers": false,
+ "EnableDeveloperAPI": false,
+ "EnableGossipBlockService": true,
+ "EnableIncomingMessageFilter": false,
+ "EnableLedgerService": false,
+ "EnableMetricReporting": false,
+ "EnableOutgoingNetworkMessageFiltering": true,
+ "EnablePingHandler": true,
+ "EnableProcessBlockStats": false,
+ "EnableProfiler": false,
+ "EnableRequestLogger": false,
+ "EnableTopAccountsReporting": false,
+ "EnableVerbosedTransactionSyncLogging": false,
+ "EndpointAddress": "127.0.0.1:0",
+ "FallbackDNSResolverAddress": "",
+ "ForceFetchTransactions": false,
+ "ForceRelayMessages": false,
+ "GossipFanout": 4,
+ "IncomingConnectionsLimit": 800,
+ "IncomingMessageFilterBucketCount": 5,
+ "IncomingMessageFilterBucketSize": 512,
+ "IsIndexerActive": false,
+ "LedgerSynchronousMode": 2,
+ "LogArchiveMaxAge": "",
+ "LogArchiveName": "node.archive.log",
+ "LogSizeLimit": 1073741824,
+ "MaxCatchpointDownloadDuration": 7200000000000,
+ "MaxConnectionsPerIP": 30,
+ "MinCatchpointFileDownloadBytesPerSecond": 20480,
+ "NetAddress": "",
+ "NetworkMessageTraceServer": "",
+ "NetworkProtocolVersion": "",
+ "NodeExporterListenAddress": ":9100",
+ "NodeExporterPath": "./node_exporter",
+ "OptimizeAccountsDatabaseOnStartup": false,
+ "OutgoingMessageFilterBucketCount": 3,
+ "OutgoingMessageFilterBucketSize": 128,
+ "ParticipationKeysRefreshInterval": 60000000000,
+ "PeerConnectionsUpdateInterval": 3600,
+ "PeerPingPeriodSeconds": 0,
+ "PriorityPeers": {},
+ "PublicAddress": "",
+ "ReconnectTime": 60000000000,
+ "ReservedFDs": 256,
+ "RestReadTimeoutSeconds": 15,
+ "RestWriteTimeoutSeconds": 120,
+ "RunHosted": false,
+ "SuggestedFeeBlockHistory": 3,
+ "SuggestedFeeSlidingWindowSize": 50,
+ "TLSCertFile": "",
+ "TLSKeyFile": "",
+ "TelemetryToLog": true,
+ "TransactionSyncDataExchangeRate": 0,
+ "TransactionSyncSignificantMessageThreshold": 0,
+ "TxPoolExponentialIncreaseFactor": 2,
+ "TxPoolSize": 15000,
+ "TxSyncIntervalSeconds": 60,
+ "TxSyncServeResponseSize": 1000000,
+ "TxSyncTimeoutSeconds": 30,
+ "UseXForwardedForAddressField": "",
+ "VerifiedTranscationsCacheSize": 30000
+}
diff --git a/test/testdata/mainnetblocks b/test/testdata/mainnetblocks
new file mode 100644
index 000000000..1acd125b0
--- /dev/null
+++ b/test/testdata/mainnetblocks
Binary files differ
diff --git a/test/testdata/nettemplates/OneNodeTwoRelays.json b/test/testdata/nettemplates/OneNodeTwoRelays.json
new file mode 100644
index 000000000..552930b3f
--- /dev/null
+++ b/test/testdata/nettemplates/OneNodeTwoRelays.json
@@ -0,0 +1,30 @@
+{
+ "Genesis": {
+ "NetworkName": "tbd",
+ "Wallets": [
+ {
+ "Name": "Wallet1",
+ "Stake": 100,
+ "Online": true
+ }
+ ]
+ },
+ "Nodes": [
+ {
+ "Name": "Relay1",
+ "IsRelay": true
+
+ },
+ {
+ "Name": "Relay2",
+ "IsRelay": true
+ },
+ {
+ "Name": "Node",
+ "Wallets": [
+ { "Name": "Wallet1",
+ "ParticipationOnly": false }
+ ]
+ }
+ ]
+}
diff --git a/test/testdata/nettemplates/TwoNodes50EachWithTwoRelays.json b/test/testdata/nettemplates/TwoNodes50EachWithTwoRelays.json
new file mode 100644
index 000000000..70bae5b7e
--- /dev/null
+++ b/test/testdata/nettemplates/TwoNodes50EachWithTwoRelays.json
@@ -0,0 +1,41 @@
+{
+ "Genesis": {
+ "NetworkName": "tbd",
+ "Wallets": [
+ {
+ "Name": "Wallet1",
+ "Stake": 50,
+ "Online": true
+ },
+ {
+ "Name": "Wallet2",
+ "Stake": 50,
+ "Online": true
+ }
+ ]
+ },
+ "Nodes": [
+ {
+ "Name": "Relay1",
+ "IsRelay": true
+ },
+ {
+ "Name": "Relay2",
+ "IsRelay": true
+ },
+ {
+ "Name": "Node1",
+ "Wallets": [
+ { "Name": "Wallet1",
+ "ParticipationOnly": false }
+ ]
+ },
+ {
+ "Name": "Node2",
+ "Wallets": [
+ { "Name": "Wallet2",
+ "ParticipationOnly": false }
+ ]
+ }
+ ]
+}
diff --git a/test/testdata/nettemplates/TwoNodesExpiredOfflineV29.json b/test/testdata/nettemplates/TwoNodesExpiredOfflineV29.json
new file mode 100644
index 000000000..198657b6c
--- /dev/null
+++ b/test/testdata/nettemplates/TwoNodesExpiredOfflineV29.json
@@ -0,0 +1,36 @@
+{
+ "Genesis": {
+ "NetworkName": "tbd",
+ "ConsensusProtocol": "https://github.com/algorandfoundation/specs/tree/abc54f79f9ad679d2d22f0fb9909fb005c16f8a1",
+ "Wallets": [
+ {
+ "Name": "Online1",
+ "Stake": 90,
+ "Online": true
+ },
+ {
+ "Name": "Online2",
+ "Stake": 10,
+ "Online": false
+ }
+ ]
+ },
+ "Nodes": [
+ {
+ "Name": "Primary",
+ "IsRelay": true,
+ "Wallets": [
+ { "Name": "Online1",
+ "ParticipationOnly": false }
+ ]
+ },
+ {
+ "Name": "Secondary",
+ "IsRelay": true,
+ "Wallets": [
+ { "Name": "Online2",
+ "ParticipationOnly": false }
+ ]
+ }
+ ]
+}
diff --git a/test/testdata/nettemplates/TwoNodesExpiredOfflineVFuture.json b/test/testdata/nettemplates/TwoNodesExpiredOfflineVFuture.json
new file mode 100644
index 000000000..8c2d2e669
--- /dev/null
+++ b/test/testdata/nettemplates/TwoNodesExpiredOfflineVFuture.json
@@ -0,0 +1,36 @@
+{
+ "Genesis": {
+ "NetworkName": "tbd",
+ "ConsensusProtocol": "future",
+ "Wallets": [
+ {
+ "Name": "Online1",
+ "Stake": 90,
+ "Online": true
+ },
+ {
+ "Name": "Online2",
+ "Stake": 10,
+ "Online": false
+ }
+ ]
+ },
+ "Nodes": [
+ {
+ "Name": "Primary",
+ "IsRelay": true,
+ "Wallets": [
+ { "Name": "Online1",
+ "ParticipationOnly": false }
+ ]
+ },
+ {
+ "Name": "Secondary",
+ "IsRelay": true,
+ "Wallets": [
+ { "Name": "Online2",
+ "ParticipationOnly": false }
+ ]
+ }
+ ]
+}
diff --git a/txnsync/bitmask.go b/txnsync/bitmask.go
new file mode 100644
index 000000000..6990fc1d7
--- /dev/null
+++ b/txnsync/bitmask.go
@@ -0,0 +1,250 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "errors"
+)
+
+var errIndexNotFound = errors.New("invalid bitmask: index not found")
+var errInvalidBitmaskType = errors.New("invalid bitmask type")
+
+//msgp:allocbound bitmask maxBitmaskSize
+type bitmask []byte
+
+// assumed to be in mode 0, sets bit at index to 1
+func (b *bitmask) setBit(index int) {
+ // bitmask type is stored at index 0, so the rest of the data is stored after.
+ byteIndex := index/8 + 1
+ (*b)[byteIndex] |= 1 << (index % 8)
+}
+
+// trimBitmask compresses the bitmask into one of the 4 types:
+// type 0: input bitmask bit pos x b -> output bitmask bit pos x b
+// type 1: input bitmask bit pos x b -> output bitmask bit pos x !b
+// type 2: stores the positions of bits where the bit value is 1
+// input bitmask first bit 1 at pos A, second bit 1 at pos B, ...
+// output bitmask stores A, B-A, ...
+// type 3: same as type 2, but stores the positons where the bit is 0
+func (b *bitmask) trimBitmask(entries int) {
+ if *b == nil {
+ return
+ }
+ numBitsCase0 := 0
+ numBitsCase1 := 0
+ numExists := 0
+ for i := 0; i < entries; i++ {
+ byteIndex := i/8 + 1
+ if (*b)[byteIndex]&(1<<(i%8)) != 0 {
+ numBitsCase0 = i + 1
+ numExists++
+ } else {
+ numBitsCase1 = i + 1
+ }
+ }
+ bitmaskType := 0
+ bestSize := bytesNeededBitmask(numBitsCase0)
+ if bestSize > bytesNeededBitmask(numBitsCase1) {
+ bitmaskType = 1
+ bestSize = bytesNeededBitmask(numBitsCase1)
+ }
+ if bestSize > numExists*2+1 {
+ bitmaskType = 2
+ bestSize = numExists*2 + 1
+ }
+ if bestSize > (entries-numExists)*2+1 {
+ bitmaskType = 3
+ bestSize = (entries-numExists)*2 + 1
+ }
+ switch bitmaskType {
+ case 0:
+ *b = (*b)[:bestSize]
+ case 1:
+ (*b)[0] = 1
+ for i := range *b {
+ if i != 0 {
+ (*b)[i] = 255 - (*b)[i] // invert bits
+ }
+ }
+ *b = (*b)[:bestSize]
+ case 2:
+ newBitmask := make(bitmask, 1, bestSize)
+ newBitmask[0] = 2
+ last := 0
+ for i := 0; i < entries; i++ {
+ byteIndex := i/8 + 1
+ if (*b)[byteIndex]&(1<<(i%8)) != 0 {
+ diff := i - last
+ newBitmask = append(newBitmask, byte(diff/256), byte(diff%256))
+ last = i
+ }
+ }
+ *b = newBitmask
+ case 3:
+ newBitmask := make(bitmask, 1, bestSize)
+ newBitmask[0] = 3
+ last := 0
+ for i := 0; i < entries; i++ {
+ byteIndex := i/8 + 1
+ if (*b)[byteIndex]&(1<<(i%8)) == 0 {
+ diff := i - last
+ newBitmask = append(newBitmask, byte(diff/256), byte(diff%256))
+ last = i
+ }
+ }
+ *b = newBitmask
+ }
+}
+
+// iterate through the elements of bitmask without expanding it.
+// call the func(entriesCount, setBitIndex) for every set bit
+// numTransactions: is the size of the array that transactionIndex is accessing: transactionIndex < numTransactions
+// numItems: is the size of the array that itemIndex is accessing: itemIndex < numItems (itemIndex is also the set bit counter)
+func (b *bitmask) iterate(numTransactions int, numItems int, callback func(int, int) error) error {
+ option := 0
+ if len(*b) > 0 {
+ option = int((*b)[0])
+ } else { // nothing to iterate
+ return nil
+ }
+ itemIndex := 0
+ switch option {
+ case 0:
+ transactionIndex := 0
+ maxV := bytesNeededBitmask(numTransactions)
+ if len(*b) > maxV {
+ return errIndexNotFound
+ }
+ for i, v := range (*b)[1:] {
+ for ; transactionIndex < numTransactions && v > 0; transactionIndex++ {
+ if v&1 != 0 {
+ if itemIndex >= numItems {
+ return errDataMissing
+ }
+ if err := callback(transactionIndex, itemIndex); err != nil {
+ return err
+ }
+ itemIndex++
+ }
+ v >>= 1
+ }
+ if v > 0 {
+ // remaining set bits, but transactionIndex exceeded numTransactions
+ return errIndexNotFound
+ }
+ // in case the loop is cut short because there are no more set bits in the byte
+ transactionIndex = (i + 1) * 8
+ }
+ case 1:
+ transactionIndex := 0
+ maxV := bytesNeededBitmask(numTransactions)
+ if len(*b) > maxV {
+ return errIndexNotFound
+ }
+ for _, v := range (*b)[1:] {
+ // after the first iteration of the loop below, v will be less than 255
+ if v >= 255 {
+ transactionIndex += 8
+ continue
+ }
+ maxJ := 8
+ if maxJ > numTransactions-transactionIndex {
+ maxJ = numTransactions - transactionIndex
+ }
+ for j := 0; j < maxJ; j++ {
+ if v&1 == 0 {
+ if itemIndex >= numItems {
+ return errDataMissing
+ }
+ if err := callback(transactionIndex, itemIndex); err != nil {
+ return err
+ }
+ itemIndex++
+ }
+ v >>= 1
+ transactionIndex++
+ }
+ if 255>>maxJ != v {
+ // The remaining of the bits must be 1
+ return errIndexNotFound
+ }
+ }
+ if numTransactions-transactionIndex > numItems-itemIndex {
+ return errDataMissing
+ }
+ for ; transactionIndex < numTransactions; transactionIndex++ {
+ if err := callback(transactionIndex, itemIndex); err != nil {
+ return err
+ }
+ itemIndex++
+ }
+ case 2:
+ sum := 0 // transactionIndex
+ elementsCount := (len(*b) - 1) / 2
+ if elementsCount > numItems {
+ return errDataMissing
+ }
+ for itemIndex := 0; itemIndex < elementsCount; itemIndex++ {
+ sum += int((*b)[itemIndex*2+1])*256 + int((*b)[itemIndex*2+2])
+ if sum >= numTransactions {
+ return errIndexNotFound
+ }
+ if err := callback(sum, itemIndex); err != nil {
+ return err
+ }
+ }
+ case 3:
+ sum := 0
+ // This is the least amount of elements can be set.
+ // There could be more, if the numbers are corrupted
+ // i.e. when sum >= numTransactions
+ elementsCount := numTransactions - (len(*b)-1)/2
+ if elementsCount > numItems || elementsCount < 0 {
+ return errDataMissing
+ }
+ transactionIndex := 0
+ for i := 0; i*2+2 < len(*b); i++ {
+ sum += int((*b)[i*2+1])*256 + int((*b)[i*2+2])
+ if sum >= numTransactions {
+ return errIndexNotFound
+ }
+ for transactionIndex < sum {
+ if err := callback(transactionIndex, itemIndex); err != nil {
+ return err
+ }
+ transactionIndex++
+ itemIndex++
+ }
+ transactionIndex++
+ }
+ for transactionIndex < numTransactions {
+ if err := callback(transactionIndex, itemIndex); err != nil {
+ return err
+ }
+ transactionIndex++
+ itemIndex++
+ }
+ default:
+ return errInvalidBitmaskType
+ }
+ return nil
+}
+
+// bytesNeededBitmask returns the number of bytes needed to store entries bits.
+func bytesNeededBitmask(entries int) int {
+ return (entries+7)/8 + 1
+}
diff --git a/txnsync/bitmask_test.go b/txnsync/bitmask_test.go
new file mode 100644
index 000000000..516b3bc20
--- /dev/null
+++ b/txnsync/bitmask_test.go
@@ -0,0 +1,252 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "encoding/binary"
+ "errors"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/test/partitiontest"
+)
+
+func TestTrimBitmaskNil(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ var b bitmask
+ b.trimBitmask(0)
+ require.Nil(t, b)
+}
+
+func TestIterateExceptions(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ var b bitmask
+ require.Nil(t, b.iterate(0, 0, nil))
+
+}
+
+func TestBitmaskType0(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ setBits := make([]int, 0, 5)
+ setBits = append(setBits, 0)
+ setBits = append(setBits, 2)
+ setBits = append(setBits, 3)
+ setBits = append(setBits, 10)
+
+ trimIterateHelper(t, setBits)
+}
+
+func TestBitmaskType1(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ setBits := make([]int, 0, 80)
+ entries := 80
+ for i := 0; i < entries; i++ {
+ if i%3 != 0 || i > entries-10 {
+ setBits = append(setBits, i)
+ }
+ }
+ trimIterateHelper(t, setBits)
+}
+
+func TestBitmaskType2(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ setBits := make([]int, 0, 5)
+ setBits = append(setBits, 0)
+ setBits = append(setBits, 2)
+ setBits = append(setBits, 69)
+
+ trimIterateHelper(t, setBits)
+}
+
+func TestBitmaskType3(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ entries := 80
+ setBits := make([]int, 0, entries)
+ for i := 0; i < entries; i++ {
+ if i != 0 && i != 2 && i != 3 && i != 71 {
+ setBits = append(setBits, i)
+ }
+ }
+ trimIterateHelper(t, setBits)
+}
+
+// Test for corrupted bitmask
+func TestBitmaskType3Corrupted(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ // 10 entries, bitmask has 3 compliment bits (case 3): 10-3=7 set bits,
+ // last valid index should be 6
+ maxIndex := 7
+ entries := 10
+
+ var b bitmask
+ b = make([]byte, 7)
+ b[0] = 3
+ b[1] = 0
+ b[3] = 0
+ b[5] = 0
+
+ b[2] = 1 // index 1 is not set
+ b[4] = 1 // index 2 is not set
+ b[6] = 8 // index 2+8=10 is not set. 10 is outside the entries, and does not count
+ // set bits: 0, 3, 4, 5, 6, 7, 8, 9
+
+ require.Equal(t, errIndexNotFound, b.iterate(entries, maxIndex, func(entry, index int) error {
+ return nil
+ }))
+}
+
+func TestBitmaskTypeX(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ b := make(bitmask, bytesNeededBitmask(80))
+ b[0] = 4
+ require.Equal(t, b.iterate(0, 0, nil), errInvalidBitmaskType)
+}
+
+func trimIterateHelper(t *testing.T, setBits []int) {
+ entries := 80
+ b := make(bitmask, bytesNeededBitmask(entries))
+
+ for _, x := range setBits {
+ b.setBit(x)
+ }
+ iterated := make([]bool, entries)
+ iterfunc := func(i int, index int) error {
+ iterated[i] = true
+ return nil
+ }
+ var errTestError = errors.New("some error")
+ errorAfter := 0
+ errfunc := func(i int, index int) error {
+ if index > errorAfter {
+ return errTestError
+ }
+ return nil
+ }
+
+ require.Equal(t, errTestError, b.iterate(entries, len(setBits), errfunc))
+ require.Equal(t, errDataMissing, b.iterate(entries, len(setBits)-1, iterfunc)) // less than set bits
+ require.NoError(t, b.iterate(entries, len(setBits), iterfunc))
+
+ s := 0
+ for i := 0; i < entries; i++ {
+ if s < len(setBits) && i == setBits[s] {
+ require.True(t, iterated[i], i)
+ s++
+ } else {
+ require.False(t, iterated[i], i)
+ }
+ }
+ b.trimBitmask(entries)
+ if int(b[0]) < 2 {
+ // make sure TrimRight is behaving as expected
+ require.True(t, int(b[len(b)-1]) > 0)
+ }
+ iterated = make([]bool, entries)
+
+ require.Equal(t, errTestError, b.iterate(entries, len(setBits), errfunc))
+ require.Equal(t, errDataMissing, b.iterate(entries, len(setBits)-1, iterfunc))
+
+ // For types 0 and 2, let the entries be smaller than what the bitmap will provide
+ // This is the edge case, and will not be a problem for the compliment set bitmasks
+ if int((b)[0]) == 0 || int((b)[0]) == 2 {
+ require.Equal(t, errIndexNotFound, b.iterate(setBits[len(setBits)-1], len(setBits), iterfunc))
+ require.Nil(t, b.iterate(setBits[len(setBits)-1]+1, len(setBits), iterfunc))
+ }
+
+ // For types 1 and 3, let the entries be smaller than what the bitmap will provide
+ // This requires a much smaller entries limit, since it is only checked in the first stage
+ if int((b)[0]) == 1 || int((b)[0]) == 3 {
+ require.Equal(t, errIndexNotFound, b.iterate(70, len(setBits), iterfunc))
+ }
+
+ // For types 1 and 3, test the error handling in the second stage.
+ errorAfter = len(setBits) - 1 - 8
+ require.Equal(t, errTestError, b.iterate(entries, len(setBits), errfunc))
+ require.Equal(t, errDataMissing, b.iterate(entries, len(setBits)-1-8, iterfunc))
+
+ require.NoError(t, b.iterate(entries, len(setBits), func(i int, index int) error {
+ iterated[i] = true
+ return nil
+ }))
+
+ s = 0
+ for i := 0; i < entries; i++ {
+ if s < len(setBits) && i == setBits[s] {
+ require.True(t, iterated[i], i)
+ s++
+ } else {
+ require.False(t, iterated[i], i)
+ }
+ }
+}
+
+func TestFuzzBitmask(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ randSeed := uint64(0)
+ rand := func() byte {
+ bytes := [16]byte{}
+ l := binary.PutUvarint(bytes[:], randSeed)
+ h := crypto.Hash(bytes[:l])
+ randSeed = 0
+ for i := 0; i < 8; i++ {
+ randSeed += uint64(h[i]) << (i * 8)
+ }
+ return byte(h[0])
+ }
+ for iterationsCount := 0; iterationsCount < 1000; iterationsCount++ {
+ bitmaskType := rand() % 4
+ blen := int(rand()%33) + 1
+ var b bitmask
+ b = make([]byte, blen)
+ b[0] = byte(bitmaskType)
+ for i := 1; i < blen; i++ {
+ b[i] = rand()
+ }
+ entries := int(rand())
+ maxIndex := int(rand())
+ lastEntryIndex := -1
+ b.iterate(entries, maxIndex, func(i, j int) error {
+ require.Greater(t, i, lastEntryIndex)
+ lastEntryIndex = i
+ require.Less(t, i, entries)
+ require.Less(t, j, maxIndex)
+ return nil
+ })
+ // reset to mode 0
+ b[0] = 0
+ entries = (blen - 1) * 8
+ err1 := b.iterate(entries, maxIndex, func(i, j int) error {
+ return nil
+ })
+ b.trimBitmask(entries)
+ err2 := b.iterate(entries, maxIndex, func(i, j int) error {
+ return nil
+ })
+ require.Equal(t, err1, err2)
+ }
+}
diff --git a/txnsync/bloomFilter.go b/txnsync/bloomFilter.go
new file mode 100644
index 000000000..013888fa8
--- /dev/null
+++ b/txnsync/bloomFilter.go
@@ -0,0 +1,239 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "encoding/binary"
+ "errors"
+ "math"
+
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/util/bloom"
+)
+
+// bloomFilterFalsePositiveRate is used as the target false positive rate for the multiHashBloomFilter implementation.
+// the xor based bloom filters have their own hard-coded false positive rate, and therefore require no configuration.
+const bloomFilterFalsePositiveRate = 0.01
+
+var errInvalidBloomFilterEncoding = errors.New("invalid bloom filter encoding")
+var errEncodingBloomFilterFailed = errors.New("encoding bloom filter failed")
+
+//msgp:ignore bloomFilterType
+type bloomFilterType byte
+
+const (
+ invalidBloomFilter bloomFilterType = iota //nolint:deadcode,varcheck
+ multiHashBloomFilter
+ xorBloomFilter32
+ xorBloomFilter8
+)
+
+// transactionsRange helps us to identify a subset of the transaction pool pending transaction groups.
+// it's being used as part of an optimization when we're attempting to recreate a bloom filter :
+// if the new bloom filter shares the same set of parameters, then the result is expected to be the
+// same and therefore the old bloom filter can be used.
+type transactionsRange struct {
+ firstCounter uint64
+ lastCounter uint64
+ transactionsCount uint64
+}
+
+type bloomFilter struct {
+ containedTxnsRange transactionsRange
+
+ encoded encodedBloomFilter
+
+ encodedLength int
+}
+
+// testableBloomFilter is used for a bloom filters that were received from the network, decoded
+// and are ready to be tested against.
+type testableBloomFilter struct {
+ encodingParams requestParams
+
+ filter bloom.GenericFilter
+
+ clearPrevious bool
+}
+
+func decodeBloomFilter(enc encodedBloomFilter) (outFilter *testableBloomFilter, err error) {
+ outFilter = &testableBloomFilter{
+ encodingParams: enc.EncodingParams,
+ clearPrevious: enc.ClearPrevious != 0,
+ }
+ switch bloomFilterType(enc.BloomFilterType) {
+ case multiHashBloomFilter:
+ outFilter.filter, err = bloom.UnmarshalBinary(enc.BloomFilter)
+ case xorBloomFilter32:
+ outFilter.filter = new(bloom.XorFilter)
+ err = outFilter.filter.UnmarshalBinary(enc.BloomFilter)
+ case xorBloomFilter8:
+ outFilter.filter = new(bloom.XorFilter8)
+ err = outFilter.filter.UnmarshalBinary(enc.BloomFilter)
+ default:
+ return nil, errInvalidBloomFilterEncoding
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ return
+}
+
+func (bf *bloomFilter) encode(filter bloom.GenericFilter, filterType bloomFilterType) (err error) {
+ bf.encoded.BloomFilterType = byte(filterType)
+ bf.encoded.BloomFilter, err = filter.MarshalBinary()
+ bf.encodedLength = len(bf.encoded.BloomFilter)
+ if err != nil || bf.encodedLength == 0 {
+ return errEncodingBloomFilterFailed
+ }
+ // increase the counter for a successful bloom filter encoding
+ txsyncEncodedBloomFiltersTotal.Inc(nil)
+ return
+}
+
+func (bf *bloomFilter) sameParams(other bloomFilter) bool {
+ return (bf.encoded.EncodingParams == other.encoded.EncodingParams) &&
+ (bf.containedTxnsRange == other.containedTxnsRange)
+}
+
+func (bf *testableBloomFilter) test(txID transactions.Txid) bool {
+ if bf.encodingParams.Modulator > 1 {
+ if txidToUint64(txID)%uint64(bf.encodingParams.Modulator) != uint64(bf.encodingParams.Offset) {
+ return false
+ }
+ }
+ return bf.filter.Test(txID[:])
+}
+
+func filterFactoryBloom(numEntries int, s *syncState) (filter bloom.GenericFilter, filterType bloomFilterType) {
+ shuffler := uint32(s.node.Random(math.MaxUint64))
+ sizeBits, numHashes := bloom.Optimal(numEntries, bloomFilterFalsePositiveRate)
+ return bloom.New(sizeBits, numHashes, shuffler), multiHashBloomFilter
+}
+
+func filterFactoryXor8(numEntries int, s *syncState) (filter bloom.GenericFilter, filterType bloomFilterType) { //nolint:deadcode,unused
+ s.xorBuilder.RandomNumberGeneratorSeed = s.node.Random(math.MaxUint64)
+ return bloom.NewXor8(numEntries, &s.xorBuilder), xorBloomFilter8
+}
+
+func filterFactoryXor32(numEntries int, s *syncState) (filter bloom.GenericFilter, filterType bloomFilterType) {
+ s.xorBuilder.RandomNumberGeneratorSeed = s.node.Random(math.MaxUint64)
+ return bloom.NewXor(numEntries, &s.xorBuilder), xorBloomFilter32
+}
+
+var filterFactory func(int, *syncState) (filter bloom.GenericFilter, filterType bloomFilterType) = filterFactoryXor32
+
+func (s *syncState) makeBloomFilter(encodingParams requestParams, txnGroups []pooldata.SignedTxGroup, excludeTransactions *transactionCache, hintPrevBloomFilter *bloomFilter) (result bloomFilter) {
+ result.encoded.EncodingParams = encodingParams
+ if encodingParams.Modulator == 0 {
+ // we want none.
+ return
+ }
+ if encodingParams.Modulator == 1 && excludeTransactions == nil {
+ // we want all.
+ if len(txnGroups) > 0 {
+ result.containedTxnsRange.firstCounter = txnGroups[0].GroupCounter
+ result.containedTxnsRange.lastCounter = txnGroups[len(txnGroups)-1].GroupCounter
+ result.containedTxnsRange.transactionsCount = uint64(len(txnGroups))
+ } else {
+ return
+ }
+
+ if hintPrevBloomFilter != nil {
+ if result.sameParams(*hintPrevBloomFilter) {
+ return *hintPrevBloomFilter
+ }
+ }
+
+ filter, filterType := filterFactory(len(txnGroups), s)
+ for _, group := range txnGroups {
+ filter.Set(group.GroupTransactionID[:])
+ }
+ err := result.encode(filter, filterType)
+ if err != nil {
+ // fall back to standard bloom filter
+ filter, filterType = filterFactoryBloom(len(txnGroups), s)
+ for _, group := range txnGroups {
+ filter.Set(group.GroupTransactionID[:])
+ }
+ result.encode(filter, filterType) //nolint:errcheck
+ // the error in the above case can be silently ignored.
+ }
+ return result
+ }
+
+ // we want subset.
+ result.containedTxnsRange.firstCounter = math.MaxUint64
+ filteredTransactionsIDs := getTxIDSliceBuffer(len(txnGroups))
+ defer releaseTxIDSliceBuffer(filteredTransactionsIDs)
+
+ excludedTransactions := 0
+ for _, group := range txnGroups {
+ txID := group.GroupTransactionID
+ if txidToUint64(txID)%uint64(encodingParams.Modulator) != uint64(encodingParams.Offset) {
+ continue
+ }
+
+ if result.containedTxnsRange.firstCounter == math.MaxUint64 {
+ result.containedTxnsRange.firstCounter = group.GroupCounter
+ }
+ result.containedTxnsRange.lastCounter = group.GroupCounter
+
+ if excludeTransactions != nil && excludeTransactions.contained(txID) {
+ excludedTransactions++
+ continue
+ }
+
+ filteredTransactionsIDs = append(filteredTransactionsIDs, txID)
+ }
+
+ result.containedTxnsRange.transactionsCount = uint64(len(filteredTransactionsIDs) + excludedTransactions)
+
+ if hintPrevBloomFilter != nil {
+ if result.sameParams(*hintPrevBloomFilter) {
+ return *hintPrevBloomFilter
+ }
+ }
+
+ if len(filteredTransactionsIDs) == 0 {
+ return
+ }
+
+ filter, filterType := filterFactory(len(filteredTransactionsIDs), s)
+
+ for _, txid := range filteredTransactionsIDs {
+ filter.Set(txid[:])
+ }
+ err := result.encode(filter, filterType)
+ if err != nil {
+ // fall back to standard bloom filter
+ filter, filterType = filterFactoryBloom(len(filteredTransactionsIDs), s)
+ for _, txid := range filteredTransactionsIDs {
+ filter.Set(txid[:])
+ }
+ result.encode(filter, filterType) //nolint:errcheck
+ // the error in the above case can be silently ignored.
+ }
+
+ return result
+}
+
+func txidToUint64(txID transactions.Txid) uint64 {
+ return binary.LittleEndian.Uint64(txID[:8])
+}
diff --git a/txnsync/bloomFilter_test.go b/txnsync/bloomFilter_test.go
new file mode 100644
index 000000000..71a0d4151
--- /dev/null
+++ b/txnsync/bloomFilter_test.go
@@ -0,0 +1,366 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "encoding/binary"
+ "math/rand"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/algorand/go-algorand/util/bloom"
+ "github.com/algorand/go-algorand/util/timers"
+)
+
+func getTxnGroups(genesisHash crypto.Digest, genesisID string) []pooldata.SignedTxGroup {
+ return []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ GroupCounter: 0,
+ GroupTransactionID: transactions.Txid{1},
+ Transactions: []transactions.SignedTxn{
+ {
+ Txn: transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: basics.Address(crypto.Hash([]byte("2"))),
+ Fee: basics.MicroAlgos{Raw: 100},
+ GenesisHash: genesisHash,
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: basics.Address(crypto.Hash([]byte("4"))),
+ Amount: basics.MicroAlgos{Raw: 1000},
+ },
+ },
+ Sig: crypto.Signature{1},
+ },
+ },
+ },
+ pooldata.SignedTxGroup{
+ GroupCounter: 1,
+ GroupTransactionID: transactions.Txid{2},
+ Transactions: []transactions.SignedTxn{
+ {
+ Txn: transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: basics.Address(crypto.Hash([]byte("1"))),
+ Fee: basics.MicroAlgos{Raw: 100},
+ GenesisHash: genesisHash,
+ GenesisID: genesisID,
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: basics.Address(crypto.Hash([]byte("2"))),
+ Amount: basics.MicroAlgos{Raw: 1000},
+ },
+ },
+ Sig: crypto.Signature{2},
+ },
+ {
+ Txn: transactions.Transaction{
+ Type: protocol.KeyRegistrationTx,
+ Header: transactions.Header{
+ Sender: basics.Address(crypto.Hash([]byte("1"))),
+ GenesisHash: genesisHash,
+ GenesisID: genesisID,
+ },
+ },
+ Sig: crypto.Signature{3},
+ },
+ },
+ },
+ pooldata.SignedTxGroup{
+ GroupCounter: 2,
+ GroupTransactionID: transactions.Txid{3},
+ Transactions: []transactions.SignedTxn{
+ {
+ Txn: transactions.Transaction{
+ Type: protocol.AssetConfigTx,
+ Header: transactions.Header{
+ Sender: basics.Address(crypto.Hash([]byte("1"))),
+ Fee: basics.MicroAlgos{Raw: 100},
+ GenesisHash: genesisHash,
+ },
+ },
+ Sig: crypto.Signature{4},
+ },
+ {
+ Txn: transactions.Transaction{
+ Type: protocol.AssetFreezeTx,
+ Header: transactions.Header{
+ Sender: basics.Address(crypto.Hash([]byte("1"))),
+ GenesisHash: genesisHash,
+ },
+ },
+ Sig: crypto.Signature{5},
+ },
+ {
+ Txn: transactions.Transaction{
+ Type: protocol.CompactCertTx,
+ Header: transactions.Header{
+ Sender: basics.Address(crypto.Hash([]byte("1"))),
+ GenesisHash: genesisHash,
+ },
+ },
+ Msig: crypto.MultisigSig{Version: 1},
+ },
+ },
+ },
+ }
+}
+
+func BenchmarkTxidToUint64(b *testing.B) {
+ txID := transactions.Txid{1, 2, 3, 4, 5}
+ for i := 0; i < b.N; i++ {
+ txidToUint64(txID)
+ }
+}
+
+const testingGenesisID = "gID"
+
+var testingGenesisHash = crypto.Hash([]byte("gh"))
+
+func TestBloomFallback(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ var s syncState
+ s.node = &justRandomFakeNode{}
+ var encodingParams requestParams
+
+ for encodingParams.Modulator = 1; encodingParams.Modulator < 3; encodingParams.Modulator++ {
+ txnGroups := getTxnGroups(testingGenesisHash, testingGenesisID)
+ bf := s.makeBloomFilter(encodingParams, txnGroups, nil, nil)
+
+ switch bloomFilterType(bf.encoded.BloomFilterType) {
+ case multiHashBloomFilter:
+ t.Errorf("expected xorfilter but got classic bloom filter")
+ case xorBloomFilter32:
+ // ok
+ case xorBloomFilter8:
+ t.Errorf("expected xorBloomFilter32 but got xorBloomFilter8")
+ default:
+ t.Errorf("unknown internal bloom filter object : %d", bloomFilterType(bf.encoded.BloomFilterType))
+ }
+
+ // Duplicate first entry. xorfilter can't handle
+ // duplicates. We _probably_ never have duplicate txid
+ // prefixes when we grab the first 8 bytes of 32 bytes, but
+ // that's not 100%, maybe only 99.999999%
+ stg := txnGroups[1]
+ txnGroups = append(txnGroups, stg)
+
+ bf = s.makeBloomFilter(encodingParams, txnGroups, nil, nil)
+ switch bloomFilterType(bf.encoded.BloomFilterType) {
+ case multiHashBloomFilter:
+ // ok
+ case xorBloomFilter32:
+ t.Errorf("expected bloom filter but got xor")
+ case xorBloomFilter8:
+ t.Errorf("expected bloom filter but got xor")
+ default:
+ t.Errorf("unknown internal bloom filter object : %d", bloomFilterType(bf.encoded.BloomFilterType))
+ }
+ }
+}
+
+// TestHint tests that the hint is used only when it should be used
+func TestHint(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ var s syncState
+ s.node = &justRandomFakeNode{}
+ var encodingParams requestParams
+ defaultFilterType := xorBloomFilter32
+
+ for encodingParams.Modulator = 1; encodingParams.Modulator < 3; encodingParams.Modulator++ {
+ txnGroups := getTxnGroups(testingGenesisHash, testingGenesisID)
+ bf := s.makeBloomFilter(encodingParams, txnGroups, nil, nil)
+
+ switch bloomFilterType(bf.encoded.BloomFilterType) {
+ case xorBloomFilter32:
+ // ok
+ default:
+ require.Fail(t, "expect xorBloomFilter32")
+ }
+ require.Equal(t, defaultFilterType, bloomFilterType(bf.encoded.BloomFilterType))
+
+ // Change the filter of bf to other than the default filter i.e. XorFilter8
+ bf.encoded.BloomFilterType = byte(xorBloomFilter8)
+
+ // Pass bf as a hint.
+ bf2 := s.makeBloomFilter(encodingParams, txnGroups, nil, &bf)
+
+ // If the filter of bf2 is not defaultFilterType (i.e. is XorFilter8), then the hint was used.
+ // The hint must be used, and the filter should not be the default filter.
+ require.NotEqual(t, defaultFilterType, bf2.encoded.BloomFilterType)
+ switch bloomFilterType(bf2.encoded.BloomFilterType) {
+ case xorBloomFilter8:
+ // ok
+ default:
+ require.Fail(t, "expect xorBloomFilter8")
+ }
+
+ // Now change txnGroups, so that the hint will not be used
+ for i := range txnGroups {
+ txnGroups[i].GroupCounter += uint64(len(txnGroups))
+ }
+ bf2 = s.makeBloomFilter(encodingParams, txnGroups, nil, &bf)
+
+ // If the filter of bf2 is XorFilter (i.e. defaultFilterType), then the hint was not used
+ switch bloomFilterType(bf2.encoded.BloomFilterType) {
+ case xorBloomFilter32:
+ // ok
+ default:
+ require.Fail(t, "expect xorBloomFilter32")
+ }
+ require.Equal(t, defaultFilterType, bloomFilterType(bf2.encoded.BloomFilterType))
+ }
+}
+
+// TestEncodingDecoding checks the encoding/decoding of the filters
+func TestEncodingDecoding(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ var s syncState
+ s.node = &justRandomFakeNode{}
+
+ filters := []func(int, *syncState) (filter bloom.GenericFilter, filterType bloomFilterType){
+ filterFactoryXor8, filterFactoryXor32, filterFactoryBloom}
+
+ var randomEntries [10]transactions.Txid
+ for i := range randomEntries {
+ crypto.RandBytes(randomEntries[i][:])
+ }
+ var err error
+ var testableBf *testableBloomFilter
+ var remarshaled []byte
+ // For each filter type
+ for _, ff := range filters {
+
+ filter, filterType := ff(len(randomEntries), &s)
+ for i := range randomEntries {
+ filter.Set(randomEntries[i][:])
+ }
+ var enc encodedBloomFilter
+ enc.BloomFilterType = byte(filterType)
+ enc.BloomFilter, err = filter.MarshalBinary()
+ require.NoError(t, err)
+
+ testableBf, err = decodeBloomFilter(enc)
+ require.NoError(t, err)
+
+ remarshaled, err = testableBf.filter.MarshalBinary()
+
+ require.NoError(t, err)
+ require.Equal(t, enc.BloomFilter, remarshaled)
+ }
+}
+
+func TestDecodingErrors(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ bf, err := decodeBloomFilter(encodedBloomFilter{})
+ require.Equal(t, errInvalidBloomFilterEncoding, err)
+ require.Equal(t, (*testableBloomFilter)(nil), bf)
+
+ var ebf encodedBloomFilter
+ ebf.BloomFilterType = byte(multiHashBloomFilter)
+ _, err = decodeBloomFilter(ebf)
+
+ require.Error(t, err)
+}
+
+func TestBloomFilterTest(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ filters := []func(int, *syncState) (filter bloom.GenericFilter, filterType bloomFilterType){
+ filterFactoryXor8, filterFactoryXor32, filterFactoryBloom}
+
+ for _, ff := range filters {
+
+ var s syncState
+ s.node = &justRandomFakeNode{}
+ var err error
+ txnGroups := getTxnGroups(testingGenesisHash, testingGenesisID)
+
+ filter, filterType := ff(len(txnGroups), &s)
+ for _, txnGroup := range txnGroups {
+ filter.Set(txnGroup.GroupTransactionID[:])
+ }
+ var enc encodedBloomFilter
+ enc.BloomFilterType = byte(filterType)
+ enc.BloomFilter, err = filter.MarshalBinary()
+ require.NoError(t, err)
+
+ testableBf, err := decodeBloomFilter(enc)
+ require.NoError(t, err)
+
+ for testableBf.encodingParams.Modulator = 0; testableBf.encodingParams.Modulator < 7; testableBf.encodingParams.Modulator++ {
+ for testableBf.encodingParams.Offset = 0; testableBf.encodingParams.Offset < testableBf.encodingParams.Modulator; testableBf.encodingParams.Offset++ {
+ for _, tx := range txnGroups {
+ ans := testableBf.test(tx.GroupTransactionID)
+ expected := true
+ if testableBf.encodingParams.Modulator > 1 {
+ if txidToUint64(tx.GroupTransactionID)%uint64(testableBf.encodingParams.Modulator) != uint64(testableBf.encodingParams.Offset) {
+ expected = false
+ }
+ }
+ require.Equal(t, expected, ans)
+ }
+ }
+ }
+ }
+
+}
+
+type justRandomFakeNode struct {
+}
+
+func (fn *justRandomFakeNode) Events() <-chan Event { return nil }
+
+func (fn *justRandomFakeNode) GetCurrentRoundSettings() (out RoundSettings) { return }
+
+func (fn *justRandomFakeNode) Clock() (out timers.WallClock) { return }
+
+func (fn *justRandomFakeNode) Random(rng uint64) uint64 {
+ var xb [8]byte
+ rand.Read(xb[:])
+ rv := binary.LittleEndian.Uint64(xb[:])
+ return rv % rng
+}
+
+func (fn *justRandomFakeNode) GetPeers() []PeerInfo { return nil }
+
+func (fn *justRandomFakeNode) GetPeer(interface{}) (out PeerInfo) { return }
+
+func (fn *justRandomFakeNode) UpdatePeers(txsyncPeers []*Peer, netPeers []interface{}, peersAverageDataExchangeRate uint64) {
+}
+func (fn *justRandomFakeNode) SendPeerMessage(netPeer interface{}, msg []byte, callback SendMessageCallback) {
+}
+func (fn *justRandomFakeNode) GetPendingTransactionGroups() (txGroups []pooldata.SignedTxGroup, latestLocallyOriginatedGroupCounter uint64) {
+ return
+}
+func (fn *justRandomFakeNode) IncomingTransactionGroups(peer *Peer, messageSeq uint64, txGroups []pooldata.SignedTxGroup) (transactionPoolSize int) {
+ return 0
+}
+func (fn *justRandomFakeNode) NotifyMonitor() chan struct{} { return nil }
diff --git a/txnsync/emulatorCore_test.go b/txnsync/emulatorCore_test.go
new file mode 100644
index 000000000..814539827
--- /dev/null
+++ b/txnsync/emulatorCore_test.go
@@ -0,0 +1,267 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "context"
+ "encoding/binary"
+ "sort"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "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/pooldata"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/logging"
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/util/execpool"
+)
+
+const roundDuration = 4 * time.Second
+
+type emulator struct {
+ scenario scenario
+ nodes []*emulatedNode
+ syncers []*Service
+ nodeCount int
+ log logging.Logger
+ currentRound basics.Round
+ clock *guidedClock
+ t *testing.T
+ totalDuplicateTransactions uint64
+ totalDuplicateTransactionSize uint64
+ lastRandom uint64
+ totalInitialTransactions uint64
+}
+
+type nodeTransaction struct {
+ expirationRound basics.Round
+ transactionSize int
+}
+
+type nodeTransactions []nodeTransaction
+
+type emulatorResult struct {
+ nodes []nodeTransactions
+}
+
+func (a nodeTransactions) Len() int { return len(a) }
+func (a nodeTransactions) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a nodeTransactions) Less(i, j int) bool {
+ if a[i].expirationRound < a[j].expirationRound {
+ return true
+ }
+ if a[i].expirationRound > a[j].expirationRound {
+ return false
+ }
+ return a[i].transactionSize < a[j].transactionSize
+}
+
+func emulateScenario(t *testing.T, scenario scenario) {
+ e := &emulator{
+ scenario: scenario,
+ nodeCount: len(scenario.netConfig.nodes),
+ log: logging.TestingLog(t),
+ t: t,
+ }
+ e.initNodes()
+ e.run()
+
+ results := e.collectResult()
+ for n := range scenario.expectedResults.nodes {
+ sort.Stable(scenario.expectedResults.nodes[n])
+ }
+ for n := range results.nodes {
+ sort.Stable(results.nodes[n])
+ }
+
+ t.Logf("Emulation Statistics:")
+ t.Logf("Total duplicate transaction count: %d", e.totalDuplicateTransactions)
+ t.Logf("Total duplicate transactions size: %d", e.totalDuplicateTransactionSize)
+ for n := 0; n < e.nodeCount; n++ {
+ t.Logf("%s transaction groups count : %d", e.nodes[n].name, len(results.nodes[n]))
+ }
+ for n := 0; n < e.nodeCount; n++ {
+ require.Equalf(t, len(scenario.expectedResults.nodes[n]), len(results.nodes[n]), "node %d", n)
+ }
+
+ // calculating efficiency / overhead :
+ // how many transaction need to be received ?
+ // each node received all the transactions, minus the ones that it start up with.
+ totalNeededSentTransactions := e.totalInitialTransactions*uint64(len(e.nodes)) - e.totalInitialTransactions
+ actualReceivedTransactions := totalNeededSentTransactions + e.totalDuplicateTransactions
+ t.Logf("Total transaction overhead: %d%%", (actualReceivedTransactions-totalNeededSentTransactions)*100/totalNeededSentTransactions)
+
+ require.Equal(t, scenario.expectedResults, results)
+ require.Equal(t, 1, 1)
+}
+
+func (e *emulator) run() {
+ guidedClock := makeGuidedClock()
+ lastRoundStarted := guidedClock.Since()
+ e.clock = guidedClock
+ e.start()
+ // start the nodes
+ for e.clock.Since() < e.scenario.testDuration {
+ if guidedClock.Since() > lastRoundStarted+roundDuration {
+ e.nextRound()
+ lastRoundStarted = guidedClock.Since()
+ }
+ guidedClock.Advance(e.scenario.step)
+ e.unblockStep()
+ }
+ // stop the nodes
+ e.stop()
+}
+func (e *emulator) nextRound() {
+ e.currentRound++
+ for _, node := range e.nodes {
+ node.onNewRound(e.currentRound, true)
+ }
+}
+func (e *emulator) unblockStep() {
+ for _, node := range e.nodes {
+ // let it run through the clock advancement.
+ node.unblock()
+ node.waitBlocked()
+
+ // make step
+ node.step()
+ }
+}
+func (e *emulator) start() {
+ for i, node := range e.syncers {
+ node.Start()
+ e.nodes[i].waitBlocked()
+ }
+}
+func (e *emulator) stop() {
+ for i, node := range e.syncers {
+ e.nodes[i].disableBlocking()
+ node.Stop()
+ }
+}
+
+func (e *emulator) initNodes() {
+ e.nodes = make([]*emulatedNode, e.nodeCount, e.nodeCount)
+ for i := 0; i < e.nodeCount; i++ {
+ e.nodes[i] = makeEmulatedNode(e, i)
+ syncer := MakeTransactionSyncService(
+ makeNodeLogger(e.log, e.nodes[i]),
+ e.nodes[i],
+ e.scenario.netConfig.nodes[i].isRelay,
+ "",
+ crypto.Digest{},
+ config.GetDefaultLocal(),
+ e,
+ )
+ e.syncers = append(e.syncers, syncer)
+ }
+ randCounter := uint64(0)
+ var randBuf [8]byte
+ // we want to place a sender on all transaction so that they would be *somewhat* compressible.
+ defaultSender := basics.Address{1, 2, 3, 4}
+ const senderEncodingSize = 35
+ encodingBuf := protocol.GetEncodingBuf()
+ for _, initAlloc := range e.scenario.initialAlloc {
+ node := e.nodes[initAlloc.node]
+ for i := 0; i < initAlloc.transactionsCount; i++ {
+ var group = pooldata.SignedTxGroup{}
+ group.LocallyOriginated = true
+ group.GroupCounter = uint64(len(node.txpoolEntries))
+ group.Transactions = []transactions.SignedTxn{
+ {
+ Txn: transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Note: make([]byte, initAlloc.transactionSize-senderEncodingSize, initAlloc.transactionSize-senderEncodingSize),
+ LastValid: initAlloc.expirationRound,
+ Sender: defaultSender,
+ },
+ },
+ },
+ }
+ // fill up the note field with pseudo-random data.
+ for i := 0; i < len(group.Transactions[0].Txn.Note); i += crypto.DigestSize {
+ binary.LittleEndian.PutUint64(randBuf[:], randCounter)
+ digest := crypto.Hash(randBuf[:])
+ copy(group.Transactions[0].Txn.Note[i:], digest[:])
+ randCounter++
+ }
+ group.GroupTransactionID = group.Transactions.ID()
+ encodingBuf = encodingBuf[:0]
+ group.EncodedLength = len(group.Transactions[0].MarshalMsg(encodingBuf))
+ node.txpoolIds[group.Transactions[0].ID()] = true
+ node.txpoolEntries = append(node.txpoolEntries, group)
+ }
+ node.latestLocallyOriginatedGroupCounter = uint64(len(node.txpoolEntries) - 1)
+ e.totalInitialTransactions += uint64(initAlloc.transactionsCount)
+ node.txpoolGroupCounter += uint64(initAlloc.transactionsCount)
+ node.onNewTransactionPoolEntry()
+ }
+ protocol.PutEncodingBuf(encodingBuf)
+}
+
+func (e *emulator) collectResult() (result emulatorResult) {
+ result.nodes = make([]nodeTransactions, len(e.nodes))
+ const senderEncodingSize = 35
+ for i, node := range e.nodes {
+ var txns nodeTransactions
+ for _, txnGroup := range node.txpoolEntries {
+ size := len(txnGroup.Transactions[0].Txn.Note)
+ exp := txnGroup.Transactions[0].Txn.LastValid
+ txns = append(txns, nodeTransaction{expirationRound: exp, transactionSize: size + senderEncodingSize})
+ }
+ for _, txnGroup := range node.expiredTx {
+ size := len(txnGroup.Transactions[0].Txn.Note)
+ exp := txnGroup.Transactions[0].Txn.LastValid
+ txns = append(txns, nodeTransaction{expirationRound: exp, transactionSize: size + senderEncodingSize})
+ }
+ result.nodes[i] = txns
+ }
+ return result
+}
+
+// Dummy implementation of execpool.BacklogPool
+func (e *emulator) EnqueueBacklog(enqueueCtx context.Context, t execpool.ExecFunc, arg interface{}, out chan interface{}) error {
+ t(arg)
+ return nil
+}
+
+// Dummy implementation of execpool.BacklogPool
+func (e *emulator) Enqueue(enqueueCtx context.Context, t execpool.ExecFunc, arg interface{}, i execpool.Priority, out chan interface{}) error {
+ return nil
+}
+
+// Dummy implementation of execpool.BacklogPool
+func (e *emulator) GetOwner() interface{} {
+ return nil
+}
+
+// Dummy implementation of execpool.BacklogPool
+func (e *emulator) Shutdown() {
+
+}
+
+// Dummy implementation of execpool.BacklogPool
+func (e *emulator) GetParallelism() int {
+ return 0
+}
diff --git a/txnsync/emulatorLogger_test.go b/txnsync/emulatorLogger_test.go
new file mode 100644
index 000000000..7020b7512
--- /dev/null
+++ b/txnsync/emulatorLogger_test.go
@@ -0,0 +1,151 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+ "testing"
+
+ "github.com/algorand/go-algorand/logging"
+)
+
+// Foreground text colors
+const (
+ reset = 0
+ black = 30
+ red = 31
+ green = 32
+ yellow = 33
+ blue = 34
+ magenta = 35
+ cyan = 36
+ white = 37
+ hiblack = 90
+ hired = 91
+ higreen = 92
+ hiyellow = 93
+ hiblue = 94
+ himagenta = 95
+ hicyan = 96
+ hiwhite = 97
+)
+
+const escape = "\x1b"
+
+var colors = []int{red, green, yellow, blue, magenta, cyan, hired, higreen, hiyellow, hiblue, himagenta, hicyan}
+var lowColors = []int{red, green, yellow, blue, magenta, cyan}
+
+type emulatorNodeLogger struct {
+ algodlogger
+ node *emulatedNode
+ longestName int
+}
+
+func makeNodeLogger(l logging.Logger, node *emulatedNode) Logger {
+ return &emulatorNodeLogger{
+ algodlogger: l,
+ node: node,
+ }
+}
+
+type msgMode int
+
+const (
+ modeZero msgMode = iota
+ modeIncoming
+ modeOutgoing
+)
+
+// implement local interface Logger
+func (e *emulatorNodeLogger) outgoingMessage(mstat msgStats) {
+ e.printMsgStats(mstat, modeOutgoing)
+}
+
+// implement local interface Logger
+func (e *emulatorNodeLogger) incomingMessage(mstat msgStats) {
+ e.printMsgStats(mstat, modeIncoming)
+}
+
+func (e emulatorNodeLogger) printMsgStats(mstat msgStats, mode msgMode) {
+ seq := int(mstat.sequenceNumber)
+ round := mstat.round
+ transactions := mstat.transactions
+ offset := mstat.offsetModulator.Offset
+ modulator := mstat.offsetModulator.Modulator
+ bloom := mstat.bloomSize
+ nextTS := mstat.nextMsgMinDelay
+ // emulator peer addresses are just an int
+ destIndex, _ := strconv.Atoi(mstat.peerAddress)
+
+ destName := e.node.emulator.nodes[destIndex].name
+
+ if e.longestName == 0 {
+ for _, node := range e.node.emulator.nodes {
+ if len(node.name) > e.longestName {
+ e.longestName = len(node.name) + 1
+ }
+ }
+ }
+
+ elapsed := e.node.emulator.clock.Since().Milliseconds()
+ out := fmt.Sprintf("%3d.%03d ", elapsed/1000, elapsed%1000)
+ out += fmt.Sprintf("%"+fmt.Sprintf("%d", e.longestName)+"s", e.node.name)
+
+ bfColor := hiblack
+ if bloom > 0 {
+ bfColor = higreen
+ }
+ nextTSColor := hiblack
+ if nextTS > 0 {
+ nextTSColor = higreen
+ }
+ mid := fmt.Sprintf("Round %s Txns %s Req [%3d/%3d] %s %s",
+ wrapRollingColor(int(round), fmt.Sprintf("%2d", round)),
+ wrapRollingColor(transactions, fmt.Sprintf("%3d", transactions)),
+ offset,
+ modulator,
+ wrapColor(bfColor, "BF"),
+ wrapColor(nextTSColor, "TS"),
+ )
+ if mode == modeOutgoing {
+ out += wrapRollingLowColor(seq, " [ ")
+ out += mid + wrapRollingLowColor(seq, " --> ") + strings.Repeat(" ", 20)
+ out += wrapColor(hiblack, " ] ")
+ } else {
+ out += wrapColor(hiblack, " [ ")
+ out += strings.Repeat(" ", 20) + wrapRollingLowColor(seq, " <-- ") + mid
+ out += wrapRollingLowColor(seq, " ] ")
+ }
+
+ out += fmt.Sprintf("%"+fmt.Sprintf("%d", e.longestName)+"s", destName)
+ if testing.Verbose() {
+ fmt.Printf("%s\n", out)
+ }
+}
+
+func wrapRollingLowColor(color int, s string) (out string) {
+ return wrapColor(lowColors[color%len(lowColors)], s)
+}
+
+func wrapRollingColor(color int, s string) (out string) {
+ return wrapColor(colors[color%len(colors)], s)
+}
+func wrapColor(color int, s string) (out string) {
+ return fmt.Sprintf("%s[1;%dm%s%s[1;%dm", escape, color, s, escape, reset)
+}
diff --git a/txnsync/emulatorNode_test.go b/txnsync/emulatorNode_test.go
new file mode 100644
index 000000000..27bb75115
--- /dev/null
+++ b/txnsync/emulatorNode_test.go
@@ -0,0 +1,393 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "errors"
+ "fmt"
+ "sort"
+ "sync"
+ "sync/atomic"
+ "testing"
+ "time"
+
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/util/timers"
+)
+
+type queuedSentMessageCallback struct {
+ callback SendMessageCallback
+ seq uint64
+}
+type queuedMessage struct {
+ bytes []byte
+ readyAt time.Duration
+}
+type networkPeer struct {
+ peer *Peer
+ uploadSpeed uint64
+ downloadSpeed uint64
+ isOutgoing bool
+ outSeq uint64
+ inSeq uint64
+ target int
+
+ messageQ []queuedMessage // incoming message queue
+
+ mu sync.Mutex `algofix:"allow sync.Mutex"`
+
+ deferredSentMessages []queuedSentMessageCallback // outgoing messages callback queue
+}
+
+// emulatedNode implements the NodeConnector interface
+type emulatedNode struct {
+ externalEvents chan Event
+ emulator *emulator
+ peers map[int]*networkPeer
+ nodeIndex int
+ expiredTx []pooldata.SignedTxGroup
+ txpoolEntries []pooldata.SignedTxGroup
+ txpoolIds map[transactions.Txid]bool
+ latestLocallyOriginatedGroupCounter uint64
+ name string
+ blocked chan struct{}
+ mu sync.Mutex `algofix:"allow sync.Mutex"`
+ txpoolGroupCounter uint64
+ blockingEnabled bool
+ nodeBlocked chan struct{} // channel is closed when node is blocked.
+ nodeRunning chan struct{} // channel is closed when node is running.
+}
+
+func makeEmulatedNode(emulator *emulator, nodeIdx int) *emulatedNode {
+ en := &emulatedNode{
+ emulator: emulator,
+ peers: make(map[int]*networkPeer),
+ externalEvents: make(chan Event, 10000),
+ nodeIndex: nodeIdx,
+ txpoolIds: make(map[transactions.Txid]bool),
+ name: emulator.scenario.netConfig.nodes[nodeIdx].name,
+ blockingEnabled: true,
+ nodeBlocked: make(chan struct{}, 1),
+ nodeRunning: make(chan struct{}, 1),
+ }
+ close(en.nodeRunning)
+
+ // add outgoing connections
+ for _, conn := range emulator.scenario.netConfig.nodes[nodeIdx].outgoingConnections {
+ en.peers[conn.target] = &networkPeer{
+ uploadSpeed: conn.uploadSpeed,
+ downloadSpeed: conn.downloadSpeed,
+ isOutgoing: true,
+ target: conn.target,
+ }
+ }
+ // add incoming connections
+ for nodeID, nodeConfig := range emulator.scenario.netConfig.nodes {
+ if nodeID == nodeIdx {
+ continue
+ }
+ for _, conn := range nodeConfig.outgoingConnections {
+ if conn.target != nodeIdx {
+ continue
+ }
+ // the upload & download speeds are in reverse. This isn't a bug since we want the incoming
+ // connection to be the opposite side of the connection.
+ en.peers[nodeID] = &networkPeer{
+ uploadSpeed: conn.downloadSpeed,
+ downloadSpeed: conn.uploadSpeed,
+ isOutgoing: false,
+ target: nodeID,
+ }
+ }
+ }
+ return en
+}
+
+func (n *emulatedNode) Events() <-chan Event {
+ return n.externalEvents
+}
+
+func (n *emulatedNode) NotifyMonitor() chan struct{} {
+ var c chan struct{}
+ n.mu.Lock()
+ if n.blockingEnabled {
+ c = make(chan struct{})
+ n.blocked = c
+ close(n.nodeBlocked)
+ n.nodeRunning = make(chan struct{}, 1)
+ n.mu.Unlock()
+ <-c
+ n.mu.Lock()
+ close(n.nodeRunning)
+ n.nodeBlocked = make(chan struct{}, 1)
+ n.mu.Unlock()
+ // return a closed channel.
+ return c
+ }
+ n.mu.Unlock()
+ // return an open channel
+ return make(chan struct{})
+}
+func (n *emulatedNode) disableBlocking() {
+ n.mu.Lock()
+ n.blockingEnabled = false
+ n.mu.Unlock()
+ n.unblock()
+}
+func (n *emulatedNode) unblock() {
+ n.mu.Lock()
+ // wait until the state changes to StateMachineRunning
+ select {
+ case <-n.nodeBlocked:
+ // we're blocked.
+ if n.blocked != nil {
+ close(n.blocked)
+ n.blocked = nil
+ }
+ runningCh := n.nodeRunning
+ n.mu.Unlock()
+ <-runningCh
+ return
+ default:
+ }
+ n.mu.Unlock()
+}
+
+func (n *emulatedNode) waitBlocked() {
+ n.mu.Lock()
+ select {
+ case <-n.nodeRunning:
+ blockedCh := n.nodeBlocked
+ n.mu.Unlock()
+ <-blockedCh
+ return
+ default:
+ }
+ n.mu.Unlock()
+}
+
+func (n *emulatedNode) GetCurrentRoundSettings() RoundSettings {
+ return RoundSettings{
+ Round: n.emulator.currentRound,
+ FetchTransactions: true,
+ }
+
+}
+func (n *emulatedNode) Clock() timers.WallClock {
+ return n.emulator.clock.Zero().(timers.WallClock)
+}
+
+func (n *emulatedNode) Random(x uint64) (out uint64) {
+ limit := x
+ x += uint64(n.nodeIndex) * 997
+ x += uint64(n.emulator.currentRound) * 797
+ x += uint64(n.emulator.lastRandom) * 797
+ bytes := make([]byte, 8)
+ for i := 0; i < 8; i++ {
+ bytes[i] = byte(x >> (i * 8))
+ }
+ digest := crypto.Hash(bytes)
+ out = 0
+ for i := 0; i < 8; i++ {
+ out = out << 8
+ out += uint64(digest[i])
+ }
+ out = out % limit
+ n.emulator.lastRandom ^= out
+ return out
+}
+
+func (n *emulatedNode) orderedPeers() (out []*networkPeer) {
+ peerToIndex := make(map[*networkPeer]int)
+ for idx, peer := range n.peers {
+ out = append(out, peer)
+ peerToIndex[peer] = idx
+ }
+ // sort the peers, which we need in order to make the test deterministic.
+ sort.Slice(out, func(i, j int) bool {
+ netPeer1 := out[i]
+ netPeer2 := out[j]
+ return peerToIndex[netPeer1] < peerToIndex[netPeer2]
+ })
+ return
+}
+
+func (n *emulatedNode) GetPeers() (out []PeerInfo) {
+ for _, peer := range n.orderedPeers() {
+ out = append(out, PeerInfo{TxnSyncPeer: peer.peer, NetworkPeer: peer, IsOutgoing: peer.isOutgoing})
+ }
+ return out
+}
+
+func (n *emulatedNode) GetPeer(p interface{}) PeerInfo {
+ netPeer := p.(*networkPeer)
+ return PeerInfo{
+ TxnSyncPeer: netPeer.peer,
+ IsOutgoing: netPeer.isOutgoing,
+ NetworkPeer: p,
+ }
+}
+
+func (n *emulatedNode) UpdatePeers(txPeers []*Peer, netPeers []interface{}, _ uint64) {
+ for i, peer := range netPeers {
+ netPeer := peer.(*networkPeer)
+ netPeer.peer = txPeers[i]
+ }
+}
+
+func (n *emulatedNode) enqueueMessage(from int, msg queuedMessage) {
+ n.peers[from].mu.Lock()
+ baseTime := n.emulator.clock.Since()
+ if len(n.peers[from].messageQ) > 0 {
+ if n.peers[from].messageQ[len(n.peers[from].messageQ)-1].readyAt > baseTime {
+ baseTime = n.peers[from].messageQ[len(n.peers[from].messageQ)-1].readyAt
+ }
+ }
+ // the message bytes need to be copied, so that the originating bytes could be safely deleted.
+ msgBytes := make([]byte, len(msg.bytes))
+ copy(msgBytes[:], msg.bytes[:])
+ n.peers[from].messageQ = append(n.peers[from].messageQ, queuedMessage{bytes: msgBytes, readyAt: baseTime + msg.readyAt})
+ n.peers[from].mu.Unlock()
+}
+
+func (n *emulatedNode) SendPeerMessage(netPeer interface{}, msg []byte, callback SendMessageCallback) {
+ peer := netPeer.(*networkPeer)
+ otherNode := n.emulator.nodes[peer.target]
+ sendTime := time.Duration(len(msg)) * time.Second / time.Duration(peer.uploadSpeed)
+ otherNode.enqueueMessage(n.nodeIndex, queuedMessage{bytes: msg, readyAt: sendTime})
+
+ peer.deferredSentMessages = append(peer.deferredSentMessages, queuedSentMessageCallback{callback: callback, seq: peer.outSeq})
+ peer.outSeq++
+}
+
+func (n *emulatedNode) GetPendingTransactionGroups() ([]pooldata.SignedTxGroup, uint64) {
+ return n.txpoolEntries, n.latestLocallyOriginatedGroupCounter
+}
+
+func (n *emulatedNode) IncomingTransactionGroups(peer *Peer, messageSeq uint64, txGroups []pooldata.SignedTxGroup) (transactionPoolSize int) {
+ // add to transaction pool.
+ duplicateMessage := 0
+ duplicateMessageSize := 0
+ encodingBuf := protocol.GetEncodingBuf()
+ transactionPoolSize = len(n.txpoolEntries)
+ for _, group := range txGroups {
+ if group.Transactions[0].Txn.LastValid < n.emulator.currentRound {
+ continue
+ }
+ txID := group.Transactions[0].ID()
+ if n.txpoolIds[txID] {
+ duplicateMessage++
+ duplicateMessageSize += len(group.Transactions[0].Txn.Note)
+ continue
+ }
+ n.txpoolIds[txID] = true
+ group.GroupCounter = n.txpoolGroupCounter
+ n.txpoolGroupCounter++
+ group.GroupTransactionID = group.Transactions.ID()
+ for _, txn := range group.Transactions {
+ encodingBuf = encodingBuf[:0]
+ group.EncodedLength += len(txn.MarshalMsg(encodingBuf))
+ }
+ n.txpoolEntries = append(n.txpoolEntries, group)
+ }
+ protocol.PutEncodingBuf(encodingBuf)
+ if duplicateMessage > 0 && testing.Verbose() {
+ fmt.Printf("%s : %d duplicate messages recieved\n", n.name, duplicateMessage)
+ }
+ atomic.AddUint64(&n.emulator.totalDuplicateTransactions, uint64(duplicateMessage))
+ atomic.AddUint64(&n.emulator.totalDuplicateTransactionSize, uint64(duplicateMessageSize))
+ select {
+ case peer.GetTransactionPoolAckChannel() <- messageSeq:
+ default:
+ panic(errors.New("IncomingTransactionGroups was unable to write messageSeq to the ack channel"))
+ }
+ return
+}
+
+func (n *emulatedNode) step() {
+ msgHandler := n.emulator.syncers[n.nodeIndex].GetIncomingMessageHandler()
+ now := n.emulator.clock.Since()
+ // check if we have any pending network messages and forward them.
+
+ for _, peer := range n.orderedPeers() {
+ peer.mu.Lock()
+
+ for i := len(peer.deferredSentMessages); i > 0; i-- {
+ dm := peer.deferredSentMessages[0]
+ peer.deferredSentMessages = peer.deferredSentMessages[1:]
+ peer.mu.Unlock()
+ err := dm.callback(true, dm.seq)
+ if err != nil {
+ panic(err)
+ }
+ n.unblock()
+ n.waitBlocked()
+ peer.mu.Lock()
+ }
+
+ for i := len(peer.messageQ); i > 0; i-- {
+ if peer.messageQ[0].readyAt > now {
+ break
+ }
+
+ msgBytes := peer.messageQ[0].bytes
+ msgInSeq := peer.inSeq
+
+ peer.inSeq++
+ peer.messageQ = peer.messageQ[1:]
+
+ peer.mu.Unlock()
+
+ msgHandler(peer, peer.peer, msgBytes, msgInSeq)
+ n.unblock()
+ n.waitBlocked()
+ peer.mu.Lock()
+
+ }
+ peer.mu.Unlock()
+ }
+
+}
+func (n *emulatedNode) onNewRound(round basics.Round, hasParticipationKeys bool) {
+ // if this is a relay, then we always want to fetch transactions, regardless if we have participation keys.
+ fetchTransactions := hasParticipationKeys
+ if n.emulator.scenario.netConfig.nodes[n.nodeIndex].isRelay {
+ fetchTransactions = true
+ }
+
+ for i := len(n.txpoolEntries) - 1; i >= 0; i-- {
+ if n.txpoolEntries[i].Transactions[0].Txn.LastValid < round {
+ delete(n.txpoolIds, n.txpoolEntries[i].Transactions[0].ID())
+ n.expiredTx = append(n.expiredTx, n.txpoolEntries[i])
+ n.txpoolEntries = append(n.txpoolEntries[0:i], n.txpoolEntries[i+1:]...)
+ }
+ }
+
+ n.externalEvents <- MakeNewRoundEvent(round, fetchTransactions)
+}
+
+func (n *emulatedNode) onNewTransactionPoolEntry() {
+ n.externalEvents <- MakeTransactionPoolChangeEvent(len(n.txpoolEntries), false)
+}
+
+func (p *networkPeer) GetAddress() string {
+ return fmt.Sprintf("%d", p.target)
+}
diff --git a/txnsync/emulatorTimer_test.go b/txnsync/emulatorTimer_test.go
new file mode 100644
index 000000000..f6d0dc57b
--- /dev/null
+++ b/txnsync/emulatorTimer_test.go
@@ -0,0 +1,122 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "sort"
+ "sync"
+ "time"
+
+ "github.com/algorand/go-algorand/util/timers"
+)
+
+// guidedClock implements the WallClock interface
+type guidedClock struct {
+ sync.Mutex `algofix:"allow sync.Mutex"`
+ zero time.Time
+ adv time.Duration
+ timers map[time.Duration]chan time.Time
+ children []*guidedClock
+}
+
+func makeGuidedClock() *guidedClock {
+ return &guidedClock{
+ zero: time.Now(),
+ }
+}
+func (g *guidedClock) Zero() timers.Clock {
+ // the real monotonic clock doesn't return the same clock object, which is fine.. but for our testing
+ // we want to keep the same clock object so that we can tweak with it.
+ child := &guidedClock{
+ zero: g.zero.Add(g.adv),
+ }
+ g.Lock()
+ defer g.Unlock()
+ g.children = append(g.children, child)
+ return child
+}
+
+func (g *guidedClock) TimeoutAt(delta time.Duration) <-chan time.Time {
+ if delta <= g.adv {
+ c := make(chan time.Time, 1)
+ close(c)
+ return c
+ }
+ g.Lock()
+ defer g.Unlock()
+ if g.timers == nil {
+ g.timers = make(map[time.Duration]chan time.Time)
+ }
+ c, has := g.timers[delta]
+ if has {
+ return c
+ }
+ c = make(chan time.Time, 1)
+ g.timers[delta] = c
+ return c
+}
+
+func (g *guidedClock) Encode() []byte {
+ return []byte{}
+}
+func (g *guidedClock) Decode([]byte) (timers.Clock, error) {
+ return &guidedClock{}, nil
+}
+
+func (g *guidedClock) Since() time.Duration {
+ return g.adv
+}
+
+func (g *guidedClock) DeadlineMonitorAt(at time.Duration) timers.DeadlineMonitor {
+ return timers.MakeMonotonicDeadlineMonitor(g, at)
+}
+
+func (g *guidedClock) Advance(adv time.Duration) {
+ g.adv += adv
+
+ type entryStruct struct {
+ duration time.Duration
+ ch chan time.Time
+ }
+ expiredClocks := []entryStruct{}
+ g.Lock()
+ // find all the expired clocks.
+ for delta, ch := range g.timers {
+ if delta < g.adv {
+ expiredClocks = append(expiredClocks, entryStruct{delta, ch})
+ }
+ }
+ sort.SliceStable(expiredClocks, func(i, j int) bool {
+ return expiredClocks[i].duration < expiredClocks[j].duration
+ })
+
+ // remove from map
+ for _, entry := range expiredClocks {
+ delete(g.timers, entry.duration)
+ }
+ g.Unlock()
+ // fire expired clocks
+ for _, entry := range expiredClocks {
+ entry.ch <- g.zero.Add(g.adv)
+ close(entry.ch)
+ }
+ g.Lock()
+ defer g.Unlock()
+ for _, child := range g.children {
+ child.Advance(adv)
+ }
+}
diff --git a/txnsync/emulator_test.go b/txnsync/emulator_test.go
new file mode 100644
index 000000000..18a4633b4
--- /dev/null
+++ b/txnsync/emulator_test.go
@@ -0,0 +1,781 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/test/partitiontest"
+)
+
+type connectionSettings struct {
+ uploadSpeed uint64 // measured in bytes/second
+ downloadSpeed uint64 // measured in bytes/second
+ target int // node index in the networkConfiguration
+}
+
+type nodeConfiguration struct {
+ outgoingConnections []connectionSettings
+ name string
+ isRelay bool
+}
+
+// networkConfiguration defines the nodes setup and their connections.
+type networkConfiguration struct {
+ nodes []nodeConfiguration
+}
+
+// initialTransactionsAllocation defines how many transaction ( and what their sizes ) would be.
+type initialTransactionsAllocation struct {
+ node int // node index in the networkConfiguration
+ transactionsCount int
+ transactionSize int
+ expirationRound basics.Round
+}
+
+// scenario defines the emulator test scenario, which includes the network configuration,
+// initial transaction distribution, test duration, dynamic transactions creation as well
+// as expected test outcomes.
+type scenario struct {
+ netConfig networkConfiguration
+ testDuration time.Duration
+ step time.Duration
+ initialAlloc []initialTransactionsAllocation
+ expectedResults emulatorResult
+}
+
+func TestEmulatedTrivialTransactionsExchange(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ testScenario := scenario{
+ netConfig: networkConfiguration{
+ nodes: []nodeConfiguration{
+ {
+ name: "relay",
+ isRelay: true,
+ },
+ {
+ name: "node",
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ },
+ },
+ },
+ },
+ testDuration: 500 * time.Millisecond,
+ initialAlloc: []initialTransactionsAllocation{
+ {
+ node: 1,
+ transactionsCount: 1,
+ transactionSize: 250,
+ expirationRound: basics.Round(5),
+ },
+ },
+ expectedResults: emulatorResult{
+ nodes: []nodeTransactions{
+ {
+ nodeTransaction{
+ expirationRound: 5,
+ transactionSize: 250,
+ },
+ },
+ {
+ nodeTransaction{
+ expirationRound: 5,
+ transactionSize: 250,
+ },
+ },
+ },
+ },
+ step: 1 * time.Millisecond,
+ }
+ t.Run("NonRelay_To_Relay", func(t *testing.T) {
+ testScenario.netConfig.nodes[0].name = "relay"
+ testScenario.netConfig.nodes[0].isRelay = true
+ testScenario.netConfig.nodes[1].name = "node"
+ testScenario.initialAlloc[0].node = 1
+ emulateScenario(t, testScenario)
+ })
+ t.Run("Relay_To_NonRelay", func(t *testing.T) {
+ testScenario.netConfig.nodes[0].name = "relay"
+ testScenario.netConfig.nodes[0].isRelay = true
+ testScenario.netConfig.nodes[1].name = "node"
+ testScenario.initialAlloc[0].node = 0
+ emulateScenario(t, testScenario)
+ })
+ t.Run("OutgoingRelay_To_IncomingRelay", func(t *testing.T) {
+ testScenario.netConfig.nodes[0].name = "incoming-relay"
+ testScenario.netConfig.nodes[0].isRelay = true
+ testScenario.netConfig.nodes[1].name = "outgoing-relay"
+ testScenario.netConfig.nodes[1].isRelay = true
+ testScenario.initialAlloc[0].node = 1
+ emulateScenario(t, testScenario)
+ })
+ t.Run("IncomingRelay_To_OutgoingRelay", func(t *testing.T) {
+ testScenario.netConfig.nodes[0].name = "incoming-relay"
+ testScenario.netConfig.nodes[0].isRelay = true
+ testScenario.netConfig.nodes[1].name = "outgoing-relay"
+ testScenario.netConfig.nodes[1].isRelay = true
+ testScenario.initialAlloc[0].node = 0
+ emulateScenario(t, testScenario)
+ })
+}
+
+func TestEmulatedTwoNodesToRelaysTransactionsExchange(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ // this test creates the following network mode:
+ //
+ // relay1 ----------> relay2
+ // ^ ^
+ // | |
+ // node1 node2
+ //
+
+ testScenario := scenario{
+ netConfig: networkConfiguration{
+ nodes: []nodeConfiguration{
+ {
+ name: "relay1",
+ isRelay: true,
+ },
+ {
+ name: "relay2",
+ isRelay: true,
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ },
+ },
+ {
+ name: "node1",
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ },
+ },
+ {
+ name: "node2",
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 1,
+ },
+ },
+ },
+ },
+ },
+ testDuration: 1000 * time.Millisecond,
+ initialAlloc: []initialTransactionsAllocation{
+ {
+ node: 2,
+ transactionsCount: 1,
+ transactionSize: 250,
+ expirationRound: basics.Round(5),
+ },
+ },
+ expectedResults: emulatorResult{
+ nodes: []nodeTransactions{
+ {
+ nodeTransaction{
+ expirationRound: 5,
+ transactionSize: 250,
+ },
+ },
+ {
+ nodeTransaction{
+ expirationRound: 5,
+ transactionSize: 250,
+ },
+ },
+ {
+ nodeTransaction{
+ expirationRound: 5,
+ transactionSize: 250,
+ },
+ },
+ {
+ nodeTransaction{
+ expirationRound: 5,
+ transactionSize: 250,
+ },
+ },
+ },
+ },
+ step: 1 * time.Millisecond,
+ }
+ emulateScenario(t, testScenario)
+}
+
+func TestEmulatedLargeSetTransactionsExchange(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ testScenario := scenario{
+ netConfig: networkConfiguration{
+ nodes: []nodeConfiguration{
+ {
+ name: "relay",
+ isRelay: true,
+ },
+ {
+ name: "node",
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ },
+ },
+ },
+ },
+ testDuration: 1000 * time.Millisecond,
+ initialAlloc: []initialTransactionsAllocation{
+ {
+ node: 1,
+ transactionsCount: 100,
+ transactionSize: 800,
+ expirationRound: basics.Round(5),
+ },
+ },
+ expectedResults: emulatorResult{
+ nodes: []nodeTransactions{
+ {},
+ {},
+ },
+ },
+ step: 1 * time.Millisecond / 10,
+ }
+ // update the expected results to have the correct number of entries.
+ for i := 0; i < testScenario.initialAlloc[0].transactionsCount; i++ {
+ for n := range testScenario.expectedResults.nodes {
+ testScenario.expectedResults.nodes[n] = append(testScenario.expectedResults.nodes[n], nodeTransaction{expirationRound: testScenario.initialAlloc[0].expirationRound, transactionSize: testScenario.initialAlloc[0].transactionSize})
+ }
+ }
+
+ t.Run("NonRelay_To_Relay", func(t *testing.T) {
+ testScenario.netConfig.nodes[0].name = "relay"
+ testScenario.netConfig.nodes[0].isRelay = true
+ testScenario.netConfig.nodes[1].name = "node"
+ testScenario.initialAlloc[0].node = 1
+ emulateScenario(t, testScenario)
+ })
+
+ t.Run("Relay_To_NonRelay", func(t *testing.T) {
+ testScenario.netConfig.nodes[0].name = "relay"
+ testScenario.netConfig.nodes[0].isRelay = true
+ testScenario.netConfig.nodes[1].name = "node"
+ testScenario.initialAlloc[0].node = 0
+ emulateScenario(t, testScenario)
+ })
+
+ t.Run("OutgoingRelay_To_IncomingRelay", func(t *testing.T) {
+ testScenario.netConfig.nodes[0].name = "incoming-relay"
+ testScenario.netConfig.nodes[0].isRelay = true
+ testScenario.netConfig.nodes[1].name = "outgoing-relay"
+ testScenario.netConfig.nodes[1].isRelay = true
+ testScenario.initialAlloc[0].node = 1
+ emulateScenario(t, testScenario)
+ })
+
+ t.Run("OutgoingRelay_To_IncomingRelay", func(t *testing.T) {
+ testScenario.netConfig.nodes[0].name = "incoming-relay"
+ testScenario.netConfig.nodes[0].isRelay = true
+ testScenario.netConfig.nodes[1].name = "outgoing-relay"
+ testScenario.netConfig.nodes[1].isRelay = true
+ testScenario.initialAlloc[0].node = 0
+ emulateScenario(t, testScenario)
+ })
+}
+
+func TestEmulatedLargeSetTransactionsExchangeIntermixed(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ testScenario := scenario{
+ netConfig: networkConfiguration{
+ nodes: []nodeConfiguration{
+ {
+ name: "relay",
+ isRelay: true,
+ },
+ {
+ name: "node",
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ },
+ },
+ },
+ },
+ initialAlloc: []initialTransactionsAllocation{
+ {
+ node: 0,
+ transactionsCount: 200,
+ transactionSize: 400,
+ expirationRound: basics.Round(5),
+ },
+ {
+ node: 1,
+ transactionsCount: 100,
+ transactionSize: 800,
+ expirationRound: basics.Round(5),
+ },
+ },
+ expectedResults: emulatorResult{
+ nodes: []nodeTransactions{
+ {},
+ {},
+ },
+ },
+ step: 1 * time.Millisecond / 10,
+ testDuration: 1200 * time.Millisecond,
+ }
+ // update the expected results to have the correct number of entries.
+ for j := range testScenario.initialAlloc {
+ for i := 0; i < testScenario.initialAlloc[j].transactionsCount; i++ {
+ for n := range testScenario.expectedResults.nodes {
+ testScenario.expectedResults.nodes[n] = append(testScenario.expectedResults.nodes[n], nodeTransaction{expirationRound: testScenario.initialAlloc[j].expirationRound, transactionSize: testScenario.initialAlloc[j].transactionSize})
+ }
+ }
+ }
+
+ t.Run("NonRelay_To_Relay", func(t *testing.T) {
+ testScenario.netConfig.nodes[0].name = "relay"
+ testScenario.netConfig.nodes[0].isRelay = true
+ testScenario.netConfig.nodes[1].name = "node"
+ testScenario.initialAlloc[0].node = 1
+ emulateScenario(t, testScenario)
+ })
+
+ t.Run("Relay_To_NonRelay", func(t *testing.T) {
+ testScenario.netConfig.nodes[0].name = "relay"
+ testScenario.netConfig.nodes[0].isRelay = true
+ testScenario.netConfig.nodes[1].name = "node"
+ testScenario.initialAlloc[0].node = 0
+ emulateScenario(t, testScenario)
+ })
+
+ t.Run("OutgoingRelay_To_IncomingRelay", func(t *testing.T) {
+ testScenario.netConfig.nodes[0].name = "incoming-relay"
+ testScenario.netConfig.nodes[0].isRelay = true
+ testScenario.netConfig.nodes[1].name = "outgoing-relay"
+ testScenario.netConfig.nodes[1].isRelay = true
+ testScenario.initialAlloc[0].node = 1
+ emulateScenario(t, testScenario)
+ })
+
+ t.Run("IncomingRelay_To_OutgoingRelay", func(t *testing.T) {
+ testScenario.netConfig.nodes[0].name = "incoming-relay"
+ testScenario.netConfig.nodes[0].isRelay = true
+ testScenario.netConfig.nodes[1].name = "outgoing-relay"
+ testScenario.netConfig.nodes[1].isRelay = true
+ testScenario.initialAlloc[0].node = 0
+ emulateScenario(t, testScenario)
+ })
+}
+
+func TestEmulatedNonRelayToMultipleRelays(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ testScenario := scenario{
+ netConfig: networkConfiguration{
+ nodes: []nodeConfiguration{
+ {
+ name: "relay-1",
+ isRelay: true,
+ },
+ {
+ name: "relay-2",
+ isRelay: true,
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ },
+ },
+ {
+ name: "relay-3",
+ isRelay: true,
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 1,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ },
+ },
+ {
+ name: "node-1",
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 1,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 2,
+ },
+ },
+ },
+ {
+ name: "node-2",
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 2,
+ },
+ },
+ },
+ },
+ },
+ initialAlloc: []initialTransactionsAllocation{
+ {
+ node: 4, // i.e. node-2
+ transactionsCount: 1000,
+ transactionSize: 250,
+ expirationRound: basics.Round(5),
+ },
+ },
+ expectedResults: emulatorResult{
+ nodes: []nodeTransactions{
+ {},
+ {},
+ {},
+ {},
+ {},
+ },
+ },
+ step: 1 * time.Millisecond / 10,
+ testDuration: 2000 * time.Millisecond,
+ }
+ // update the expected results to have the correct number of entries.
+ for j := range testScenario.initialAlloc {
+ for i := 0; i < testScenario.initialAlloc[j].transactionsCount; i++ {
+ for n := range testScenario.expectedResults.nodes {
+ testScenario.expectedResults.nodes[n] = append(testScenario.expectedResults.nodes[n], nodeTransaction{expirationRound: testScenario.initialAlloc[j].expirationRound, transactionSize: testScenario.initialAlloc[j].transactionSize})
+ }
+ }
+ }
+
+ emulateScenario(t, testScenario)
+}
+
+func TestEmulatedTwoNodesFourRelays(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ testScenario := scenario{
+ netConfig: networkConfiguration{
+ nodes: []nodeConfiguration{
+ {
+ name: "relay-1",
+ isRelay: true,
+ },
+ {
+ name: "relay-2",
+ isRelay: true,
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 3,
+ },
+ },
+ },
+ {
+ name: "relay-3",
+ isRelay: true,
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 1,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ },
+ },
+ {
+ name: "relay-4",
+ isRelay: true,
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 2,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ },
+ },
+ {
+ name: "node-1",
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 1,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 2,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 3,
+ },
+ },
+ },
+ {
+ name: "node-2",
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 1,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 2,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 3,
+ },
+ },
+ },
+ },
+ },
+ initialAlloc: []initialTransactionsAllocation{
+ {
+ node: 4, // i.e. node-1
+ transactionsCount: 3000,
+ transactionSize: 270,
+ expirationRound: basics.Round(5),
+ },
+ {
+ node: 5, // i.e. node-2
+ transactionsCount: 1500,
+ transactionSize: 320,
+ expirationRound: basics.Round(5),
+ },
+ },
+ expectedResults: emulatorResult{
+ nodes: []nodeTransactions{
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ },
+ },
+ step: 1 * time.Millisecond / 10,
+ testDuration: 2100 * time.Millisecond,
+ }
+ // update the expected results to have the correct number of entries.
+ for j := range testScenario.initialAlloc {
+ for i := 0; i < testScenario.initialAlloc[j].transactionsCount; i++ {
+ for n := range testScenario.expectedResults.nodes {
+ testScenario.expectedResults.nodes[n] = append(testScenario.expectedResults.nodes[n], nodeTransaction{expirationRound: testScenario.initialAlloc[j].expirationRound, transactionSize: testScenario.initialAlloc[j].transactionSize})
+ }
+ }
+ }
+
+ emulateScenario(t, testScenario)
+}
+
+func TestEmulatedTwentyNodesFourRelays(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ if testing.Short() {
+ t.Skip("TestEmulatedTwentyNodesFourRelays is a long test and therefore was skipped")
+ }
+ testScenario := scenario{
+ netConfig: networkConfiguration{
+ nodes: []nodeConfiguration{
+ {
+ name: "relay-1",
+ isRelay: true,
+ },
+ {
+ name: "relay-2",
+ isRelay: true,
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 3,
+ },
+ },
+ },
+ {
+ name: "relay-3",
+ isRelay: true,
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 1,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ },
+ },
+ {
+ name: "relay-4",
+ isRelay: true,
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 2,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ },
+ },
+ },
+ },
+ initialAlloc: []initialTransactionsAllocation{},
+ expectedResults: emulatorResult{
+ nodes: []nodeTransactions{
+ {},
+ {},
+ {},
+ {},
+ },
+ },
+ step: 1 * time.Millisecond / 10,
+ testDuration: 2000 * time.Millisecond,
+ }
+
+ // add nodes.
+ for i := 0; i < 20; i++ {
+ testScenario.netConfig.nodes = append(testScenario.netConfig.nodes, nodeConfiguration{
+ name: fmt.Sprintf("node-%d", i+1),
+ outgoingConnections: []connectionSettings{
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 0,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 1,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 2,
+ },
+ {
+ uploadSpeed: 1000000,
+ downloadSpeed: 1000000,
+ target: 3,
+ },
+ },
+ })
+
+ testScenario.initialAlloc = append(testScenario.initialAlloc, initialTransactionsAllocation{
+ node: 4 + i, // i.e. node-1 + i
+ transactionsCount: 250,
+ transactionSize: 270,
+ expirationRound: basics.Round(5),
+ })
+
+ testScenario.expectedResults.nodes = append(testScenario.expectedResults.nodes, nodeTransactions{})
+ }
+
+ // update the expected results to have the correct number of entries.
+ for j := range testScenario.initialAlloc {
+ for i := 0; i < testScenario.initialAlloc[j].transactionsCount; i++ {
+ for n := range testScenario.expectedResults.nodes {
+ testScenario.expectedResults.nodes[n] = append(testScenario.expectedResults.nodes[n], nodeTransaction{expirationRound: testScenario.initialAlloc[j].expirationRound, transactionSize: testScenario.initialAlloc[j].transactionSize})
+ }
+ }
+ }
+
+ emulateScenario(t, testScenario)
+}
diff --git a/txnsync/encodedgroups_test.go b/txnsync/encodedgroups_test.go
new file mode 100644
index 000000000..0f6cef4f9
--- /dev/null
+++ b/txnsync/encodedgroups_test.go
@@ -0,0 +1,132 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "math"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/test/partitiontest"
+)
+
+func TestBadBitmask(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ txnGroups, genesisID, genesisHash, err := txnGroupsData(96)
+ require.NoError(t, err)
+
+ var s syncState
+ ptg, err := badEncodeTransactionGroups(t, &s, txnGroups, 0)
+ require.NoError(t, err)
+ require.Equal(t, ptg.CompressionFormat, compressionFormatDeflate)
+ _, err = decodeTransactionGroups(ptg, genesisID, genesisHash)
+ require.Equal(t, errIndexNotFound, err)
+}
+
+// corrupted bitmask may bcause panic during decoding. This test is to make sure it is an error and not a panic
+func badEncodeTransactionGroups(t *testing.T, s *syncState, inTxnGroups []pooldata.SignedTxGroup, dataExchangeRate uint64) (packedTransactionGroups, error) {
+ txnCount := 0
+ for _, txGroup := range inTxnGroups {
+ txnCount += len(txGroup.Transactions)
+ }
+ stub := txGroupsEncodingStub{
+ TotalTransactionsCount: uint64(txnCount),
+ TransactionGroupCount: uint64(len(inTxnGroups)),
+ TransactionGroupSizes: make([]byte, 0, len(inTxnGroups)),
+ }
+
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ index := 0
+ for _, txGroup := range inTxnGroups {
+ if len(txGroup.Transactions) > 1 {
+ for _, txn := range txGroup.Transactions {
+ err := stub.deconstructSignedTransaction(index, &txn)
+ require.NoError(t, err)
+ index++
+ }
+ stub.TransactionGroupSizes = append(stub.TransactionGroupSizes, byte(len(txGroup.Transactions)-1))
+ }
+ }
+ compactNibblesArray(&stub.TransactionGroupSizes)
+ for _, txGroup := range inTxnGroups {
+ if len(txGroup.Transactions) == 1 {
+ for _, txn := range txGroup.Transactions {
+ if !txn.Txn.Group.MsgIsZero() {
+ if len(stub.BitmaskGroup) == 0 {
+ stub.BitmaskGroup = make(bitmask, bitmaskLen)
+ }
+ stub.BitmaskGroup.setBit(index)
+ }
+ err := stub.deconstructSignedTransaction(index, &txn)
+ require.NoError(t, err)
+ index++
+ }
+ }
+ }
+
+ stub.BitmaskAuthAddr.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.finishDeconstructMsigs()
+ stub.finishDeconstructLsigs()
+ stub.BitmaskSig.trimBitmask(int(stub.TotalTransactionsCount))
+
+ stub.finishDeconstructTxType()
+ // corrupted bitmask
+ stub.BitmaskTxType = make(bitmask, bitmaskLen*10)
+ stub.BitmaskTxType.setBit(bitmaskLen*10 - 10)
+
+ stub.finishDeconstructTxnHeader()
+ stub.finishDeconstructKeyregTxnFields()
+ stub.finishDeconstructPaymentTxnFields()
+ stub.finishDeconstructAssetConfigTxnFields()
+ stub.finishDeconstructAssetTransferTxnFields()
+ stub.finishDeconstructAssetFreezeTxnFields()
+ stub.finishDeconstructApplicationCallTxnFields()
+ stub.finishDeconstructCompactCertTxnFields()
+
+ encoded := stub.MarshalMsg(getMessageBuffer())
+
+ // check if time saved by compression: estimatedDeflateCompressionGains * len(msg) / dataExchangeRate
+ // is greater than by time spent during compression: len(msg) / estimatedDeflateCompressionSpeed
+ if len(encoded) > minEncodedTransactionGroupsCompressionThreshold && float32(dataExchangeRate) < (estimatedDeflateCompressionGains*estimatedDeflateCompressionSpeed) {
+ compressedBytes, compressionFormat := s.compressTransactionGroupsBytes(encoded)
+ if compressionFormat != compressionFormatNone {
+ packedGroups := packedTransactionGroups{
+ Bytes: compressedBytes,
+ CompressionFormat: compressionFormat,
+ LenDecompressedBytes: uint64(len(encoded)),
+ }
+ releaseMessageBuffer(encoded)
+ return packedGroups, nil
+ }
+ }
+
+ return packedTransactionGroups{
+ Bytes: encoded,
+ CompressionFormat: compressionFormatNone,
+ }, nil
+}
+func TestInvalidByteToTxType(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ for i := len(protocol.TxnTypes); i <= math.MaxUint8; i++ {
+ require.Equal(t, protocol.UnknownTx, ByteToTxType(byte(i)))
+ }
+}
diff --git a/txnsync/encodedgroupsmarshalers.go b/txnsync/encodedgroupsmarshalers.go
new file mode 100644
index 000000000..583f9ede1
--- /dev/null
+++ b/txnsync/encodedgroupsmarshalers.go
@@ -0,0 +1,795 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "fmt"
+
+ "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/protocol"
+)
+
+func compactNibblesArray(b *[]byte) {
+ if len(*b)%2 == 1 {
+ *b = append(*b, byte(0))
+ }
+ for index := 0; index*2 < len(*b); index++ {
+ (*b)[index] = (*b)[index*2]*16 + (*b)[index*2+1]
+ }
+ *b = (*b)[0 : len(*b)/2]
+}
+
+// deconstructs SignedTxn's into lists of fields and bitmasks
+func (stub *txGroupsEncodingStub) deconstructSignedTransaction(i int, txn *transactions.SignedTxn) error {
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ if !txn.Sig.MsgIsZero() {
+ if len(stub.BitmaskSig) == 0 {
+ stub.BitmaskSig = make(bitmask, bitmaskLen)
+ stub.Sig = make([]byte, 0, int(stub.TotalTransactionsCount)*len(crypto.Signature{}))
+ }
+ stub.BitmaskSig.setBit(i)
+ stub.Sig = append(stub.Sig, txn.Sig[:]...)
+ }
+ stub.deconstructMsigs(i, txn)
+ stub.deconstructLsigs(i, txn)
+ if !txn.AuthAddr.MsgIsZero() {
+ if len(stub.BitmaskAuthAddr) == 0 {
+ stub.BitmaskAuthAddr = make(bitmask, bitmaskLen)
+ stub.AuthAddr = make([]byte, 0, int(stub.TotalTransactionsCount)*crypto.DigestSize)
+ }
+ stub.BitmaskAuthAddr.setBit(i)
+ stub.AuthAddr = append(stub.AuthAddr, txn.AuthAddr[:]...)
+ }
+ return stub.deconstructTransactions(i, txn)
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructSignedTransactions() {
+ stub.BitmaskAuthAddr.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.finishDeconstructMsigs()
+ stub.finishDeconstructLsigs()
+ stub.BitmaskSig.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.finishDeconstructTransactions()
+}
+
+func (stub *txGroupsEncodingStub) deconstructMsigs(i int, txn *transactions.SignedTxn) {
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ if txn.Msig.Version != 0 {
+ if len(stub.BitmaskVersion) == 0 {
+ stub.BitmaskVersion = make(bitmask, bitmaskLen)
+ stub.Version = make([]byte, 0, int(stub.TotalTransactionsCount))
+ }
+ stub.BitmaskVersion.setBit(i)
+ stub.Version = append(stub.Version, txn.Msig.Version)
+ }
+ if txn.Msig.Threshold != 0 {
+ if len(stub.BitmaskThreshold) == 0 {
+ stub.BitmaskThreshold = make(bitmask, bitmaskLen)
+ stub.Threshold = make([]byte, 0, int(stub.TotalTransactionsCount))
+ }
+ stub.BitmaskThreshold.setBit(i)
+ stub.Threshold = append(stub.Threshold, txn.Msig.Threshold)
+ }
+ if txn.Msig.Subsigs != nil {
+ if len(stub.BitmaskSubsigs) == 0 {
+ stub.BitmaskSubsigs = make(bitmask, bitmaskLen)
+ stub.Subsigs = make([][]crypto.MultisigSubsig, 0, int(stub.TotalTransactionsCount))
+ }
+ stub.BitmaskSubsigs.setBit(i)
+ stub.Subsigs = append(stub.Subsigs, txn.Msig.Subsigs)
+ }
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructMsigs() {
+ stub.BitmaskVersion.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskThreshold.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskSubsigs.trimBitmask(int(stub.TotalTransactionsCount))
+}
+
+func (stub *txGroupsEncodingStub) deconstructLsigs(i int, txn *transactions.SignedTxn) {
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ if txn.Lsig.Logic != nil {
+ if len(stub.BitmaskLogic) == 0 {
+ stub.BitmaskLogic = make(bitmask, bitmaskLen)
+ stub.Logic = make([][]byte, 0, int(stub.TotalTransactionsCount))
+ }
+ stub.BitmaskLogic.setBit(i)
+ stub.Logic = append(stub.Logic, txn.Lsig.Logic)
+ }
+ if txn.Lsig.Args != nil {
+ if len(stub.BitmaskLogicArgs) == 0 {
+ stub.BitmaskLogicArgs = make(bitmask, bitmaskLen)
+ stub.LogicArgs = make([][][]byte, 0, int(stub.TotalTransactionsCount))
+ }
+ stub.BitmaskLogicArgs.setBit(i)
+ stub.LogicArgs = append(stub.LogicArgs, txn.Lsig.Args)
+ }
+ if !txn.Lsig.Sig.MsgIsZero() {
+ if len(stub.BitmaskSig) == 0 {
+ stub.BitmaskSig = make(bitmask, bitmaskLen)
+ stub.Sig = make([]byte, 0, int(stub.TotalTransactionsCount)*len(crypto.Signature{}))
+ }
+ stub.BitmaskSig.setBit(i)
+ stub.Sig = append(stub.Sig, txn.Lsig.Sig[:]...)
+ }
+ if txn.Lsig.Msig.Version != 0 {
+ if len(stub.BitmaskVersion) == 0 {
+ stub.BitmaskVersion = make(bitmask, bitmaskLen)
+ stub.Version = make([]byte, 0, int(stub.TotalTransactionsCount))
+ }
+ stub.BitmaskVersion.setBit(i)
+ stub.Version = append(stub.Version, txn.Lsig.Msig.Version)
+ }
+ if txn.Lsig.Msig.Threshold != 0 {
+ if len(stub.BitmaskThreshold) == 0 {
+ stub.BitmaskThreshold = make(bitmask, bitmaskLen)
+ stub.Threshold = make([]byte, 0, int(stub.TotalTransactionsCount))
+ }
+ stub.BitmaskThreshold.setBit(i)
+ stub.Threshold = append(stub.Threshold, txn.Lsig.Msig.Threshold)
+ }
+ if txn.Lsig.Msig.Subsigs != nil {
+ if len(stub.BitmaskSubsigs) == 0 {
+ stub.BitmaskSubsigs = make(bitmask, bitmaskLen)
+ stub.Subsigs = make([][]crypto.MultisigSubsig, 0, int(stub.TotalTransactionsCount))
+ }
+ stub.BitmaskSubsigs.setBit(i)
+ stub.Subsigs = append(stub.Subsigs, txn.Lsig.Msig.Subsigs)
+ }
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructLsigs() {
+ stub.BitmaskLogic.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskLogicArgs.trimBitmask(int(stub.TotalTransactionsCount))
+}
+
+func (stub *txGroupsEncodingStub) deconstructTransactions(i int, txn *transactions.SignedTxn) error {
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ txTypeByte, err := TxTypeToByte(txn.Txn.Type)
+ if err != nil {
+ return fmt.Errorf("failed to deconstructTransactions: %w", err)
+ }
+ if len(stub.BitmaskTxType) == 0 {
+ stub.BitmaskTxType = make(bitmask, bitmaskLen)
+ stub.TxType = make([]byte, 0, int(stub.TotalTransactionsCount))
+ }
+ stub.TxType = append(stub.TxType, txTypeByte)
+ stub.deconstructTxnHeader(i, txn)
+ switch txTypeByte {
+ case paymentTx:
+ stub.deconstructPaymentTxnFields(i, txn)
+ case keyRegistrationTx:
+ stub.deconstructKeyregTxnFields(i, txn)
+ case assetConfigTx:
+ stub.deconstructAssetConfigTxnFields(i, txn)
+ case assetTransferTx:
+ stub.deconstructAssetTransferTxnFields(i, txn)
+ case assetFreezeTx:
+ stub.deconstructAssetFreezeTxnFields(i, txn)
+ case applicationCallTx:
+ stub.deconstructApplicationCallTxnFields(i, txn)
+ case compactCertTx:
+ stub.deconstructCompactCertTxnFields(i, txn)
+ }
+ return nil
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructTransactions() {
+ stub.finishDeconstructTxType()
+ stub.finishDeconstructTxnHeader()
+ stub.finishDeconstructKeyregTxnFields()
+ stub.finishDeconstructPaymentTxnFields()
+ stub.finishDeconstructAssetConfigTxnFields()
+ stub.finishDeconstructAssetTransferTxnFields()
+ stub.finishDeconstructAssetFreezeTxnFields()
+ stub.finishDeconstructApplicationCallTxnFields()
+ stub.finishDeconstructCompactCertTxnFields()
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructTxType() {
+ offset := byte(0)
+ count := make([]int, len(protocol.TxnTypes))
+ maxcount := 0
+ for _, t := range stub.TxType {
+ count[int(t)]++
+ }
+ for i, c := range count {
+ if c > maxcount {
+ offset = byte(i)
+ maxcount = c
+ }
+ }
+ newTxTypes := make([]byte, 0, stub.TotalTransactionsCount)
+ for i := 0; i < int(stub.TotalTransactionsCount); i++ {
+ if stub.TxType[i] != offset {
+ stub.BitmaskTxType.setBit(i)
+ newTxTypes = append(newTxTypes, stub.TxType[i])
+ }
+ }
+ stub.TxType = newTxTypes
+ stub.TxTypeOffset = offset
+ compactNibblesArray(&stub.TxType)
+ stub.BitmaskTxType.trimBitmask(int(stub.TotalTransactionsCount))
+}
+
+func (stub *txGroupsEncodingStub) deconstructTxnHeader(i int, txn *transactions.SignedTxn) {
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ if !txn.Txn.Sender.MsgIsZero() {
+ if len(stub.BitmaskSender) == 0 {
+ stub.BitmaskSender = make(bitmask, bitmaskLen)
+ stub.Sender = make([]byte, 0, int(stub.TotalTransactionsCount)*crypto.DigestSize)
+ }
+ stub.BitmaskSender.setBit(i)
+ stub.Sender = append(stub.Sender, txn.Txn.Sender[:]...)
+ }
+ if !txn.Txn.Fee.MsgIsZero() {
+ if len(stub.BitmaskFee) == 0 {
+ stub.BitmaskFee = make(bitmask, bitmaskLen)
+ stub.Fee = make([]basics.MicroAlgos, 0, int(stub.TotalTransactionsCount))
+ }
+ stub.BitmaskFee.setBit(i)
+ stub.Fee = append(stub.Fee, txn.Txn.Fee)
+ }
+ if !txn.Txn.FirstValid.MsgIsZero() {
+ if len(stub.BitmaskFirstValid) == 0 {
+ stub.BitmaskFirstValid = make(bitmask, bitmaskLen)
+ stub.FirstValid = make([]basics.Round, 0, int(stub.TotalTransactionsCount))
+ }
+ stub.BitmaskFirstValid.setBit(i)
+ stub.FirstValid = append(stub.FirstValid, txn.Txn.FirstValid)
+ }
+ if !txn.Txn.LastValid.MsgIsZero() {
+ if len(stub.BitmaskLastValid) == 0 {
+ stub.BitmaskLastValid = make(bitmask, bitmaskLen)
+ stub.LastValid = make([]basics.Round, 0, int(stub.TotalTransactionsCount))
+ }
+ stub.BitmaskLastValid.setBit(i)
+ stub.LastValid = append(stub.LastValid, txn.Txn.LastValid)
+ }
+ if txn.Txn.Note != nil {
+ if len(stub.BitmaskNote) == 0 {
+ stub.BitmaskNote = make(bitmask, bitmaskLen)
+ stub.Note = make([][]byte, 0, int(stub.TotalTransactionsCount))
+ }
+ stub.BitmaskNote.setBit(i)
+ stub.Note = append(stub.Note, txn.Txn.Note)
+ }
+ if txn.Txn.GenesisID != "" {
+ if len(stub.BitmaskGenesisID) == 0 {
+ stub.BitmaskGenesisID = make(bitmask, bitmaskLen)
+ }
+ stub.BitmaskGenesisID.setBit(i)
+ }
+ if txn.Txn.Lease != ([32]byte{}) {
+ if len(stub.BitmaskLease) == 0 {
+ stub.BitmaskLease = make(bitmask, bitmaskLen)
+ stub.Lease = make([]byte, 0, int(stub.TotalTransactionsCount)*transactions.LeaseByteLength)
+ }
+ stub.BitmaskLease.setBit(i)
+ stub.Lease = append(stub.Lease, txn.Txn.Lease[:]...)
+ }
+ if !txn.Txn.RekeyTo.MsgIsZero() {
+ if len(stub.BitmaskRekeyTo) == 0 {
+ stub.BitmaskRekeyTo = make(bitmask, bitmaskLen)
+ stub.RekeyTo = make([]byte, 0, int(stub.TotalTransactionsCount)*crypto.DigestSize)
+ }
+ stub.BitmaskRekeyTo.setBit(i)
+ stub.RekeyTo = append(stub.RekeyTo, txn.Txn.RekeyTo[:]...)
+ }
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructTxnHeader() {
+ stub.BitmaskSender.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskFee.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskFirstValid.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskLastValid.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskNote.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskGenesisID.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskGroup.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskLease.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskRekeyTo.trimBitmask(int(stub.TotalTransactionsCount))
+}
+
+func (stub *txGroupsEncodingStub) deconstructKeyregTxnFields(i int, txn *transactions.SignedTxn) {
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ if !txn.Txn.VotePK.MsgIsZero() || !txn.Txn.SelectionPK.MsgIsZero() || txn.Txn.VoteKeyDilution != 0 {
+ if len(stub.BitmaskKeys) == 0 {
+ stub.BitmaskKeys = make(bitmask, bitmaskLen)
+ stub.VotePK = make([]byte, 0, stub.TotalTransactionsCount*crypto.PublicKeyByteLength)
+ stub.SelectionPK = make([]byte, 0, stub.TotalTransactionsCount*crypto.VrfPubkeyByteLength)
+ stub.VoteKeyDilution = make([]uint64, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskKeys.setBit(i)
+ stub.VotePK = append(stub.VotePK, txn.Txn.VotePK[:]...)
+ stub.SelectionPK = append(stub.SelectionPK, txn.Txn.SelectionPK[:]...)
+ stub.VoteKeyDilution = append(stub.VoteKeyDilution, txn.Txn.VoteKeyDilution)
+ }
+ if !txn.Txn.VoteFirst.MsgIsZero() {
+ if len(stub.BitmaskVoteFirst) == 0 {
+ stub.BitmaskVoteFirst = make(bitmask, bitmaskLen)
+ stub.VoteFirst = make([]basics.Round, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskVoteFirst.setBit(i)
+ stub.VoteFirst = append(stub.VoteFirst, txn.Txn.VoteFirst)
+ }
+ if !txn.Txn.VoteLast.MsgIsZero() {
+ if len(stub.BitmaskVoteLast) == 0 {
+ stub.BitmaskVoteLast = make(bitmask, bitmaskLen)
+ stub.VoteLast = make([]basics.Round, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskVoteLast.setBit(i)
+ stub.VoteLast = append(stub.VoteLast, txn.Txn.VoteLast)
+ }
+ if txn.Txn.Nonparticipation {
+ if len(stub.BitmaskNonparticipation) == 0 {
+ stub.BitmaskNonparticipation = make(bitmask, bitmaskLen)
+ }
+ stub.BitmaskNonparticipation.setBit(i)
+ }
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructKeyregTxnFields() {
+ stub.BitmaskKeys.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskVoteFirst.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskVoteLast.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskNonparticipation.trimBitmask(int(stub.TotalTransactionsCount))
+}
+
+func (stub *txGroupsEncodingStub) deconstructPaymentTxnFields(i int, txn *transactions.SignedTxn) {
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ if !txn.Txn.Receiver.MsgIsZero() {
+ if len(stub.BitmaskReceiver) == 0 {
+ stub.BitmaskReceiver = make(bitmask, bitmaskLen)
+ stub.Receiver = make([]byte, 0, int(stub.TotalTransactionsCount)*crypto.DigestSize)
+ }
+ stub.BitmaskReceiver.setBit(i)
+ stub.Receiver = append(stub.Receiver, txn.Txn.Receiver[:]...)
+ }
+ if !txn.Txn.Amount.MsgIsZero() {
+ if len(stub.BitmaskAmount) == 0 {
+ stub.BitmaskAmount = make(bitmask, bitmaskLen)
+ stub.Amount = make([]basics.MicroAlgos, 0, int(stub.TotalTransactionsCount))
+ }
+ stub.BitmaskAmount.setBit(i)
+ stub.Amount = append(stub.Amount, txn.Txn.Amount)
+ }
+ if !txn.Txn.CloseRemainderTo.MsgIsZero() {
+ if len(stub.BitmaskCloseRemainderTo) == 0 {
+ stub.BitmaskCloseRemainderTo = make(bitmask, bitmaskLen)
+ stub.CloseRemainderTo = make([]byte, 0, int(stub.TotalTransactionsCount)*crypto.DigestSize)
+ }
+ stub.BitmaskCloseRemainderTo.setBit(i)
+ stub.CloseRemainderTo = append(stub.CloseRemainderTo, txn.Txn.CloseRemainderTo[:]...)
+ }
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructPaymentTxnFields() {
+ stub.BitmaskReceiver.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskAmount.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskCloseRemainderTo.trimBitmask(int(stub.TotalTransactionsCount))
+}
+
+func (stub *txGroupsEncodingStub) deconstructAssetConfigTxnFields(i int, txn *transactions.SignedTxn) {
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ if !txn.Txn.ConfigAsset.MsgIsZero() {
+ if len(stub.BitmaskConfigAsset) == 0 {
+ stub.BitmaskConfigAsset = make(bitmask, bitmaskLen)
+ stub.ConfigAsset = make([]basics.AssetIndex, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskConfigAsset.setBit(i)
+ stub.ConfigAsset = append(stub.ConfigAsset, txn.Txn.ConfigAsset)
+ }
+ stub.deconstructAssetParams(i, txn)
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructAssetConfigTxnFields() {
+ stub.BitmaskConfigAsset.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.finishDeconstructAssetParams()
+}
+
+func (stub *txGroupsEncodingStub) deconstructAssetParams(i int, txn *transactions.SignedTxn) {
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ if txn.Txn.AssetParams.Total != 0 {
+ if len(stub.BitmaskTotal) == 0 {
+ stub.BitmaskTotal = make(bitmask, bitmaskLen)
+ stub.Total = make([]uint64, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskTotal.setBit(i)
+ stub.Total = append(stub.Total, txn.Txn.AssetParams.Total)
+ }
+ if txn.Txn.AssetParams.Decimals != 0 {
+ if len(stub.BitmaskDecimals) == 0 {
+ stub.BitmaskDecimals = make(bitmask, bitmaskLen)
+ stub.Decimals = make([]uint32, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskDecimals.setBit(i)
+ stub.Decimals = append(stub.Decimals, txn.Txn.AssetParams.Decimals)
+ }
+ if txn.Txn.AssetParams.DefaultFrozen {
+ if len(stub.BitmaskDefaultFrozen) == 0 {
+ stub.BitmaskDefaultFrozen = make(bitmask, bitmaskLen)
+ }
+ stub.BitmaskDefaultFrozen.setBit(i)
+ }
+ if txn.Txn.AssetParams.UnitName != "" {
+ if len(stub.BitmaskUnitName) == 0 {
+ stub.BitmaskUnitName = make(bitmask, bitmaskLen)
+ stub.UnitName = make([]string, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskUnitName.setBit(i)
+ stub.UnitName = append(stub.UnitName, txn.Txn.AssetParams.UnitName)
+ }
+ if txn.Txn.AssetParams.AssetName != "" {
+ if len(stub.BitmaskAssetName) == 0 {
+ stub.BitmaskAssetName = make(bitmask, bitmaskLen)
+ stub.AssetName = make([]string, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskAssetName.setBit(i)
+ stub.AssetName = append(stub.AssetName, txn.Txn.AssetParams.AssetName)
+ }
+ if txn.Txn.AssetParams.URL != "" {
+ if len(stub.BitmaskURL) == 0 {
+ stub.BitmaskURL = make(bitmask, bitmaskLen)
+ stub.URL = make([]string, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskURL.setBit(i)
+ stub.URL = append(stub.URL, txn.Txn.AssetParams.URL)
+ }
+ if txn.Txn.AssetParams.MetadataHash != [32]byte{} {
+ if len(stub.BitmaskMetadataHash) == 0 {
+ stub.BitmaskMetadataHash = make(bitmask, bitmaskLen)
+ stub.MetadataHash = make([]byte, 0, stub.TotalTransactionsCount*crypto.DigestSize)
+ }
+ stub.BitmaskMetadataHash.setBit(i)
+ stub.MetadataHash = append(stub.MetadataHash, txn.Txn.AssetParams.MetadataHash[:]...)
+ }
+ if !txn.Txn.AssetParams.Manager.MsgIsZero() {
+ if len(stub.BitmaskManager) == 0 {
+ stub.BitmaskManager = make(bitmask, bitmaskLen)
+ stub.Manager = make([]byte, 0, stub.TotalTransactionsCount*crypto.DigestSize)
+ }
+ stub.BitmaskManager.setBit(i)
+ stub.Manager = append(stub.Manager, txn.Txn.AssetParams.Manager[:]...)
+ }
+ if !txn.Txn.AssetParams.Reserve.MsgIsZero() {
+ if len(stub.BitmaskReserve) == 0 {
+ stub.BitmaskReserve = make(bitmask, bitmaskLen)
+ stub.Reserve = make([]byte, 0, stub.TotalTransactionsCount*crypto.DigestSize)
+ }
+ stub.BitmaskReserve.setBit(i)
+ stub.Reserve = append(stub.Reserve, txn.Txn.AssetParams.Reserve[:]...)
+ }
+ if !txn.Txn.AssetParams.Freeze.MsgIsZero() {
+ if len(stub.BitmaskFreeze) == 0 {
+ stub.BitmaskFreeze = make(bitmask, bitmaskLen)
+ stub.Freeze = make([]byte, 0, stub.TotalTransactionsCount*crypto.DigestSize)
+ }
+ stub.BitmaskFreeze.setBit(i)
+ stub.Freeze = append(stub.Freeze, txn.Txn.AssetParams.Freeze[:]...)
+ }
+ if !txn.Txn.AssetParams.Clawback.MsgIsZero() {
+ if len(stub.BitmaskClawback) == 0 {
+ stub.BitmaskClawback = make(bitmask, bitmaskLen)
+ stub.Clawback = make([]byte, 0, stub.TotalTransactionsCount*crypto.DigestSize)
+ }
+ stub.BitmaskClawback.setBit(i)
+ stub.Clawback = append(stub.Clawback, txn.Txn.AssetParams.Clawback[:]...)
+ }
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructAssetParams() {
+ stub.BitmaskTotal.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskDecimals.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskDefaultFrozen.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskUnitName.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskAssetName.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskURL.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskMetadataHash.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskManager.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskReserve.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskFreeze.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskClawback.trimBitmask(int(stub.TotalTransactionsCount))
+}
+
+func (stub *txGroupsEncodingStub) deconstructAssetTransferTxnFields(i int, txn *transactions.SignedTxn) {
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ if !txn.Txn.XferAsset.MsgIsZero() {
+ if len(stub.BitmaskXferAsset) == 0 {
+ stub.BitmaskXferAsset = make(bitmask, bitmaskLen)
+ stub.XferAsset = make([]basics.AssetIndex, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskXferAsset.setBit(i)
+ stub.XferAsset = append(stub.XferAsset, txn.Txn.XferAsset)
+ }
+ if txn.Txn.AssetAmount != 0 {
+ if len(stub.BitmaskAssetAmount) == 0 {
+ stub.BitmaskAssetAmount = make(bitmask, bitmaskLen)
+ stub.AssetAmount = make([]uint64, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskAssetAmount.setBit(i)
+ stub.AssetAmount = append(stub.AssetAmount, txn.Txn.AssetAmount)
+ }
+ if !txn.Txn.AssetSender.MsgIsZero() {
+ if len(stub.BitmaskAssetSender) == 0 {
+ stub.BitmaskAssetSender = make(bitmask, bitmaskLen)
+ stub.AssetSender = make([]byte, 0, stub.TotalTransactionsCount*crypto.DigestSize)
+ }
+ stub.BitmaskAssetSender.setBit(i)
+ stub.AssetSender = append(stub.AssetSender, txn.Txn.AssetSender[:]...)
+ }
+ if !txn.Txn.AssetReceiver.MsgIsZero() {
+ if len(stub.BitmaskAssetReceiver) == 0 {
+ stub.BitmaskAssetReceiver = make(bitmask, bitmaskLen)
+ stub.AssetReceiver = make([]byte, 0, stub.TotalTransactionsCount*crypto.DigestSize)
+ }
+ stub.BitmaskAssetReceiver.setBit(i)
+ stub.AssetReceiver = append(stub.AssetReceiver, txn.Txn.AssetReceiver[:]...)
+ }
+ if !txn.Txn.AssetCloseTo.MsgIsZero() {
+ if len(stub.BitmaskAssetCloseTo) == 0 {
+ stub.BitmaskAssetCloseTo = make(bitmask, bitmaskLen)
+ stub.AssetCloseTo = make([]byte, 0, stub.TotalTransactionsCount*crypto.DigestSize)
+ }
+ stub.BitmaskAssetCloseTo.setBit(i)
+ stub.AssetCloseTo = append(stub.AssetCloseTo, txn.Txn.AssetCloseTo[:]...)
+ }
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructAssetTransferTxnFields() {
+ stub.BitmaskXferAsset.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskAssetAmount.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskAssetSender.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskAssetReceiver.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskAssetCloseTo.trimBitmask(int(stub.TotalTransactionsCount))
+}
+
+func (stub *txGroupsEncodingStub) deconstructAssetFreezeTxnFields(i int, txn *transactions.SignedTxn) {
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ if !txn.Txn.FreezeAccount.MsgIsZero() {
+ if len(stub.BitmaskFreezeAccount) == 0 {
+ stub.BitmaskFreezeAccount = make(bitmask, bitmaskLen)
+ stub.FreezeAccount = make([]byte, 0, stub.TotalTransactionsCount*crypto.DigestSize)
+ }
+ stub.BitmaskFreezeAccount.setBit(i)
+ stub.FreezeAccount = append(stub.FreezeAccount, txn.Txn.FreezeAccount[:]...)
+ }
+ if txn.Txn.FreezeAsset != 0 {
+ if len(stub.BitmaskFreezeAsset) == 0 {
+ stub.BitmaskFreezeAsset = make(bitmask, bitmaskLen)
+ stub.FreezeAsset = make([]basics.AssetIndex, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskFreezeAsset.setBit(i)
+ stub.FreezeAsset = append(stub.FreezeAsset, txn.Txn.FreezeAsset)
+ }
+ if txn.Txn.AssetFrozen {
+ if len(stub.BitmaskAssetFrozen) == 0 {
+ stub.BitmaskAssetFrozen = make(bitmask, bitmaskLen)
+ }
+ stub.BitmaskAssetFrozen.setBit(i)
+ }
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructAssetFreezeTxnFields() {
+ stub.BitmaskFreezeAccount.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskFreezeAsset.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskAssetFrozen.trimBitmask(int(stub.TotalTransactionsCount))
+}
+
+func (stub *txGroupsEncodingStub) deconstructApplicationCallTxnFields(i int, txn *transactions.SignedTxn) {
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ if !txn.Txn.ApplicationID.MsgIsZero() {
+ if len(stub.BitmaskApplicationID) == 0 {
+ stub.BitmaskApplicationID = make(bitmask, bitmaskLen)
+ stub.ApplicationID = make([]basics.AppIndex, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskApplicationID.setBit(i)
+ stub.ApplicationID = append(stub.ApplicationID, txn.Txn.ApplicationID)
+ }
+ if txn.Txn.OnCompletion != 0 {
+ if len(stub.BitmaskOnCompletion) == 0 {
+ stub.BitmaskOnCompletion = make(bitmask, bitmaskLen)
+ stub.OnCompletion = make([]byte, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskOnCompletion.setBit(i)
+ stub.OnCompletion = append(stub.OnCompletion, byte(txn.Txn.OnCompletion))
+ }
+ if txn.Txn.ApplicationArgs != nil {
+ if len(stub.BitmaskApplicationArgs) == 0 {
+ stub.BitmaskApplicationArgs = make(bitmask, bitmaskLen)
+ stub.ApplicationArgs = make([]applicationArgs, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskApplicationArgs.setBit(i)
+ stub.ApplicationArgs = append(stub.ApplicationArgs, txn.Txn.ApplicationArgs)
+ }
+ if txn.Txn.Accounts != nil {
+ if len(stub.BitmaskAccounts) == 0 {
+ stub.BitmaskAccounts = make(bitmask, bitmaskLen)
+ stub.Accounts = make([]addresses, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskAccounts.setBit(i)
+ stub.Accounts = append(stub.Accounts, txn.Txn.Accounts)
+ }
+ if txn.Txn.ForeignApps != nil {
+ if len(stub.BitmaskForeignApps) == 0 {
+ stub.BitmaskForeignApps = make(bitmask, bitmaskLen)
+ stub.ForeignApps = make([]appIndices, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskForeignApps.setBit(i)
+ stub.ForeignApps = append(stub.ForeignApps, txn.Txn.ForeignApps)
+ }
+ if txn.Txn.ForeignAssets != nil {
+ if len(stub.BitmaskForeignAssets) == 0 {
+ stub.BitmaskForeignAssets = make(bitmask, bitmaskLen)
+ stub.ForeignAssets = make([]assetIndices, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskForeignAssets.setBit(i)
+ stub.ForeignAssets = append(stub.ForeignAssets, txn.Txn.ForeignAssets)
+ }
+ if txn.Txn.LocalStateSchema.NumUint != 0 {
+ if len(stub.BitmaskLocalNumUint) == 0 {
+ stub.BitmaskLocalNumUint = make(bitmask, bitmaskLen)
+ stub.LocalNumUint = make([]uint64, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskLocalNumUint.setBit(i)
+ stub.LocalNumUint = append(stub.LocalNumUint, txn.Txn.LocalStateSchema.NumUint)
+ }
+ if txn.Txn.LocalStateSchema.NumByteSlice != 0 {
+ if len(stub.BitmaskLocalNumByteSlice) == 0 {
+ stub.BitmaskLocalNumByteSlice = make(bitmask, bitmaskLen)
+ stub.LocalNumByteSlice = make([]uint64, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskLocalNumByteSlice.setBit(i)
+ stub.LocalNumByteSlice = append(stub.LocalNumByteSlice, txn.Txn.LocalStateSchema.NumByteSlice)
+ }
+ if txn.Txn.GlobalStateSchema.NumUint != 0 {
+ if len(stub.BitmaskGlobalNumUint) == 0 {
+ stub.BitmaskGlobalNumUint = make(bitmask, bitmaskLen)
+ stub.GlobalNumUint = make([]uint64, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskGlobalNumUint.setBit(i)
+ stub.GlobalNumUint = append(stub.GlobalNumUint, txn.Txn.GlobalStateSchema.NumUint)
+ }
+ if txn.Txn.GlobalStateSchema.NumByteSlice != 0 {
+ if len(stub.BitmaskGlobalNumByteSlice) == 0 {
+ stub.BitmaskGlobalNumByteSlice = make(bitmask, bitmaskLen)
+ stub.GlobalNumByteSlice = make([]uint64, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskGlobalNumByteSlice.setBit(i)
+ stub.GlobalNumByteSlice = append(stub.GlobalNumByteSlice, txn.Txn.GlobalStateSchema.NumByteSlice)
+ }
+ if txn.Txn.ApprovalProgram != nil {
+ if len(stub.BitmaskApprovalProgram) == 0 {
+ stub.BitmaskApprovalProgram = make(bitmask, bitmaskLen)
+ stub.ApprovalProgram = make([]program, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskApprovalProgram.setBit(i)
+ stub.ApprovalProgram = append(stub.ApprovalProgram, txn.Txn.ApprovalProgram)
+ }
+ if txn.Txn.ClearStateProgram != nil {
+ if len(stub.BitmaskClearStateProgram) == 0 {
+ stub.BitmaskClearStateProgram = make(bitmask, bitmaskLen)
+ stub.ClearStateProgram = make([]program, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskClearStateProgram.setBit(i)
+ stub.ClearStateProgram = append(stub.ClearStateProgram, txn.Txn.ClearStateProgram)
+ }
+ if txn.Txn.ExtraProgramPages != 0 {
+ if len(stub.BitmaskExtraProgramPages) == 0 {
+ stub.BitmaskExtraProgramPages = make(bitmask, bitmaskLen)
+ stub.ExtraProgramPages = make([]uint32, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskExtraProgramPages.setBit(i)
+ stub.ExtraProgramPages = append(stub.ExtraProgramPages, txn.Txn.ExtraProgramPages)
+ }
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructApplicationCallTxnFields() {
+ compactNibblesArray(&stub.OnCompletion)
+ stub.BitmaskApplicationID.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskOnCompletion.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskApplicationArgs.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskAccounts.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskForeignApps.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskForeignAssets.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskLocalNumUint.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskLocalNumByteSlice.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskGlobalNumUint.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskGlobalNumByteSlice.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskApprovalProgram.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskClearStateProgram.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskExtraProgramPages.trimBitmask(int(stub.TotalTransactionsCount))
+}
+
+func (stub *txGroupsEncodingStub) deconstructCompactCertTxnFields(i int, txn *transactions.SignedTxn) {
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ if !txn.Txn.CertRound.MsgIsZero() {
+ if len(stub.BitmaskCertRound) == 0 {
+ stub.BitmaskCertRound = make(bitmask, bitmaskLen)
+ stub.CertRound = make([]basics.Round, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskCertRound.setBit(i)
+ stub.CertRound = append(stub.CertRound, txn.Txn.CertRound)
+ }
+ if txn.Txn.CertType != 0 {
+ if len(stub.BitmaskCertType) == 0 {
+ stub.BitmaskCertType = make(bitmask, bitmaskLen)
+ stub.CertType = make([]protocol.CompactCertType, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskCertType.setBit(i)
+ stub.CertType = append(stub.CertType, txn.Txn.CertType)
+ }
+ stub.deconstructCert(i, txn)
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructCompactCertTxnFields() {
+ stub.BitmaskCertRound.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskCertType.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.finishDeconstructCert()
+}
+
+func (stub *txGroupsEncodingStub) deconstructCert(i int, txn *transactions.SignedTxn) {
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ if !txn.Txn.Cert.SigCommit.MsgIsZero() {
+ if len(stub.BitmaskSigCommit) == 0 {
+ stub.BitmaskSigCommit = make(bitmask, bitmaskLen)
+ stub.SigCommit = make([]byte, 0, stub.TotalTransactionsCount*crypto.DigestSize)
+ }
+ stub.BitmaskSigCommit.setBit(i)
+ stub.SigCommit = append(stub.SigCommit, txn.Txn.Cert.SigCommit[:]...)
+ }
+ if txn.Txn.Cert.SignedWeight != 0 {
+ if len(stub.BitmaskSignedWeight) == 0 {
+ stub.BitmaskSignedWeight = make(bitmask, bitmaskLen)
+ stub.SignedWeight = make([]uint64, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskSignedWeight.setBit(i)
+ stub.SignedWeight = append(stub.SignedWeight, txn.Txn.Cert.SignedWeight)
+ }
+ if txn.Txn.Cert.SigProofs != nil {
+ if len(stub.BitmaskSigProofs) == 0 {
+ stub.BitmaskSigProofs = make(bitmask, bitmaskLen)
+ stub.SigProofs = make([]certProofs, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskSigProofs.setBit(i)
+ stub.SigProofs = append(stub.SigProofs, txn.Txn.Cert.SigProofs)
+ }
+ if txn.Txn.Cert.PartProofs != nil {
+ if len(stub.BitmaskPartProofs) == 0 {
+ stub.BitmaskPartProofs = make(bitmask, bitmaskLen)
+ stub.PartProofs = make([]certProofs, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskPartProofs.setBit(i)
+ stub.PartProofs = append(stub.PartProofs, txn.Txn.Cert.PartProofs)
+ }
+ if txn.Txn.Cert.Reveals != nil {
+ if len(stub.BitmaskReveals) == 0 {
+ stub.BitmaskReveals = make(bitmask, bitmaskLen)
+ stub.Reveals = make([]revealMap, 0, stub.TotalTransactionsCount)
+ }
+ stub.BitmaskReveals.setBit(i)
+ stub.Reveals = append(stub.Reveals, txn.Txn.Cert.Reveals)
+ }
+}
+
+func (stub *txGroupsEncodingStub) finishDeconstructCert() {
+ stub.BitmaskSigCommit.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskSignedWeight.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskSigProofs.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskPartProofs.trimBitmask(int(stub.TotalTransactionsCount))
+ stub.BitmaskReveals.trimBitmask(int(stub.TotalTransactionsCount))
+}
diff --git a/txnsync/encodedgroupstypes.go b/txnsync/encodedgroupstypes.go
new file mode 100644
index 000000000..727d67ee8
--- /dev/null
+++ b/txnsync/encodedgroupstypes.go
@@ -0,0 +1,372 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "errors"
+
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/crypto/compactcert"
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/protocol"
+)
+
+const maxEncodedTransactionGroups = 30000
+const maxEncodedTransactionGroupEntries = 30000
+const maxBitmaskSize = (maxEncodedTransactionGroupEntries+7)/8 + 1
+const maxSignatureBytes = maxEncodedTransactionGroupEntries * len(crypto.Signature{})
+const maxAddressBytes = maxEncodedTransactionGroupEntries * crypto.DigestSize
+
+var errInvalidTxType = errors.New("invalid txtype")
+
+//msgp:allocbound txnGroups maxEncodedTransactionGroupEntries
+type txnGroups pooldata.SignedTxnSlice //nolint:unused
+
+// old data structure for encoding (only used for testing)
+type txGroupsEncodingStubOld struct { //nolint:unused
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ TxnGroups []txnGroups `codec:"t,allocbound=maxEncodedTransactionGroups"`
+}
+
+type txGroupsEncodingStub struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ TotalTransactionsCount uint64 `codec:"ttc"`
+ TransactionGroupCount uint64 `codec:"tgc"`
+ TransactionGroupSizes []byte `codec:"tgs,allocbound=maxEncodedTransactionGroups"`
+
+ encodedSignedTxns
+}
+
+type encodedSignedTxns struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ Sig []byte `codec:"sig,allocbound=maxSignatureBytes"`
+ BitmaskSig bitmask `codec:"sigbm"`
+
+ encodedMsigs
+ encodedLsigs
+
+ AuthAddr []byte `codec:"sgnr,allocbound=maxAddressBytes"`
+ BitmaskAuthAddr bitmask `codec:"sgnrbm"`
+
+ encodedTxns
+}
+
+type encodedMsigs struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ Version []byte `codec:"msigv,allocbound=maxEncodedTransactionGroups"`
+ BitmaskVersion bitmask `codec:"msigvbm"`
+ Threshold []byte `codec:"msigthr,allocbound=maxEncodedTransactionGroups"`
+ BitmaskThreshold bitmask `codec:"msigthrbm"`
+ // splitting subsigs further make the code much more complicated / does not give gains
+ Subsigs [][]crypto.MultisigSubsig `codec:"subsig,allocbound=maxEncodedTransactionGroups,allocbound=crypto.MaxMultisig"`
+ BitmaskSubsigs bitmask `codec:"subsigsbm"`
+}
+
+type encodedLsigs struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ Logic [][]byte `codec:"lsigl,allocbound=maxEncodedTransactionGroups,allocbound=config.MaxLogicSigMaxSize"`
+ BitmaskLogic bitmask `codec:"lsiglbm"`
+ LogicArgs [][][]byte `codec:"lsigarg,allocbound=maxEncodedTransactionGroups,allocbound=transactions.EvalMaxArgs,allocbound=config.MaxLogicSigMaxSize"`
+ BitmaskLogicArgs bitmask `codec:"lsigargbm"`
+}
+
+type encodedTxns struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ TxType []byte `codec:"type,allocbound=maxEncodedTransactionGroups"`
+ BitmaskTxType bitmask `codec:"typebm"`
+ TxTypeOffset byte `codec:"typeo"`
+
+ encodedTxnHeaders
+ encodedKeyregTxnFields
+ encodedPaymentTxnFields
+ encodedAssetConfigTxnFields
+ encodedAssetTransferTxnFields
+ encodedAssetFreezeTxnFields
+ encodedApplicationCallTxnFields
+ encodedCompactCertTxnFields
+}
+
+type encodedTxnHeaders struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ Sender []byte `codec:"snd,allocbound=maxAddressBytes"`
+ BitmaskSender bitmask `codec:"sndbm"`
+ Fee []basics.MicroAlgos `codec:"fee,allocbound=maxEncodedTransactionGroups"`
+ BitmaskFee bitmask `codec:"feebm"`
+ FirstValid []basics.Round `codec:"fv,allocbound=maxEncodedTransactionGroups"`
+ BitmaskFirstValid bitmask `codec:"fvbm"`
+ LastValid []basics.Round `codec:"lv,allocbound=maxEncodedTransactionGroups"`
+ BitmaskLastValid bitmask `codec:"lvbm"`
+ Note [][]byte `codec:"note,allocbound=maxEncodedTransactionGroups,allocbound=config.MaxTxnNoteBytes"`
+ BitmaskNote bitmask `codec:"notebm"`
+ BitmaskGenesisID bitmask `codec:"genbm"`
+
+ BitmaskGroup bitmask `codec:"grpbm"`
+
+ Lease []byte `codec:"lx,allocbound=maxAddressBytes"`
+ BitmaskLease bitmask `codec:"lxbm"`
+
+ RekeyTo []byte `codec:"rekey,allocbound=maxAddressBytes"`
+ BitmaskRekeyTo bitmask `codec:"rekeybm"`
+}
+
+type encodedKeyregTxnFields struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ VotePK []byte `codec:"votekey,allocbound=maxAddressBytes"`
+ SelectionPK []byte `codec:"selkey,allocbound=maxAddressBytes"`
+ VoteFirst []basics.Round `codec:"votefst,allocbound=maxEncodedTransactionGroups"`
+ BitmaskVoteFirst bitmask `codec:"votefstbm"`
+ VoteLast []basics.Round `codec:"votelst,allocbound=maxEncodedTransactionGroups"`
+ BitmaskVoteLast bitmask `codec:"votelstbm"`
+ VoteKeyDilution []uint64 `codec:"votekd,allocbound=maxEncodedTransactionGroups"`
+ BitmaskKeys bitmask `codec:"votekbm"`
+ BitmaskNonparticipation bitmask `codec:"nonpartbm"`
+}
+
+type encodedPaymentTxnFields struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ Receiver []byte `codec:"rcv,allocbound=maxAddressBytes"`
+ BitmaskReceiver bitmask `codec:"rcvbm"`
+ Amount []basics.MicroAlgos `codec:"amt,allocbound=maxEncodedTransactionGroups"`
+ BitmaskAmount bitmask `codec:"amtbm"`
+
+ CloseRemainderTo []byte `codec:"close,allocbound=maxAddressBytes"`
+ BitmaskCloseRemainderTo bitmask `codec:"closebm"`
+}
+
+type encodedAssetConfigTxnFields struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ ConfigAsset []basics.AssetIndex `codec:"caid,allocbound=maxEncodedTransactionGroups"`
+ BitmaskConfigAsset bitmask `codec:"caidbm"`
+
+ encodedAssetParams
+}
+
+type encodedAssetParams struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ Total []uint64 `codec:"t,allocbound=maxEncodedTransactionGroups"`
+ BitmaskTotal bitmask `codec:"tbm"`
+
+ Decimals []uint32 `codec:"dc,allocbound=maxEncodedTransactionGroups"`
+ BitmaskDecimals bitmask `codec:"dcbm"`
+
+ BitmaskDefaultFrozen bitmask `codec:"dfbm"`
+
+ UnitName []string `codec:"un,allocbound=maxEncodedTransactionGroups"`
+ BitmaskUnitName bitmask `codec:"unbm"`
+
+ AssetName []string `codec:"an,allocbound=maxEncodedTransactionGroups"`
+ BitmaskAssetName bitmask `codec:"anbm"`
+
+ URL []string `codec:"au,allocbound=maxEncodedTransactionGroups"`
+ BitmaskURL bitmask `codec:"aubm"`
+
+ MetadataHash []byte `codec:"am,allocbound=maxAddressBytes"`
+ BitmaskMetadataHash bitmask `codec:"ambm"`
+
+ Manager []byte `codec:"m,allocbound=maxAddressBytes"`
+ BitmaskManager bitmask `codec:"mbm"`
+
+ Reserve []byte `codec:"r,allocbound=maxAddressBytes"`
+ BitmaskReserve bitmask `codec:"rbm"`
+
+ Freeze []byte `codec:"f,allocbound=maxAddressBytes"`
+ BitmaskFreeze bitmask `codec:"fbm"`
+
+ Clawback []byte `codec:"c,allocbound=maxAddressBytes"`
+ BitmaskClawback bitmask `codec:"cbm"`
+}
+
+type encodedAssetTransferTxnFields struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ XferAsset []basics.AssetIndex `codec:"xaid,allocbound=maxEncodedTransactionGroups"`
+ BitmaskXferAsset bitmask `codec:"xaidbm"`
+
+ AssetAmount []uint64 `codec:"aamt,allocbound=maxEncodedTransactionGroups"`
+ BitmaskAssetAmount bitmask `codec:"aamtbm"`
+
+ AssetSender []byte `codec:"asnd,allocbound=maxAddressBytes"`
+ BitmaskAssetSender bitmask `codec:"asndbm"`
+
+ AssetReceiver []byte `codec:"arcv,allocbound=maxAddressBytes"`
+ BitmaskAssetReceiver bitmask `codec:"arcvbm"`
+
+ AssetCloseTo []byte `codec:"aclose,allocbound=maxAddressBytes"`
+ BitmaskAssetCloseTo bitmask `codec:"aclosebm"`
+}
+
+type encodedAssetFreezeTxnFields struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ FreezeAccount []byte `codec:"fadd,allocbound=maxAddressBytes"`
+ BitmaskFreezeAccount bitmask `codec:"faddbm"`
+
+ FreezeAsset []basics.AssetIndex `codec:"faid,allocbound=maxEncodedTransactionGroups"`
+ BitmaskFreezeAsset bitmask `codec:"faidbm"`
+
+ BitmaskAssetFrozen bitmask `codec:"afrzbm"`
+}
+
+//msgp:allocbound applicationArgs transactions.EncodedMaxApplicationArgs
+type applicationArgs [][]byte
+
+//msgp:allocbound addresses transactions.EncodedMaxAccounts
+type addresses []basics.Address
+
+//msgp:allocbound appIndices transactions.EncodedMaxForeignApps
+type appIndices []basics.AppIndex
+
+//msgp:allocbound assetIndices transactions.EncodedMaxForeignAssets
+type assetIndices []basics.AssetIndex
+
+//msgp:allocbound program config.MaxAvailableAppProgramLen
+type program []byte
+
+type encodedApplicationCallTxnFields struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ ApplicationID []basics.AppIndex `codec:"apid,allocbound=maxEncodedTransactionGroups"`
+ BitmaskApplicationID bitmask `codec:"apidbm"`
+
+ OnCompletion []byte `codec:"apan,allocbound=maxEncodedTransactionGroups"`
+ BitmaskOnCompletion bitmask `codec:"apanbm"`
+
+ ApplicationArgs []applicationArgs `codec:"apaa,allocbound=maxEncodedTransactionGroups"`
+ BitmaskApplicationArgs bitmask `codec:"apaabm"`
+
+ Accounts []addresses `codec:"apat,allocbound=maxEncodedTransactionGroups"`
+ BitmaskAccounts bitmask `codec:"apatbm"`
+
+ ForeignApps []appIndices `codec:"apfa,allocbound=maxEncodedTransactionGroups"`
+ BitmaskForeignApps bitmask `codec:"apfabm"`
+
+ ForeignAssets []assetIndices `codec:"apas,allocbound=maxEncodedTransactionGroups"`
+ BitmaskForeignAssets bitmask `codec:"apasbm"`
+
+ LocalNumUint []uint64 `codec:"lnui,allocbound=maxEncodedTransactionGroups"`
+ BitmaskLocalNumUint bitmask `codec:"lnuibm"`
+ LocalNumByteSlice []uint64 `codec:"lnbs,allocbound=maxEncodedTransactionGroups"`
+ BitmaskLocalNumByteSlice bitmask `codec:"lnbsbm"`
+
+ GlobalNumUint []uint64 `codec:"gnui,allocbound=maxEncodedTransactionGroups"`
+ BitmaskGlobalNumUint bitmask `codec:"gnuibm"`
+ GlobalNumByteSlice []uint64 `codec:"gnbs,allocbound=maxEncodedTransactionGroups"`
+ BitmaskGlobalNumByteSlice bitmask `codec:"gnbsbm"`
+
+ ApprovalProgram []program `codec:"apap,allocbound=maxEncodedTransactionGroups"`
+ BitmaskApprovalProgram bitmask `codec:"apapbm"`
+
+ ClearStateProgram []program `codec:"apsu,allocbound=maxEncodedTransactionGroups"`
+ BitmaskClearStateProgram bitmask `codec:"apsubm"`
+
+ ExtraProgramPages []uint32 `codec:"apep,allocbound=maxEncodedTransactionGroups"`
+ BitmaskExtraProgramPages bitmask `codec:"apepbm"`
+}
+
+type encodedCompactCertTxnFields struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ CertRound []basics.Round `codec:"certrnd,allocbound=maxEncodedTransactionGroups"`
+ BitmaskCertRound bitmask `codec:"certrndbm"`
+
+ CertType []protocol.CompactCertType `codec:"certtype,allocbound=maxEncodedTransactionGroups"`
+ BitmaskCertType bitmask `codec:"certtypebm"`
+
+ encodedCert
+}
+
+//msgp:allocbound certProofs compactcert.MaxProofDigests
+type certProofs []crypto.Digest
+
+//msgp:allocbound revealMap compactcert.MaxReveals
+type revealMap map[uint64]compactcert.Reveal
+
+// SortUint64 implements sorting by uint64 keys for
+// canonical encoding of maps in msgpack format.
+type SortUint64 = compactcert.SortUint64
+
+type encodedCert struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ SigCommit []byte `codec:"certc,allocbound=maxAddressBytes"`
+ BitmaskSigCommit bitmask `codec:"certcbm"`
+
+ SignedWeight []uint64 `codec:"certw,allocbound=maxEncodedTransactionGroups"`
+ BitmaskSignedWeight bitmask `codec:"certwbm"`
+
+ SigProofs []certProofs `codec:"certS,allocbound=maxEncodedTransactionGroups"`
+ BitmaskSigProofs bitmask `codec:"certSbm"`
+
+ PartProofs []certProofs `codec:"certP,allocbound=maxEncodedTransactionGroups"`
+ BitmaskPartProofs bitmask `codec:"certPbm"`
+
+ Reveals []revealMap `codec:"certr,allocbound=maxEncodedTransactionGroups"`
+ BitmaskReveals bitmask `codec:"certrbm"`
+}
+
+const (
+ paymentTx = iota
+ keyRegistrationTx
+ assetConfigTx
+ assetTransferTx
+ assetFreezeTx
+ applicationCallTx
+ compactCertTx
+ unknownTx
+)
+
+// TxTypeToByte converts a TxType to byte encoding
+func TxTypeToByte(t protocol.TxType) (byte, error) {
+ switch t {
+ case protocol.PaymentTx:
+ return paymentTx, nil
+ case protocol.KeyRegistrationTx:
+ return keyRegistrationTx, nil
+ case protocol.AssetConfigTx:
+ return assetConfigTx, nil
+ case protocol.AssetTransferTx:
+ return assetTransferTx, nil
+ case protocol.AssetFreezeTx:
+ return assetFreezeTx, nil
+ case protocol.ApplicationCallTx:
+ return applicationCallTx, nil
+ case protocol.CompactCertTx:
+ return compactCertTx, nil
+ default:
+ return unknownTx, errInvalidTxType
+ }
+}
+
+// ByteToTxType converts a byte encoding to TxType
+func ByteToTxType(b byte) protocol.TxType {
+ if int(b) >= len(protocol.TxnTypes) {
+ return protocol.UnknownTx
+ }
+ return protocol.TxnTypes[b]
+}
diff --git a/txnsync/encodedgroupsunmarshalers.go b/txnsync/encodedgroupsunmarshalers.go
new file mode 100644
index 000000000..750bb0871
--- /dev/null
+++ b/txnsync/encodedgroupsunmarshalers.go
@@ -0,0 +1,648 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "errors"
+ "fmt"
+
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/data/transactions"
+)
+
+var errDataMissing = errors.New("failed to decode: data missing")
+
+// the nextSlice definition - copy the next slice and slide the src window.
+func nextSlice(src *[]byte, dst []byte, size int) error {
+ if len(*src) < size {
+ return errDataMissing
+ }
+ copy(dst[:], (*src)[:size])
+ // slice the src window so next call would get the next entry.
+ *src = (*src)[size:]
+ return nil
+}
+
+// getNibble returns the nibble at the given index from the provided
+// byte array. A errDataMissing is returned if index is beyond the size
+// of the array.
+func getNibble(b []byte, index int) (byte, error) {
+ if index >= len(b)*2 {
+ return 0, errDataMissing
+ }
+ if index%2 == 0 {
+ return b[index/2] / 16, nil
+ }
+ return b[index/2] % 16, nil
+}
+
+func addGroupHashes(txnGroups []pooldata.SignedTxGroup, txnCount int, b bitmask) (err error) {
+ index := 0
+ txGroupHashes := make([]crypto.Digest, 16)
+ tStart := 0
+
+ // addGroupHashesFunc adds hashes to transactions in groups of more than 1 transaction,
+ // or to transactions with one transaction and bitmask set for that index.
+ // It stops at index nextSetBitIndex, or stops when all in txnGroups are visited.
+ addGroupHashesFunc := func(nextSetBitIndex int, count int) error {
+ remainingTxnGroups := txnGroups[tStart:]
+ for t, txns := range remainingTxnGroups {
+ if len(txns.Transactions) == 1 && index != nextSetBitIndex {
+ index++
+ continue
+ }
+ var txGroup transactions.TxGroup
+ txGroup.TxGroupHashes = txGroupHashes[:len(txns.Transactions)]
+ for i, tx := range txns.Transactions {
+ txGroup.TxGroupHashes[i] = crypto.HashObj(tx.Txn)
+ }
+ groupHash := crypto.HashObj(txGroup)
+ for i := range txns.Transactions {
+ txns.Transactions[i].Txn.Group = groupHash
+ index++
+ }
+ if index > nextSetBitIndex {
+ tStart += t + 1
+ return nil
+ }
+ }
+ tStart = len(txnGroups)
+ return nil
+ }
+ // addGroupHashesFunc will be called for each set bit. Between set bits, all transactions
+ // in groups of more than 1 transactions will have the hashes added.
+ err = b.iterate(txnCount, txnCount, addGroupHashesFunc)
+
+ if err == nil {
+ // One more call to addGroupHashesFunc to cover all the remaining transactions in groups of
+ // more than 1 transaction that were not added because no groups with one transaction are left.
+ err = addGroupHashesFunc(txnCount+1, -1)
+ }
+ return
+}
+
+func (stub *txGroupsEncodingStub) reconstructSignedTransactions(signedTxns []transactions.SignedTxn, genesisID string, genesisHash crypto.Digest) error {
+ err := stub.BitmaskSig.iterate(int(stub.TotalTransactionsCount), len(stub.Sig)/len(crypto.Signature{}), func(i int, _ int) error {
+ return nextSlice(&stub.Sig, signedTxns[i].Sig[:], len(crypto.Signature{}))
+ })
+ if err != nil {
+ return err
+ }
+
+ if err = stub.reconstructMsigs(signedTxns); err != nil {
+ return fmt.Errorf("failed to msigs: %w", err)
+ }
+ if err = stub.reconstructLsigs(signedTxns); err != nil {
+ return fmt.Errorf("failed to lsigs: %w", err)
+ }
+ err = stub.BitmaskAuthAddr.iterate(int(stub.TotalTransactionsCount), len(stub.AuthAddr)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.AuthAddr, signedTxns[i].AuthAddr[:], crypto.DigestSize)
+ })
+ if err != nil {
+ return err
+ }
+
+ return stub.reconstructTransactions(signedTxns, genesisID, genesisHash)
+}
+
+func (stub *txGroupsEncodingStub) reconstructMsigs(signedTxns []transactions.SignedTxn) (err error) {
+ err = stub.BitmaskVersion.iterate(int(stub.TotalTransactionsCount), len(stub.Version), func(i int, index int) error {
+ signedTxns[i].Msig.Version = stub.Version[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskThreshold.iterate(int(stub.TotalTransactionsCount), len(stub.Threshold), func(i int, index int) error {
+ signedTxns[i].Msig.Threshold = stub.Threshold[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskSubsigs.iterate(int(stub.TotalTransactionsCount), len(stub.Subsigs), func(i int, index int) error {
+ signedTxns[i].Msig.Subsigs = stub.Subsigs[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (stub *txGroupsEncodingStub) reconstructLsigs(signedTxns []transactions.SignedTxn) (err error) {
+ err = stub.BitmaskLogic.iterate(int(stub.TotalTransactionsCount), len(stub.Logic), func(i int, index int) error {
+ signedTxns[i].Lsig.Logic = stub.Logic[index]
+ // fetch sig/msig
+ signedTxns[i].Lsig.Sig = signedTxns[i].Sig
+ signedTxns[i].Sig = crypto.Signature{}
+ signedTxns[i].Lsig.Msig = signedTxns[i].Msig
+ signedTxns[i].Msig = crypto.MultisigSig{}
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskLogicArgs.iterate(int(stub.TotalTransactionsCount), len(stub.LogicArgs), func(i int, index int) error {
+ signedTxns[i].Lsig.Args = stub.LogicArgs[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (stub *txGroupsEncodingStub) reconstructTransactions(signedTxns []transactions.SignedTxn, genesisID string, genesisHash crypto.Digest) (err error) {
+ err = stub.BitmaskTxType.iterate(int(stub.TotalTransactionsCount), len(stub.TxType)*2, func(i int, index int) error {
+ b, err := getNibble(stub.TxType, index)
+ if err != nil {
+ return err
+ }
+ signedTxns[i].Txn.Type = ByteToTxType(b)
+ return nil
+ })
+ for i := range signedTxns {
+ if signedTxns[i].Txn.Type == "" {
+ signedTxns[i].Txn.Type = ByteToTxType(stub.TxTypeOffset)
+ }
+ }
+ if err != nil {
+ return err
+ }
+
+ if err := stub.reconstructTxnHeader(signedTxns, genesisID, genesisHash); err != nil {
+ return fmt.Errorf("failed to reconstructTxnHeader: %w", err)
+ }
+ if err := stub.reconstructKeyregTxnFields(signedTxns); err != nil {
+ return fmt.Errorf("failed to reconstructKeyregTxnFields: %w", err)
+ }
+ if err := stub.reconstructPaymentTxnFields(signedTxns); err != nil {
+ return fmt.Errorf("failed to reconstructPaymentTxnFields: %w", err)
+ }
+ if err := stub.reconstructAssetConfigTxnFields(signedTxns); err != nil {
+ return fmt.Errorf("failed to reconstructAssetConfigTxnFields: %w", err)
+ }
+ if err := stub.reconstructAssetTransferTxnFields(signedTxns); err != nil {
+ return fmt.Errorf("failed to reconstructAssetTransferTxnFields: %w", err)
+ }
+ if err := stub.reconstructAssetFreezeTxnFields(signedTxns); err != nil {
+ return fmt.Errorf("failed to reconstructAssetFreezeTxnFields: %w", err)
+ }
+ if err := stub.reconstructApplicationCallTxnFields(signedTxns); err != nil {
+ return fmt.Errorf("failed to reconstructApplicationCallTxnFields: %w", err)
+ }
+ if err := stub.reconstructCompactCertTxnFields(signedTxns); err != nil {
+ return fmt.Errorf("failed to reconstructCompactCertTxnFields: %w", err)
+ }
+ return nil
+}
+
+func (stub *txGroupsEncodingStub) reconstructTxnHeader(signedTxns []transactions.SignedTxn, genesisID string, genesisHash crypto.Digest) (err error) {
+ err = stub.BitmaskSender.iterate(int(stub.TotalTransactionsCount), len(stub.Sender)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.Sender, signedTxns[i].Txn.Sender[:], crypto.DigestSize)
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskFee.iterate(int(stub.TotalTransactionsCount), len(stub.Fee), func(i int, index int) error {
+ signedTxns[i].Txn.Fee = stub.Fee[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskFirstValid.iterate(int(stub.TotalTransactionsCount), len(stub.FirstValid), func(i int, index int) error {
+ signedTxns[i].Txn.FirstValid = stub.FirstValid[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskLastValid.iterate(int(stub.TotalTransactionsCount), len(stub.LastValid), func(i int, index int) error {
+ signedTxns[i].Txn.LastValid = stub.LastValid[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskNote.iterate(int(stub.TotalTransactionsCount), len(stub.Note), func(i int, index int) error {
+ signedTxns[i].Txn.Note = stub.Note[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskGenesisID.iterate(int(stub.TotalTransactionsCount), int(stub.TotalTransactionsCount), func(i int, index int) error {
+ signedTxns[i].Txn.GenesisID = genesisID
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ for i := range signedTxns {
+ signedTxns[i].Txn.GenesisHash = genesisHash
+ }
+ err = stub.BitmaskLease.iterate(int(stub.TotalTransactionsCount), len(stub.Lease)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.Lease, signedTxns[i].Txn.Lease[:], transactions.LeaseByteLength)
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskRekeyTo.iterate(int(stub.TotalTransactionsCount), len(stub.RekeyTo)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.RekeyTo, signedTxns[i].Txn.RekeyTo[:], crypto.DigestSize)
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (stub *txGroupsEncodingStub) reconstructKeyregTxnFields(signedTxns []transactions.SignedTxn) (err error) {
+ // should all have same number of elements
+ if len(stub.VotePK)/len(crypto.OneTimeSignatureVerifier{}) != len(stub.VoteKeyDilution) || len(stub.SelectionPK)/len(crypto.VRFVerifier{}) != len(stub.VoteKeyDilution) {
+ return errDataMissing
+ }
+ err = stub.BitmaskKeys.iterate(int(stub.TotalTransactionsCount), len(stub.VoteKeyDilution), func(i int, index int) error {
+ signedTxns[i].Txn.VoteKeyDilution = stub.VoteKeyDilution[index]
+ err := nextSlice(&stub.VotePK, signedTxns[i].Txn.VotePK[:], len(crypto.OneTimeSignatureVerifier{}))
+ if err != nil {
+ return err
+ }
+ return nextSlice(&stub.SelectionPK, signedTxns[i].Txn.SelectionPK[:], len(crypto.VRFVerifier{}))
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskVoteFirst.iterate(int(stub.TotalTransactionsCount), len(stub.VoteFirst), func(i int, index int) error {
+ if index >= len(stub.VoteFirst) {
+ return errDataMissing
+ }
+ signedTxns[i].Txn.VoteFirst = stub.VoteFirst[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskVoteLast.iterate(int(stub.TotalTransactionsCount), len(stub.VoteLast), func(i int, index int) error {
+ if index >= len(stub.VoteLast) {
+ return errDataMissing
+ }
+ signedTxns[i].Txn.VoteLast = stub.VoteLast[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+
+ err = stub.BitmaskNonparticipation.iterate(int(stub.TotalTransactionsCount), int(stub.TotalTransactionsCount), func(i int, index int) error {
+ signedTxns[i].Txn.Nonparticipation = true
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (stub *txGroupsEncodingStub) reconstructPaymentTxnFields(signedTxns []transactions.SignedTxn) (err error) {
+ err = stub.BitmaskReceiver.iterate(int(stub.TotalTransactionsCount), len(stub.Receiver)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.Receiver, signedTxns[i].Txn.Receiver[:], crypto.DigestSize)
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskAmount.iterate(int(stub.TotalTransactionsCount), len(stub.Amount), func(i int, index int) error {
+ signedTxns[i].Txn.Amount = stub.Amount[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskCloseRemainderTo.iterate(int(stub.TotalTransactionsCount), len(stub.CloseRemainderTo)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.CloseRemainderTo, signedTxns[i].Txn.CloseRemainderTo[:], crypto.DigestSize)
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (stub *txGroupsEncodingStub) reconstructAssetConfigTxnFields(signedTxns []transactions.SignedTxn) (err error) {
+ err = stub.BitmaskConfigAsset.iterate(int(stub.TotalTransactionsCount), len(stub.ConfigAsset), func(i int, index int) error {
+ signedTxns[i].Txn.ConfigAsset = stub.ConfigAsset[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ return stub.reconstructAssetParams(signedTxns)
+}
+
+func (stub *txGroupsEncodingStub) reconstructAssetParams(signedTxns []transactions.SignedTxn) (err error) {
+ err = stub.BitmaskTotal.iterate(int(stub.TotalTransactionsCount), len(stub.Total), func(i int, index int) error {
+ signedTxns[i].Txn.AssetParams.Total = stub.Total[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskDecimals.iterate(int(stub.TotalTransactionsCount), len(stub.Decimals), func(i int, index int) error {
+ signedTxns[i].Txn.AssetParams.Decimals = stub.Decimals[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskDefaultFrozen.iterate(int(stub.TotalTransactionsCount), int(stub.TotalTransactionsCount), func(i int, index int) error {
+ signedTxns[i].Txn.AssetParams.DefaultFrozen = true
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskUnitName.iterate(int(stub.TotalTransactionsCount), len(stub.UnitName), func(i int, index int) error {
+ signedTxns[i].Txn.AssetParams.UnitName = stub.UnitName[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskAssetName.iterate(int(stub.TotalTransactionsCount), len(stub.AssetName), func(i int, index int) error {
+ signedTxns[i].Txn.AssetParams.AssetName = stub.AssetName[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskURL.iterate(int(stub.TotalTransactionsCount), len(stub.URL), func(i int, index int) error {
+ signedTxns[i].Txn.AssetParams.URL = stub.URL[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskMetadataHash.iterate(int(stub.TotalTransactionsCount), len(stub.MetadataHash)/basics.MetadataHashLength, func(i int, index int) error {
+ return nextSlice(&stub.MetadataHash, signedTxns[i].Txn.AssetParams.MetadataHash[:], basics.MetadataHashLength)
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskManager.iterate(int(stub.TotalTransactionsCount), len(stub.Manager)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.Manager, signedTxns[i].Txn.AssetParams.Manager[:], crypto.DigestSize)
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskReserve.iterate(int(stub.TotalTransactionsCount), len(stub.Reserve)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.Reserve, signedTxns[i].Txn.AssetParams.Reserve[:], crypto.DigestSize)
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskFreeze.iterate(int(stub.TotalTransactionsCount), len(stub.Freeze)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.Freeze, signedTxns[i].Txn.AssetParams.Freeze[:], crypto.DigestSize)
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskClawback.iterate(int(stub.TotalTransactionsCount), len(stub.Clawback)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.Clawback, signedTxns[i].Txn.AssetParams.Clawback[:], crypto.DigestSize)
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (stub *txGroupsEncodingStub) reconstructAssetTransferTxnFields(signedTxns []transactions.SignedTxn) (err error) {
+ err = stub.BitmaskXferAsset.iterate(int(stub.TotalTransactionsCount), len(stub.XferAsset), func(i int, index int) error {
+ signedTxns[i].Txn.XferAsset = stub.XferAsset[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskAssetAmount.iterate(int(stub.TotalTransactionsCount), len(stub.AssetAmount), func(i int, index int) error {
+ signedTxns[i].Txn.AssetAmount = stub.AssetAmount[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskAssetSender.iterate(int(stub.TotalTransactionsCount), len(stub.AssetSender)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.AssetSender, signedTxns[i].Txn.AssetSender[:], crypto.DigestSize)
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskAssetReceiver.iterate(int(stub.TotalTransactionsCount), len(stub.AssetReceiver)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.AssetReceiver, signedTxns[i].Txn.AssetReceiver[:], crypto.DigestSize)
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskAssetCloseTo.iterate(int(stub.TotalTransactionsCount), len(stub.AssetCloseTo)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.AssetCloseTo, signedTxns[i].Txn.AssetCloseTo[:], crypto.DigestSize)
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (stub *txGroupsEncodingStub) reconstructAssetFreezeTxnFields(signedTxns []transactions.SignedTxn) (err error) {
+ err = stub.BitmaskFreezeAccount.iterate(int(stub.TotalTransactionsCount), len(stub.FreezeAccount)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.FreezeAccount, signedTxns[i].Txn.FreezeAccount[:], crypto.DigestSize)
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskFreezeAsset.iterate(int(stub.TotalTransactionsCount), len(stub.FreezeAsset), func(i int, index int) error {
+ signedTxns[i].Txn.FreezeAsset = stub.FreezeAsset[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+
+ err = stub.BitmaskAssetFrozen.iterate(int(stub.TotalTransactionsCount), int(stub.TotalTransactionsCount), func(i int, index int) error {
+ signedTxns[i].Txn.AssetFrozen = true
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (stub *txGroupsEncodingStub) reconstructApplicationCallTxnFields(signedTxns []transactions.SignedTxn) (err error) {
+ err = stub.BitmaskApplicationID.iterate(int(stub.TotalTransactionsCount), len(stub.ApplicationID), func(i int, index int) error {
+ signedTxns[i].Txn.ApplicationID = stub.ApplicationID[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskOnCompletion.iterate(int(stub.TotalTransactionsCount), len(stub.OnCompletion)*2, func(i int, index int) error {
+ b, err := getNibble(stub.OnCompletion, index)
+ if err != nil {
+ return err
+ }
+ signedTxns[i].Txn.OnCompletion = transactions.OnCompletion(b)
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskApplicationArgs.iterate(int(stub.TotalTransactionsCount), len(stub.ApplicationArgs), func(i int, index int) error {
+ signedTxns[i].Txn.ApplicationArgs = stub.ApplicationArgs[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskAccounts.iterate(int(stub.TotalTransactionsCount), len(stub.Accounts), func(i int, index int) error {
+ signedTxns[i].Txn.Accounts = stub.Accounts[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskForeignApps.iterate(int(stub.TotalTransactionsCount), len(stub.ForeignApps), func(i int, index int) error {
+ signedTxns[i].Txn.ForeignApps = stub.ForeignApps[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskForeignAssets.iterate(int(stub.TotalTransactionsCount), len(stub.ForeignAssets), func(i int, index int) error {
+ signedTxns[i].Txn.ForeignAssets = stub.ForeignAssets[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskLocalNumUint.iterate(int(stub.TotalTransactionsCount), len(stub.LocalNumUint), func(i int, index int) error {
+ signedTxns[i].Txn.LocalStateSchema.NumUint = stub.LocalNumUint[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskLocalNumByteSlice.iterate(int(stub.TotalTransactionsCount), len(stub.LocalNumByteSlice), func(i int, index int) error {
+ signedTxns[i].Txn.LocalStateSchema.NumByteSlice = stub.LocalNumByteSlice[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskGlobalNumUint.iterate(int(stub.TotalTransactionsCount), len(stub.GlobalNumUint), func(i int, index int) error {
+ signedTxns[i].Txn.GlobalStateSchema.NumUint = stub.GlobalNumUint[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskGlobalNumByteSlice.iterate(int(stub.TotalTransactionsCount), len(stub.GlobalNumByteSlice), func(i int, index int) error {
+ signedTxns[i].Txn.GlobalStateSchema.NumByteSlice = stub.GlobalNumByteSlice[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskApprovalProgram.iterate(int(stub.TotalTransactionsCount), len(stub.ApprovalProgram), func(i int, index int) error {
+ signedTxns[i].Txn.ApprovalProgram = stub.ApprovalProgram[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskClearStateProgram.iterate(int(stub.TotalTransactionsCount), len(stub.ClearStateProgram), func(i int, index int) error {
+ signedTxns[i].Txn.ClearStateProgram = stub.ClearStateProgram[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskExtraProgramPages.iterate(int(stub.TotalTransactionsCount), len(stub.ExtraProgramPages), func(i int, index int) error {
+ signedTxns[i].Txn.ExtraProgramPages = stub.ExtraProgramPages[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (stub *txGroupsEncodingStub) reconstructCompactCertTxnFields(signedTxns []transactions.SignedTxn) (err error) {
+ err = stub.BitmaskCertRound.iterate(int(stub.TotalTransactionsCount), len(stub.CertRound), func(i int, index int) error {
+ signedTxns[i].Txn.CertRound = stub.CertRound[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskCertType.iterate(int(stub.TotalTransactionsCount), len(stub.CertType), func(i int, index int) error {
+ signedTxns[i].Txn.CertType = stub.CertType[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ return stub.reconstructCert(signedTxns)
+}
+
+func (stub *txGroupsEncodingStub) reconstructCert(signedTxns []transactions.SignedTxn) (err error) {
+ err = stub.BitmaskSigCommit.iterate(int(stub.TotalTransactionsCount), len(stub.SigCommit)/crypto.DigestSize, func(i int, index int) error {
+ return nextSlice(&stub.SigCommit, signedTxns[i].Txn.Cert.SigCommit[:], crypto.DigestSize)
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskSignedWeight.iterate(int(stub.TotalTransactionsCount), len(stub.SignedWeight), func(i int, index int) error {
+ signedTxns[i].Txn.Cert.SignedWeight = stub.SignedWeight[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskSigProofs.iterate(int(stub.TotalTransactionsCount), len(stub.SigProofs), func(i int, index int) error {
+ signedTxns[i].Txn.Cert.SigProofs = stub.SigProofs[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskPartProofs.iterate(int(stub.TotalTransactionsCount), len(stub.PartProofs), func(i int, index int) error {
+ signedTxns[i].Txn.Cert.PartProofs = stub.PartProofs[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ err = stub.BitmaskReveals.iterate(int(stub.TotalTransactionsCount), len(stub.Reveals), func(i int, index int) error {
+ signedTxns[i].Txn.Cert.Reveals = stub.Reveals[index]
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/txnsync/exchange.go b/txnsync/exchange.go
new file mode 100644
index 000000000..32b08fdb8
--- /dev/null
+++ b/txnsync/exchange.go
@@ -0,0 +1,91 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/basics"
+)
+
+const txnBlockMessageVersion = 1
+const maxBloomFilterSize = 100000
+const maxAcceptedMsgSeq = 64
+const maxEncodedTransactionGroupBytes = 10000000
+const maxProposalSize = 350000
+
+type transactionBlockMessage struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ Version int32 `codec:"v"`
+ Round basics.Round `codec:"r"`
+ TxnBloomFilter encodedBloomFilter `codec:"b"`
+ UpdatedRequestParams requestParams `codec:"p"`
+ TransactionGroups packedTransactionGroups `codec:"g"`
+ MsgSync timingParams `codec:"t"`
+ RelayedProposal relayedProposal `codec:"rp"`
+}
+
+type encodedBloomFilter struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ BloomFilterType byte `codec:"t"`
+ EncodingParams requestParams `codec:"p"`
+ BloomFilter []byte `codec:"f,allocbound=maxBloomFilterSize"`
+ ClearPrevious byte `codec:"c"`
+}
+
+type requestParams struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ Offset byte `codec:"o"`
+ Modulator byte `codec:"m"`
+}
+
+const (
+ compressionFormatNone byte = iota
+ compressionFormatDeflate
+)
+
+type packedTransactionGroups struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ Bytes []byte `codec:"g,allocbound=maxEncodedTransactionGroupBytes"`
+ CompressionFormat byte `codec:"c"`
+ LenDecompressedBytes uint64 `codec:"l"`
+}
+
+type timingParams struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"` //nolint:structcheck,unused
+
+ RefTxnBlockMsgSeq uint64 `codec:"s"`
+ ResponseElapsedTime uint64 `codec:"r"`
+ AcceptedMsgSeq []uint64 `codec:"a,allocbound=maxAcceptedMsgSeq"`
+ NextMsgMinDelay uint64 `codec:"m"`
+}
+
+const (
+ noProposal byte = iota //nolint:deadcode,unused,varcheck
+ transactionsForProposal //nolint:deadcode,unused,varcheck
+)
+
+type relayedProposal struct {
+ _struct struct{} `codec:",omitempty,omitemptyarray"`
+
+ RawBytes []byte `codec:"b,allocbound=maxProposalSize"`
+ ExcludeProposal crypto.Digest `codec:"e"`
+ Content byte `codec:"c"`
+}
diff --git a/txnsync/incoming.go b/txnsync/incoming.go
new file mode 100644
index 000000000..d6365a6de
--- /dev/null
+++ b/txnsync/incoming.go
@@ -0,0 +1,313 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "errors"
+ "time"
+
+ "github.com/algorand/go-deadlock"
+
+ "github.com/algorand/go-algorand/data/pooldata"
+)
+
+var (
+ errUnsupportedTransactionSyncMessageVersion = errors.New("unsupported transaction sync message version")
+ errTransactionSyncIncomingMessageQueueFull = errors.New("transaction sync incoming message queue is full")
+ errInvalidBloomFilter = errors.New("invalid bloom filter")
+ errDecodingReceivedTransactionGroupsFailed = errors.New("failed to decode incoming transaction groups")
+)
+
+type incomingMessage struct {
+ networkPeer interface{}
+ message transactionBlockMessage
+ sequenceNumber uint64
+ peer *Peer
+ encodedSize int // the byte length of the incoming network message
+ bloomFilter *testableBloomFilter
+ transactionGroups []pooldata.SignedTxGroup
+}
+
+// incomingMessageQueue manages the global incoming message queue across all the incoming peers.
+type incomingMessageQueue struct {
+ incomingMessages chan incomingMessage
+ enqueuedPeers map[*Peer]struct{}
+ enqueuedPeersMu deadlock.Mutex
+}
+
+// maxPeersCount defines the maximum number of supported peers that can have their messages waiting
+// in the incoming message queue at the same time. This number can be lower then the actual number of
+// connected peers, as it's used only for pending messages.
+const maxPeersCount = 1024
+
+// makeIncomingMessageQueue creates an incomingMessageQueue object and initializes all the internal variables.
+func makeIncomingMessageQueue() incomingMessageQueue {
+ return incomingMessageQueue{
+ incomingMessages: make(chan incomingMessage, maxPeersCount),
+ enqueuedPeers: make(map[*Peer]struct{}, maxPeersCount),
+ }
+}
+
+// getIncomingMessageChannel returns the incoming messages channel, which would contain entries once
+// we have one ( or more ) pending incoming messages.
+func (imq *incomingMessageQueue) getIncomingMessageChannel() <-chan incomingMessage {
+ return imq.incomingMessages
+}
+
+// enqueue places the given message on the queue, if and only if it's associated peer doesn't
+// appear on the incoming message queue already. In the case there is no peer, the message
+// would be placed on the queue as is.
+// The method returns false if the incoming message doesn't have it's peer on the queue and
+// the method has failed to place the message on the queue. True is returned otherwise.
+func (imq *incomingMessageQueue) enqueue(m incomingMessage) bool {
+ if m.peer != nil {
+ imq.enqueuedPeersMu.Lock()
+ defer imq.enqueuedPeersMu.Unlock()
+ if _, has := imq.enqueuedPeers[m.peer]; has {
+ return true
+ }
+ }
+ select {
+ case imq.incomingMessages <- m:
+ // if we successfully enqueued the message, set the enqueuedPeers so that we won't enqueue the same peer twice.
+ if m.peer != nil {
+ // at this time, the enqueuedPeersMu is still under lock ( due to the above defer ), so we can access
+ // the enqueuedPeers here.
+ imq.enqueuedPeers[m.peer] = struct{}{}
+ }
+ return true
+ default:
+ return false
+ }
+}
+
+// clear removes the peer that is associated with the message ( if any ) from
+// the enqueuedPeers map, allowing future messages from this peer to be placed on the
+// incoming message queue.
+func (imq *incomingMessageQueue) clear(m incomingMessage) {
+ if m.peer != nil {
+ imq.enqueuedPeersMu.Lock()
+ defer imq.enqueuedPeersMu.Unlock()
+ delete(imq.enqueuedPeers, m.peer)
+ }
+}
+
+// incomingMessageHandler
+// note - this message is called by the network go-routine dispatch pool, and is not synchronized with the rest of the transaction synchronizer
+func (s *syncState) asyncIncomingMessageHandler(networkPeer interface{}, peer *Peer, message []byte, sequenceNumber uint64) (err error) {
+ // increase number of incoming messages metric.
+ txsyncIncomingMessagesTotal.Inc(nil)
+
+ // check the return value when we exit this function. if we fail, we increase the metric.
+ defer func() {
+ if err != nil {
+ // increase number of unprocessed incoming messages metric.
+ txsyncUnprocessedIncomingMessagesTotal.Inc(nil)
+ }
+ }()
+
+ incomingMessage := incomingMessage{networkPeer: networkPeer, sequenceNumber: sequenceNumber, encodedSize: len(message), peer: peer}
+ _, err = incomingMessage.message.UnmarshalMsg(message)
+ if err != nil {
+ // if we received a message that we cannot parse, disconnect.
+ s.log.Infof("received unparsable transaction sync message from peer. disconnecting from peer.")
+ return err
+ }
+
+ if incomingMessage.message.Version != txnBlockMessageVersion {
+ // we receive a message from a version that we don't support, disconnect.
+ s.log.Infof("received unsupported transaction sync message version from peer (%d). disconnecting from peer.", incomingMessage.message.Version)
+ return errUnsupportedTransactionSyncMessageVersion
+ }
+
+ // if the peer sent us a bloom filter, decode it
+ if !incomingMessage.message.TxnBloomFilter.MsgIsZero() {
+ bloomFilter, err := decodeBloomFilter(incomingMessage.message.TxnBloomFilter)
+ if err != nil {
+ s.log.Infof("Invalid bloom filter received from peer : %v", err)
+ return errInvalidBloomFilter
+ }
+ incomingMessage.bloomFilter = bloomFilter
+ // increase number of decoded bloom filters.
+ txsyncDecodedBloomFiltersTotal.Inc(nil)
+ }
+
+ // if the peer sent us any transactions, decode these.
+ incomingMessage.transactionGroups, err = decodeTransactionGroups(incomingMessage.message.TransactionGroups, s.genesisID, s.genesisHash)
+ if err != nil {
+ s.log.Infof("failed to decode received transactions groups: %v\n", err)
+ return errDecodingReceivedTransactionGroupsFailed
+ }
+
+ if peer == nil {
+ // if we don't have a peer, then we need to enqueue this task to be handled by the main loop since we want to ensure that
+ // all the peer objects are created synchronously.
+ enqueued := s.incomingMessagesQ.enqueue(incomingMessage)
+ if !enqueued {
+ // if we can't enqueue that, return an error, which would disconnect the peer.
+ // ( we have to disconnect, since otherwise, we would have no way to synchronize the sequence number)
+ s.log.Infof("unable to enqueue incoming message from a peer without txsync allocated data; incoming messages queue is full. disconnecting from peer.")
+ return errTransactionSyncIncomingMessageQueueFull
+ }
+ return nil
+ }
+ // place the incoming message on the *peer* heap, allowing us to dequeue it in the order by which it was received by the network library.
+ err = peer.incomingMessages.enqueue(incomingMessage)
+ if err != nil {
+ // if the incoming message queue for this peer is full, disconnect from this peer.
+ s.log.Infof("unable to enqueue incoming message into peer incoming message backlog. disconnecting from peer.")
+ return err
+ }
+
+ // (maybe) place the peer message on the main queue. This would get skipped if the peer is already on the queue.
+ enqueued := s.incomingMessagesQ.enqueue(incomingMessage)
+ if !enqueued {
+ // if we can't enqueue that, return an error, which would disconnect the peer.
+ s.log.Infof("unable to enqueue incoming message from a peer with txsync allocated data; incoming messages queue is full. disconnecting from peer.")
+ return errTransactionSyncIncomingMessageQueueFull
+ }
+ return nil
+}
+
+func (s *syncState) evaluateIncomingMessage(message incomingMessage) {
+ peer := message.peer
+ if peer == nil {
+ // check if a peer was created already for this network peer object.
+ peerInfo := s.node.GetPeer(message.networkPeer)
+ if peerInfo.NetworkPeer == nil {
+ // the message.networkPeer isn't a valid unicast peer, so we can exit right here.
+ return
+ }
+ if peerInfo.TxnSyncPeer == nil {
+ // we couldn't really do much about this message previously, since we didn't have the peer.
+ peer = makePeer(message.networkPeer, peerInfo.IsOutgoing, s.isRelay, &s.config, s.log)
+ // let the network peer object know about our peer
+ s.node.UpdatePeers([]*Peer{peer}, []interface{}{message.networkPeer}, 0)
+ } else {
+ peer = peerInfo.TxnSyncPeer
+ }
+ message.peer = peer
+ err := peer.incomingMessages.enqueue(message)
+ if err != nil {
+ // this is not really likely, since we won't saturate the peer heap right after creating it..
+ return
+ }
+ }
+ // clear the peer that is associated with this incoming message from the message queue, allowing future
+ // messages from the peer to be placed on the message queue.
+ s.incomingMessagesQ.clear(message)
+ messageProcessed := false
+ transactionPoolSize := 0
+ totalAccumulatedTransactionsCount := 0 // the number of transactions that were added during the execution of this method
+ transactionHandlerBacklogFull := false
+incomingMessageLoop:
+ for {
+ incomingMsg, seq, err := peer.incomingMessages.popSequence(peer.nextReceivedMessageSeq)
+ switch err {
+ case errHeapEmpty:
+ // this is very likely, once we run out of consecutive messages.
+ break incomingMessageLoop
+ case errSequenceNumberMismatch:
+ // if we receive a message which wasn't in-order, just let it go.
+ s.log.Debugf("received message out of order; seq = %d, expecting seq = %d\n", seq, peer.nextReceivedMessageSeq)
+ break incomingMessageLoop
+ }
+
+ // increase the message sequence number, since we're processing this message.
+ peer.nextReceivedMessageSeq++
+
+ // skip txnsync messages with proposalData for now
+ if !incomingMsg.message.RelayedProposal.MsgIsZero() {
+ continue
+ }
+
+ // update the round number if needed.
+ if incomingMsg.message.Round > peer.lastRound {
+ peer.lastRound = incomingMsg.message.Round
+ } else if incomingMsg.message.Round < peer.lastRound {
+ // peer sent us message for an older round, *after* a new round ?!
+ continue
+ }
+
+ // if the peer sent us a bloom filter, store this.
+ if incomingMsg.bloomFilter != nil {
+ peer.addIncomingBloomFilter(incomingMsg.message.Round, incomingMsg.bloomFilter, s.round)
+ }
+
+ peer.updateRequestParams(incomingMsg.message.UpdatedRequestParams.Modulator, incomingMsg.message.UpdatedRequestParams.Offset)
+ peer.updateIncomingMessageTiming(incomingMsg.message.MsgSync, s.round, s.clock.Since(), incomingMsg.encodedSize)
+
+ // if the peer's round is more than a single round behind the local node, then we don't want to
+ // try and load the transactions. The other peer should first catch up before getting transactions.
+ if (peer.lastRound + 1) < s.round {
+ if s.config.EnableVerbosedTransactionSyncLogging {
+ s.log.Infof("Incoming Txsync #%d late round %d", seq, peer.lastRound)
+ }
+ continue
+ }
+
+ // add the received transaction groups to the peer's recentSentTransactions so that we won't be sending these back to the peer.
+ peer.updateIncomingTransactionGroups(incomingMsg.transactionGroups)
+
+ // before enqueuing more data to the transaction pool, make sure we flush the ack channel
+ peer.dequeuePendingTransactionPoolAckMessages()
+
+ // if we received at least a single transaction group, then forward it to the transaction handler.
+ if len(incomingMsg.transactionGroups) > 0 {
+ // get the number of transactions ( not transaction groups !! ) from the transaction groups slice.
+ // this code is using the fact the we allocate all the transactions as a single array, and then slice
+ // them for the different transaction groups. The transaction handler would re-allocate the transactions that
+ // would be stored in the transaction pool.
+ totalTransactionCount := cap(incomingMsg.transactionGroups[0].Transactions)
+
+ // send the incoming transaction group to the node last, so that the txhandler could modify the underlaying array if needed.
+ currentTransactionPoolSize := s.node.IncomingTransactionGroups(peer, peer.nextReceivedMessageSeq-1, incomingMsg.transactionGroups)
+ // was the call reached the transaction handler queue ?
+ if currentTransactionPoolSize >= 0 {
+ // we want to store in transactionPoolSize only the first call to IncomingTransactionGroups:
+ // when multiple IncomingTransactionGroups calls are made within this for-loop, we want to get the current transaction pool size,
+ // plus an estimate for the optimistic size after all the transaction groups would get added. For that purpose, it would be sufficient
+ // to get the transaction pool size once. The precise size of the transaction pool here is not critical - we use it only for the purpose
+ // of calculating the beta number as well as figure if the transaction pool is full or not ( both of them are range-based ).
+ if transactionPoolSize == 0 {
+ transactionPoolSize = currentTransactionPoolSize
+ }
+ // add the transactions count to the accumulated count.
+ totalAccumulatedTransactionsCount += totalTransactionCount
+ } else {
+ // no - we couldn't add this group since the transaction handler buffer backlog exceeded it's capacity.
+ transactionHandlerBacklogFull = true
+ }
+ }
+
+ s.log.incomingMessage(msgStats{seq, incomingMsg.message.Round, len(incomingMsg.transactionGroups), incomingMsg.message.UpdatedRequestParams, len(incomingMsg.message.TxnBloomFilter.BloomFilter), incomingMsg.message.MsgSync.NextMsgMinDelay, peer.networkAddress()})
+ messageProcessed = true
+ }
+
+ // if we're a relay, this is an outgoing peer and we've processed a valid message,
+ // then we want to respond right away as well as schedule bloom message.
+ if messageProcessed && peer.isOutgoing && s.isRelay && peer.lastReceivedMessageNextMsgMinDelay != time.Duration(0) {
+ peer.state = peerStateStartup
+ // if we had another message coming from this peer previously, we need to ensure there are not scheduled tasks.
+ s.scheduler.peerDuration(peer)
+
+ s.scheduler.schedulePeer(peer, s.clock.Since())
+ }
+ if transactionPoolSize > 0 || transactionHandlerBacklogFull {
+ s.onTransactionPoolChangedEvent(MakeTransactionPoolChangeEvent(transactionPoolSize+totalAccumulatedTransactionsCount, transactionHandlerBacklogFull))
+ }
+}
diff --git a/txnsync/incoming_test.go b/txnsync/incoming_test.go
new file mode 100644
index 000000000..62782ff84
--- /dev/null
+++ b/txnsync/incoming_test.go
@@ -0,0 +1,343 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "errors"
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/msgp/msgp"
+
+ "github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/logging"
+ "github.com/algorand/go-algorand/test/partitiontest"
+)
+
+type incomingLogger struct {
+ logging.Logger
+ lastLogged string
+}
+
+func (ml *incomingLogger) Debugf(format string, args ...interface{}) {
+ ml.lastLogged = fmt.Sprintf(format, args...)
+}
+
+func (ml *incomingLogger) Infof(format string, args ...interface{}) {
+ ml.lastLogged = fmt.Sprintf(format, args...)
+}
+
+func TestAsyncIncomingMessageHandlerAndErrors(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ message := transactionBlockMessage{Version: 1}
+ messageBytes := message.MarshalMsg(nil)
+ sequenceNumber := uint64(1)
+ incLogger := incomingLogger{}
+
+ cfg := config.GetDefaultLocal()
+ mNodeConnector := &mockNodeConnector{transactionPoolSize: 3}
+ s := syncState{
+ log: wrapLogger(&incLogger, &cfg),
+ node: mNodeConnector,
+ }
+
+ // expect UnmarshalMsg error
+ messageBytes[0] = 0
+ err := s.asyncIncomingMessageHandler(nil, nil, messageBytes, sequenceNumber)
+ msgpe := msgp.TypeError{}
+ require.True(t, errors.As(err, &msgpe))
+
+ // expect wrong version error
+ message = transactionBlockMessage{Version: -3}
+ messageBytes = message.MarshalMsg(nil)
+ err = s.asyncIncomingMessageHandler(nil, nil, messageBytes, sequenceNumber)
+ require.Equal(t, errUnsupportedTransactionSyncMessageVersion, err)
+
+ // expect error decoding bloomFilter
+ message.Version = 1
+ message.TxnBloomFilter.BloomFilterType = byte(multiHashBloomFilter)
+ messageBytes = message.MarshalMsg(nil)
+ err = s.asyncIncomingMessageHandler(nil, nil, messageBytes, sequenceNumber)
+ require.Equal(t, errInvalidBloomFilter, err)
+
+ // error decoding transaction groups
+ message.TxnBloomFilter.BloomFilterType = byte(xorBloomFilter32)
+ bf, _ := filterFactoryXor32(1, &s)
+ bf.Set([]byte("aoeu1234aoeu1234"))
+ message.TxnBloomFilter.BloomFilter, err = bf.MarshalBinary()
+ require.NoError(t, err)
+ message.TransactionGroups = packedTransactionGroups{Bytes: []byte{1}}
+ messageBytes = message.MarshalMsg(nil)
+ err = s.asyncIncomingMessageHandler(nil, nil, messageBytes, sequenceNumber)
+ require.Equal(t, errDecodingReceivedTransactionGroupsFailed, err)
+
+ // error queue full
+ message.TransactionGroups = packedTransactionGroups{}
+ messageBytes = message.MarshalMsg(nil)
+ err = s.asyncIncomingMessageHandler(nil, nil, messageBytes, sequenceNumber)
+ require.Equal(t, errTransactionSyncIncomingMessageQueueFull, err)
+
+ // Success where peer == nil
+ s.incomingMessagesQ = makeIncomingMessageQueue()
+ err = s.asyncIncomingMessageHandler(nil, nil, messageBytes, sequenceNumber)
+ require.NoError(t, err)
+
+ peer := Peer{}
+
+ // error when placing the peer message on the main queue (incomingMessages cannot accept messages)
+ s.incomingMessagesQ = incomingMessageQueue{}
+ err = s.asyncIncomingMessageHandler(nil, &peer, messageBytes, sequenceNumber)
+ require.Equal(t, errTransactionSyncIncomingMessageQueueFull, err)
+
+ s.incomingMessagesQ = makeIncomingMessageQueue()
+ err = nil
+ // fill up the incoming message queue (one was already added)
+ for x := 1; x <= messageOrderingHeapLimit; x++ {
+ require.NoError(t, err)
+ err = s.asyncIncomingMessageHandler(nil, &peer, messageBytes, sequenceNumber)
+ }
+ require.Equal(t, errHeapReachedCapacity, err)
+}
+
+func TestEvaluateIncomingMessagePart1(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ message := incomingMessage{}
+ cfg := config.GetDefaultLocal()
+ peer := &Peer{}
+
+ incLogger := incomingLogger{}
+
+ mNodeConnector := &mockNodeConnector{}
+ mNodeConnector.peerInfo = PeerInfo{}
+ s := syncState{
+ node: mNodeConnector,
+ log: wrapLogger(&incLogger, &cfg),
+ clock: mNodeConnector.Clock()}
+
+ // Test the cases inside the peer == nil condition
+
+ // the message.networkPeer isn't a valid unicast peer
+ s.evaluateIncomingMessage(message)
+
+ // peer was already created
+ mNodeConnector.peerInfo.NetworkPeer = peer
+
+ s.evaluateIncomingMessage(message)
+ // no TxnSyncPeer in peerInfo
+ require.True(t, mNodeConnector.updatingPeers)
+ mNodeConnector.updatingPeers = false
+
+ s.incomingMessagesQ = makeIncomingMessageQueue()
+ // Add a peer here, and make sure it is cleared
+ s.incomingMessagesQ.enqueuedPeers[peer] = struct{}{}
+ mNodeConnector.peerInfo.TxnSyncPeer = peer
+ peer.incomingMessages = messageOrderingHeap{}
+ // TxnSyncPeer in peerInfo
+ s.evaluateIncomingMessage(message)
+ require.False(t, mNodeConnector.updatingPeers)
+ _, found := s.incomingMessagesQ.enqueuedPeers[peer]
+ require.False(t, found)
+
+ // fill the hip with messageOrderingHeapLimit elements so that the incomingMessages enqueue fails
+ for x := 0; x < messageOrderingHeapLimit; x++ {
+ err := peer.incomingMessages.enqueue(message)
+ require.NoError(t, err)
+ }
+ // Add a peer here, and make sure it is not cleared after the error
+ s.incomingMessagesQ.enqueuedPeers[peer] = struct{}{}
+ // TxnSyncPeer in peerInfo
+ s.evaluateIncomingMessage(message)
+ require.False(t, mNodeConnector.updatingPeers)
+ _, found = s.incomingMessagesQ.enqueuedPeers[peer]
+ require.True(t, found)
+}
+
+func TestEvaluateIncomingMessagePart2(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ cfg := config.GetDefaultLocal()
+ cfg.EnableVerbosedTransactionSyncLogging = true
+ peer := &Peer{}
+
+ incLogger := incomingLogger{}
+
+ mNodeConnector := &mockNodeConnector{transactionPoolSize: 3}
+ mNodeConnector.peerInfo = PeerInfo{NetworkPeer: peer}
+
+ s := syncState{
+ node: mNodeConnector,
+ log: wrapLogger(&incLogger, &cfg),
+ clock: mNodeConnector.Clock()}
+
+ // Test the branches in the for loop
+
+ mNodeConnector.peerInfo.TxnSyncPeer = peer
+ peer.incomingMessages = messageOrderingHeap{}
+
+ // txnsync messages with proposalData
+ err := peer.incomingMessages.enqueue(
+ incomingMessage{
+ sequenceNumber: 0,
+ message: transactionBlockMessage{
+ RelayedProposal: relayedProposal{Content: 10}}})
+ require.NoError(t, err)
+
+ // update the round number
+ err = peer.incomingMessages.enqueue(
+ incomingMessage{
+ sequenceNumber: 1,
+ message: transactionBlockMessage{Round: 4}})
+ require.NoError(t, err)
+
+ // peer sent a message for an older round, *after* a new round
+ err = peer.incomingMessages.enqueue(
+ incomingMessage{
+ sequenceNumber: 2,
+ message: transactionBlockMessage{Round: 2}})
+ require.NoError(t, err)
+
+ // peer sends a bloom filter
+ err = peer.incomingMessages.enqueue(
+ incomingMessage{
+ sequenceNumber: 3,
+ bloomFilter: &testableBloomFilter{encodingParams: requestParams{Offset: 8}},
+ message: transactionBlockMessage{Round: 4}})
+ require.NoError(t, err)
+
+ // message with a transaction group
+ err = peer.incomingMessages.enqueue(
+ incomingMessage{
+ sequenceNumber: 4,
+ transactionGroups: []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ Transactions: []transactions.SignedTxn{
+ transactions.SignedTxn{}}}},
+ message: transactionBlockMessage{Round: 4}})
+ require.NoError(t, err)
+ peer.recentSentTransactions = makeTransactionCache(5, 10, 20)
+
+ // receive a message not in order
+ s.evaluateIncomingMessage(incomingMessage{sequenceNumber: 11})
+ require.Equal(t, "received message out of order; seq = 11, expecting seq = 5\n", incLogger.lastLogged)
+ require.Equal(t, uint8(8), peer.recentIncomingBloomFilters[0].filter.encodingParams.Offset)
+
+ // currentTransactionPoolSize is -1
+ peer.incomingMessages = messageOrderingHeap{}
+ mNodeConnector.transactionPoolSize = -1
+ s.evaluateIncomingMessage(incomingMessage{
+ sequenceNumber: 5,
+ message: transactionBlockMessage{Round: 5},
+ transactionGroups: []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ Transactions: []transactions.SignedTxn{
+ transactions.SignedTxn{}}}},
+ })
+ require.Equal(t, "Incoming Txsync #5 round 5 transactions 1 request [0/0] bloom 0 nextTS 0 from ''", incLogger.lastLogged)
+
+}
+
+func TestEvaluateIncomingMessagePart3(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ cfg := config.GetDefaultLocal()
+ cfg.EnableVerbosedTransactionSyncLogging = true
+ peer := &Peer{isOutgoing: true, lastReceivedMessageNextMsgMinDelay: time.Duration(3)}
+
+ incLogger := incomingLogger{}
+
+ mNodeConnector := &mockNodeConnector{}
+ mNodeConnector.peerInfo = PeerInfo{NetworkPeer: peer}
+ mNodeConnector.peerInfo.TxnSyncPeer = peer
+
+ s := syncState{
+ node: mNodeConnector,
+ log: wrapLogger(&incLogger, &cfg),
+ clock: mNodeConnector.Clock(),
+ round: 1,
+ config: cfg,
+ isRelay: true,
+ scheduler: makePeerScheduler(),
+ }
+
+ // the peer will be added to s.scheduler
+ s.evaluateIncomingMessage(incomingMessage{
+ sequenceNumber: 0,
+ message: transactionBlockMessage{
+ MsgSync: timingParams{
+ NextMsgMinDelay: 3}}})
+ require.Equal(t, 1, len(s.scheduler.peers))
+
+ s.round = 3
+ s.evaluateIncomingMessage(incomingMessage{
+ sequenceNumber: 1,
+ message: transactionBlockMessage{
+ MsgSync: timingParams{
+ NextMsgMinDelay: 3}}})
+
+ require.Equal(t, "Incoming Txsync #1 late round 0", incLogger.lastLogged)
+}
+
+func TestEvaluateIncomingMessageAccumulatedTransactionsCount(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ cfg := config.GetDefaultLocal()
+ cfg.EnableVerbosedTransactionSyncLogging = true
+ peer := &Peer{}
+ peer.recentSentTransactions = makeTransactionCache(5, 10, 20)
+ incLogger := incomingLogger{}
+
+ mNodeConnector := &mockNodeConnector{transactionPoolSize: 3}
+ mNodeConnector.peerInfo = PeerInfo{NetworkPeer: peer}
+
+ s := syncState{
+ node: mNodeConnector,
+ log: wrapLogger(&incLogger, &cfg),
+ clock: mNodeConnector.Clock()}
+
+ mNodeConnector.peerInfo.TxnSyncPeer = peer
+ peer.incomingMessages = messageOrderingHeap{}
+
+ genesisID := "gID"
+ genesisHash := crypto.Hash([]byte("gh"))
+ txnGroups := getTxnGroups(genesisHash, genesisID)
+
+ // test with more than 200 transactions in the txnGroups
+ for x := 0; x < 100; x++ {
+ t := getTxnGroups(genesisHash, genesisID)
+ txnGroups = append(txnGroups, t...)
+ }
+
+ ptg, err := s.encodeTransactionGroups(txnGroups, 1000000000)
+ require.NoError(t, err)
+ txGroups, err := decodeTransactionGroups(ptg, genesisID, genesisHash)
+ require.NoError(t, err)
+
+ s.evaluateIncomingMessage(incomingMessage{
+ sequenceNumber: 0,
+ message: transactionBlockMessage{Round: 5},
+ transactionGroups: txGroups,
+ })
+ require.Equal(t, time.Duration(115586426), s.lastBeta)
+}
diff --git a/txnsync/interfaces.go b/txnsync/interfaces.go
new file mode 100644
index 000000000..976bdbc00
--- /dev/null
+++ b/txnsync/interfaces.go
@@ -0,0 +1,113 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/util/timers"
+)
+
+//msgp:ignore eventType
+type eventType int
+
+const (
+ transactionPoolChangedEvent eventType = 1
+ newRoundEvent eventType = 2
+)
+
+// RoundSettings is used to communicate the transaction syncer setting for a specific round
+type RoundSettings struct {
+ Round basics.Round
+ FetchTransactions bool // for non-relays that has no participation keys, there is no need to request transactions
+}
+
+// Event is an external triggering event
+type Event struct {
+ eventType
+
+ transactionPoolSize int
+ roundSettings RoundSettings
+ transactionHandlerBacklogFull bool
+}
+
+// IncomingMessageHandler is the signature of the incoming message handler used by the transaction sync to receive network messages
+type IncomingMessageHandler func(networkPeer interface{}, peer *Peer, message []byte, sequenceNumber uint64) error
+
+// SendMessageCallback define a message sent feedback for performing message tracking
+type SendMessageCallback func(enqueued bool, sequenceNumber uint64) error
+
+// PeerInfo describes a single peer returned by GetPeers or GetPeer
+type PeerInfo struct {
+ TxnSyncPeer *Peer
+ NetworkPeer interface{}
+ IsOutgoing bool
+}
+
+// networkPeerAddress is a subset of the network package HTTPPeer and UnicastPeer interface that
+// provides feedback for the destination address. It's used for logging out packet's destination addresses.
+type networkPeerAddress interface {
+ GetAddress() string
+}
+
+// NodeConnector is used by the transaction sync for communicating with components external to the txnsync package.
+type NodeConnector interface {
+ Events() <-chan Event
+ GetCurrentRoundSettings() RoundSettings // return the current round settings from the node
+ Clock() timers.WallClock
+ Random(uint64) uint64
+ GetPeers() []PeerInfo
+ GetPeer(interface{}) PeerInfo // get a single peer given a network peer opaque interface
+ // UpdatePeers call is being made to inform the node that either a link need to be established
+ // between the set of the txsyncPeers peers and the set of netPeers, or that the peersAverageDataExchangeRate
+ // was recalculated and could potentially be updated.
+ // The peersAverageDataExchangeRate passed in here is the average communication rate ( measured in bytes per second )
+ // across all the connected peers.
+ UpdatePeers(txsyncPeers []*Peer, netPeers []interface{}, peersAverageDataExchangeRate uint64)
+ SendPeerMessage(netPeer interface{}, msg []byte, callback SendMessageCallback)
+ // GetPendingTransactionGroups is called by the transaction sync when it needs to look into the transaction
+ // pool and get the updated set of pending transactions. The second returned argument is the latest locally originated
+ // group counter within the given transaction groups list. If there is no group that is locally originated, the expected
+ // value is InvalidSignedTxGroupCounter.
+ GetPendingTransactionGroups() (txGroups []pooldata.SignedTxGroup, latestLocallyOriginatedGroupCounter uint64)
+ // IncomingTransactionGroups is called by the transaction sync when transactions have been received and need
+ // to be stored in the transaction pool. The method returns the number of transactions in the transaction
+ // pool before the txGroups is applied. A negative value is returned if the provided txGroups could not be applied
+ // to the transaction pool.
+ IncomingTransactionGroups(peer *Peer, messageSeq uint64, txGroups []pooldata.SignedTxGroup) (transactionPoolSize int)
+ NotifyMonitor() chan struct{}
+}
+
+// MakeTransactionPoolChangeEvent creates an event for when a txn pool size has changed.
+func MakeTransactionPoolChangeEvent(transactionPoolSize int, transactionHandlerBacklogFull bool) Event {
+ return Event{
+ eventType: transactionPoolChangedEvent,
+ transactionPoolSize: transactionPoolSize,
+ transactionHandlerBacklogFull: transactionHandlerBacklogFull,
+ }
+}
+
+// MakeNewRoundEvent creates an event for when a new round starts
+func MakeNewRoundEvent(roundNumber basics.Round, fetchTransactions bool) Event {
+ return Event{
+ eventType: newRoundEvent,
+ roundSettings: RoundSettings{
+ Round: roundNumber,
+ FetchTransactions: fetchTransactions,
+ },
+ }
+}
diff --git a/txnsync/logger.go b/txnsync/logger.go
new file mode 100644
index 000000000..802387168
--- /dev/null
+++ b/txnsync/logger.go
@@ -0,0 +1,88 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/logging"
+)
+
+// make a local alias of the type so that we can refer to it without '.'
+type algodlogger = logging.Logger
+
+type msgStats struct {
+ sequenceNumber uint64
+ round basics.Round
+ transactions int
+ offsetModulator requestParams
+ bloomSize int
+ nextMsgMinDelay uint64
+ peerAddress string
+}
+
+type msgLogger interface {
+ outgoingMessage(mstat msgStats)
+ incomingMessage(mstat msgStats)
+}
+
+// Logger is go-algorand/logging.Logger with some private additions for txnsync
+type Logger interface {
+ logging.Logger
+ msgLogger
+}
+
+type basicMsgLogger struct {
+ algodlogger
+ config *config.Local
+}
+
+func wrapLogger(l logging.Logger, config *config.Local) Logger {
+ if ll, ok := l.(Logger); ok {
+ return ll
+ }
+ out := &basicMsgLogger{
+ algodlogger: l,
+ config: config,
+ }
+ return out
+}
+
+func (l *basicMsgLogger) logMessage(mstat msgStats, mode, tofrom string) {
+ if !l.config.EnableVerbosedTransactionSyncLogging {
+ return
+ }
+ l.Infof(
+ "%s Txsync #%d round %d transactions %d request [%d/%d] bloom %d nextTS %d %s '%s'",
+ mode,
+ mstat.sequenceNumber,
+ mstat.round,
+ mstat.transactions,
+ mstat.offsetModulator.Offset,
+ mstat.offsetModulator.Modulator,
+ mstat.bloomSize,
+ mstat.nextMsgMinDelay,
+ tofrom,
+ mstat.peerAddress,
+ )
+}
+func (l *basicMsgLogger) outgoingMessage(mstat msgStats) {
+ l.logMessage(mstat, "Outgoing", "to")
+}
+func (l *basicMsgLogger) incomingMessage(mstat msgStats) {
+ l.logMessage(mstat, "Incoming", "from")
+}
diff --git a/txnsync/mainloop.go b/txnsync/mainloop.go
new file mode 100644
index 000000000..ca899bc9c
--- /dev/null
+++ b/txnsync/mainloop.go
@@ -0,0 +1,437 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "context"
+ "math"
+ "sync"
+ "time"
+
+ "github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/util/bloom"
+ "github.com/algorand/go-algorand/util/execpool"
+ "github.com/algorand/go-algorand/util/timers"
+)
+
+const (
+ kickoffTime = 200 * time.Millisecond
+ randomRange = 100 * time.Millisecond
+ sendMessagesTime = 10 * time.Millisecond
+
+ // transactionPoolLowWatermark is the low watermark for the transaction pool, relative
+ // to the transaction pool size. When the number of transactions in the transaction pool
+ // drops below this value, the transactionPoolFull flag would get cleared.
+ transactionPoolLowWatermark = float32(0.8)
+
+ // transactionPoolHighWatermark is the low watermark for the transaction pool, relative
+ // to the transaction pool size. When the number of transactions in the transaction pool
+ // grows beyond this value, the transactionPoolFull flag would get set.
+ transactionPoolHighWatermark = float32(0.9)
+
+ // betaGranularChangeThreshold defined the difference threshold for changing the beta value.
+ // Changes to the beta value only takes effect once the difference is sufficiently big enough
+ // comared to the current beta value.
+ betaGranularChangeThreshold = 0.1
+)
+
+type syncState struct {
+ service *Service
+ log Logger
+ node NodeConnector
+ isRelay bool
+ clock timers.WallClock
+ config config.Local
+ threadpool execpool.BacklogPool
+
+ genesisID string
+ genesisHash crypto.Digest
+
+ // lastBeta is the last beta value that was calculated for this node
+ lastBeta time.Duration
+ round basics.Round
+ fetchTransactions bool
+ scheduler peerScheduler
+ interruptablePeers []*Peer
+ interruptablePeersMap map[*Peer]int // map a peer into the index of interruptablePeers
+ incomingMessagesQ incomingMessageQueue
+ outgoingMessagesCallbackCh chan sentMessageMetadata
+ nextOffsetRollingCh <-chan time.Time
+ requestsOffset uint64
+
+ // The lastBloomFilter allows us to share the same bloom filter across multiples messages,
+ // and compute it only once. Since this bloom filter could contain many hashes ( especially on relays )
+ // it's important to avoid recomputing it needlessly.
+ lastBloomFilter bloomFilter
+
+ // The profiler helps us monitor the transaction sync components execution time. When enabled, it would report these
+ // to the telemetry.
+ profiler *profiler
+
+ // transactionPoolFull indicates whether the transaction pool is currently in "full" state or not. While the transaction
+ // pool is full, a node would not ask any of the other peers for additional transactions.
+ transactionPoolFull bool
+
+ // messageSendWaitGroup coordinates the messages that are being sent to the network. Before aborting the mainloop, we want to make
+ // sure there are no outbound messages that are waiting to be sent to the network ( i.e. that all the tasks that we enqueued to the
+ // execution pool were completed ). This does not include the time where the message spent while waiting on the network queue itself.
+ messageSendWaitGroup sync.WaitGroup
+
+ xorBuilder bloom.XorBuilder
+}
+
+func (s *syncState) mainloop(serviceCtx context.Context, wg *sync.WaitGroup) {
+ defer wg.Done()
+ defer s.messageSendWaitGroup.Wait()
+
+ // The following would allow the emulator to start the service in a "stopped" mode.
+ s.node.NotifyMonitor()
+
+ s.clock = s.node.Clock()
+ s.incomingMessagesQ = makeIncomingMessageQueue()
+ s.outgoingMessagesCallbackCh = make(chan sentMessageMetadata, 1024)
+ s.interruptablePeersMap = make(map[*Peer]int)
+ s.scheduler.node = s.node
+ s.lastBeta = beta(0)
+ roundSettings := s.node.GetCurrentRoundSettings()
+ s.onNewRoundEvent(MakeNewRoundEvent(roundSettings.Round, roundSettings.FetchTransactions))
+
+ // create a profiler, and its profiling elements.
+ s.profiler = makeProfiler(200*time.Millisecond, s.clock, s.log, 2000*time.Millisecond) // todo : make the time configurable.
+ profIdle := s.profiler.getElement(profElementIdle)
+ profTxChange := s.profiler.getElement(profElementTxChange)
+ profNewRounnd := s.profiler.getElement(profElementNewRound)
+ profPeerState := s.profiler.getElement(profElementPeerState)
+ profIncomingMsg := s.profiler.getElement(profElementIncomingMsg)
+ profOutgoingMsg := s.profiler.getElement(profElementOutgoingMsg)
+ profNextOffset := s.profiler.getElement(profElementNextOffset)
+
+ externalEvents := s.node.Events()
+ var nextPeerStateCh <-chan time.Time
+ for {
+ nextPeerStateTime := s.scheduler.nextDuration()
+ if nextPeerStateTime != time.Duration(0) {
+ nextPeerStateCh = s.clock.TimeoutAt(nextPeerStateTime)
+ } else {
+ nextPeerStateCh = nil
+ }
+
+ select {
+ case ent := <-externalEvents:
+ switch ent.eventType {
+ case transactionPoolChangedEvent:
+ profTxChange.start()
+ s.onTransactionPoolChangedEvent(ent)
+ profTxChange.end()
+ case newRoundEvent:
+ profNewRounnd.start()
+ s.onNewRoundEvent(ent)
+ profNewRounnd.end()
+ }
+ continue
+ case <-nextPeerStateCh:
+ profPeerState.start()
+ s.evaluatePeerStateChanges(nextPeerStateTime)
+ profPeerState.end()
+ continue
+ case incomingMsg := <-s.incomingMessagesQ.getIncomingMessageChannel():
+ profIncomingMsg.start()
+ s.evaluateIncomingMessage(incomingMsg)
+ profIncomingMsg.end()
+ continue
+ case msgSent := <-s.outgoingMessagesCallbackCh:
+ profOutgoingMsg.start()
+ s.evaluateOutgoingMessage(msgSent)
+ profOutgoingMsg.end()
+ continue
+ case <-s.nextOffsetRollingCh:
+ profNextOffset.start()
+ s.rollOffsets()
+ profNextOffset.end()
+ continue
+ case <-serviceCtx.Done():
+ return
+ default:
+ }
+
+ profIdle.start()
+ select {
+ case ent := <-externalEvents:
+ profIdle.end()
+ switch ent.eventType {
+ case transactionPoolChangedEvent:
+ profTxChange.start()
+ s.onTransactionPoolChangedEvent(ent)
+ profTxChange.end()
+ case newRoundEvent:
+ profNewRounnd.start()
+ s.onNewRoundEvent(ent)
+ profNewRounnd.end()
+ }
+ case <-nextPeerStateCh:
+ profIdle.end()
+ profPeerState.start()
+ s.evaluatePeerStateChanges(nextPeerStateTime)
+ profPeerState.end()
+ case incomingMsg := <-s.incomingMessagesQ.getIncomingMessageChannel():
+ profIdle.end()
+ profIncomingMsg.start()
+ s.evaluateIncomingMessage(incomingMsg)
+ profIncomingMsg.end()
+ case msgSent := <-s.outgoingMessagesCallbackCh:
+ profIdle.end()
+ profOutgoingMsg.start()
+ s.evaluateOutgoingMessage(msgSent)
+ profOutgoingMsg.end()
+ case <-s.nextOffsetRollingCh:
+ profIdle.end()
+ profNextOffset.start()
+ s.rollOffsets()
+ profNextOffset.end()
+ case <-serviceCtx.Done():
+ profIdle.end()
+ return
+ case <-s.node.NotifyMonitor():
+ profIdle.end()
+ }
+ }
+}
+
+func (s *syncState) onTransactionPoolChangedEvent(ent Event) {
+ if ent.transactionHandlerBacklogFull {
+ // if the transaction handler backlog is full, we don't want to receive any more transactions.
+ // setting the transactionPoolFull here would notify other nodes that we don't want any more messages.
+ s.transactionPoolFull = true
+ } else if s.transactionPoolFull {
+ // the transaction pool is currently full.
+ if float32(ent.transactionPoolSize) < float32(s.config.TxPoolSize)*transactionPoolLowWatermark {
+ s.transactionPoolFull = false
+ }
+ } else {
+ if float32(ent.transactionPoolSize) > float32(s.config.TxPoolSize)*transactionPoolHighWatermark {
+ s.transactionPoolFull = true
+ }
+ }
+
+ newBeta := beta(ent.transactionPoolSize)
+
+ // check if beta should be updated
+ if !shouldUpdateBeta(s.lastBeta, newBeta, betaGranularChangeThreshold) {
+ // no changes
+ return
+ }
+ // yes, change beta as the number of transactions in the pool have changed dramatically since the last time.
+ s.lastBeta = newBeta
+
+ peers := make([]*Peer, 0, len(s.interruptablePeers))
+ for _, peer := range s.interruptablePeers {
+ if peer == nil {
+ continue
+ }
+ peers = append(peers, peer)
+ peer.state = peerStateHoldsoff
+ }
+
+ // reset the interruptablePeers array, since all it's members were made into holdsoff
+ s.interruptablePeers = nil
+ s.interruptablePeersMap = make(map[*Peer]int)
+ deadlineMonitor := s.clock.DeadlineMonitorAt(s.clock.Since() + sendMessagesTime)
+ s.sendMessageLoop(s.clock.Since(), deadlineMonitor, peers)
+
+ currentTimeout := s.clock.Since()
+ for _, peer := range peers {
+ peerNext := s.scheduler.peerDuration(peer)
+ if peerNext < currentTimeout {
+ // shouldn't be, but let's reschedule it if this is the case.
+ s.scheduler.schedulePeer(peer, currentTimeout+s.lastBeta)
+ continue
+ }
+ // given that peerNext is after currentTimeout, find out what's the difference, and divide by the beta.
+ betaCount := (peerNext - currentTimeout) / s.lastBeta
+ peerNext = currentTimeout + s.lastBeta*betaCount
+ s.scheduler.schedulePeer(peer, peerNext)
+ }
+}
+
+// calculate the beta parameter, based on the transaction pool size.
+func beta(txPoolSize int) time.Duration {
+ if txPoolSize < 200 {
+ txPoolSize = 200
+ } else if txPoolSize > 10000 {
+ txPoolSize = 10000
+ }
+ beta := 1.0 / (2 * 3.6923 * math.Exp(float64(txPoolSize)*0.00026))
+ return time.Duration(float64(time.Second) * beta)
+
+}
+
+func shouldUpdateBeta(currentBeta, newBeta time.Duration, betaGranularChangeThreshold float32) bool {
+ // see if the newBeta is at least threshold percent smaller or bigger than the current one
+ if float32(newBeta) >= (float32(currentBeta) * (1.0 + betaGranularChangeThreshold)) {
+ return true
+ }
+ if float32(newBeta) <= (float32(currentBeta) * (1.0 - betaGranularChangeThreshold)) {
+ return true
+ }
+ // no, it's not.
+ return false
+}
+
+func (s *syncState) onNewRoundEvent(ent Event) {
+ s.clock = s.clock.Zero().(timers.WallClock)
+ peers := s.getPeers()
+ newRoundPeers := peers
+ if s.isRelay {
+ // on relays, outgoing peers have a difference scheduling, which is based on the incoming message timing
+ // rather then a periodic message transmission.
+ newRoundPeers = incomingPeersOnly(newRoundPeers)
+ }
+ s.scheduler.scheduleNewRound(newRoundPeers)
+ s.round = ent.roundSettings.Round
+ s.fetchTransactions = ent.roundSettings.FetchTransactions
+ if !s.isRelay {
+ s.nextOffsetRollingCh = s.clock.TimeoutAt(kickoffTime + 2*s.lastBeta)
+ }
+ s.updatePeersRequestParams(peers)
+}
+
+func (s *syncState) evaluatePeerStateChanges(currentTimeout time.Duration) {
+ peers := s.scheduler.getNextPeers()
+ if len(peers) == 0 {
+ return
+ }
+
+ sendMessagePeers := 0
+ for _, peer := range peers {
+ ops := peer.advancePeerState(currentTimeout, s.isRelay)
+ if (ops & peerOpsSendMessage) == peerOpsSendMessage {
+ peers[sendMessagePeers] = peer
+ sendMessagePeers++
+ }
+ if (ops & peerOpsSetInterruptible) == peerOpsSetInterruptible {
+ if _, has := s.interruptablePeersMap[peer]; !has {
+ s.interruptablePeers = append(s.interruptablePeers, peer)
+ s.interruptablePeersMap[peer] = len(s.interruptablePeers) - 1
+ }
+ }
+ if (ops & peerOpsClearInterruptible) == peerOpsClearInterruptible {
+ if idx, has := s.interruptablePeersMap[peer]; has {
+ delete(s.interruptablePeersMap, peer)
+ s.interruptablePeers[idx] = nil
+ }
+ }
+ if (ops & peerOpsReschedule) == peerOpsReschedule {
+ s.scheduler.schedulePeer(peer, currentTimeout+s.lastBeta)
+ }
+ }
+
+ peers = peers[:sendMessagePeers]
+ deadlineMonitor := s.clock.DeadlineMonitorAt(currentTimeout + sendMessagesTime)
+ s.sendMessageLoop(currentTimeout, deadlineMonitor, peers)
+}
+
+// rollOffsets rolls the "base" offset for the peers offset selection. This method is only called
+// for non-relays.
+func (s *syncState) rollOffsets() {
+ s.nextOffsetRollingCh = s.clock.TimeoutAt(s.clock.Since() + 2*s.lastBeta)
+ s.requestsOffset++
+
+ if !s.fetchTransactions {
+ return
+ }
+
+ // iterate on the outgoing peers and see if we want to send them an update as needed.
+ // note that because this function is only called for non-relays, then all the connections
+ // are outgoing.
+ peers := s.getPeers()
+ s.updatePeersRequestParams(peers)
+
+ // check when each of these peers is expected to send a message. we might want to promote a message to be sent earlier.
+ currentTimeOffset := s.clock.Since()
+ deadlineMonitor := s.clock.DeadlineMonitorAt(currentTimeOffset + sendMessagesTime)
+
+ for _, peer := range peers {
+ nextSchedule := s.scheduler.peerDuration(peer)
+ if nextSchedule == 0 {
+ // a new peer - ignore for now. This peer would get scheduled on the next new round.
+ continue
+ }
+ if currentTimeOffset+sendMessagesTime > nextSchedule {
+ // there was a message scheduled already in less than 20ms, so keep that one.
+ s.scheduler.schedulePeer(peer, nextSchedule)
+ continue
+ }
+
+ // otherwise, send a message to that peer. Note that we're passing the `nextSchedule-s.lastBeta` as the currentTime,
+ // so that the time offset would be based on that one. ( i.e. effectively, it would retain the existing timing, and prevent
+ // the peers from getting aligned )
+ s.sendMessageLoop(nextSchedule-s.lastBeta, deadlineMonitor, []*Peer{peer})
+ }
+}
+
+func (s *syncState) getPeers() (result []*Peer) {
+ peersInfo := s.node.GetPeers()
+ updatedNetworkPeers := []interface{}{}
+ updatedNetworkPeersSync := []*Peer{}
+
+ var averageDataExchangeRate uint64
+
+ // some of the network peers might not have a sync peer, so we need to create one for these.
+ for _, peerInfo := range peersInfo {
+ if peerInfo.TxnSyncPeer == nil {
+ syncPeer := makePeer(peerInfo.NetworkPeer, peerInfo.IsOutgoing, s.isRelay, &s.config, s.log)
+ peerInfo.TxnSyncPeer = syncPeer
+ updatedNetworkPeers = append(updatedNetworkPeers, peerInfo.NetworkPeer)
+ updatedNetworkPeersSync = append(updatedNetworkPeersSync, syncPeer)
+ }
+ result = append(result, peerInfo.TxnSyncPeer)
+ averageDataExchangeRate += peerInfo.TxnSyncPeer.dataExchangeRate
+ }
+ if len(peersInfo) > 0 {
+ averageDataExchangeRate /= uint64(len(peersInfo))
+ }
+
+ // if we have any update for the transaction sync connector, the send them via
+ // a UpdatePeers call.
+ if len(updatedNetworkPeers) > 0 || len(peersInfo) > 0 {
+ s.node.UpdatePeers(updatedNetworkPeersSync, updatedNetworkPeers, averageDataExchangeRate)
+ }
+ return result
+}
+
+func (s *syncState) updatePeersRequestParams(peers []*Peer) {
+ if s.transactionPoolFull {
+ for _, peer := range peers {
+ peer.setLocalRequestParams(0, 0)
+ }
+ return
+ }
+ if s.isRelay {
+ for _, peer := range peers {
+ peer.setLocalRequestParams(0, 1)
+ }
+ } else {
+ if s.fetchTransactions {
+ for i, peer := range peers {
+ // on non-relay, ask for offset/modulator
+ peer.setLocalRequestParams(uint64(i)+s.requestsOffset, uint64(len(peers)))
+ }
+ }
+ }
+}
diff --git a/txnsync/mainloop_test.go b/txnsync/mainloop_test.go
new file mode 100644
index 000000000..5622636d8
--- /dev/null
+++ b/txnsync/mainloop_test.go
@@ -0,0 +1,71 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/test/partitiontest"
+)
+
+func TestBeta(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ beta0 := beta(0)
+ beta10000 := beta(10000)
+ require.GreaterOrEqual(t, int64(beta0), int64(100*time.Millisecond))
+ require.LessOrEqual(t, int64(beta10000), int64(20*time.Millisecond))
+ for i := 50; i < 20000; i += 50 {
+ prev := beta(i - 50)
+ cur := beta(i)
+ require.LessOrEqualf(t, int64(cur), int64(prev), fmt.Sprintf("beta(%d) < beta(%d)", i, i-50))
+ }
+
+}
+
+func TestShouldUpdateBeta(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ beta0 := beta(0)
+ beta100 := beta(100)
+ beta5000 := beta(5000)
+ beta5100 := beta(5100)
+ beta5900 := beta(5900)
+ beta6000 := beta(6000)
+ beta10000 := beta(10000)
+ beta15000 := beta(15000)
+
+ // new beta greater than betaGranularChangeThreshold times previous beta
+ require.True(t, shouldUpdateBeta(beta0, beta10000, betaGranularChangeThreshold))
+ require.True(t, shouldUpdateBeta(beta5000, beta6000, betaGranularChangeThreshold))
+
+ //same beta values
+ require.False(t, shouldUpdateBeta(beta0, beta100, betaGranularChangeThreshold))
+ require.False(t, shouldUpdateBeta(beta10000, beta15000, betaGranularChangeThreshold))
+
+ // new beta lesser than betaGranularChangeThreshold times previous beta
+ require.True(t, shouldUpdateBeta(beta15000, beta0, betaGranularChangeThreshold))
+ require.True(t, shouldUpdateBeta(beta6000, beta100, betaGranularChangeThreshold))
+
+ // no change in beta is expected
+ require.False(t, shouldUpdateBeta(beta5000, beta5100, betaGranularChangeThreshold))
+ require.False(t, shouldUpdateBeta(beta6000, beta5900, betaGranularChangeThreshold))
+}
diff --git a/txnsync/metrics.go b/txnsync/metrics.go
new file mode 100644
index 000000000..d2bcbdd9b
--- /dev/null
+++ b/txnsync/metrics.go
@@ -0,0 +1,28 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "github.com/algorand/go-algorand/util/metrics"
+)
+
+var txsyncIncomingMessagesTotal = metrics.MakeCounter(metrics.MetricName{Name: "algod_txsync_incoming_messages_total", Description: "total number of incoming transaction sync messages"})
+var txsyncUnprocessedIncomingMessagesTotal = metrics.MakeCounter(metrics.MetricName{Name: "algod_txsync_unprocessed_incoming_messages_total", Description: "total number of incoming transaction sync messages that were not processed"})
+var txsyncDecodedBloomFiltersTotal = metrics.MakeCounter(metrics.MetricName{Name: "algod_txsync_decoded_bloom_filters_total", Description: "total number of decoded bloom filters"})
+var txsyncCreatedPeersTotal = metrics.MakeCounter(metrics.MetricName{Name: "algod_txsync_created_peers_total", Description: "total number of created peers"})
+var txsyncOutgoingMessagesTotal = metrics.MakeCounter(metrics.MetricName{Name: "algod_txsync_outgoing_messages_total", Description: "total number of outgoing transaction sync messages"})
+var txsyncEncodedBloomFiltersTotal = metrics.MakeCounter(metrics.MetricName{Name: "algod_txsync_encoded_bloom_filters_total", Description: "total number of bloom filters encoded"})
diff --git a/txnsync/msgbuffers.go b/txnsync/msgbuffers.go
new file mode 100644
index 000000000..a531f6da2
--- /dev/null
+++ b/txnsync/msgbuffers.go
@@ -0,0 +1,76 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "sync"
+
+ "github.com/algorand/go-algorand/data/transactions"
+)
+
+const messageBufferDefaultInitialSize = 10240
+
+// msgBuffersPool holds temporary byte slice buffers used for encoding messages.
+var msgBuffersPool = sync.Pool{
+ New: func() interface{} {
+ return make([]byte, 0, messageBufferDefaultInitialSize)
+ },
+}
+
+// GetEncodingBuf returns a byte slice that can be used for encoding a
+// temporary message. The byte slice has zero length but potentially
+// non-zero capacity. The caller gets full ownership of the byte slice,
+// but is encouraged to return it using releaseMessageBuffer().
+func getMessageBuffer() []byte {
+ return msgBuffersPool.Get().([]byte)[:0]
+}
+
+// releaseMessageBuffer places a byte slice into the pool of temporary buffers
+// for encoding. The caller gives up ownership of the byte slice when
+// passing it to releaseMessageBuffer().
+func releaseMessageBuffer(s []byte) {
+ msgBuffersPool.Put(s) //nolint:staticcheck
+}
+
+// txidSlicePool holds temporary byte slice buffers used for encoding messages.
+var txidSlicePool = sync.Pool{}
+
+// getTxIDSliceBuffer returns a slice that can be used for storing a
+// list of transaction IDs. The slice has zero length but potentially
+// non-zero capacity. The caller gets full ownership of the slice,
+// but is encouraged to return it using releaseTxIDSliceBuffer().
+func getTxIDSliceBuffer(minSize int) []transactions.Txid {
+ alloc := txidSlicePool.Get()
+ if alloc == nil {
+ return make([]transactions.Txid, 0, minSize)
+ }
+ buf := alloc.([]transactions.Txid)[:0]
+ if cap(buf) >= minSize {
+ return buf
+ }
+ txidSlicePool.Put(alloc)
+ return make([]transactions.Txid, 0, minSize)
+}
+
+// releaseTxIDSliceBuffer places a slice into the pool of buffers
+// for storage. The caller gives up ownership of the byte slice when
+// passing it to releaseMessageBuffer().
+func releaseTxIDSliceBuffer(s []transactions.Txid) {
+ if cap(s) > 0 {
+ txidSlicePool.Put(s) //nolint:staticcheck
+ }
+}
diff --git a/txnsync/msgbuffers_test.go b/txnsync/msgbuffers_test.go
new file mode 100644
index 000000000..f53a4bd0d
--- /dev/null
+++ b/txnsync/msgbuffers_test.go
@@ -0,0 +1,143 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/test/partitiontest"
+)
+
+// A unique length that we can use to identify non-default allocated buffers
+var uniqueLength int = messageBufferDefaultInitialSize + 482
+var uniqueIdentifier int = 50
+
+// Stamp a byte buffer with a unique identifier, assumes a capacity of at least unique_length
+func stampBuffer(i int, buf *[]byte) {
+ if cap(*buf) < uniqueLength {
+ return
+ }
+
+ *buf = (*buf)[:cap(*buf)]
+
+ for j := 0; j < i; j++ {
+ (*buf)[uniqueLength-1-j] = byte(j)
+ }
+
+}
+
+func validBuffer(i int, buf *[]byte) bool {
+
+ if cap(*buf) != uniqueLength {
+ return false
+ }
+
+ *buf = (*buf)[:cap(*buf)]
+
+ for j := 0; j < i; j++ {
+ if (*buf)[uniqueLength-1-j] != byte(j) {
+ return false
+ }
+ }
+
+ return true
+}
+
+// TestMessageBuffersPool tests that a buffer pool can be retrieved and has proper length/capacity properties
+func TestMessageBuffersPool(t *testing.T) {
+
+ partitiontest.PartitionTest(t)
+
+ foundBuffer := false
+
+ for retryCount := 0; retryCount < 10; retryCount++ {
+
+ // Let's put a bunch of uniquely identifiable buffers in the global pool
+ for i := 0; i < 10; i++ {
+
+ bytes := make([]byte, 0, uniqueLength)
+ stampBuffer(uniqueIdentifier, &bytes)
+
+ releaseMessageBuffer(bytes)
+ }
+
+ collector := [][]byte{}
+
+ // Let's try to get at least one buffer that is uniquely identifiable over a period of time
+ for i := 0; i < 10000; i++ {
+ byte := getMessageBuffer()
+
+ collector = append(collector, byte)
+
+ if validBuffer(uniqueIdentifier, &byte) {
+ foundBuffer = true
+ break
+ }
+
+ time.Sleep(500 * time.Microsecond)
+ }
+
+ for _, b := range collector {
+ releaseMessageBuffer(b)
+ }
+
+ if foundBuffer {
+ // If we found a buffer, we passed the test
+ break
+ }
+
+ // Otherwise, let's start all over again
+ }
+
+ require.True(t, foundBuffer)
+
+}
+
+// TestTxIDSlicePool tests that the transaction id pool can be retrieved and has proper length/capacity properties
+func TestTxIDSlicePool(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ maxTestCount := 200
+ for testCount := 0; testCount < maxTestCount; testCount++ {
+ for i := 10; i < 100; i += 10 {
+ txIDs := getTxIDSliceBuffer(i)
+ require.Equal(t, 0, len(txIDs))
+ require.GreaterOrEqual(t, cap(txIDs), i)
+ releaseTxIDSliceBuffer(txIDs)
+ }
+
+ // Test that one of the previous buffers can be reused
+ // We can assess this because all the previous buffers created
+ // had a capacity greater than 10, so if one of these buffers
+ // has a buffer size of at least 10 (when we asked for 5), we can
+ // be assured that we have reused a previous buffer
+ txIDs := getTxIDSliceBuffer(5)
+ require.Equal(t, 0, len(txIDs))
+ require.GreaterOrEqual(t, cap(txIDs), 5)
+ if cap(txIDs) < 10 {
+ // repeat this test again. it looks like the GC collected all the content
+ // of the pool and forced us to allocate a new buffer.
+ time.Sleep(10 * time.Millisecond)
+ continue
+ }
+ releaseTxIDSliceBuffer(txIDs)
+ return
+ }
+ require.FailNow(t, "failed to get a 5 entries buffer from slice pool")
+}
diff --git a/txnsync/msgorderingheap.go b/txnsync/msgorderingheap.go
new file mode 100644
index 000000000..69758216b
--- /dev/null
+++ b/txnsync/msgorderingheap.go
@@ -0,0 +1,100 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "container/heap"
+ "errors"
+
+ "github.com/algorand/go-deadlock"
+)
+
+var errHeapEmpty = errors.New("message ordering heap is empty")
+var errHeapReachedCapacity = errors.New("message ordering heap reached capacity")
+var errSequenceNumberMismatch = errors.New("sequence number mismatch")
+
+const messageOrderingHeapLimit = 128
+
+type messageHeapItem incomingMessage
+
+type messageOrderingHeap struct {
+ mu deadlock.Mutex
+ messages []messageHeapItem
+}
+
+// Push implements heap.Interface
+func (p *messageOrderingHeap) Push(x interface{}) {
+ entry := x.(messageHeapItem)
+ p.messages = append(p.messages, entry)
+}
+
+// Pop implements heap.Interface
+func (p *messageOrderingHeap) Pop() interface{} {
+ end := len(p.messages) - 1
+ res := p.messages[end]
+ p.messages[end] = messageHeapItem{}
+ p.messages = p.messages[0:end]
+ return res
+}
+
+// Len implements heap.Interface
+func (p *messageOrderingHeap) Len() int {
+ return len(p.messages)
+}
+
+// Swap implements heap.Interface
+func (p *messageOrderingHeap) Swap(i, j int) {
+ p.messages[i], p.messages[j] = p.messages[j], p.messages[i]
+}
+
+// Less implements heap.Interface
+func (p *messageOrderingHeap) Less(i, j int) bool {
+ return p.messages[i].sequenceNumber < p.messages[j].sequenceNumber
+}
+
+func (p *messageOrderingHeap) enqueue(msg incomingMessage) error {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if len(p.messages) >= messageOrderingHeapLimit {
+ return errHeapReachedCapacity
+ }
+ heap.Push(p, messageHeapItem(msg))
+ return nil
+}
+
+func (p *messageOrderingHeap) popSequence(sequenceNumber uint64) (msg incomingMessage, heapSequenceNumber uint64, err error) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if len(p.messages) == 0 {
+ return incomingMessage{}, 0, errHeapEmpty
+ }
+ if p.messages[0].sequenceNumber != sequenceNumber {
+ return incomingMessage{}, p.messages[0].sequenceNumber, errSequenceNumberMismatch
+ }
+ entry := heap.Pop(p).(messageHeapItem)
+ return incomingMessage(entry), sequenceNumber, nil
+}
+
+func (p *messageOrderingHeap) pop() (msg incomingMessage, err error) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if len(p.messages) == 0 {
+ return incomingMessage{}, errHeapEmpty
+ }
+ entry := heap.Pop(p).(messageHeapItem)
+ return incomingMessage(entry), nil
+}
diff --git a/txnsync/msgorderingheap_test.go b/txnsync/msgorderingheap_test.go
new file mode 100644
index 000000000..cd1a352a5
--- /dev/null
+++ b/txnsync/msgorderingheap_test.go
@@ -0,0 +1,271 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "math/rand"
+ "reflect"
+ "sort"
+ "sync"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-deadlock"
+
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/test/partitiontest"
+)
+
+func TestMessageOrderingHeap_PushPopSwapLess(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ heap := messageOrderingHeap{}
+
+ msg1 := messageHeapItem{sequenceNumber: 1}
+ msg2 := messageHeapItem{sequenceNumber: 2}
+ msg3 := messageHeapItem{sequenceNumber: 3}
+
+ a.Equal(len(heap.messages), 0)
+ heap.Push(msg1)
+ heap.Push(msg2)
+ a.Equal(len(heap.messages), int(2))
+ a.Equal(heap.Len(), int(2))
+
+ a.True(heap.Less(0, 1))
+
+ res := heap.Pop().(messageHeapItem)
+ a.Equal(res.sequenceNumber, uint64(2))
+ a.Equal(len(heap.messages), int(1))
+ a.Equal(heap.Len(), int(1))
+ a.Equal(heap.messages[0].sequenceNumber, uint64(1))
+ heap.Push(msg2)
+ heap.Push(msg3)
+ heap.Swap(0, 1)
+ a.Equal(heap.messages[0].sequenceNumber, uint64(2))
+ a.Equal(heap.messages[1].sequenceNumber, uint64(1))
+
+ a.False(heap.Less(0, 1))
+}
+
+func TestEnqueueHeapPop(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ heap := messageOrderingHeap{}
+
+ for i := messageOrderingHeapLimit - 1; i >= 0; i-- {
+ a.Nil(heap.enqueue(incomingMessage{sequenceNumber: uint64(i)}))
+ }
+
+ a.Equal(heap.Len(), int(messageOrderingHeapLimit))
+ a.Equal(heap.enqueue(incomingMessage{}), errHeapReachedCapacity)
+ a.Equal(heap.Len(), int(messageOrderingHeapLimit))
+
+ for i := 0; i < messageOrderingHeapLimit; i++ {
+ msg, err := heap.pop()
+ a.Nil(err)
+ a.Equal(msg.sequenceNumber, uint64(i))
+ }
+
+ _, err := heap.pop()
+
+ a.Equal(heap.Len(), int(0))
+ a.Equal(err, errHeapEmpty)
+
+}
+
+func TestPopSequence(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ heap := messageOrderingHeap{}
+
+ _, _, err := heap.popSequence(0)
+
+ a.Equal(err, errHeapEmpty)
+ for i := messageOrderingHeapLimit - 1; i >= 0; i-- {
+ a.Nil(heap.enqueue(incomingMessage{sequenceNumber: uint64(i)}))
+ }
+ a.Equal(heap.Len(), messageOrderingHeapLimit)
+ _, heapSeqNum, err := heap.popSequence(3)
+ a.Equal(heap.Len(), messageOrderingHeapLimit)
+ a.Equal(heapSeqNum, uint64(0), errSequenceNumberMismatch)
+ a.Error(err, errSequenceNumberMismatch)
+
+ msg, heapSeqNum, err := heap.popSequence(0)
+
+ a.NotNil(msg)
+ a.Equal(heap.Len(), messageOrderingHeapLimit-1)
+ a.Equal(msg.sequenceNumber, uint64(0))
+ a.Equal(heapSeqNum, uint64(0))
+ a.NoError(err)
+
+}
+
+func TestMultiThreaded(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ loopCount := 1000
+ numThreads := 100
+ itemsPerThread := 10
+
+ totalItems := numThreads * itemsPerThread
+
+ var (
+ heap messageOrderingHeap
+ startChan chan struct{}
+ wg sync.WaitGroup
+ )
+
+ peers := []Peer{
+ {},
+ {},
+ {},
+ {},
+ {},
+ }
+
+ genTxnGrp := func(value int) []pooldata.SignedTxGroup {
+
+ if value%2 == 0 {
+ return []pooldata.SignedTxGroup{
+ {
+ GroupTransactionID: transactions.Txid{byte(value % 255)},
+ },
+ }
+ }
+
+ return []pooldata.SignedTxGroup{
+ {
+ GroupTransactionID: transactions.Txid{byte(value % 255)},
+ },
+ {
+ GroupTransactionID: transactions.Txid{byte(value + 1%255)},
+ },
+ }
+ }
+
+ encodeMsg := func(value int, peers []Peer) incomingMessage {
+
+ rval := incomingMessage{
+ sequenceNumber: uint64(value),
+ peer: &peers[value%len(peers)],
+ encodedSize: value + 874,
+ transactionGroups: genTxnGrp(value),
+ }
+
+ return rval
+ }
+
+ validateMsg := func(message incomingMessage) bool {
+ val := int(message.sequenceNumber)
+
+ if message.peer != &peers[val%len(peers)] {
+ return false
+ }
+
+ if message.encodedSize != val+874 {
+ return false
+ }
+
+ if !reflect.DeepEqual(message.transactionGroups, genTxnGrp(val)) {
+ return false
+ }
+
+ return true
+
+ }
+
+ fxn := func(values []int, heap *messageOrderingHeap, start chan struct{}, wg *sync.WaitGroup,
+ enqueuedMtx *deadlock.Mutex, enqueuedList *[]int) {
+ defer wg.Done()
+ // Wait for the start
+ <-start
+
+ for _, value := range values {
+ msg := encodeMsg(value, peers)
+ err := heap.enqueue(msg)
+
+ if err == nil {
+ enqueuedMtx.Lock()
+ *enqueuedList = append(*enqueuedList, value)
+ enqueuedMtx.Unlock()
+ }
+ }
+
+ }
+
+ for i := 0; i < loopCount; i++ {
+
+ var enqueuedList []int
+ var enqueuedMtx deadlock.Mutex
+
+ var masterList []int
+
+ for j := 0; j < totalItems; j++ {
+ masterList = append(masterList, j)
+ }
+
+ rand.Seed(time.Now().UnixNano())
+ rand.Shuffle(len(masterList), func(i, j int) { masterList[i], masterList[j] = masterList[j], masterList[i] })
+
+ heap = messageOrderingHeap{}
+ startChan = make(chan struct{})
+
+ currentIdx := 0
+
+ for j := 0; j < numThreads; j++ {
+ wg.Add(1)
+
+ randomList := masterList[currentIdx : currentIdx+itemsPerThread]
+ currentIdx = currentIdx + itemsPerThread
+
+ go fxn(randomList, &heap, startChan, &wg, &enqueuedMtx, &enqueuedList)
+ }
+
+ // Tell all goroutines to go
+ close(startChan)
+
+ wg.Wait()
+
+ a.Equal(heap.Len(), int(messageOrderingHeapLimit))
+ a.Equal(heap.enqueue(incomingMessage{}), errHeapReachedCapacity)
+ a.Equal(heap.Len(), int(messageOrderingHeapLimit))
+
+ sort.Ints(enqueuedList)
+
+ for _, val := range enqueuedList {
+
+ msg, sequenceNumber, err := heap.popSequence(uint64(val))
+ a.Nil(err)
+ a.Equal(sequenceNumber, uint64(val))
+ a.True(validateMsg(msg))
+ }
+
+ a.Equal(heap.Len(), int(0))
+ }
+
+}
diff --git a/txnsync/msgp_gen.go b/txnsync/msgp_gen.go
new file mode 100644
index 000000000..1c1b51256
--- /dev/null
+++ b/txnsync/msgp_gen.go
@@ -0,0 +1,35449 @@
+package txnsync
+
+// Code generated by github.com/algorand/msgp DO NOT EDIT.
+
+import (
+ "sort"
+
+ "github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/crypto/compactcert"
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/msgp/msgp"
+)
+
+// The following msgp objects are implemented in this file:
+// addresses
+// |-----> MarshalMsg
+// |-----> CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> Msgsize
+// |-----> MsgIsZero
+//
+// appIndices
+// |-----> MarshalMsg
+// |-----> CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> Msgsize
+// |-----> MsgIsZero
+//
+// applicationArgs
+// |-----> MarshalMsg
+// |-----> CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> Msgsize
+// |-----> MsgIsZero
+//
+// assetIndices
+// |-----> MarshalMsg
+// |-----> CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> Msgsize
+// |-----> MsgIsZero
+//
+// bitmask
+// |-----> MarshalMsg
+// |-----> CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> Msgsize
+// |-----> MsgIsZero
+//
+// certProofs
+// |-----> MarshalMsg
+// |-----> CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> Msgsize
+// |-----> MsgIsZero
+//
+// encodedApplicationCallTxnFields
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// encodedAssetConfigTxnFields
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// encodedAssetFreezeTxnFields
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// encodedAssetParams
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// encodedAssetTransferTxnFields
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// encodedBloomFilter
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// encodedCert
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// encodedCompactCertTxnFields
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// encodedKeyregTxnFields
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// encodedLsigs
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// encodedMsigs
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// encodedPaymentTxnFields
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// encodedSignedTxns
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// encodedTxnHeaders
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// encodedTxns
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// packedTransactionGroups
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// program
+// |-----> MarshalMsg
+// |-----> CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> Msgsize
+// |-----> MsgIsZero
+//
+// relayedProposal
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// requestParams
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// revealMap
+// |-----> MarshalMsg
+// |-----> CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> Msgsize
+// |-----> MsgIsZero
+//
+// timingParams
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// transactionBlockMessage
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// txGroupsEncodingStub
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// txGroupsEncodingStubOld
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+// txnGroups
+// |-----> (*) MarshalMsg
+// |-----> (*) CanMarshalMsg
+// |-----> (*) UnmarshalMsg
+// |-----> (*) CanUnmarshalMsg
+// |-----> (*) Msgsize
+// |-----> (*) MsgIsZero
+//
+
+// MarshalMsg implements msgp.Marshaler
+func (z addresses) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ if z == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len(z)))
+ }
+ for za0005 := range z {
+ o = z[za0005].MarshalMsg(o)
+ }
+ return
+}
+
+func (_ addresses) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(addresses)
+ if !ok {
+ _, ok = (z).(*addresses)
+ }
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *addresses) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var zb0002 int
+ var zb0003 bool
+ zb0002, zb0003, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 > transactions.EncodedMaxAccounts {
+ err = msgp.ErrOverflow(uint64(zb0002), uint64(transactions.EncodedMaxAccounts))
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0003 {
+ (*z) = nil
+ } else if (*z) != nil && cap((*z)) >= zb0002 {
+ (*z) = (*z)[:zb0002]
+ } else {
+ (*z) = make(addresses, zb0002)
+ }
+ for zb0001 := range *z {
+ bts, err = (*z)[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, zb0001)
+ return
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *addresses) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*addresses)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z addresses) Msgsize() (s int) {
+ s = msgp.ArrayHeaderSize
+ for za0005 := range z {
+ s += z[za0005].Msgsize()
+ }
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z addresses) MsgIsZero() bool {
+ return len(z) == 0
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z appIndices) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ if z == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len(z)))
+ }
+ for za0001 := range z {
+ o = z[za0001].MarshalMsg(o)
+ }
+ return
+}
+
+func (_ appIndices) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(appIndices)
+ if !ok {
+ _, ok = (z).(*appIndices)
+ }
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *appIndices) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var zb0002 int
+ var zb0003 bool
+ zb0002, zb0003, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 > transactions.EncodedMaxForeignApps {
+ err = msgp.ErrOverflow(uint64(zb0002), uint64(transactions.EncodedMaxForeignApps))
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0003 {
+ (*z) = nil
+ } else if (*z) != nil && cap((*z)) >= zb0002 {
+ (*z) = (*z)[:zb0002]
+ } else {
+ (*z) = make(appIndices, zb0002)
+ }
+ for zb0001 := range *z {
+ bts, err = (*z)[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, zb0001)
+ return
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *appIndices) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*appIndices)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z appIndices) Msgsize() (s int) {
+ s = msgp.ArrayHeaderSize
+ for za0001 := range z {
+ s += z[za0001].Msgsize()
+ }
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z appIndices) MsgIsZero() bool {
+ return len(z) == 0
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z applicationArgs) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ if z == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len(z)))
+ }
+ for za0001 := range z {
+ o = msgp.AppendBytes(o, z[za0001])
+ }
+ return
+}
+
+func (_ applicationArgs) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(applicationArgs)
+ if !ok {
+ _, ok = (z).(*applicationArgs)
+ }
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *applicationArgs) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var zb0002 int
+ var zb0003 bool
+ zb0002, zb0003, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 > transactions.EncodedMaxApplicationArgs {
+ err = msgp.ErrOverflow(uint64(zb0002), uint64(transactions.EncodedMaxApplicationArgs))
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0003 {
+ (*z) = nil
+ } else if (*z) != nil && cap((*z)) >= zb0002 {
+ (*z) = (*z)[:zb0002]
+ } else {
+ (*z) = make(applicationArgs, zb0002)
+ }
+ for zb0001 := range *z {
+ (*z)[zb0001], bts, err = msgp.ReadBytesBytes(bts, (*z)[zb0001])
+ if err != nil {
+ err = msgp.WrapError(err, zb0001)
+ return
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *applicationArgs) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*applicationArgs)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z applicationArgs) Msgsize() (s int) {
+ s = msgp.ArrayHeaderSize
+ for za0001 := range z {
+ s += msgp.BytesPrefixSize + len(z[za0001])
+ }
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z applicationArgs) MsgIsZero() bool {
+ return len(z) == 0
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z assetIndices) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ if z == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len(z)))
+ }
+ for za0001 := range z {
+ o = z[za0001].MarshalMsg(o)
+ }
+ return
+}
+
+func (_ assetIndices) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(assetIndices)
+ if !ok {
+ _, ok = (z).(*assetIndices)
+ }
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *assetIndices) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var zb0002 int
+ var zb0003 bool
+ zb0002, zb0003, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 > transactions.EncodedMaxForeignAssets {
+ err = msgp.ErrOverflow(uint64(zb0002), uint64(transactions.EncodedMaxForeignAssets))
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0003 {
+ (*z) = nil
+ } else if (*z) != nil && cap((*z)) >= zb0002 {
+ (*z) = (*z)[:zb0002]
+ } else {
+ (*z) = make(assetIndices, zb0002)
+ }
+ for zb0001 := range *z {
+ bts, err = (*z)[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, zb0001)
+ return
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *assetIndices) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*assetIndices)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z assetIndices) Msgsize() (s int) {
+ s = msgp.ArrayHeaderSize
+ for za0001 := range z {
+ s += z[za0001].Msgsize()
+ }
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z assetIndices) MsgIsZero() bool {
+ return len(z) == 0
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z bitmask) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ o = msgp.AppendBytes(o, []byte(z))
+ return
+}
+
+func (_ bitmask) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(bitmask)
+ if !ok {
+ _, ok = (z).(*bitmask)
+ }
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *bitmask) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ {
+ var zb0001 []byte
+ var zb0002 int
+ zb0002, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0002), uint64(maxBitmaskSize))
+ return
+ }
+ zb0001, bts, err = msgp.ReadBytesBytes(bts, []byte((*z)))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ (*z) = bitmask(zb0001)
+ }
+ o = bts
+ return
+}
+
+func (_ *bitmask) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*bitmask)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z bitmask) Msgsize() (s int) {
+ s = msgp.BytesPrefixSize + len([]byte(z))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z bitmask) MsgIsZero() bool {
+ return len(z) == 0
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z certProofs) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ if z == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len(z)))
+ }
+ for za0001 := range z {
+ o = z[za0001].MarshalMsg(o)
+ }
+ return
+}
+
+func (_ certProofs) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(certProofs)
+ if !ok {
+ _, ok = (z).(*certProofs)
+ }
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *certProofs) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var zb0002 int
+ var zb0003 bool
+ zb0002, zb0003, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0002), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0003 {
+ (*z) = nil
+ } else if (*z) != nil && cap((*z)) >= zb0002 {
+ (*z) = (*z)[:zb0002]
+ } else {
+ (*z) = make(certProofs, zb0002)
+ }
+ for zb0001 := range *z {
+ bts, err = (*z)[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, zb0001)
+ return
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *certProofs) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*certProofs)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z certProofs) Msgsize() (s int) {
+ s = msgp.ArrayHeaderSize
+ for za0001 := range z {
+ s += z[za0001].Msgsize()
+ }
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z certProofs) MsgIsZero() bool {
+ return len(z) == 0
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedApplicationCallTxnFields) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0017Len := uint32(26)
+ var zb0017Mask uint32 /* 27 bits */
+ if len((*z).ApplicationArgs) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x2
+ }
+ if len((*z).BitmaskApplicationArgs) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x4
+ }
+ if len((*z).OnCompletion) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x8
+ }
+ if len((*z).BitmaskOnCompletion) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x10
+ }
+ if len((*z).ApprovalProgram) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x20
+ }
+ if len((*z).BitmaskApprovalProgram) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x40
+ }
+ if len((*z).ForeignAssets) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x80
+ }
+ if len((*z).BitmaskForeignAssets) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x100
+ }
+ if len((*z).Accounts) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x200
+ }
+ if len((*z).BitmaskAccounts) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x400
+ }
+ if len((*z).ExtraProgramPages) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x800
+ }
+ if len((*z).BitmaskExtraProgramPages) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x1000
+ }
+ if len((*z).ForeignApps) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x2000
+ }
+ if len((*z).BitmaskForeignApps) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x4000
+ }
+ if len((*z).ApplicationID) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x8000
+ }
+ if len((*z).BitmaskApplicationID) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x10000
+ }
+ if len((*z).ClearStateProgram) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x20000
+ }
+ if len((*z).BitmaskClearStateProgram) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x40000
+ }
+ if len((*z).GlobalNumByteSlice) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x80000
+ }
+ if len((*z).BitmaskGlobalNumByteSlice) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x100000
+ }
+ if len((*z).GlobalNumUint) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x200000
+ }
+ if len((*z).BitmaskGlobalNumUint) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x400000
+ }
+ if len((*z).LocalNumByteSlice) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x800000
+ }
+ if len((*z).BitmaskLocalNumByteSlice) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x1000000
+ }
+ if len((*z).LocalNumUint) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x2000000
+ }
+ if len((*z).BitmaskLocalNumUint) == 0 {
+ zb0017Len--
+ zb0017Mask |= 0x4000000
+ }
+ // variable map header, size zb0017Len
+ o = msgp.AppendMapHeader(o, zb0017Len)
+ if zb0017Len != 0 {
+ if (zb0017Mask & 0x2) == 0 { // if not empty
+ // string "apaa"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x61)
+ if (*z).ApplicationArgs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).ApplicationArgs)))
+ }
+ for zb0002 := range (*z).ApplicationArgs {
+ if (*z).ApplicationArgs[zb0002] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).ApplicationArgs[zb0002])))
+ }
+ for zb0003 := range (*z).ApplicationArgs[zb0002] {
+ o = msgp.AppendBytes(o, (*z).ApplicationArgs[zb0002][zb0003])
+ }
+ }
+ }
+ if (zb0017Mask & 0x4) == 0 { // if not empty
+ // string "apaabm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x61, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskApplicationArgs))
+ }
+ if (zb0017Mask & 0x8) == 0 { // if not empty
+ // string "apan"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x6e)
+ o = msgp.AppendBytes(o, (*z).OnCompletion)
+ }
+ if (zb0017Mask & 0x10) == 0 { // if not empty
+ // string "apanbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskOnCompletion))
+ }
+ if (zb0017Mask & 0x20) == 0 { // if not empty
+ // string "apap"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x70)
+ if (*z).ApprovalProgram == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).ApprovalProgram)))
+ }
+ for zb0014 := range (*z).ApprovalProgram {
+ o = msgp.AppendBytes(o, []byte((*z).ApprovalProgram[zb0014]))
+ }
+ }
+ if (zb0017Mask & 0x40) == 0 { // if not empty
+ // string "apapbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x70, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskApprovalProgram))
+ }
+ if (zb0017Mask & 0x80) == 0 { // if not empty
+ // string "apas"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x73)
+ if (*z).ForeignAssets == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).ForeignAssets)))
+ }
+ for zb0008 := range (*z).ForeignAssets {
+ if (*z).ForeignAssets[zb0008] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).ForeignAssets[zb0008])))
+ }
+ for zb0009 := range (*z).ForeignAssets[zb0008] {
+ o = (*z).ForeignAssets[zb0008][zb0009].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0017Mask & 0x100) == 0 { // if not empty
+ // string "apasbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskForeignAssets))
+ }
+ if (zb0017Mask & 0x200) == 0 { // if not empty
+ // string "apat"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x74)
+ if (*z).Accounts == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).Accounts)))
+ }
+ for zb0004 := range (*z).Accounts {
+ if (*z).Accounts[zb0004] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).Accounts[zb0004])))
+ }
+ for zb0005 := range (*z).Accounts[zb0004] {
+ o = (*z).Accounts[zb0004][zb0005].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0017Mask & 0x400) == 0 { // if not empty
+ // string "apatbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskAccounts))
+ }
+ if (zb0017Mask & 0x800) == 0 { // if not empty
+ // string "apep"
+ o = append(o, 0xa4, 0x61, 0x70, 0x65, 0x70)
+ if (*z).ExtraProgramPages == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).ExtraProgramPages)))
+ }
+ for zb0016 := range (*z).ExtraProgramPages {
+ o = msgp.AppendUint32(o, (*z).ExtraProgramPages[zb0016])
+ }
+ }
+ if (zb0017Mask & 0x1000) == 0 { // if not empty
+ // string "apepbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x65, 0x70, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskExtraProgramPages))
+ }
+ if (zb0017Mask & 0x2000) == 0 { // if not empty
+ // string "apfa"
+ o = append(o, 0xa4, 0x61, 0x70, 0x66, 0x61)
+ if (*z).ForeignApps == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).ForeignApps)))
+ }
+ for zb0006 := range (*z).ForeignApps {
+ if (*z).ForeignApps[zb0006] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).ForeignApps[zb0006])))
+ }
+ for zb0007 := range (*z).ForeignApps[zb0006] {
+ o = (*z).ForeignApps[zb0006][zb0007].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0017Mask & 0x4000) == 0 { // if not empty
+ // string "apfabm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x66, 0x61, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskForeignApps))
+ }
+ if (zb0017Mask & 0x8000) == 0 { // if not empty
+ // string "apid"
+ o = append(o, 0xa4, 0x61, 0x70, 0x69, 0x64)
+ if (*z).ApplicationID == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).ApplicationID)))
+ }
+ for zb0001 := range (*z).ApplicationID {
+ o = (*z).ApplicationID[zb0001].MarshalMsg(o)
+ }
+ }
+ if (zb0017Mask & 0x10000) == 0 { // if not empty
+ // string "apidbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskApplicationID))
+ }
+ if (zb0017Mask & 0x20000) == 0 { // if not empty
+ // string "apsu"
+ o = append(o, 0xa4, 0x61, 0x70, 0x73, 0x75)
+ if (*z).ClearStateProgram == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).ClearStateProgram)))
+ }
+ for zb0015 := range (*z).ClearStateProgram {
+ o = msgp.AppendBytes(o, []byte((*z).ClearStateProgram[zb0015]))
+ }
+ }
+ if (zb0017Mask & 0x40000) == 0 { // if not empty
+ // string "apsubm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x73, 0x75, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskClearStateProgram))
+ }
+ if (zb0017Mask & 0x80000) == 0 { // if not empty
+ // string "gnbs"
+ o = append(o, 0xa4, 0x67, 0x6e, 0x62, 0x73)
+ if (*z).GlobalNumByteSlice == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).GlobalNumByteSlice)))
+ }
+ for zb0013 := range (*z).GlobalNumByteSlice {
+ o = msgp.AppendUint64(o, (*z).GlobalNumByteSlice[zb0013])
+ }
+ }
+ if (zb0017Mask & 0x100000) == 0 { // if not empty
+ // string "gnbsbm"
+ o = append(o, 0xa6, 0x67, 0x6e, 0x62, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskGlobalNumByteSlice))
+ }
+ if (zb0017Mask & 0x200000) == 0 { // if not empty
+ // string "gnui"
+ o = append(o, 0xa4, 0x67, 0x6e, 0x75, 0x69)
+ if (*z).GlobalNumUint == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).GlobalNumUint)))
+ }
+ for zb0012 := range (*z).GlobalNumUint {
+ o = msgp.AppendUint64(o, (*z).GlobalNumUint[zb0012])
+ }
+ }
+ if (zb0017Mask & 0x400000) == 0 { // if not empty
+ // string "gnuibm"
+ o = append(o, 0xa6, 0x67, 0x6e, 0x75, 0x69, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskGlobalNumUint))
+ }
+ if (zb0017Mask & 0x800000) == 0 { // if not empty
+ // string "lnbs"
+ o = append(o, 0xa4, 0x6c, 0x6e, 0x62, 0x73)
+ if (*z).LocalNumByteSlice == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).LocalNumByteSlice)))
+ }
+ for zb0011 := range (*z).LocalNumByteSlice {
+ o = msgp.AppendUint64(o, (*z).LocalNumByteSlice[zb0011])
+ }
+ }
+ if (zb0017Mask & 0x1000000) == 0 { // if not empty
+ // string "lnbsbm"
+ o = append(o, 0xa6, 0x6c, 0x6e, 0x62, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskLocalNumByteSlice))
+ }
+ if (zb0017Mask & 0x2000000) == 0 { // if not empty
+ // string "lnui"
+ o = append(o, 0xa4, 0x6c, 0x6e, 0x75, 0x69)
+ if (*z).LocalNumUint == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).LocalNumUint)))
+ }
+ for zb0010 := range (*z).LocalNumUint {
+ o = msgp.AppendUint64(o, (*z).LocalNumUint[zb0010])
+ }
+ }
+ if (zb0017Mask & 0x4000000) == 0 { // if not empty
+ // string "lnuibm"
+ o = append(o, 0xa6, 0x6c, 0x6e, 0x75, 0x69, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskLocalNumUint))
+ }
+ }
+ return
+}
+
+func (_ *encodedApplicationCallTxnFields) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedApplicationCallTxnFields)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedApplicationCallTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0017 int
+ var zb0018 bool
+ zb0017, zb0018, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0017, zb0018, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0017 > 0 {
+ zb0017--
+ var zb0019 int
+ var zb0020 bool
+ zb0019, zb0020, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationID")
+ return
+ }
+ if zb0019 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0019), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationID")
+ return
+ }
+ if zb0020 {
+ (*z).ApplicationID = nil
+ } else if (*z).ApplicationID != nil && cap((*z).ApplicationID) >= zb0019 {
+ (*z).ApplicationID = ((*z).ApplicationID)[:zb0019]
+ } else {
+ (*z).ApplicationID = make([]basics.AppIndex, zb0019)
+ }
+ for zb0001 := range (*z).ApplicationID {
+ bts, err = (*z).ApplicationID[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationID", zb0001)
+ return
+ }
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ {
+ var zb0021 []byte
+ var zb0022 int
+ zb0022, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationID")
+ return
+ }
+ if zb0022 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0022), uint64(maxBitmaskSize))
+ return
+ }
+ zb0021, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskApplicationID))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationID")
+ return
+ }
+ (*z).BitmaskApplicationID = bitmask(zb0021)
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ var zb0023 int
+ zb0023, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "OnCompletion")
+ return
+ }
+ if zb0023 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0023), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).OnCompletion, bts, err = msgp.ReadBytesBytes(bts, (*z).OnCompletion)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "OnCompletion")
+ return
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ {
+ var zb0024 []byte
+ var zb0025 int
+ zb0025, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskOnCompletion")
+ return
+ }
+ if zb0025 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0025), uint64(maxBitmaskSize))
+ return
+ }
+ zb0024, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskOnCompletion))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskOnCompletion")
+ return
+ }
+ (*z).BitmaskOnCompletion = bitmask(zb0024)
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ var zb0026 int
+ var zb0027 bool
+ zb0026, zb0027, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs")
+ return
+ }
+ if zb0026 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0026), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs")
+ return
+ }
+ if zb0027 {
+ (*z).ApplicationArgs = nil
+ } else if (*z).ApplicationArgs != nil && cap((*z).ApplicationArgs) >= zb0026 {
+ (*z).ApplicationArgs = ((*z).ApplicationArgs)[:zb0026]
+ } else {
+ (*z).ApplicationArgs = make([]applicationArgs, zb0026)
+ }
+ for zb0002 := range (*z).ApplicationArgs {
+ var zb0028 int
+ var zb0029 bool
+ zb0028, zb0029, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs", zb0002)
+ return
+ }
+ if zb0028 > transactions.EncodedMaxApplicationArgs {
+ err = msgp.ErrOverflow(uint64(zb0028), uint64(transactions.EncodedMaxApplicationArgs))
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs", zb0002)
+ return
+ }
+ if zb0029 {
+ (*z).ApplicationArgs[zb0002] = nil
+ } else if (*z).ApplicationArgs[zb0002] != nil && cap((*z).ApplicationArgs[zb0002]) >= zb0028 {
+ (*z).ApplicationArgs[zb0002] = ((*z).ApplicationArgs[zb0002])[:zb0028]
+ } else {
+ (*z).ApplicationArgs[zb0002] = make(applicationArgs, zb0028)
+ }
+ for zb0003 := range (*z).ApplicationArgs[zb0002] {
+ (*z).ApplicationArgs[zb0002][zb0003], bts, err = msgp.ReadBytesBytes(bts, (*z).ApplicationArgs[zb0002][zb0003])
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs", zb0002, zb0003)
+ return
+ }
+ }
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ {
+ var zb0030 []byte
+ var zb0031 int
+ zb0031, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationArgs")
+ return
+ }
+ if zb0031 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0031), uint64(maxBitmaskSize))
+ return
+ }
+ zb0030, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskApplicationArgs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationArgs")
+ return
+ }
+ (*z).BitmaskApplicationArgs = bitmask(zb0030)
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ var zb0032 int
+ var zb0033 bool
+ zb0032, zb0033, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Accounts")
+ return
+ }
+ if zb0032 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0032), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Accounts")
+ return
+ }
+ if zb0033 {
+ (*z).Accounts = nil
+ } else if (*z).Accounts != nil && cap((*z).Accounts) >= zb0032 {
+ (*z).Accounts = ((*z).Accounts)[:zb0032]
+ } else {
+ (*z).Accounts = make([]addresses, zb0032)
+ }
+ for zb0004 := range (*z).Accounts {
+ var zb0034 int
+ var zb0035 bool
+ zb0034, zb0035, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Accounts", zb0004)
+ return
+ }
+ if zb0034 > transactions.EncodedMaxAccounts {
+ err = msgp.ErrOverflow(uint64(zb0034), uint64(transactions.EncodedMaxAccounts))
+ err = msgp.WrapError(err, "struct-from-array", "Accounts", zb0004)
+ return
+ }
+ if zb0035 {
+ (*z).Accounts[zb0004] = nil
+ } else if (*z).Accounts[zb0004] != nil && cap((*z).Accounts[zb0004]) >= zb0034 {
+ (*z).Accounts[zb0004] = ((*z).Accounts[zb0004])[:zb0034]
+ } else {
+ (*z).Accounts[zb0004] = make(addresses, zb0034)
+ }
+ for zb0005 := range (*z).Accounts[zb0004] {
+ bts, err = (*z).Accounts[zb0004][zb0005].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Accounts", zb0004, zb0005)
+ return
+ }
+ }
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ {
+ var zb0036 []byte
+ var zb0037 int
+ zb0037, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAccounts")
+ return
+ }
+ if zb0037 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0037), uint64(maxBitmaskSize))
+ return
+ }
+ zb0036, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAccounts))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAccounts")
+ return
+ }
+ (*z).BitmaskAccounts = bitmask(zb0036)
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ var zb0038 int
+ var zb0039 bool
+ zb0038, zb0039, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps")
+ return
+ }
+ if zb0038 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0038), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps")
+ return
+ }
+ if zb0039 {
+ (*z).ForeignApps = nil
+ } else if (*z).ForeignApps != nil && cap((*z).ForeignApps) >= zb0038 {
+ (*z).ForeignApps = ((*z).ForeignApps)[:zb0038]
+ } else {
+ (*z).ForeignApps = make([]appIndices, zb0038)
+ }
+ for zb0006 := range (*z).ForeignApps {
+ var zb0040 int
+ var zb0041 bool
+ zb0040, zb0041, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps", zb0006)
+ return
+ }
+ if zb0040 > transactions.EncodedMaxForeignApps {
+ err = msgp.ErrOverflow(uint64(zb0040), uint64(transactions.EncodedMaxForeignApps))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps", zb0006)
+ return
+ }
+ if zb0041 {
+ (*z).ForeignApps[zb0006] = nil
+ } else if (*z).ForeignApps[zb0006] != nil && cap((*z).ForeignApps[zb0006]) >= zb0040 {
+ (*z).ForeignApps[zb0006] = ((*z).ForeignApps[zb0006])[:zb0040]
+ } else {
+ (*z).ForeignApps[zb0006] = make(appIndices, zb0040)
+ }
+ for zb0007 := range (*z).ForeignApps[zb0006] {
+ bts, err = (*z).ForeignApps[zb0006][zb0007].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps", zb0006, zb0007)
+ return
+ }
+ }
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ {
+ var zb0042 []byte
+ var zb0043 int
+ zb0043, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignApps")
+ return
+ }
+ if zb0043 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0043), uint64(maxBitmaskSize))
+ return
+ }
+ zb0042, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskForeignApps))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignApps")
+ return
+ }
+ (*z).BitmaskForeignApps = bitmask(zb0042)
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ var zb0044 int
+ var zb0045 bool
+ zb0044, zb0045, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets")
+ return
+ }
+ if zb0044 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0044), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets")
+ return
+ }
+ if zb0045 {
+ (*z).ForeignAssets = nil
+ } else if (*z).ForeignAssets != nil && cap((*z).ForeignAssets) >= zb0044 {
+ (*z).ForeignAssets = ((*z).ForeignAssets)[:zb0044]
+ } else {
+ (*z).ForeignAssets = make([]assetIndices, zb0044)
+ }
+ for zb0008 := range (*z).ForeignAssets {
+ var zb0046 int
+ var zb0047 bool
+ zb0046, zb0047, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets", zb0008)
+ return
+ }
+ if zb0046 > transactions.EncodedMaxForeignAssets {
+ err = msgp.ErrOverflow(uint64(zb0046), uint64(transactions.EncodedMaxForeignAssets))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets", zb0008)
+ return
+ }
+ if zb0047 {
+ (*z).ForeignAssets[zb0008] = nil
+ } else if (*z).ForeignAssets[zb0008] != nil && cap((*z).ForeignAssets[zb0008]) >= zb0046 {
+ (*z).ForeignAssets[zb0008] = ((*z).ForeignAssets[zb0008])[:zb0046]
+ } else {
+ (*z).ForeignAssets[zb0008] = make(assetIndices, zb0046)
+ }
+ for zb0009 := range (*z).ForeignAssets[zb0008] {
+ bts, err = (*z).ForeignAssets[zb0008][zb0009].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets", zb0008, zb0009)
+ return
+ }
+ }
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ {
+ var zb0048 []byte
+ var zb0049 int
+ zb0049, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignAssets")
+ return
+ }
+ if zb0049 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0049), uint64(maxBitmaskSize))
+ return
+ }
+ zb0048, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskForeignAssets))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignAssets")
+ return
+ }
+ (*z).BitmaskForeignAssets = bitmask(zb0048)
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ var zb0050 int
+ var zb0051 bool
+ zb0050, zb0051, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumUint")
+ return
+ }
+ if zb0050 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0050), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumUint")
+ return
+ }
+ if zb0051 {
+ (*z).LocalNumUint = nil
+ } else if (*z).LocalNumUint != nil && cap((*z).LocalNumUint) >= zb0050 {
+ (*z).LocalNumUint = ((*z).LocalNumUint)[:zb0050]
+ } else {
+ (*z).LocalNumUint = make([]uint64, zb0050)
+ }
+ for zb0010 := range (*z).LocalNumUint {
+ (*z).LocalNumUint[zb0010], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumUint", zb0010)
+ return
+ }
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ {
+ var zb0052 []byte
+ var zb0053 int
+ zb0053, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumUint")
+ return
+ }
+ if zb0053 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0053), uint64(maxBitmaskSize))
+ return
+ }
+ zb0052, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskLocalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumUint")
+ return
+ }
+ (*z).BitmaskLocalNumUint = bitmask(zb0052)
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ var zb0054 int
+ var zb0055 bool
+ zb0054, zb0055, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumByteSlice")
+ return
+ }
+ if zb0054 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0054), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumByteSlice")
+ return
+ }
+ if zb0055 {
+ (*z).LocalNumByteSlice = nil
+ } else if (*z).LocalNumByteSlice != nil && cap((*z).LocalNumByteSlice) >= zb0054 {
+ (*z).LocalNumByteSlice = ((*z).LocalNumByteSlice)[:zb0054]
+ } else {
+ (*z).LocalNumByteSlice = make([]uint64, zb0054)
+ }
+ for zb0011 := range (*z).LocalNumByteSlice {
+ (*z).LocalNumByteSlice[zb0011], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumByteSlice", zb0011)
+ return
+ }
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ {
+ var zb0056 []byte
+ var zb0057 int
+ zb0057, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumByteSlice")
+ return
+ }
+ if zb0057 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0057), uint64(maxBitmaskSize))
+ return
+ }
+ zb0056, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskLocalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumByteSlice")
+ return
+ }
+ (*z).BitmaskLocalNumByteSlice = bitmask(zb0056)
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ var zb0058 int
+ var zb0059 bool
+ zb0058, zb0059, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumUint")
+ return
+ }
+ if zb0058 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0058), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumUint")
+ return
+ }
+ if zb0059 {
+ (*z).GlobalNumUint = nil
+ } else if (*z).GlobalNumUint != nil && cap((*z).GlobalNumUint) >= zb0058 {
+ (*z).GlobalNumUint = ((*z).GlobalNumUint)[:zb0058]
+ } else {
+ (*z).GlobalNumUint = make([]uint64, zb0058)
+ }
+ for zb0012 := range (*z).GlobalNumUint {
+ (*z).GlobalNumUint[zb0012], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumUint", zb0012)
+ return
+ }
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ {
+ var zb0060 []byte
+ var zb0061 int
+ zb0061, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumUint")
+ return
+ }
+ if zb0061 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0061), uint64(maxBitmaskSize))
+ return
+ }
+ zb0060, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskGlobalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumUint")
+ return
+ }
+ (*z).BitmaskGlobalNumUint = bitmask(zb0060)
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ var zb0062 int
+ var zb0063 bool
+ zb0062, zb0063, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumByteSlice")
+ return
+ }
+ if zb0062 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0062), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumByteSlice")
+ return
+ }
+ if zb0063 {
+ (*z).GlobalNumByteSlice = nil
+ } else if (*z).GlobalNumByteSlice != nil && cap((*z).GlobalNumByteSlice) >= zb0062 {
+ (*z).GlobalNumByteSlice = ((*z).GlobalNumByteSlice)[:zb0062]
+ } else {
+ (*z).GlobalNumByteSlice = make([]uint64, zb0062)
+ }
+ for zb0013 := range (*z).GlobalNumByteSlice {
+ (*z).GlobalNumByteSlice[zb0013], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumByteSlice", zb0013)
+ return
+ }
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ {
+ var zb0064 []byte
+ var zb0065 int
+ zb0065, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumByteSlice")
+ return
+ }
+ if zb0065 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0065), uint64(maxBitmaskSize))
+ return
+ }
+ zb0064, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskGlobalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumByteSlice")
+ return
+ }
+ (*z).BitmaskGlobalNumByteSlice = bitmask(zb0064)
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ var zb0066 int
+ var zb0067 bool
+ zb0066, zb0067, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram")
+ return
+ }
+ if zb0066 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0066), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram")
+ return
+ }
+ if zb0067 {
+ (*z).ApprovalProgram = nil
+ } else if (*z).ApprovalProgram != nil && cap((*z).ApprovalProgram) >= zb0066 {
+ (*z).ApprovalProgram = ((*z).ApprovalProgram)[:zb0066]
+ } else {
+ (*z).ApprovalProgram = make([]program, zb0066)
+ }
+ for zb0014 := range (*z).ApprovalProgram {
+ {
+ var zb0068 []byte
+ var zb0069 int
+ zb0069, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram", zb0014)
+ return
+ }
+ if zb0069 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0069), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0068, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).ApprovalProgram[zb0014]))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram", zb0014)
+ return
+ }
+ (*z).ApprovalProgram[zb0014] = program(zb0068)
+ }
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ {
+ var zb0070 []byte
+ var zb0071 int
+ zb0071, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApprovalProgram")
+ return
+ }
+ if zb0071 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0071), uint64(maxBitmaskSize))
+ return
+ }
+ zb0070, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskApprovalProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApprovalProgram")
+ return
+ }
+ (*z).BitmaskApprovalProgram = bitmask(zb0070)
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ var zb0072 int
+ var zb0073 bool
+ zb0072, zb0073, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram")
+ return
+ }
+ if zb0072 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0072), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram")
+ return
+ }
+ if zb0073 {
+ (*z).ClearStateProgram = nil
+ } else if (*z).ClearStateProgram != nil && cap((*z).ClearStateProgram) >= zb0072 {
+ (*z).ClearStateProgram = ((*z).ClearStateProgram)[:zb0072]
+ } else {
+ (*z).ClearStateProgram = make([]program, zb0072)
+ }
+ for zb0015 := range (*z).ClearStateProgram {
+ {
+ var zb0074 []byte
+ var zb0075 int
+ zb0075, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram", zb0015)
+ return
+ }
+ if zb0075 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0075), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0074, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).ClearStateProgram[zb0015]))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram", zb0015)
+ return
+ }
+ (*z).ClearStateProgram[zb0015] = program(zb0074)
+ }
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ {
+ var zb0076 []byte
+ var zb0077 int
+ zb0077, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClearStateProgram")
+ return
+ }
+ if zb0077 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0077), uint64(maxBitmaskSize))
+ return
+ }
+ zb0076, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskClearStateProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClearStateProgram")
+ return
+ }
+ (*z).BitmaskClearStateProgram = bitmask(zb0076)
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ var zb0078 int
+ var zb0079 bool
+ zb0078, zb0079, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExtraProgramPages")
+ return
+ }
+ if zb0078 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0078), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ExtraProgramPages")
+ return
+ }
+ if zb0079 {
+ (*z).ExtraProgramPages = nil
+ } else if (*z).ExtraProgramPages != nil && cap((*z).ExtraProgramPages) >= zb0078 {
+ (*z).ExtraProgramPages = ((*z).ExtraProgramPages)[:zb0078]
+ } else {
+ (*z).ExtraProgramPages = make([]uint32, zb0078)
+ }
+ for zb0016 := range (*z).ExtraProgramPages {
+ (*z).ExtraProgramPages[zb0016], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExtraProgramPages", zb0016)
+ return
+ }
+ }
+ }
+ if zb0017 > 0 {
+ zb0017--
+ {
+ var zb0080 []byte
+ var zb0081 int
+ zb0081, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskExtraProgramPages")
+ return
+ }
+ if zb0081 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0081), uint64(maxBitmaskSize))
+ return
+ }
+ zb0080, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskExtraProgramPages))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskExtraProgramPages")
+ return
+ }
+ (*z).BitmaskExtraProgramPages = bitmask(zb0080)
+ }
+ }
+ if zb0017 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0017)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0018 {
+ (*z) = encodedApplicationCallTxnFields{}
+ }
+ for zb0017 > 0 {
+ zb0017--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "apid":
+ var zb0082 int
+ var zb0083 bool
+ zb0082, zb0083, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationID")
+ return
+ }
+ if zb0082 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0082), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ApplicationID")
+ return
+ }
+ if zb0083 {
+ (*z).ApplicationID = nil
+ } else if (*z).ApplicationID != nil && cap((*z).ApplicationID) >= zb0082 {
+ (*z).ApplicationID = ((*z).ApplicationID)[:zb0082]
+ } else {
+ (*z).ApplicationID = make([]basics.AppIndex, zb0082)
+ }
+ for zb0001 := range (*z).ApplicationID {
+ bts, err = (*z).ApplicationID[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationID", zb0001)
+ return
+ }
+ }
+ case "apidbm":
+ {
+ var zb0084 []byte
+ var zb0085 int
+ zb0085, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationID")
+ return
+ }
+ if zb0085 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0085), uint64(maxBitmaskSize))
+ return
+ }
+ zb0084, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskApplicationID))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationID")
+ return
+ }
+ (*z).BitmaskApplicationID = bitmask(zb0084)
+ }
+ case "apan":
+ var zb0086 int
+ zb0086, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "OnCompletion")
+ return
+ }
+ if zb0086 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0086), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).OnCompletion, bts, err = msgp.ReadBytesBytes(bts, (*z).OnCompletion)
+ if err != nil {
+ err = msgp.WrapError(err, "OnCompletion")
+ return
+ }
+ case "apanbm":
+ {
+ var zb0087 []byte
+ var zb0088 int
+ zb0088, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskOnCompletion")
+ return
+ }
+ if zb0088 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0088), uint64(maxBitmaskSize))
+ return
+ }
+ zb0087, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskOnCompletion))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskOnCompletion")
+ return
+ }
+ (*z).BitmaskOnCompletion = bitmask(zb0087)
+ }
+ case "apaa":
+ var zb0089 int
+ var zb0090 bool
+ zb0089, zb0090, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationArgs")
+ return
+ }
+ if zb0089 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0089), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ApplicationArgs")
+ return
+ }
+ if zb0090 {
+ (*z).ApplicationArgs = nil
+ } else if (*z).ApplicationArgs != nil && cap((*z).ApplicationArgs) >= zb0089 {
+ (*z).ApplicationArgs = ((*z).ApplicationArgs)[:zb0089]
+ } else {
+ (*z).ApplicationArgs = make([]applicationArgs, zb0089)
+ }
+ for zb0002 := range (*z).ApplicationArgs {
+ var zb0091 int
+ var zb0092 bool
+ zb0091, zb0092, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationArgs", zb0002)
+ return
+ }
+ if zb0091 > transactions.EncodedMaxApplicationArgs {
+ err = msgp.ErrOverflow(uint64(zb0091), uint64(transactions.EncodedMaxApplicationArgs))
+ err = msgp.WrapError(err, "ApplicationArgs", zb0002)
+ return
+ }
+ if zb0092 {
+ (*z).ApplicationArgs[zb0002] = nil
+ } else if (*z).ApplicationArgs[zb0002] != nil && cap((*z).ApplicationArgs[zb0002]) >= zb0091 {
+ (*z).ApplicationArgs[zb0002] = ((*z).ApplicationArgs[zb0002])[:zb0091]
+ } else {
+ (*z).ApplicationArgs[zb0002] = make(applicationArgs, zb0091)
+ }
+ for zb0003 := range (*z).ApplicationArgs[zb0002] {
+ (*z).ApplicationArgs[zb0002][zb0003], bts, err = msgp.ReadBytesBytes(bts, (*z).ApplicationArgs[zb0002][zb0003])
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationArgs", zb0002, zb0003)
+ return
+ }
+ }
+ }
+ case "apaabm":
+ {
+ var zb0093 []byte
+ var zb0094 int
+ zb0094, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationArgs")
+ return
+ }
+ if zb0094 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0094), uint64(maxBitmaskSize))
+ return
+ }
+ zb0093, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskApplicationArgs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationArgs")
+ return
+ }
+ (*z).BitmaskApplicationArgs = bitmask(zb0093)
+ }
+ case "apat":
+ var zb0095 int
+ var zb0096 bool
+ zb0095, zb0096, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Accounts")
+ return
+ }
+ if zb0095 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0095), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Accounts")
+ return
+ }
+ if zb0096 {
+ (*z).Accounts = nil
+ } else if (*z).Accounts != nil && cap((*z).Accounts) >= zb0095 {
+ (*z).Accounts = ((*z).Accounts)[:zb0095]
+ } else {
+ (*z).Accounts = make([]addresses, zb0095)
+ }
+ for zb0004 := range (*z).Accounts {
+ var zb0097 int
+ var zb0098 bool
+ zb0097, zb0098, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Accounts", zb0004)
+ return
+ }
+ if zb0097 > transactions.EncodedMaxAccounts {
+ err = msgp.ErrOverflow(uint64(zb0097), uint64(transactions.EncodedMaxAccounts))
+ err = msgp.WrapError(err, "Accounts", zb0004)
+ return
+ }
+ if zb0098 {
+ (*z).Accounts[zb0004] = nil
+ } else if (*z).Accounts[zb0004] != nil && cap((*z).Accounts[zb0004]) >= zb0097 {
+ (*z).Accounts[zb0004] = ((*z).Accounts[zb0004])[:zb0097]
+ } else {
+ (*z).Accounts[zb0004] = make(addresses, zb0097)
+ }
+ for zb0005 := range (*z).Accounts[zb0004] {
+ bts, err = (*z).Accounts[zb0004][zb0005].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Accounts", zb0004, zb0005)
+ return
+ }
+ }
+ }
+ case "apatbm":
+ {
+ var zb0099 []byte
+ var zb0100 int
+ zb0100, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAccounts")
+ return
+ }
+ if zb0100 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0100), uint64(maxBitmaskSize))
+ return
+ }
+ zb0099, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAccounts))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAccounts")
+ return
+ }
+ (*z).BitmaskAccounts = bitmask(zb0099)
+ }
+ case "apfa":
+ var zb0101 int
+ var zb0102 bool
+ zb0101, zb0102, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignApps")
+ return
+ }
+ if zb0101 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0101), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ForeignApps")
+ return
+ }
+ if zb0102 {
+ (*z).ForeignApps = nil
+ } else if (*z).ForeignApps != nil && cap((*z).ForeignApps) >= zb0101 {
+ (*z).ForeignApps = ((*z).ForeignApps)[:zb0101]
+ } else {
+ (*z).ForeignApps = make([]appIndices, zb0101)
+ }
+ for zb0006 := range (*z).ForeignApps {
+ var zb0103 int
+ var zb0104 bool
+ zb0103, zb0104, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignApps", zb0006)
+ return
+ }
+ if zb0103 > transactions.EncodedMaxForeignApps {
+ err = msgp.ErrOverflow(uint64(zb0103), uint64(transactions.EncodedMaxForeignApps))
+ err = msgp.WrapError(err, "ForeignApps", zb0006)
+ return
+ }
+ if zb0104 {
+ (*z).ForeignApps[zb0006] = nil
+ } else if (*z).ForeignApps[zb0006] != nil && cap((*z).ForeignApps[zb0006]) >= zb0103 {
+ (*z).ForeignApps[zb0006] = ((*z).ForeignApps[zb0006])[:zb0103]
+ } else {
+ (*z).ForeignApps[zb0006] = make(appIndices, zb0103)
+ }
+ for zb0007 := range (*z).ForeignApps[zb0006] {
+ bts, err = (*z).ForeignApps[zb0006][zb0007].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignApps", zb0006, zb0007)
+ return
+ }
+ }
+ }
+ case "apfabm":
+ {
+ var zb0105 []byte
+ var zb0106 int
+ zb0106, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignApps")
+ return
+ }
+ if zb0106 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0106), uint64(maxBitmaskSize))
+ return
+ }
+ zb0105, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskForeignApps))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignApps")
+ return
+ }
+ (*z).BitmaskForeignApps = bitmask(zb0105)
+ }
+ case "apas":
+ var zb0107 int
+ var zb0108 bool
+ zb0107, zb0108, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignAssets")
+ return
+ }
+ if zb0107 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0107), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ForeignAssets")
+ return
+ }
+ if zb0108 {
+ (*z).ForeignAssets = nil
+ } else if (*z).ForeignAssets != nil && cap((*z).ForeignAssets) >= zb0107 {
+ (*z).ForeignAssets = ((*z).ForeignAssets)[:zb0107]
+ } else {
+ (*z).ForeignAssets = make([]assetIndices, zb0107)
+ }
+ for zb0008 := range (*z).ForeignAssets {
+ var zb0109 int
+ var zb0110 bool
+ zb0109, zb0110, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignAssets", zb0008)
+ return
+ }
+ if zb0109 > transactions.EncodedMaxForeignAssets {
+ err = msgp.ErrOverflow(uint64(zb0109), uint64(transactions.EncodedMaxForeignAssets))
+ err = msgp.WrapError(err, "ForeignAssets", zb0008)
+ return
+ }
+ if zb0110 {
+ (*z).ForeignAssets[zb0008] = nil
+ } else if (*z).ForeignAssets[zb0008] != nil && cap((*z).ForeignAssets[zb0008]) >= zb0109 {
+ (*z).ForeignAssets[zb0008] = ((*z).ForeignAssets[zb0008])[:zb0109]
+ } else {
+ (*z).ForeignAssets[zb0008] = make(assetIndices, zb0109)
+ }
+ for zb0009 := range (*z).ForeignAssets[zb0008] {
+ bts, err = (*z).ForeignAssets[zb0008][zb0009].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignAssets", zb0008, zb0009)
+ return
+ }
+ }
+ }
+ case "apasbm":
+ {
+ var zb0111 []byte
+ var zb0112 int
+ zb0112, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignAssets")
+ return
+ }
+ if zb0112 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0112), uint64(maxBitmaskSize))
+ return
+ }
+ zb0111, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskForeignAssets))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignAssets")
+ return
+ }
+ (*z).BitmaskForeignAssets = bitmask(zb0111)
+ }
+ case "lnui":
+ var zb0113 int
+ var zb0114 bool
+ zb0113, zb0114, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumUint")
+ return
+ }
+ if zb0113 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0113), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LocalNumUint")
+ return
+ }
+ if zb0114 {
+ (*z).LocalNumUint = nil
+ } else if (*z).LocalNumUint != nil && cap((*z).LocalNumUint) >= zb0113 {
+ (*z).LocalNumUint = ((*z).LocalNumUint)[:zb0113]
+ } else {
+ (*z).LocalNumUint = make([]uint64, zb0113)
+ }
+ for zb0010 := range (*z).LocalNumUint {
+ (*z).LocalNumUint[zb0010], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumUint", zb0010)
+ return
+ }
+ }
+ case "lnuibm":
+ {
+ var zb0115 []byte
+ var zb0116 int
+ zb0116, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumUint")
+ return
+ }
+ if zb0116 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0116), uint64(maxBitmaskSize))
+ return
+ }
+ zb0115, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskLocalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumUint")
+ return
+ }
+ (*z).BitmaskLocalNumUint = bitmask(zb0115)
+ }
+ case "lnbs":
+ var zb0117 int
+ var zb0118 bool
+ zb0117, zb0118, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumByteSlice")
+ return
+ }
+ if zb0117 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0117), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LocalNumByteSlice")
+ return
+ }
+ if zb0118 {
+ (*z).LocalNumByteSlice = nil
+ } else if (*z).LocalNumByteSlice != nil && cap((*z).LocalNumByteSlice) >= zb0117 {
+ (*z).LocalNumByteSlice = ((*z).LocalNumByteSlice)[:zb0117]
+ } else {
+ (*z).LocalNumByteSlice = make([]uint64, zb0117)
+ }
+ for zb0011 := range (*z).LocalNumByteSlice {
+ (*z).LocalNumByteSlice[zb0011], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumByteSlice", zb0011)
+ return
+ }
+ }
+ case "lnbsbm":
+ {
+ var zb0119 []byte
+ var zb0120 int
+ zb0120, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumByteSlice")
+ return
+ }
+ if zb0120 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0120), uint64(maxBitmaskSize))
+ return
+ }
+ zb0119, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskLocalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumByteSlice")
+ return
+ }
+ (*z).BitmaskLocalNumByteSlice = bitmask(zb0119)
+ }
+ case "gnui":
+ var zb0121 int
+ var zb0122 bool
+ zb0121, zb0122, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumUint")
+ return
+ }
+ if zb0121 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0121), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "GlobalNumUint")
+ return
+ }
+ if zb0122 {
+ (*z).GlobalNumUint = nil
+ } else if (*z).GlobalNumUint != nil && cap((*z).GlobalNumUint) >= zb0121 {
+ (*z).GlobalNumUint = ((*z).GlobalNumUint)[:zb0121]
+ } else {
+ (*z).GlobalNumUint = make([]uint64, zb0121)
+ }
+ for zb0012 := range (*z).GlobalNumUint {
+ (*z).GlobalNumUint[zb0012], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumUint", zb0012)
+ return
+ }
+ }
+ case "gnuibm":
+ {
+ var zb0123 []byte
+ var zb0124 int
+ zb0124, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumUint")
+ return
+ }
+ if zb0124 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0124), uint64(maxBitmaskSize))
+ return
+ }
+ zb0123, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskGlobalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumUint")
+ return
+ }
+ (*z).BitmaskGlobalNumUint = bitmask(zb0123)
+ }
+ case "gnbs":
+ var zb0125 int
+ var zb0126 bool
+ zb0125, zb0126, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumByteSlice")
+ return
+ }
+ if zb0125 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0125), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "GlobalNumByteSlice")
+ return
+ }
+ if zb0126 {
+ (*z).GlobalNumByteSlice = nil
+ } else if (*z).GlobalNumByteSlice != nil && cap((*z).GlobalNumByteSlice) >= zb0125 {
+ (*z).GlobalNumByteSlice = ((*z).GlobalNumByteSlice)[:zb0125]
+ } else {
+ (*z).GlobalNumByteSlice = make([]uint64, zb0125)
+ }
+ for zb0013 := range (*z).GlobalNumByteSlice {
+ (*z).GlobalNumByteSlice[zb0013], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumByteSlice", zb0013)
+ return
+ }
+ }
+ case "gnbsbm":
+ {
+ var zb0127 []byte
+ var zb0128 int
+ zb0128, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumByteSlice")
+ return
+ }
+ if zb0128 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0128), uint64(maxBitmaskSize))
+ return
+ }
+ zb0127, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskGlobalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumByteSlice")
+ return
+ }
+ (*z).BitmaskGlobalNumByteSlice = bitmask(zb0127)
+ }
+ case "apap":
+ var zb0129 int
+ var zb0130 bool
+ zb0129, zb0130, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApprovalProgram")
+ return
+ }
+ if zb0129 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0129), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ApprovalProgram")
+ return
+ }
+ if zb0130 {
+ (*z).ApprovalProgram = nil
+ } else if (*z).ApprovalProgram != nil && cap((*z).ApprovalProgram) >= zb0129 {
+ (*z).ApprovalProgram = ((*z).ApprovalProgram)[:zb0129]
+ } else {
+ (*z).ApprovalProgram = make([]program, zb0129)
+ }
+ for zb0014 := range (*z).ApprovalProgram {
+ {
+ var zb0131 []byte
+ var zb0132 int
+ zb0132, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApprovalProgram", zb0014)
+ return
+ }
+ if zb0132 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0132), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0131, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).ApprovalProgram[zb0014]))
+ if err != nil {
+ err = msgp.WrapError(err, "ApprovalProgram", zb0014)
+ return
+ }
+ (*z).ApprovalProgram[zb0014] = program(zb0131)
+ }
+ }
+ case "apapbm":
+ {
+ var zb0133 []byte
+ var zb0134 int
+ zb0134, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApprovalProgram")
+ return
+ }
+ if zb0134 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0134), uint64(maxBitmaskSize))
+ return
+ }
+ zb0133, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskApprovalProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApprovalProgram")
+ return
+ }
+ (*z).BitmaskApprovalProgram = bitmask(zb0133)
+ }
+ case "apsu":
+ var zb0135 int
+ var zb0136 bool
+ zb0135, zb0136, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ClearStateProgram")
+ return
+ }
+ if zb0135 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0135), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ClearStateProgram")
+ return
+ }
+ if zb0136 {
+ (*z).ClearStateProgram = nil
+ } else if (*z).ClearStateProgram != nil && cap((*z).ClearStateProgram) >= zb0135 {
+ (*z).ClearStateProgram = ((*z).ClearStateProgram)[:zb0135]
+ } else {
+ (*z).ClearStateProgram = make([]program, zb0135)
+ }
+ for zb0015 := range (*z).ClearStateProgram {
+ {
+ var zb0137 []byte
+ var zb0138 int
+ zb0138, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ClearStateProgram", zb0015)
+ return
+ }
+ if zb0138 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0138), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0137, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).ClearStateProgram[zb0015]))
+ if err != nil {
+ err = msgp.WrapError(err, "ClearStateProgram", zb0015)
+ return
+ }
+ (*z).ClearStateProgram[zb0015] = program(zb0137)
+ }
+ }
+ case "apsubm":
+ {
+ var zb0139 []byte
+ var zb0140 int
+ zb0140, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClearStateProgram")
+ return
+ }
+ if zb0140 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0140), uint64(maxBitmaskSize))
+ return
+ }
+ zb0139, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskClearStateProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClearStateProgram")
+ return
+ }
+ (*z).BitmaskClearStateProgram = bitmask(zb0139)
+ }
+ case "apep":
+ var zb0141 int
+ var zb0142 bool
+ zb0141, zb0142, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExtraProgramPages")
+ return
+ }
+ if zb0141 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0141), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ExtraProgramPages")
+ return
+ }
+ if zb0142 {
+ (*z).ExtraProgramPages = nil
+ } else if (*z).ExtraProgramPages != nil && cap((*z).ExtraProgramPages) >= zb0141 {
+ (*z).ExtraProgramPages = ((*z).ExtraProgramPages)[:zb0141]
+ } else {
+ (*z).ExtraProgramPages = make([]uint32, zb0141)
+ }
+ for zb0016 := range (*z).ExtraProgramPages {
+ (*z).ExtraProgramPages[zb0016], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExtraProgramPages", zb0016)
+ return
+ }
+ }
+ case "apepbm":
+ {
+ var zb0143 []byte
+ var zb0144 int
+ zb0144, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskExtraProgramPages")
+ return
+ }
+ if zb0144 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0144), uint64(maxBitmaskSize))
+ return
+ }
+ zb0143, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskExtraProgramPages))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskExtraProgramPages")
+ return
+ }
+ (*z).BitmaskExtraProgramPages = bitmask(zb0143)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedApplicationCallTxnFields) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedApplicationCallTxnFields)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedApplicationCallTxnFields) Msgsize() (s int) {
+ s = 3 + 5 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).ApplicationID {
+ s += (*z).ApplicationID[zb0001].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskApplicationID)) + 5 + msgp.BytesPrefixSize + len((*z).OnCompletion) + 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskOnCompletion)) + 5 + msgp.ArrayHeaderSize
+ for zb0002 := range (*z).ApplicationArgs {
+ s += msgp.ArrayHeaderSize
+ for zb0003 := range (*z).ApplicationArgs[zb0002] {
+ s += msgp.BytesPrefixSize + len((*z).ApplicationArgs[zb0002][zb0003])
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskApplicationArgs)) + 5 + msgp.ArrayHeaderSize
+ for zb0004 := range (*z).Accounts {
+ s += msgp.ArrayHeaderSize
+ for zb0005 := range (*z).Accounts[zb0004] {
+ s += (*z).Accounts[zb0004][zb0005].Msgsize()
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskAccounts)) + 5 + msgp.ArrayHeaderSize
+ for zb0006 := range (*z).ForeignApps {
+ s += msgp.ArrayHeaderSize
+ for zb0007 := range (*z).ForeignApps[zb0006] {
+ s += (*z).ForeignApps[zb0006][zb0007].Msgsize()
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskForeignApps)) + 5 + msgp.ArrayHeaderSize
+ for zb0008 := range (*z).ForeignAssets {
+ s += msgp.ArrayHeaderSize
+ for zb0009 := range (*z).ForeignAssets[zb0008] {
+ s += (*z).ForeignAssets[zb0008][zb0009].Msgsize()
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskForeignAssets)) + 5 + msgp.ArrayHeaderSize + (len((*z).LocalNumUint) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskLocalNumUint)) + 5 + msgp.ArrayHeaderSize + (len((*z).LocalNumByteSlice) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskLocalNumByteSlice)) + 5 + msgp.ArrayHeaderSize + (len((*z).GlobalNumUint) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskGlobalNumUint)) + 5 + msgp.ArrayHeaderSize + (len((*z).GlobalNumByteSlice) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskGlobalNumByteSlice)) + 5 + msgp.ArrayHeaderSize
+ for zb0014 := range (*z).ApprovalProgram {
+ s += msgp.BytesPrefixSize + len([]byte((*z).ApprovalProgram[zb0014]))
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskApprovalProgram)) + 5 + msgp.ArrayHeaderSize
+ for zb0015 := range (*z).ClearStateProgram {
+ s += msgp.BytesPrefixSize + len([]byte((*z).ClearStateProgram[zb0015]))
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskClearStateProgram)) + 5 + msgp.ArrayHeaderSize + (len((*z).ExtraProgramPages) * (msgp.Uint32Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskExtraProgramPages))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedApplicationCallTxnFields) MsgIsZero() bool {
+ return (len((*z).ApplicationID) == 0) && (len((*z).BitmaskApplicationID) == 0) && (len((*z).OnCompletion) == 0) && (len((*z).BitmaskOnCompletion) == 0) && (len((*z).ApplicationArgs) == 0) && (len((*z).BitmaskApplicationArgs) == 0) && (len((*z).Accounts) == 0) && (len((*z).BitmaskAccounts) == 0) && (len((*z).ForeignApps) == 0) && (len((*z).BitmaskForeignApps) == 0) && (len((*z).ForeignAssets) == 0) && (len((*z).BitmaskForeignAssets) == 0) && (len((*z).LocalNumUint) == 0) && (len((*z).BitmaskLocalNumUint) == 0) && (len((*z).LocalNumByteSlice) == 0) && (len((*z).BitmaskLocalNumByteSlice) == 0) && (len((*z).GlobalNumUint) == 0) && (len((*z).BitmaskGlobalNumUint) == 0) && (len((*z).GlobalNumByteSlice) == 0) && (len((*z).BitmaskGlobalNumByteSlice) == 0) && (len((*z).ApprovalProgram) == 0) && (len((*z).BitmaskApprovalProgram) == 0) && (len((*z).ClearStateProgram) == 0) && (len((*z).BitmaskClearStateProgram) == 0) && (len((*z).ExtraProgramPages) == 0) && (len((*z).BitmaskExtraProgramPages) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedAssetConfigTxnFields) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0007Len := uint32(23)
+ var zb0007Mask uint32 /* 25 bits */
+ if len((*z).encodedAssetParams.MetadataHash) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x4
+ }
+ if len((*z).encodedAssetParams.BitmaskMetadataHash) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x8
+ }
+ if len((*z).encodedAssetParams.AssetName) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x10
+ }
+ if len((*z).encodedAssetParams.BitmaskAssetName) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x20
+ }
+ if len((*z).encodedAssetParams.URL) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x40
+ }
+ if len((*z).encodedAssetParams.BitmaskURL) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x80
+ }
+ if len((*z).encodedAssetParams.Clawback) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x100
+ }
+ if len((*z).ConfigAsset) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x200
+ }
+ if len((*z).BitmaskConfigAsset) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x400
+ }
+ if len((*z).encodedAssetParams.BitmaskClawback) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x800
+ }
+ if len((*z).encodedAssetParams.Decimals) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x1000
+ }
+ if len((*z).encodedAssetParams.BitmaskDecimals) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x2000
+ }
+ if len((*z).encodedAssetParams.BitmaskDefaultFrozen) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x4000
+ }
+ if len((*z).encodedAssetParams.Freeze) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x8000
+ }
+ if len((*z).encodedAssetParams.BitmaskFreeze) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x10000
+ }
+ if len((*z).encodedAssetParams.Manager) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x20000
+ }
+ if len((*z).encodedAssetParams.BitmaskManager) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x40000
+ }
+ if len((*z).encodedAssetParams.Reserve) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x80000
+ }
+ if len((*z).encodedAssetParams.BitmaskReserve) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x100000
+ }
+ if len((*z).encodedAssetParams.Total) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x200000
+ }
+ if len((*z).encodedAssetParams.BitmaskTotal) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x400000
+ }
+ if len((*z).encodedAssetParams.UnitName) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x800000
+ }
+ if len((*z).encodedAssetParams.BitmaskUnitName) == 0 {
+ zb0007Len--
+ zb0007Mask |= 0x1000000
+ }
+ // variable map header, size zb0007Len
+ o = msgp.AppendMapHeader(o, zb0007Len)
+ if zb0007Len != 0 {
+ if (zb0007Mask & 0x4) == 0 { // if not empty
+ // string "am"
+ o = append(o, 0xa2, 0x61, 0x6d)
+ o = msgp.AppendBytes(o, (*z).encodedAssetParams.MetadataHash)
+ }
+ if (zb0007Mask & 0x8) == 0 { // if not empty
+ // string "ambm"
+ o = append(o, 0xa4, 0x61, 0x6d, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetParams.BitmaskMetadataHash))
+ }
+ if (zb0007Mask & 0x10) == 0 { // if not empty
+ // string "an"
+ o = append(o, 0xa2, 0x61, 0x6e)
+ if (*z).encodedAssetParams.AssetName == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedAssetParams.AssetName)))
+ }
+ for zb0005 := range (*z).encodedAssetParams.AssetName {
+ o = msgp.AppendString(o, (*z).encodedAssetParams.AssetName[zb0005])
+ }
+ }
+ if (zb0007Mask & 0x20) == 0 { // if not empty
+ // string "anbm"
+ o = append(o, 0xa4, 0x61, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetParams.BitmaskAssetName))
+ }
+ if (zb0007Mask & 0x40) == 0 { // if not empty
+ // string "au"
+ o = append(o, 0xa2, 0x61, 0x75)
+ if (*z).encodedAssetParams.URL == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedAssetParams.URL)))
+ }
+ for zb0006 := range (*z).encodedAssetParams.URL {
+ o = msgp.AppendString(o, (*z).encodedAssetParams.URL[zb0006])
+ }
+ }
+ if (zb0007Mask & 0x80) == 0 { // if not empty
+ // string "aubm"
+ o = append(o, 0xa4, 0x61, 0x75, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetParams.BitmaskURL))
+ }
+ if (zb0007Mask & 0x100) == 0 { // if not empty
+ // string "c"
+ o = append(o, 0xa1, 0x63)
+ o = msgp.AppendBytes(o, (*z).encodedAssetParams.Clawback)
+ }
+ if (zb0007Mask & 0x200) == 0 { // if not empty
+ // string "caid"
+ o = append(o, 0xa4, 0x63, 0x61, 0x69, 0x64)
+ if (*z).ConfigAsset == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).ConfigAsset)))
+ }
+ for zb0001 := range (*z).ConfigAsset {
+ o = (*z).ConfigAsset[zb0001].MarshalMsg(o)
+ }
+ }
+ if (zb0007Mask & 0x400) == 0 { // if not empty
+ // string "caidbm"
+ o = append(o, 0xa6, 0x63, 0x61, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskConfigAsset))
+ }
+ if (zb0007Mask & 0x800) == 0 { // if not empty
+ // string "cbm"
+ o = append(o, 0xa3, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetParams.BitmaskClawback))
+ }
+ if (zb0007Mask & 0x1000) == 0 { // if not empty
+ // string "dc"
+ o = append(o, 0xa2, 0x64, 0x63)
+ if (*z).encodedAssetParams.Decimals == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedAssetParams.Decimals)))
+ }
+ for zb0003 := range (*z).encodedAssetParams.Decimals {
+ o = msgp.AppendUint32(o, (*z).encodedAssetParams.Decimals[zb0003])
+ }
+ }
+ if (zb0007Mask & 0x2000) == 0 { // if not empty
+ // string "dcbm"
+ o = append(o, 0xa4, 0x64, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetParams.BitmaskDecimals))
+ }
+ if (zb0007Mask & 0x4000) == 0 { // if not empty
+ // string "dfbm"
+ o = append(o, 0xa4, 0x64, 0x66, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetParams.BitmaskDefaultFrozen))
+ }
+ if (zb0007Mask & 0x8000) == 0 { // if not empty
+ // string "f"
+ o = append(o, 0xa1, 0x66)
+ o = msgp.AppendBytes(o, (*z).encodedAssetParams.Freeze)
+ }
+ if (zb0007Mask & 0x10000) == 0 { // if not empty
+ // string "fbm"
+ o = append(o, 0xa3, 0x66, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetParams.BitmaskFreeze))
+ }
+ if (zb0007Mask & 0x20000) == 0 { // if not empty
+ // string "m"
+ o = append(o, 0xa1, 0x6d)
+ o = msgp.AppendBytes(o, (*z).encodedAssetParams.Manager)
+ }
+ if (zb0007Mask & 0x40000) == 0 { // if not empty
+ // string "mbm"
+ o = append(o, 0xa3, 0x6d, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetParams.BitmaskManager))
+ }
+ if (zb0007Mask & 0x80000) == 0 { // if not empty
+ // string "r"
+ o = append(o, 0xa1, 0x72)
+ o = msgp.AppendBytes(o, (*z).encodedAssetParams.Reserve)
+ }
+ if (zb0007Mask & 0x100000) == 0 { // if not empty
+ // string "rbm"
+ o = append(o, 0xa3, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetParams.BitmaskReserve))
+ }
+ if (zb0007Mask & 0x200000) == 0 { // if not empty
+ // string "t"
+ o = append(o, 0xa1, 0x74)
+ if (*z).encodedAssetParams.Total == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedAssetParams.Total)))
+ }
+ for zb0002 := range (*z).encodedAssetParams.Total {
+ o = msgp.AppendUint64(o, (*z).encodedAssetParams.Total[zb0002])
+ }
+ }
+ if (zb0007Mask & 0x400000) == 0 { // if not empty
+ // string "tbm"
+ o = append(o, 0xa3, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetParams.BitmaskTotal))
+ }
+ if (zb0007Mask & 0x800000) == 0 { // if not empty
+ // string "un"
+ o = append(o, 0xa2, 0x75, 0x6e)
+ if (*z).encodedAssetParams.UnitName == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedAssetParams.UnitName)))
+ }
+ for zb0004 := range (*z).encodedAssetParams.UnitName {
+ o = msgp.AppendString(o, (*z).encodedAssetParams.UnitName[zb0004])
+ }
+ }
+ if (zb0007Mask & 0x1000000) == 0 { // if not empty
+ // string "unbm"
+ o = append(o, 0xa4, 0x75, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetParams.BitmaskUnitName))
+ }
+ }
+ return
+}
+
+func (_ *encodedAssetConfigTxnFields) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedAssetConfigTxnFields)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedAssetConfigTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0007 int
+ var zb0008 bool
+ zb0007, zb0008, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0007, zb0008, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0007 > 0 {
+ zb0007--
+ var zb0009 int
+ var zb0010 bool
+ zb0009, zb0010, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ConfigAsset")
+ return
+ }
+ if zb0009 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0009), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ConfigAsset")
+ return
+ }
+ if zb0010 {
+ (*z).ConfigAsset = nil
+ } else if (*z).ConfigAsset != nil && cap((*z).ConfigAsset) >= zb0009 {
+ (*z).ConfigAsset = ((*z).ConfigAsset)[:zb0009]
+ } else {
+ (*z).ConfigAsset = make([]basics.AssetIndex, zb0009)
+ }
+ for zb0001 := range (*z).ConfigAsset {
+ bts, err = (*z).ConfigAsset[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ConfigAsset", zb0001)
+ return
+ }
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ {
+ var zb0011 []byte
+ var zb0012 int
+ zb0012, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskConfigAsset")
+ return
+ }
+ if zb0012 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0012), uint64(maxBitmaskSize))
+ return
+ }
+ zb0011, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskConfigAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskConfigAsset")
+ return
+ }
+ (*z).BitmaskConfigAsset = bitmask(zb0011)
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ var zb0013 int
+ var zb0014 bool
+ zb0013, zb0014, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Total")
+ return
+ }
+ if zb0013 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0013), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Total")
+ return
+ }
+ if zb0014 {
+ (*z).encodedAssetParams.Total = nil
+ } else if (*z).encodedAssetParams.Total != nil && cap((*z).encodedAssetParams.Total) >= zb0013 {
+ (*z).encodedAssetParams.Total = ((*z).encodedAssetParams.Total)[:zb0013]
+ } else {
+ (*z).encodedAssetParams.Total = make([]uint64, zb0013)
+ }
+ for zb0002 := range (*z).encodedAssetParams.Total {
+ (*z).encodedAssetParams.Total[zb0002], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Total", zb0002)
+ return
+ }
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ {
+ var zb0015 []byte
+ var zb0016 int
+ zb0016, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTotal")
+ return
+ }
+ if zb0016 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0016), uint64(maxBitmaskSize))
+ return
+ }
+ zb0015, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskTotal))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTotal")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskTotal = bitmask(zb0015)
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ var zb0017 int
+ var zb0018 bool
+ zb0017, zb0018, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Decimals")
+ return
+ }
+ if zb0017 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0017), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Decimals")
+ return
+ }
+ if zb0018 {
+ (*z).encodedAssetParams.Decimals = nil
+ } else if (*z).encodedAssetParams.Decimals != nil && cap((*z).encodedAssetParams.Decimals) >= zb0017 {
+ (*z).encodedAssetParams.Decimals = ((*z).encodedAssetParams.Decimals)[:zb0017]
+ } else {
+ (*z).encodedAssetParams.Decimals = make([]uint32, zb0017)
+ }
+ for zb0003 := range (*z).encodedAssetParams.Decimals {
+ (*z).encodedAssetParams.Decimals[zb0003], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Decimals", zb0003)
+ return
+ }
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ {
+ var zb0019 []byte
+ var zb0020 int
+ zb0020, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDecimals")
+ return
+ }
+ if zb0020 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0020), uint64(maxBitmaskSize))
+ return
+ }
+ zb0019, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskDecimals))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDecimals")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskDecimals = bitmask(zb0019)
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ {
+ var zb0021 []byte
+ var zb0022 int
+ zb0022, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDefaultFrozen")
+ return
+ }
+ if zb0022 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0022), uint64(maxBitmaskSize))
+ return
+ }
+ zb0021, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskDefaultFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDefaultFrozen")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskDefaultFrozen = bitmask(zb0021)
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ var zb0023 int
+ var zb0024 bool
+ zb0023, zb0024, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UnitName")
+ return
+ }
+ if zb0023 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0023), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "UnitName")
+ return
+ }
+ if zb0024 {
+ (*z).encodedAssetParams.UnitName = nil
+ } else if (*z).encodedAssetParams.UnitName != nil && cap((*z).encodedAssetParams.UnitName) >= zb0023 {
+ (*z).encodedAssetParams.UnitName = ((*z).encodedAssetParams.UnitName)[:zb0023]
+ } else {
+ (*z).encodedAssetParams.UnitName = make([]string, zb0023)
+ }
+ for zb0004 := range (*z).encodedAssetParams.UnitName {
+ (*z).encodedAssetParams.UnitName[zb0004], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UnitName", zb0004)
+ return
+ }
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ {
+ var zb0025 []byte
+ var zb0026 int
+ zb0026, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskUnitName")
+ return
+ }
+ if zb0026 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0026), uint64(maxBitmaskSize))
+ return
+ }
+ zb0025, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskUnitName))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskUnitName")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskUnitName = bitmask(zb0025)
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ var zb0027 int
+ var zb0028 bool
+ zb0027, zb0028, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetName")
+ return
+ }
+ if zb0027 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0027), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "AssetName")
+ return
+ }
+ if zb0028 {
+ (*z).encodedAssetParams.AssetName = nil
+ } else if (*z).encodedAssetParams.AssetName != nil && cap((*z).encodedAssetParams.AssetName) >= zb0027 {
+ (*z).encodedAssetParams.AssetName = ((*z).encodedAssetParams.AssetName)[:zb0027]
+ } else {
+ (*z).encodedAssetParams.AssetName = make([]string, zb0027)
+ }
+ for zb0005 := range (*z).encodedAssetParams.AssetName {
+ (*z).encodedAssetParams.AssetName[zb0005], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetName", zb0005)
+ return
+ }
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ {
+ var zb0029 []byte
+ var zb0030 int
+ zb0030, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetName")
+ return
+ }
+ if zb0030 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0030), uint64(maxBitmaskSize))
+ return
+ }
+ zb0029, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskAssetName))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetName")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskAssetName = bitmask(zb0029)
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ var zb0031 int
+ var zb0032 bool
+ zb0031, zb0032, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "URL")
+ return
+ }
+ if zb0031 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0031), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "URL")
+ return
+ }
+ if zb0032 {
+ (*z).encodedAssetParams.URL = nil
+ } else if (*z).encodedAssetParams.URL != nil && cap((*z).encodedAssetParams.URL) >= zb0031 {
+ (*z).encodedAssetParams.URL = ((*z).encodedAssetParams.URL)[:zb0031]
+ } else {
+ (*z).encodedAssetParams.URL = make([]string, zb0031)
+ }
+ for zb0006 := range (*z).encodedAssetParams.URL {
+ (*z).encodedAssetParams.URL[zb0006], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "URL", zb0006)
+ return
+ }
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ {
+ var zb0033 []byte
+ var zb0034 int
+ zb0034, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskURL")
+ return
+ }
+ if zb0034 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0034), uint64(maxBitmaskSize))
+ return
+ }
+ zb0033, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskURL))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskURL")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskURL = bitmask(zb0033)
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ var zb0035 int
+ zb0035, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "MetadataHash")
+ return
+ }
+ if zb0035 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0035), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetParams.MetadataHash, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetParams.MetadataHash)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "MetadataHash")
+ return
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ {
+ var zb0036 []byte
+ var zb0037 int
+ zb0037, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskMetadataHash")
+ return
+ }
+ if zb0037 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0037), uint64(maxBitmaskSize))
+ return
+ }
+ zb0036, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskMetadataHash))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskMetadataHash")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskMetadataHash = bitmask(zb0036)
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ var zb0038 int
+ zb0038, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Manager")
+ return
+ }
+ if zb0038 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0038), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetParams.Manager, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetParams.Manager)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Manager")
+ return
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ {
+ var zb0039 []byte
+ var zb0040 int
+ zb0040, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskManager")
+ return
+ }
+ if zb0040 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0040), uint64(maxBitmaskSize))
+ return
+ }
+ zb0039, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskManager))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskManager")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskManager = bitmask(zb0039)
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ var zb0041 int
+ zb0041, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reserve")
+ return
+ }
+ if zb0041 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0041), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetParams.Reserve, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetParams.Reserve)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reserve")
+ return
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ {
+ var zb0042 []byte
+ var zb0043 int
+ zb0043, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReserve")
+ return
+ }
+ if zb0043 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0043), uint64(maxBitmaskSize))
+ return
+ }
+ zb0042, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskReserve))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReserve")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskReserve = bitmask(zb0042)
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ var zb0044 int
+ zb0044, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Freeze")
+ return
+ }
+ if zb0044 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0044), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetParams.Freeze, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetParams.Freeze)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Freeze")
+ return
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ {
+ var zb0045 []byte
+ var zb0046 int
+ zb0046, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreeze")
+ return
+ }
+ if zb0046 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0046), uint64(maxBitmaskSize))
+ return
+ }
+ zb0045, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskFreeze))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreeze")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskFreeze = bitmask(zb0045)
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ var zb0047 int
+ zb0047, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Clawback")
+ return
+ }
+ if zb0047 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0047), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetParams.Clawback, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetParams.Clawback)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Clawback")
+ return
+ }
+ }
+ if zb0007 > 0 {
+ zb0007--
+ {
+ var zb0048 []byte
+ var zb0049 int
+ zb0049, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClawback")
+ return
+ }
+ if zb0049 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0049), uint64(maxBitmaskSize))
+ return
+ }
+ zb0048, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskClawback))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClawback")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskClawback = bitmask(zb0048)
+ }
+ }
+ if zb0007 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0007)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0008 {
+ (*z) = encodedAssetConfigTxnFields{}
+ }
+ for zb0007 > 0 {
+ zb0007--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "caid":
+ var zb0050 int
+ var zb0051 bool
+ zb0050, zb0051, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ConfigAsset")
+ return
+ }
+ if zb0050 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0050), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ConfigAsset")
+ return
+ }
+ if zb0051 {
+ (*z).ConfigAsset = nil
+ } else if (*z).ConfigAsset != nil && cap((*z).ConfigAsset) >= zb0050 {
+ (*z).ConfigAsset = ((*z).ConfigAsset)[:zb0050]
+ } else {
+ (*z).ConfigAsset = make([]basics.AssetIndex, zb0050)
+ }
+ for zb0001 := range (*z).ConfigAsset {
+ bts, err = (*z).ConfigAsset[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ConfigAsset", zb0001)
+ return
+ }
+ }
+ case "caidbm":
+ {
+ var zb0052 []byte
+ var zb0053 int
+ zb0053, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskConfigAsset")
+ return
+ }
+ if zb0053 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0053), uint64(maxBitmaskSize))
+ return
+ }
+ zb0052, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskConfigAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskConfigAsset")
+ return
+ }
+ (*z).BitmaskConfigAsset = bitmask(zb0052)
+ }
+ case "t":
+ var zb0054 int
+ var zb0055 bool
+ zb0054, zb0055, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Total")
+ return
+ }
+ if zb0054 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0054), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Total")
+ return
+ }
+ if zb0055 {
+ (*z).encodedAssetParams.Total = nil
+ } else if (*z).encodedAssetParams.Total != nil && cap((*z).encodedAssetParams.Total) >= zb0054 {
+ (*z).encodedAssetParams.Total = ((*z).encodedAssetParams.Total)[:zb0054]
+ } else {
+ (*z).encodedAssetParams.Total = make([]uint64, zb0054)
+ }
+ for zb0002 := range (*z).encodedAssetParams.Total {
+ (*z).encodedAssetParams.Total[zb0002], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Total", zb0002)
+ return
+ }
+ }
+ case "tbm":
+ {
+ var zb0056 []byte
+ var zb0057 int
+ zb0057, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTotal")
+ return
+ }
+ if zb0057 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0057), uint64(maxBitmaskSize))
+ return
+ }
+ zb0056, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskTotal))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTotal")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskTotal = bitmask(zb0056)
+ }
+ case "dc":
+ var zb0058 int
+ var zb0059 bool
+ zb0058, zb0059, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Decimals")
+ return
+ }
+ if zb0058 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0058), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Decimals")
+ return
+ }
+ if zb0059 {
+ (*z).encodedAssetParams.Decimals = nil
+ } else if (*z).encodedAssetParams.Decimals != nil && cap((*z).encodedAssetParams.Decimals) >= zb0058 {
+ (*z).encodedAssetParams.Decimals = ((*z).encodedAssetParams.Decimals)[:zb0058]
+ } else {
+ (*z).encodedAssetParams.Decimals = make([]uint32, zb0058)
+ }
+ for zb0003 := range (*z).encodedAssetParams.Decimals {
+ (*z).encodedAssetParams.Decimals[zb0003], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Decimals", zb0003)
+ return
+ }
+ }
+ case "dcbm":
+ {
+ var zb0060 []byte
+ var zb0061 int
+ zb0061, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDecimals")
+ return
+ }
+ if zb0061 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0061), uint64(maxBitmaskSize))
+ return
+ }
+ zb0060, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskDecimals))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDecimals")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskDecimals = bitmask(zb0060)
+ }
+ case "dfbm":
+ {
+ var zb0062 []byte
+ var zb0063 int
+ zb0063, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDefaultFrozen")
+ return
+ }
+ if zb0063 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0063), uint64(maxBitmaskSize))
+ return
+ }
+ zb0062, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskDefaultFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDefaultFrozen")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskDefaultFrozen = bitmask(zb0062)
+ }
+ case "un":
+ var zb0064 int
+ var zb0065 bool
+ zb0064, zb0065, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UnitName")
+ return
+ }
+ if zb0064 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0064), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "UnitName")
+ return
+ }
+ if zb0065 {
+ (*z).encodedAssetParams.UnitName = nil
+ } else if (*z).encodedAssetParams.UnitName != nil && cap((*z).encodedAssetParams.UnitName) >= zb0064 {
+ (*z).encodedAssetParams.UnitName = ((*z).encodedAssetParams.UnitName)[:zb0064]
+ } else {
+ (*z).encodedAssetParams.UnitName = make([]string, zb0064)
+ }
+ for zb0004 := range (*z).encodedAssetParams.UnitName {
+ (*z).encodedAssetParams.UnitName[zb0004], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UnitName", zb0004)
+ return
+ }
+ }
+ case "unbm":
+ {
+ var zb0066 []byte
+ var zb0067 int
+ zb0067, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskUnitName")
+ return
+ }
+ if zb0067 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0067), uint64(maxBitmaskSize))
+ return
+ }
+ zb0066, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskUnitName))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskUnitName")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskUnitName = bitmask(zb0066)
+ }
+ case "an":
+ var zb0068 int
+ var zb0069 bool
+ zb0068, zb0069, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetName")
+ return
+ }
+ if zb0068 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0068), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "AssetName")
+ return
+ }
+ if zb0069 {
+ (*z).encodedAssetParams.AssetName = nil
+ } else if (*z).encodedAssetParams.AssetName != nil && cap((*z).encodedAssetParams.AssetName) >= zb0068 {
+ (*z).encodedAssetParams.AssetName = ((*z).encodedAssetParams.AssetName)[:zb0068]
+ } else {
+ (*z).encodedAssetParams.AssetName = make([]string, zb0068)
+ }
+ for zb0005 := range (*z).encodedAssetParams.AssetName {
+ (*z).encodedAssetParams.AssetName[zb0005], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetName", zb0005)
+ return
+ }
+ }
+ case "anbm":
+ {
+ var zb0070 []byte
+ var zb0071 int
+ zb0071, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetName")
+ return
+ }
+ if zb0071 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0071), uint64(maxBitmaskSize))
+ return
+ }
+ zb0070, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskAssetName))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetName")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskAssetName = bitmask(zb0070)
+ }
+ case "au":
+ var zb0072 int
+ var zb0073 bool
+ zb0072, zb0073, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "URL")
+ return
+ }
+ if zb0072 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0072), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "URL")
+ return
+ }
+ if zb0073 {
+ (*z).encodedAssetParams.URL = nil
+ } else if (*z).encodedAssetParams.URL != nil && cap((*z).encodedAssetParams.URL) >= zb0072 {
+ (*z).encodedAssetParams.URL = ((*z).encodedAssetParams.URL)[:zb0072]
+ } else {
+ (*z).encodedAssetParams.URL = make([]string, zb0072)
+ }
+ for zb0006 := range (*z).encodedAssetParams.URL {
+ (*z).encodedAssetParams.URL[zb0006], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "URL", zb0006)
+ return
+ }
+ }
+ case "aubm":
+ {
+ var zb0074 []byte
+ var zb0075 int
+ zb0075, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskURL")
+ return
+ }
+ if zb0075 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0075), uint64(maxBitmaskSize))
+ return
+ }
+ zb0074, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskURL))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskURL")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskURL = bitmask(zb0074)
+ }
+ case "am":
+ var zb0076 int
+ zb0076, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "MetadataHash")
+ return
+ }
+ if zb0076 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0076), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetParams.MetadataHash, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetParams.MetadataHash)
+ if err != nil {
+ err = msgp.WrapError(err, "MetadataHash")
+ return
+ }
+ case "ambm":
+ {
+ var zb0077 []byte
+ var zb0078 int
+ zb0078, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskMetadataHash")
+ return
+ }
+ if zb0078 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0078), uint64(maxBitmaskSize))
+ return
+ }
+ zb0077, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskMetadataHash))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskMetadataHash")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskMetadataHash = bitmask(zb0077)
+ }
+ case "m":
+ var zb0079 int
+ zb0079, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Manager")
+ return
+ }
+ if zb0079 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0079), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetParams.Manager, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetParams.Manager)
+ if err != nil {
+ err = msgp.WrapError(err, "Manager")
+ return
+ }
+ case "mbm":
+ {
+ var zb0080 []byte
+ var zb0081 int
+ zb0081, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskManager")
+ return
+ }
+ if zb0081 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0081), uint64(maxBitmaskSize))
+ return
+ }
+ zb0080, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskManager))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskManager")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskManager = bitmask(zb0080)
+ }
+ case "r":
+ var zb0082 int
+ zb0082, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reserve")
+ return
+ }
+ if zb0082 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0082), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetParams.Reserve, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetParams.Reserve)
+ if err != nil {
+ err = msgp.WrapError(err, "Reserve")
+ return
+ }
+ case "rbm":
+ {
+ var zb0083 []byte
+ var zb0084 int
+ zb0084, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReserve")
+ return
+ }
+ if zb0084 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0084), uint64(maxBitmaskSize))
+ return
+ }
+ zb0083, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskReserve))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReserve")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskReserve = bitmask(zb0083)
+ }
+ case "f":
+ var zb0085 int
+ zb0085, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Freeze")
+ return
+ }
+ if zb0085 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0085), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetParams.Freeze, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetParams.Freeze)
+ if err != nil {
+ err = msgp.WrapError(err, "Freeze")
+ return
+ }
+ case "fbm":
+ {
+ var zb0086 []byte
+ var zb0087 int
+ zb0087, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreeze")
+ return
+ }
+ if zb0087 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0087), uint64(maxBitmaskSize))
+ return
+ }
+ zb0086, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskFreeze))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreeze")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskFreeze = bitmask(zb0086)
+ }
+ case "c":
+ var zb0088 int
+ zb0088, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Clawback")
+ return
+ }
+ if zb0088 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0088), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetParams.Clawback, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetParams.Clawback)
+ if err != nil {
+ err = msgp.WrapError(err, "Clawback")
+ return
+ }
+ case "cbm":
+ {
+ var zb0089 []byte
+ var zb0090 int
+ zb0090, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClawback")
+ return
+ }
+ if zb0090 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0090), uint64(maxBitmaskSize))
+ return
+ }
+ zb0089, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetParams.BitmaskClawback))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClawback")
+ return
+ }
+ (*z).encodedAssetParams.BitmaskClawback = bitmask(zb0089)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedAssetConfigTxnFields) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedAssetConfigTxnFields)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedAssetConfigTxnFields) Msgsize() (s int) {
+ s = 3 + 5 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).ConfigAsset {
+ s += (*z).ConfigAsset[zb0001].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskConfigAsset)) + 2 + msgp.ArrayHeaderSize + (len((*z).encodedAssetParams.Total) * (msgp.Uint64Size)) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetParams.BitmaskTotal)) + 3 + msgp.ArrayHeaderSize + (len((*z).encodedAssetParams.Decimals) * (msgp.Uint32Size)) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetParams.BitmaskDecimals)) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetParams.BitmaskDefaultFrozen)) + 3 + msgp.ArrayHeaderSize
+ for zb0004 := range (*z).encodedAssetParams.UnitName {
+ s += msgp.StringPrefixSize + len((*z).encodedAssetParams.UnitName[zb0004])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetParams.BitmaskUnitName)) + 3 + msgp.ArrayHeaderSize
+ for zb0005 := range (*z).encodedAssetParams.AssetName {
+ s += msgp.StringPrefixSize + len((*z).encodedAssetParams.AssetName[zb0005])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetParams.BitmaskAssetName)) + 3 + msgp.ArrayHeaderSize
+ for zb0006 := range (*z).encodedAssetParams.URL {
+ s += msgp.StringPrefixSize + len((*z).encodedAssetParams.URL[zb0006])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetParams.BitmaskURL)) + 3 + msgp.BytesPrefixSize + len((*z).encodedAssetParams.MetadataHash) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetParams.BitmaskMetadataHash)) + 2 + msgp.BytesPrefixSize + len((*z).encodedAssetParams.Manager) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetParams.BitmaskManager)) + 2 + msgp.BytesPrefixSize + len((*z).encodedAssetParams.Reserve) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetParams.BitmaskReserve)) + 2 + msgp.BytesPrefixSize + len((*z).encodedAssetParams.Freeze) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetParams.BitmaskFreeze)) + 2 + msgp.BytesPrefixSize + len((*z).encodedAssetParams.Clawback) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetParams.BitmaskClawback))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedAssetConfigTxnFields) MsgIsZero() bool {
+ return (len((*z).ConfigAsset) == 0) && (len((*z).BitmaskConfigAsset) == 0) && (len((*z).encodedAssetParams.Total) == 0) && (len((*z).encodedAssetParams.BitmaskTotal) == 0) && (len((*z).encodedAssetParams.Decimals) == 0) && (len((*z).encodedAssetParams.BitmaskDecimals) == 0) && (len((*z).encodedAssetParams.BitmaskDefaultFrozen) == 0) && (len((*z).encodedAssetParams.UnitName) == 0) && (len((*z).encodedAssetParams.BitmaskUnitName) == 0) && (len((*z).encodedAssetParams.AssetName) == 0) && (len((*z).encodedAssetParams.BitmaskAssetName) == 0) && (len((*z).encodedAssetParams.URL) == 0) && (len((*z).encodedAssetParams.BitmaskURL) == 0) && (len((*z).encodedAssetParams.MetadataHash) == 0) && (len((*z).encodedAssetParams.BitmaskMetadataHash) == 0) && (len((*z).encodedAssetParams.Manager) == 0) && (len((*z).encodedAssetParams.BitmaskManager) == 0) && (len((*z).encodedAssetParams.Reserve) == 0) && (len((*z).encodedAssetParams.BitmaskReserve) == 0) && (len((*z).encodedAssetParams.Freeze) == 0) && (len((*z).encodedAssetParams.BitmaskFreeze) == 0) && (len((*z).encodedAssetParams.Clawback) == 0) && (len((*z).encodedAssetParams.BitmaskClawback) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedAssetFreezeTxnFields) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0002Len := uint32(5)
+ var zb0002Mask uint8 /* 6 bits */
+ if len((*z).BitmaskAssetFrozen) == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x2
+ }
+ if len((*z).FreezeAccount) == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x4
+ }
+ if len((*z).BitmaskFreezeAccount) == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x8
+ }
+ if len((*z).FreezeAsset) == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x10
+ }
+ if len((*z).BitmaskFreezeAsset) == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x20
+ }
+ // variable map header, size zb0002Len
+ o = append(o, 0x80|uint8(zb0002Len))
+ if zb0002Len != 0 {
+ if (zb0002Mask & 0x2) == 0 { // if not empty
+ // string "afrzbm"
+ o = append(o, 0xa6, 0x61, 0x66, 0x72, 0x7a, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskAssetFrozen))
+ }
+ if (zb0002Mask & 0x4) == 0 { // if not empty
+ // string "fadd"
+ o = append(o, 0xa4, 0x66, 0x61, 0x64, 0x64)
+ o = msgp.AppendBytes(o, (*z).FreezeAccount)
+ }
+ if (zb0002Mask & 0x8) == 0 { // if not empty
+ // string "faddbm"
+ o = append(o, 0xa6, 0x66, 0x61, 0x64, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskFreezeAccount))
+ }
+ if (zb0002Mask & 0x10) == 0 { // if not empty
+ // string "faid"
+ o = append(o, 0xa4, 0x66, 0x61, 0x69, 0x64)
+ if (*z).FreezeAsset == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).FreezeAsset)))
+ }
+ for zb0001 := range (*z).FreezeAsset {
+ o = (*z).FreezeAsset[zb0001].MarshalMsg(o)
+ }
+ }
+ if (zb0002Mask & 0x20) == 0 { // if not empty
+ // string "faidbm"
+ o = append(o, 0xa6, 0x66, 0x61, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskFreezeAsset))
+ }
+ }
+ return
+}
+
+func (_ *encodedAssetFreezeTxnFields) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedAssetFreezeTxnFields)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedAssetFreezeTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0002 int
+ var zb0003 bool
+ zb0002, zb0003, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0002, zb0003, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 > 0 {
+ zb0002--
+ var zb0004 int
+ zb0004, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAccount")
+ return
+ }
+ if zb0004 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0004), uint64(maxAddressBytes))
+ return
+ }
+ (*z).FreezeAccount, bts, err = msgp.ReadBytesBytes(bts, (*z).FreezeAccount)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAccount")
+ return
+ }
+ }
+ if zb0002 > 0 {
+ zb0002--
+ {
+ var zb0005 []byte
+ var zb0006 int
+ zb0006, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAccount")
+ return
+ }
+ if zb0006 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0006), uint64(maxBitmaskSize))
+ return
+ }
+ zb0005, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskFreezeAccount))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAccount")
+ return
+ }
+ (*z).BitmaskFreezeAccount = bitmask(zb0005)
+ }
+ }
+ if zb0002 > 0 {
+ zb0002--
+ var zb0007 int
+ var zb0008 bool
+ zb0007, zb0008, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAsset")
+ return
+ }
+ if zb0007 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0007), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAsset")
+ return
+ }
+ if zb0008 {
+ (*z).FreezeAsset = nil
+ } else if (*z).FreezeAsset != nil && cap((*z).FreezeAsset) >= zb0007 {
+ (*z).FreezeAsset = ((*z).FreezeAsset)[:zb0007]
+ } else {
+ (*z).FreezeAsset = make([]basics.AssetIndex, zb0007)
+ }
+ for zb0001 := range (*z).FreezeAsset {
+ bts, err = (*z).FreezeAsset[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAsset", zb0001)
+ return
+ }
+ }
+ }
+ if zb0002 > 0 {
+ zb0002--
+ {
+ var zb0009 []byte
+ var zb0010 int
+ zb0010, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAsset")
+ return
+ }
+ if zb0010 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0010), uint64(maxBitmaskSize))
+ return
+ }
+ zb0009, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskFreezeAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAsset")
+ return
+ }
+ (*z).BitmaskFreezeAsset = bitmask(zb0009)
+ }
+ }
+ if zb0002 > 0 {
+ zb0002--
+ {
+ var zb0011 []byte
+ var zb0012 int
+ zb0012, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetFrozen")
+ return
+ }
+ if zb0012 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0012), uint64(maxBitmaskSize))
+ return
+ }
+ zb0011, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAssetFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetFrozen")
+ return
+ }
+ (*z).BitmaskAssetFrozen = bitmask(zb0011)
+ }
+ }
+ if zb0002 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0002)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0003 {
+ (*z) = encodedAssetFreezeTxnFields{}
+ }
+ for zb0002 > 0 {
+ zb0002--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "fadd":
+ var zb0013 int
+ zb0013, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAccount")
+ return
+ }
+ if zb0013 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0013), uint64(maxAddressBytes))
+ return
+ }
+ (*z).FreezeAccount, bts, err = msgp.ReadBytesBytes(bts, (*z).FreezeAccount)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAccount")
+ return
+ }
+ case "faddbm":
+ {
+ var zb0014 []byte
+ var zb0015 int
+ zb0015, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAccount")
+ return
+ }
+ if zb0015 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0015), uint64(maxBitmaskSize))
+ return
+ }
+ zb0014, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskFreezeAccount))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAccount")
+ return
+ }
+ (*z).BitmaskFreezeAccount = bitmask(zb0014)
+ }
+ case "faid":
+ var zb0016 int
+ var zb0017 bool
+ zb0016, zb0017, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAsset")
+ return
+ }
+ if zb0016 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0016), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "FreezeAsset")
+ return
+ }
+ if zb0017 {
+ (*z).FreezeAsset = nil
+ } else if (*z).FreezeAsset != nil && cap((*z).FreezeAsset) >= zb0016 {
+ (*z).FreezeAsset = ((*z).FreezeAsset)[:zb0016]
+ } else {
+ (*z).FreezeAsset = make([]basics.AssetIndex, zb0016)
+ }
+ for zb0001 := range (*z).FreezeAsset {
+ bts, err = (*z).FreezeAsset[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAsset", zb0001)
+ return
+ }
+ }
+ case "faidbm":
+ {
+ var zb0018 []byte
+ var zb0019 int
+ zb0019, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAsset")
+ return
+ }
+ if zb0019 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0019), uint64(maxBitmaskSize))
+ return
+ }
+ zb0018, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskFreezeAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAsset")
+ return
+ }
+ (*z).BitmaskFreezeAsset = bitmask(zb0018)
+ }
+ case "afrzbm":
+ {
+ var zb0020 []byte
+ var zb0021 int
+ zb0021, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetFrozen")
+ return
+ }
+ if zb0021 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0021), uint64(maxBitmaskSize))
+ return
+ }
+ zb0020, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAssetFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetFrozen")
+ return
+ }
+ (*z).BitmaskAssetFrozen = bitmask(zb0020)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedAssetFreezeTxnFields) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedAssetFreezeTxnFields)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedAssetFreezeTxnFields) Msgsize() (s int) {
+ s = 1 + 5 + msgp.BytesPrefixSize + len((*z).FreezeAccount) + 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskFreezeAccount)) + 5 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).FreezeAsset {
+ s += (*z).FreezeAsset[zb0001].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskFreezeAsset)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskAssetFrozen))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedAssetFreezeTxnFields) MsgIsZero() bool {
+ return (len((*z).FreezeAccount) == 0) && (len((*z).BitmaskFreezeAccount) == 0) && (len((*z).FreezeAsset) == 0) && (len((*z).BitmaskFreezeAsset) == 0) && (len((*z).BitmaskAssetFrozen) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedAssetParams) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0006Len := uint32(21)
+ var zb0006Mask uint32 /* 22 bits */
+ if len((*z).MetadataHash) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x2
+ }
+ if len((*z).BitmaskMetadataHash) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x4
+ }
+ if len((*z).AssetName) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x8
+ }
+ if len((*z).BitmaskAssetName) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x10
+ }
+ if len((*z).URL) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x20
+ }
+ if len((*z).BitmaskURL) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x40
+ }
+ if len((*z).Clawback) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x80
+ }
+ if len((*z).BitmaskClawback) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x100
+ }
+ if len((*z).Decimals) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x200
+ }
+ if len((*z).BitmaskDecimals) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x400
+ }
+ if len((*z).BitmaskDefaultFrozen) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x800
+ }
+ if len((*z).Freeze) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x1000
+ }
+ if len((*z).BitmaskFreeze) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x2000
+ }
+ if len((*z).Manager) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x4000
+ }
+ if len((*z).BitmaskManager) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x8000
+ }
+ if len((*z).Reserve) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x10000
+ }
+ if len((*z).BitmaskReserve) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x20000
+ }
+ if len((*z).Total) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x40000
+ }
+ if len((*z).BitmaskTotal) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x80000
+ }
+ if len((*z).UnitName) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x100000
+ }
+ if len((*z).BitmaskUnitName) == 0 {
+ zb0006Len--
+ zb0006Mask |= 0x200000
+ }
+ // variable map header, size zb0006Len
+ o = msgp.AppendMapHeader(o, zb0006Len)
+ if zb0006Len != 0 {
+ if (zb0006Mask & 0x2) == 0 { // if not empty
+ // string "am"
+ o = append(o, 0xa2, 0x61, 0x6d)
+ o = msgp.AppendBytes(o, (*z).MetadataHash)
+ }
+ if (zb0006Mask & 0x4) == 0 { // if not empty
+ // string "ambm"
+ o = append(o, 0xa4, 0x61, 0x6d, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskMetadataHash))
+ }
+ if (zb0006Mask & 0x8) == 0 { // if not empty
+ // string "an"
+ o = append(o, 0xa2, 0x61, 0x6e)
+ if (*z).AssetName == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).AssetName)))
+ }
+ for zb0004 := range (*z).AssetName {
+ o = msgp.AppendString(o, (*z).AssetName[zb0004])
+ }
+ }
+ if (zb0006Mask & 0x10) == 0 { // if not empty
+ // string "anbm"
+ o = append(o, 0xa4, 0x61, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskAssetName))
+ }
+ if (zb0006Mask & 0x20) == 0 { // if not empty
+ // string "au"
+ o = append(o, 0xa2, 0x61, 0x75)
+ if (*z).URL == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).URL)))
+ }
+ for zb0005 := range (*z).URL {
+ o = msgp.AppendString(o, (*z).URL[zb0005])
+ }
+ }
+ if (zb0006Mask & 0x40) == 0 { // if not empty
+ // string "aubm"
+ o = append(o, 0xa4, 0x61, 0x75, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskURL))
+ }
+ if (zb0006Mask & 0x80) == 0 { // if not empty
+ // string "c"
+ o = append(o, 0xa1, 0x63)
+ o = msgp.AppendBytes(o, (*z).Clawback)
+ }
+ if (zb0006Mask & 0x100) == 0 { // if not empty
+ // string "cbm"
+ o = append(o, 0xa3, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskClawback))
+ }
+ if (zb0006Mask & 0x200) == 0 { // if not empty
+ // string "dc"
+ o = append(o, 0xa2, 0x64, 0x63)
+ if (*z).Decimals == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).Decimals)))
+ }
+ for zb0002 := range (*z).Decimals {
+ o = msgp.AppendUint32(o, (*z).Decimals[zb0002])
+ }
+ }
+ if (zb0006Mask & 0x400) == 0 { // if not empty
+ // string "dcbm"
+ o = append(o, 0xa4, 0x64, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskDecimals))
+ }
+ if (zb0006Mask & 0x800) == 0 { // if not empty
+ // string "dfbm"
+ o = append(o, 0xa4, 0x64, 0x66, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskDefaultFrozen))
+ }
+ if (zb0006Mask & 0x1000) == 0 { // if not empty
+ // string "f"
+ o = append(o, 0xa1, 0x66)
+ o = msgp.AppendBytes(o, (*z).Freeze)
+ }
+ if (zb0006Mask & 0x2000) == 0 { // if not empty
+ // string "fbm"
+ o = append(o, 0xa3, 0x66, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskFreeze))
+ }
+ if (zb0006Mask & 0x4000) == 0 { // if not empty
+ // string "m"
+ o = append(o, 0xa1, 0x6d)
+ o = msgp.AppendBytes(o, (*z).Manager)
+ }
+ if (zb0006Mask & 0x8000) == 0 { // if not empty
+ // string "mbm"
+ o = append(o, 0xa3, 0x6d, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskManager))
+ }
+ if (zb0006Mask & 0x10000) == 0 { // if not empty
+ // string "r"
+ o = append(o, 0xa1, 0x72)
+ o = msgp.AppendBytes(o, (*z).Reserve)
+ }
+ if (zb0006Mask & 0x20000) == 0 { // if not empty
+ // string "rbm"
+ o = append(o, 0xa3, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskReserve))
+ }
+ if (zb0006Mask & 0x40000) == 0 { // if not empty
+ // string "t"
+ o = append(o, 0xa1, 0x74)
+ if (*z).Total == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).Total)))
+ }
+ for zb0001 := range (*z).Total {
+ o = msgp.AppendUint64(o, (*z).Total[zb0001])
+ }
+ }
+ if (zb0006Mask & 0x80000) == 0 { // if not empty
+ // string "tbm"
+ o = append(o, 0xa3, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskTotal))
+ }
+ if (zb0006Mask & 0x100000) == 0 { // if not empty
+ // string "un"
+ o = append(o, 0xa2, 0x75, 0x6e)
+ if (*z).UnitName == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).UnitName)))
+ }
+ for zb0003 := range (*z).UnitName {
+ o = msgp.AppendString(o, (*z).UnitName[zb0003])
+ }
+ }
+ if (zb0006Mask & 0x200000) == 0 { // if not empty
+ // string "unbm"
+ o = append(o, 0xa4, 0x75, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskUnitName))
+ }
+ }
+ return
+}
+
+func (_ *encodedAssetParams) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedAssetParams)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedAssetParams) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0006 int
+ var zb0007 bool
+ zb0006, zb0007, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0006, zb0007, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0006 > 0 {
+ zb0006--
+ var zb0008 int
+ var zb0009 bool
+ zb0008, zb0009, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Total")
+ return
+ }
+ if zb0008 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0008), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Total")
+ return
+ }
+ if zb0009 {
+ (*z).Total = nil
+ } else if (*z).Total != nil && cap((*z).Total) >= zb0008 {
+ (*z).Total = ((*z).Total)[:zb0008]
+ } else {
+ (*z).Total = make([]uint64, zb0008)
+ }
+ for zb0001 := range (*z).Total {
+ (*z).Total[zb0001], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Total", zb0001)
+ return
+ }
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ {
+ var zb0010 []byte
+ var zb0011 int
+ zb0011, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTotal")
+ return
+ }
+ if zb0011 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0011), uint64(maxBitmaskSize))
+ return
+ }
+ zb0010, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskTotal))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTotal")
+ return
+ }
+ (*z).BitmaskTotal = bitmask(zb0010)
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ var zb0012 int
+ var zb0013 bool
+ zb0012, zb0013, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Decimals")
+ return
+ }
+ if zb0012 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0012), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Decimals")
+ return
+ }
+ if zb0013 {
+ (*z).Decimals = nil
+ } else if (*z).Decimals != nil && cap((*z).Decimals) >= zb0012 {
+ (*z).Decimals = ((*z).Decimals)[:zb0012]
+ } else {
+ (*z).Decimals = make([]uint32, zb0012)
+ }
+ for zb0002 := range (*z).Decimals {
+ (*z).Decimals[zb0002], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Decimals", zb0002)
+ return
+ }
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ {
+ var zb0014 []byte
+ var zb0015 int
+ zb0015, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDecimals")
+ return
+ }
+ if zb0015 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0015), uint64(maxBitmaskSize))
+ return
+ }
+ zb0014, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskDecimals))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDecimals")
+ return
+ }
+ (*z).BitmaskDecimals = bitmask(zb0014)
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ {
+ var zb0016 []byte
+ var zb0017 int
+ zb0017, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDefaultFrozen")
+ return
+ }
+ if zb0017 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0017), uint64(maxBitmaskSize))
+ return
+ }
+ zb0016, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskDefaultFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDefaultFrozen")
+ return
+ }
+ (*z).BitmaskDefaultFrozen = bitmask(zb0016)
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ var zb0018 int
+ var zb0019 bool
+ zb0018, zb0019, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UnitName")
+ return
+ }
+ if zb0018 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0018), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "UnitName")
+ return
+ }
+ if zb0019 {
+ (*z).UnitName = nil
+ } else if (*z).UnitName != nil && cap((*z).UnitName) >= zb0018 {
+ (*z).UnitName = ((*z).UnitName)[:zb0018]
+ } else {
+ (*z).UnitName = make([]string, zb0018)
+ }
+ for zb0003 := range (*z).UnitName {
+ (*z).UnitName[zb0003], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UnitName", zb0003)
+ return
+ }
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ {
+ var zb0020 []byte
+ var zb0021 int
+ zb0021, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskUnitName")
+ return
+ }
+ if zb0021 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0021), uint64(maxBitmaskSize))
+ return
+ }
+ zb0020, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskUnitName))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskUnitName")
+ return
+ }
+ (*z).BitmaskUnitName = bitmask(zb0020)
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ var zb0022 int
+ var zb0023 bool
+ zb0022, zb0023, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetName")
+ return
+ }
+ if zb0022 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0022), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "AssetName")
+ return
+ }
+ if zb0023 {
+ (*z).AssetName = nil
+ } else if (*z).AssetName != nil && cap((*z).AssetName) >= zb0022 {
+ (*z).AssetName = ((*z).AssetName)[:zb0022]
+ } else {
+ (*z).AssetName = make([]string, zb0022)
+ }
+ for zb0004 := range (*z).AssetName {
+ (*z).AssetName[zb0004], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetName", zb0004)
+ return
+ }
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ {
+ var zb0024 []byte
+ var zb0025 int
+ zb0025, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetName")
+ return
+ }
+ if zb0025 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0025), uint64(maxBitmaskSize))
+ return
+ }
+ zb0024, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAssetName))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetName")
+ return
+ }
+ (*z).BitmaskAssetName = bitmask(zb0024)
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ var zb0026 int
+ var zb0027 bool
+ zb0026, zb0027, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "URL")
+ return
+ }
+ if zb0026 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0026), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "URL")
+ return
+ }
+ if zb0027 {
+ (*z).URL = nil
+ } else if (*z).URL != nil && cap((*z).URL) >= zb0026 {
+ (*z).URL = ((*z).URL)[:zb0026]
+ } else {
+ (*z).URL = make([]string, zb0026)
+ }
+ for zb0005 := range (*z).URL {
+ (*z).URL[zb0005], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "URL", zb0005)
+ return
+ }
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ {
+ var zb0028 []byte
+ var zb0029 int
+ zb0029, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskURL")
+ return
+ }
+ if zb0029 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0029), uint64(maxBitmaskSize))
+ return
+ }
+ zb0028, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskURL))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskURL")
+ return
+ }
+ (*z).BitmaskURL = bitmask(zb0028)
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ var zb0030 int
+ zb0030, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "MetadataHash")
+ return
+ }
+ if zb0030 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0030), uint64(maxAddressBytes))
+ return
+ }
+ (*z).MetadataHash, bts, err = msgp.ReadBytesBytes(bts, (*z).MetadataHash)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "MetadataHash")
+ return
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ {
+ var zb0031 []byte
+ var zb0032 int
+ zb0032, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskMetadataHash")
+ return
+ }
+ if zb0032 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0032), uint64(maxBitmaskSize))
+ return
+ }
+ zb0031, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskMetadataHash))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskMetadataHash")
+ return
+ }
+ (*z).BitmaskMetadataHash = bitmask(zb0031)
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ var zb0033 int
+ zb0033, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Manager")
+ return
+ }
+ if zb0033 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0033), uint64(maxAddressBytes))
+ return
+ }
+ (*z).Manager, bts, err = msgp.ReadBytesBytes(bts, (*z).Manager)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Manager")
+ return
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ {
+ var zb0034 []byte
+ var zb0035 int
+ zb0035, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskManager")
+ return
+ }
+ if zb0035 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0035), uint64(maxBitmaskSize))
+ return
+ }
+ zb0034, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskManager))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskManager")
+ return
+ }
+ (*z).BitmaskManager = bitmask(zb0034)
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ var zb0036 int
+ zb0036, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reserve")
+ return
+ }
+ if zb0036 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0036), uint64(maxAddressBytes))
+ return
+ }
+ (*z).Reserve, bts, err = msgp.ReadBytesBytes(bts, (*z).Reserve)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reserve")
+ return
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ {
+ var zb0037 []byte
+ var zb0038 int
+ zb0038, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReserve")
+ return
+ }
+ if zb0038 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0038), uint64(maxBitmaskSize))
+ return
+ }
+ zb0037, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskReserve))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReserve")
+ return
+ }
+ (*z).BitmaskReserve = bitmask(zb0037)
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ var zb0039 int
+ zb0039, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Freeze")
+ return
+ }
+ if zb0039 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0039), uint64(maxAddressBytes))
+ return
+ }
+ (*z).Freeze, bts, err = msgp.ReadBytesBytes(bts, (*z).Freeze)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Freeze")
+ return
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ {
+ var zb0040 []byte
+ var zb0041 int
+ zb0041, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreeze")
+ return
+ }
+ if zb0041 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0041), uint64(maxBitmaskSize))
+ return
+ }
+ zb0040, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskFreeze))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreeze")
+ return
+ }
+ (*z).BitmaskFreeze = bitmask(zb0040)
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ var zb0042 int
+ zb0042, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Clawback")
+ return
+ }
+ if zb0042 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0042), uint64(maxAddressBytes))
+ return
+ }
+ (*z).Clawback, bts, err = msgp.ReadBytesBytes(bts, (*z).Clawback)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Clawback")
+ return
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ {
+ var zb0043 []byte
+ var zb0044 int
+ zb0044, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClawback")
+ return
+ }
+ if zb0044 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0044), uint64(maxBitmaskSize))
+ return
+ }
+ zb0043, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskClawback))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClawback")
+ return
+ }
+ (*z).BitmaskClawback = bitmask(zb0043)
+ }
+ }
+ if zb0006 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0006)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0007 {
+ (*z) = encodedAssetParams{}
+ }
+ for zb0006 > 0 {
+ zb0006--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "t":
+ var zb0045 int
+ var zb0046 bool
+ zb0045, zb0046, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Total")
+ return
+ }
+ if zb0045 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0045), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Total")
+ return
+ }
+ if zb0046 {
+ (*z).Total = nil
+ } else if (*z).Total != nil && cap((*z).Total) >= zb0045 {
+ (*z).Total = ((*z).Total)[:zb0045]
+ } else {
+ (*z).Total = make([]uint64, zb0045)
+ }
+ for zb0001 := range (*z).Total {
+ (*z).Total[zb0001], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Total", zb0001)
+ return
+ }
+ }
+ case "tbm":
+ {
+ var zb0047 []byte
+ var zb0048 int
+ zb0048, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTotal")
+ return
+ }
+ if zb0048 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0048), uint64(maxBitmaskSize))
+ return
+ }
+ zb0047, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskTotal))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTotal")
+ return
+ }
+ (*z).BitmaskTotal = bitmask(zb0047)
+ }
+ case "dc":
+ var zb0049 int
+ var zb0050 bool
+ zb0049, zb0050, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Decimals")
+ return
+ }
+ if zb0049 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0049), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Decimals")
+ return
+ }
+ if zb0050 {
+ (*z).Decimals = nil
+ } else if (*z).Decimals != nil && cap((*z).Decimals) >= zb0049 {
+ (*z).Decimals = ((*z).Decimals)[:zb0049]
+ } else {
+ (*z).Decimals = make([]uint32, zb0049)
+ }
+ for zb0002 := range (*z).Decimals {
+ (*z).Decimals[zb0002], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Decimals", zb0002)
+ return
+ }
+ }
+ case "dcbm":
+ {
+ var zb0051 []byte
+ var zb0052 int
+ zb0052, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDecimals")
+ return
+ }
+ if zb0052 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0052), uint64(maxBitmaskSize))
+ return
+ }
+ zb0051, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskDecimals))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDecimals")
+ return
+ }
+ (*z).BitmaskDecimals = bitmask(zb0051)
+ }
+ case "dfbm":
+ {
+ var zb0053 []byte
+ var zb0054 int
+ zb0054, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDefaultFrozen")
+ return
+ }
+ if zb0054 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0054), uint64(maxBitmaskSize))
+ return
+ }
+ zb0053, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskDefaultFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDefaultFrozen")
+ return
+ }
+ (*z).BitmaskDefaultFrozen = bitmask(zb0053)
+ }
+ case "un":
+ var zb0055 int
+ var zb0056 bool
+ zb0055, zb0056, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UnitName")
+ return
+ }
+ if zb0055 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0055), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "UnitName")
+ return
+ }
+ if zb0056 {
+ (*z).UnitName = nil
+ } else if (*z).UnitName != nil && cap((*z).UnitName) >= zb0055 {
+ (*z).UnitName = ((*z).UnitName)[:zb0055]
+ } else {
+ (*z).UnitName = make([]string, zb0055)
+ }
+ for zb0003 := range (*z).UnitName {
+ (*z).UnitName[zb0003], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UnitName", zb0003)
+ return
+ }
+ }
+ case "unbm":
+ {
+ var zb0057 []byte
+ var zb0058 int
+ zb0058, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskUnitName")
+ return
+ }
+ if zb0058 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0058), uint64(maxBitmaskSize))
+ return
+ }
+ zb0057, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskUnitName))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskUnitName")
+ return
+ }
+ (*z).BitmaskUnitName = bitmask(zb0057)
+ }
+ case "an":
+ var zb0059 int
+ var zb0060 bool
+ zb0059, zb0060, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetName")
+ return
+ }
+ if zb0059 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0059), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "AssetName")
+ return
+ }
+ if zb0060 {
+ (*z).AssetName = nil
+ } else if (*z).AssetName != nil && cap((*z).AssetName) >= zb0059 {
+ (*z).AssetName = ((*z).AssetName)[:zb0059]
+ } else {
+ (*z).AssetName = make([]string, zb0059)
+ }
+ for zb0004 := range (*z).AssetName {
+ (*z).AssetName[zb0004], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetName", zb0004)
+ return
+ }
+ }
+ case "anbm":
+ {
+ var zb0061 []byte
+ var zb0062 int
+ zb0062, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetName")
+ return
+ }
+ if zb0062 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0062), uint64(maxBitmaskSize))
+ return
+ }
+ zb0061, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAssetName))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetName")
+ return
+ }
+ (*z).BitmaskAssetName = bitmask(zb0061)
+ }
+ case "au":
+ var zb0063 int
+ var zb0064 bool
+ zb0063, zb0064, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "URL")
+ return
+ }
+ if zb0063 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0063), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "URL")
+ return
+ }
+ if zb0064 {
+ (*z).URL = nil
+ } else if (*z).URL != nil && cap((*z).URL) >= zb0063 {
+ (*z).URL = ((*z).URL)[:zb0063]
+ } else {
+ (*z).URL = make([]string, zb0063)
+ }
+ for zb0005 := range (*z).URL {
+ (*z).URL[zb0005], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "URL", zb0005)
+ return
+ }
+ }
+ case "aubm":
+ {
+ var zb0065 []byte
+ var zb0066 int
+ zb0066, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskURL")
+ return
+ }
+ if zb0066 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0066), uint64(maxBitmaskSize))
+ return
+ }
+ zb0065, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskURL))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskURL")
+ return
+ }
+ (*z).BitmaskURL = bitmask(zb0065)
+ }
+ case "am":
+ var zb0067 int
+ zb0067, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "MetadataHash")
+ return
+ }
+ if zb0067 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0067), uint64(maxAddressBytes))
+ return
+ }
+ (*z).MetadataHash, bts, err = msgp.ReadBytesBytes(bts, (*z).MetadataHash)
+ if err != nil {
+ err = msgp.WrapError(err, "MetadataHash")
+ return
+ }
+ case "ambm":
+ {
+ var zb0068 []byte
+ var zb0069 int
+ zb0069, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskMetadataHash")
+ return
+ }
+ if zb0069 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0069), uint64(maxBitmaskSize))
+ return
+ }
+ zb0068, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskMetadataHash))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskMetadataHash")
+ return
+ }
+ (*z).BitmaskMetadataHash = bitmask(zb0068)
+ }
+ case "m":
+ var zb0070 int
+ zb0070, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Manager")
+ return
+ }
+ if zb0070 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0070), uint64(maxAddressBytes))
+ return
+ }
+ (*z).Manager, bts, err = msgp.ReadBytesBytes(bts, (*z).Manager)
+ if err != nil {
+ err = msgp.WrapError(err, "Manager")
+ return
+ }
+ case "mbm":
+ {
+ var zb0071 []byte
+ var zb0072 int
+ zb0072, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskManager")
+ return
+ }
+ if zb0072 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0072), uint64(maxBitmaskSize))
+ return
+ }
+ zb0071, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskManager))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskManager")
+ return
+ }
+ (*z).BitmaskManager = bitmask(zb0071)
+ }
+ case "r":
+ var zb0073 int
+ zb0073, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reserve")
+ return
+ }
+ if zb0073 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0073), uint64(maxAddressBytes))
+ return
+ }
+ (*z).Reserve, bts, err = msgp.ReadBytesBytes(bts, (*z).Reserve)
+ if err != nil {
+ err = msgp.WrapError(err, "Reserve")
+ return
+ }
+ case "rbm":
+ {
+ var zb0074 []byte
+ var zb0075 int
+ zb0075, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReserve")
+ return
+ }
+ if zb0075 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0075), uint64(maxBitmaskSize))
+ return
+ }
+ zb0074, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskReserve))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReserve")
+ return
+ }
+ (*z).BitmaskReserve = bitmask(zb0074)
+ }
+ case "f":
+ var zb0076 int
+ zb0076, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Freeze")
+ return
+ }
+ if zb0076 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0076), uint64(maxAddressBytes))
+ return
+ }
+ (*z).Freeze, bts, err = msgp.ReadBytesBytes(bts, (*z).Freeze)
+ if err != nil {
+ err = msgp.WrapError(err, "Freeze")
+ return
+ }
+ case "fbm":
+ {
+ var zb0077 []byte
+ var zb0078 int
+ zb0078, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreeze")
+ return
+ }
+ if zb0078 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0078), uint64(maxBitmaskSize))
+ return
+ }
+ zb0077, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskFreeze))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreeze")
+ return
+ }
+ (*z).BitmaskFreeze = bitmask(zb0077)
+ }
+ case "c":
+ var zb0079 int
+ zb0079, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Clawback")
+ return
+ }
+ if zb0079 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0079), uint64(maxAddressBytes))
+ return
+ }
+ (*z).Clawback, bts, err = msgp.ReadBytesBytes(bts, (*z).Clawback)
+ if err != nil {
+ err = msgp.WrapError(err, "Clawback")
+ return
+ }
+ case "cbm":
+ {
+ var zb0080 []byte
+ var zb0081 int
+ zb0081, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClawback")
+ return
+ }
+ if zb0081 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0081), uint64(maxBitmaskSize))
+ return
+ }
+ zb0080, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskClawback))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClawback")
+ return
+ }
+ (*z).BitmaskClawback = bitmask(zb0080)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedAssetParams) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedAssetParams)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedAssetParams) Msgsize() (s int) {
+ s = 3 + 2 + msgp.ArrayHeaderSize + (len((*z).Total) * (msgp.Uint64Size)) + 4 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskTotal)) + 3 + msgp.ArrayHeaderSize + (len((*z).Decimals) * (msgp.Uint32Size)) + 5 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskDecimals)) + 5 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskDefaultFrozen)) + 3 + msgp.ArrayHeaderSize
+ for zb0003 := range (*z).UnitName {
+ s += msgp.StringPrefixSize + len((*z).UnitName[zb0003])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskUnitName)) + 3 + msgp.ArrayHeaderSize
+ for zb0004 := range (*z).AssetName {
+ s += msgp.StringPrefixSize + len((*z).AssetName[zb0004])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskAssetName)) + 3 + msgp.ArrayHeaderSize
+ for zb0005 := range (*z).URL {
+ s += msgp.StringPrefixSize + len((*z).URL[zb0005])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskURL)) + 3 + msgp.BytesPrefixSize + len((*z).MetadataHash) + 5 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskMetadataHash)) + 2 + msgp.BytesPrefixSize + len((*z).Manager) + 4 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskManager)) + 2 + msgp.BytesPrefixSize + len((*z).Reserve) + 4 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskReserve)) + 2 + msgp.BytesPrefixSize + len((*z).Freeze) + 4 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskFreeze)) + 2 + msgp.BytesPrefixSize + len((*z).Clawback) + 4 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskClawback))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedAssetParams) MsgIsZero() bool {
+ return (len((*z).Total) == 0) && (len((*z).BitmaskTotal) == 0) && (len((*z).Decimals) == 0) && (len((*z).BitmaskDecimals) == 0) && (len((*z).BitmaskDefaultFrozen) == 0) && (len((*z).UnitName) == 0) && (len((*z).BitmaskUnitName) == 0) && (len((*z).AssetName) == 0) && (len((*z).BitmaskAssetName) == 0) && (len((*z).URL) == 0) && (len((*z).BitmaskURL) == 0) && (len((*z).MetadataHash) == 0) && (len((*z).BitmaskMetadataHash) == 0) && (len((*z).Manager) == 0) && (len((*z).BitmaskManager) == 0) && (len((*z).Reserve) == 0) && (len((*z).BitmaskReserve) == 0) && (len((*z).Freeze) == 0) && (len((*z).BitmaskFreeze) == 0) && (len((*z).Clawback) == 0) && (len((*z).BitmaskClawback) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedAssetTransferTxnFields) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0003Len := uint32(10)
+ var zb0003Mask uint16 /* 11 bits */
+ if len((*z).AssetAmount) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x2
+ }
+ if len((*z).BitmaskAssetAmount) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x4
+ }
+ if len((*z).AssetCloseTo) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x8
+ }
+ if len((*z).BitmaskAssetCloseTo) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x10
+ }
+ if len((*z).AssetReceiver) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x20
+ }
+ if len((*z).BitmaskAssetReceiver) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x40
+ }
+ if len((*z).AssetSender) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x80
+ }
+ if len((*z).BitmaskAssetSender) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x100
+ }
+ if len((*z).XferAsset) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x200
+ }
+ if len((*z).BitmaskXferAsset) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x400
+ }
+ // variable map header, size zb0003Len
+ o = append(o, 0x80|uint8(zb0003Len))
+ if zb0003Len != 0 {
+ if (zb0003Mask & 0x2) == 0 { // if not empty
+ // string "aamt"
+ o = append(o, 0xa4, 0x61, 0x61, 0x6d, 0x74)
+ if (*z).AssetAmount == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).AssetAmount)))
+ }
+ for zb0002 := range (*z).AssetAmount {
+ o = msgp.AppendUint64(o, (*z).AssetAmount[zb0002])
+ }
+ }
+ if (zb0003Mask & 0x4) == 0 { // if not empty
+ // string "aamtbm"
+ o = append(o, 0xa6, 0x61, 0x61, 0x6d, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskAssetAmount))
+ }
+ if (zb0003Mask & 0x8) == 0 { // if not empty
+ // string "aclose"
+ o = append(o, 0xa6, 0x61, 0x63, 0x6c, 0x6f, 0x73, 0x65)
+ o = msgp.AppendBytes(o, (*z).AssetCloseTo)
+ }
+ if (zb0003Mask & 0x10) == 0 { // if not empty
+ // string "aclosebm"
+ o = append(o, 0xa8, 0x61, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskAssetCloseTo))
+ }
+ if (zb0003Mask & 0x20) == 0 { // if not empty
+ // string "arcv"
+ o = append(o, 0xa4, 0x61, 0x72, 0x63, 0x76)
+ o = msgp.AppendBytes(o, (*z).AssetReceiver)
+ }
+ if (zb0003Mask & 0x40) == 0 { // if not empty
+ // string "arcvbm"
+ o = append(o, 0xa6, 0x61, 0x72, 0x63, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskAssetReceiver))
+ }
+ if (zb0003Mask & 0x80) == 0 { // if not empty
+ // string "asnd"
+ o = append(o, 0xa4, 0x61, 0x73, 0x6e, 0x64)
+ o = msgp.AppendBytes(o, (*z).AssetSender)
+ }
+ if (zb0003Mask & 0x100) == 0 { // if not empty
+ // string "asndbm"
+ o = append(o, 0xa6, 0x61, 0x73, 0x6e, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskAssetSender))
+ }
+ if (zb0003Mask & 0x200) == 0 { // if not empty
+ // string "xaid"
+ o = append(o, 0xa4, 0x78, 0x61, 0x69, 0x64)
+ if (*z).XferAsset == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).XferAsset)))
+ }
+ for zb0001 := range (*z).XferAsset {
+ o = (*z).XferAsset[zb0001].MarshalMsg(o)
+ }
+ }
+ if (zb0003Mask & 0x400) == 0 { // if not empty
+ // string "xaidbm"
+ o = append(o, 0xa6, 0x78, 0x61, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskXferAsset))
+ }
+ }
+ return
+}
+
+func (_ *encodedAssetTransferTxnFields) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedAssetTransferTxnFields)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedAssetTransferTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0003 int
+ var zb0004 bool
+ zb0003, zb0004, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0003, zb0004, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0003 > 0 {
+ zb0003--
+ var zb0005 int
+ var zb0006 bool
+ zb0005, zb0006, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "XferAsset")
+ return
+ }
+ if zb0005 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0005), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "XferAsset")
+ return
+ }
+ if zb0006 {
+ (*z).XferAsset = nil
+ } else if (*z).XferAsset != nil && cap((*z).XferAsset) >= zb0005 {
+ (*z).XferAsset = ((*z).XferAsset)[:zb0005]
+ } else {
+ (*z).XferAsset = make([]basics.AssetIndex, zb0005)
+ }
+ for zb0001 := range (*z).XferAsset {
+ bts, err = (*z).XferAsset[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "XferAsset", zb0001)
+ return
+ }
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ {
+ var zb0007 []byte
+ var zb0008 int
+ zb0008, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskXferAsset")
+ return
+ }
+ if zb0008 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0008), uint64(maxBitmaskSize))
+ return
+ }
+ zb0007, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskXferAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskXferAsset")
+ return
+ }
+ (*z).BitmaskXferAsset = bitmask(zb0007)
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ var zb0009 int
+ var zb0010 bool
+ zb0009, zb0010, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetAmount")
+ return
+ }
+ if zb0009 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0009), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "AssetAmount")
+ return
+ }
+ if zb0010 {
+ (*z).AssetAmount = nil
+ } else if (*z).AssetAmount != nil && cap((*z).AssetAmount) >= zb0009 {
+ (*z).AssetAmount = ((*z).AssetAmount)[:zb0009]
+ } else {
+ (*z).AssetAmount = make([]uint64, zb0009)
+ }
+ for zb0002 := range (*z).AssetAmount {
+ (*z).AssetAmount[zb0002], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetAmount", zb0002)
+ return
+ }
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ {
+ var zb0011 []byte
+ var zb0012 int
+ zb0012, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetAmount")
+ return
+ }
+ if zb0012 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0012), uint64(maxBitmaskSize))
+ return
+ }
+ zb0011, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAssetAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetAmount")
+ return
+ }
+ (*z).BitmaskAssetAmount = bitmask(zb0011)
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ var zb0013 int
+ zb0013, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetSender")
+ return
+ }
+ if zb0013 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0013), uint64(maxAddressBytes))
+ return
+ }
+ (*z).AssetSender, bts, err = msgp.ReadBytesBytes(bts, (*z).AssetSender)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetSender")
+ return
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ {
+ var zb0014 []byte
+ var zb0015 int
+ zb0015, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetSender")
+ return
+ }
+ if zb0015 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0015), uint64(maxBitmaskSize))
+ return
+ }
+ zb0014, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAssetSender))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetSender")
+ return
+ }
+ (*z).BitmaskAssetSender = bitmask(zb0014)
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ var zb0016 int
+ zb0016, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetReceiver")
+ return
+ }
+ if zb0016 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0016), uint64(maxAddressBytes))
+ return
+ }
+ (*z).AssetReceiver, bts, err = msgp.ReadBytesBytes(bts, (*z).AssetReceiver)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetReceiver")
+ return
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ {
+ var zb0017 []byte
+ var zb0018 int
+ zb0018, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetReceiver")
+ return
+ }
+ if zb0018 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0018), uint64(maxBitmaskSize))
+ return
+ }
+ zb0017, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAssetReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetReceiver")
+ return
+ }
+ (*z).BitmaskAssetReceiver = bitmask(zb0017)
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ var zb0019 int
+ zb0019, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetCloseTo")
+ return
+ }
+ if zb0019 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0019), uint64(maxAddressBytes))
+ return
+ }
+ (*z).AssetCloseTo, bts, err = msgp.ReadBytesBytes(bts, (*z).AssetCloseTo)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetCloseTo")
+ return
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ {
+ var zb0020 []byte
+ var zb0021 int
+ zb0021, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetCloseTo")
+ return
+ }
+ if zb0021 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0021), uint64(maxBitmaskSize))
+ return
+ }
+ zb0020, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAssetCloseTo))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetCloseTo")
+ return
+ }
+ (*z).BitmaskAssetCloseTo = bitmask(zb0020)
+ }
+ }
+ if zb0003 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0003)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0004 {
+ (*z) = encodedAssetTransferTxnFields{}
+ }
+ for zb0003 > 0 {
+ zb0003--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "xaid":
+ var zb0022 int
+ var zb0023 bool
+ zb0022, zb0023, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "XferAsset")
+ return
+ }
+ if zb0022 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0022), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "XferAsset")
+ return
+ }
+ if zb0023 {
+ (*z).XferAsset = nil
+ } else if (*z).XferAsset != nil && cap((*z).XferAsset) >= zb0022 {
+ (*z).XferAsset = ((*z).XferAsset)[:zb0022]
+ } else {
+ (*z).XferAsset = make([]basics.AssetIndex, zb0022)
+ }
+ for zb0001 := range (*z).XferAsset {
+ bts, err = (*z).XferAsset[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "XferAsset", zb0001)
+ return
+ }
+ }
+ case "xaidbm":
+ {
+ var zb0024 []byte
+ var zb0025 int
+ zb0025, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskXferAsset")
+ return
+ }
+ if zb0025 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0025), uint64(maxBitmaskSize))
+ return
+ }
+ zb0024, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskXferAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskXferAsset")
+ return
+ }
+ (*z).BitmaskXferAsset = bitmask(zb0024)
+ }
+ case "aamt":
+ var zb0026 int
+ var zb0027 bool
+ zb0026, zb0027, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetAmount")
+ return
+ }
+ if zb0026 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0026), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "AssetAmount")
+ return
+ }
+ if zb0027 {
+ (*z).AssetAmount = nil
+ } else if (*z).AssetAmount != nil && cap((*z).AssetAmount) >= zb0026 {
+ (*z).AssetAmount = ((*z).AssetAmount)[:zb0026]
+ } else {
+ (*z).AssetAmount = make([]uint64, zb0026)
+ }
+ for zb0002 := range (*z).AssetAmount {
+ (*z).AssetAmount[zb0002], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetAmount", zb0002)
+ return
+ }
+ }
+ case "aamtbm":
+ {
+ var zb0028 []byte
+ var zb0029 int
+ zb0029, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetAmount")
+ return
+ }
+ if zb0029 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0029), uint64(maxBitmaskSize))
+ return
+ }
+ zb0028, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAssetAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetAmount")
+ return
+ }
+ (*z).BitmaskAssetAmount = bitmask(zb0028)
+ }
+ case "asnd":
+ var zb0030 int
+ zb0030, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetSender")
+ return
+ }
+ if zb0030 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0030), uint64(maxAddressBytes))
+ return
+ }
+ (*z).AssetSender, bts, err = msgp.ReadBytesBytes(bts, (*z).AssetSender)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetSender")
+ return
+ }
+ case "asndbm":
+ {
+ var zb0031 []byte
+ var zb0032 int
+ zb0032, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetSender")
+ return
+ }
+ if zb0032 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0032), uint64(maxBitmaskSize))
+ return
+ }
+ zb0031, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAssetSender))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetSender")
+ return
+ }
+ (*z).BitmaskAssetSender = bitmask(zb0031)
+ }
+ case "arcv":
+ var zb0033 int
+ zb0033, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetReceiver")
+ return
+ }
+ if zb0033 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0033), uint64(maxAddressBytes))
+ return
+ }
+ (*z).AssetReceiver, bts, err = msgp.ReadBytesBytes(bts, (*z).AssetReceiver)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetReceiver")
+ return
+ }
+ case "arcvbm":
+ {
+ var zb0034 []byte
+ var zb0035 int
+ zb0035, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetReceiver")
+ return
+ }
+ if zb0035 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0035), uint64(maxBitmaskSize))
+ return
+ }
+ zb0034, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAssetReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetReceiver")
+ return
+ }
+ (*z).BitmaskAssetReceiver = bitmask(zb0034)
+ }
+ case "aclose":
+ var zb0036 int
+ zb0036, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetCloseTo")
+ return
+ }
+ if zb0036 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0036), uint64(maxAddressBytes))
+ return
+ }
+ (*z).AssetCloseTo, bts, err = msgp.ReadBytesBytes(bts, (*z).AssetCloseTo)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetCloseTo")
+ return
+ }
+ case "aclosebm":
+ {
+ var zb0037 []byte
+ var zb0038 int
+ zb0038, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetCloseTo")
+ return
+ }
+ if zb0038 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0038), uint64(maxBitmaskSize))
+ return
+ }
+ zb0037, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAssetCloseTo))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetCloseTo")
+ return
+ }
+ (*z).BitmaskAssetCloseTo = bitmask(zb0037)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedAssetTransferTxnFields) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedAssetTransferTxnFields)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedAssetTransferTxnFields) Msgsize() (s int) {
+ s = 1 + 5 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).XferAsset {
+ s += (*z).XferAsset[zb0001].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskXferAsset)) + 5 + msgp.ArrayHeaderSize + (len((*z).AssetAmount) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskAssetAmount)) + 5 + msgp.BytesPrefixSize + len((*z).AssetSender) + 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskAssetSender)) + 5 + msgp.BytesPrefixSize + len((*z).AssetReceiver) + 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskAssetReceiver)) + 7 + msgp.BytesPrefixSize + len((*z).AssetCloseTo) + 9 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskAssetCloseTo))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedAssetTransferTxnFields) MsgIsZero() bool {
+ return (len((*z).XferAsset) == 0) && (len((*z).BitmaskXferAsset) == 0) && (len((*z).AssetAmount) == 0) && (len((*z).BitmaskAssetAmount) == 0) && (len((*z).AssetSender) == 0) && (len((*z).BitmaskAssetSender) == 0) && (len((*z).AssetReceiver) == 0) && (len((*z).BitmaskAssetReceiver) == 0) && (len((*z).AssetCloseTo) == 0) && (len((*z).BitmaskAssetCloseTo) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedBloomFilter) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0001Len := uint32(4)
+ var zb0001Mask uint8 /* 5 bits */
+ if (*z).ClearPrevious == 0 {
+ zb0001Len--
+ zb0001Mask |= 0x2
+ }
+ if len((*z).BloomFilter) == 0 {
+ zb0001Len--
+ zb0001Mask |= 0x4
+ }
+ if ((*z).EncodingParams.Offset == 0) && ((*z).EncodingParams.Modulator == 0) {
+ zb0001Len--
+ zb0001Mask |= 0x8
+ }
+ if (*z).BloomFilterType == 0 {
+ zb0001Len--
+ zb0001Mask |= 0x10
+ }
+ // variable map header, size zb0001Len
+ o = append(o, 0x80|uint8(zb0001Len))
+ if zb0001Len != 0 {
+ if (zb0001Mask & 0x2) == 0 { // if not empty
+ // string "c"
+ o = append(o, 0xa1, 0x63)
+ o = msgp.AppendByte(o, (*z).ClearPrevious)
+ }
+ if (zb0001Mask & 0x4) == 0 { // if not empty
+ // string "f"
+ o = append(o, 0xa1, 0x66)
+ o = msgp.AppendBytes(o, (*z).BloomFilter)
+ }
+ if (zb0001Mask & 0x8) == 0 { // if not empty
+ // string "p"
+ o = append(o, 0xa1, 0x70)
+ // omitempty: check for empty values
+ zb0002Len := uint32(2)
+ var zb0002Mask uint8 /* 3 bits */
+ if (*z).EncodingParams.Modulator == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x2
+ }
+ if (*z).EncodingParams.Offset == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x4
+ }
+ // variable map header, size zb0002Len
+ o = append(o, 0x80|uint8(zb0002Len))
+ if (zb0002Mask & 0x2) == 0 { // if not empty
+ // string "m"
+ o = append(o, 0xa1, 0x6d)
+ o = msgp.AppendByte(o, (*z).EncodingParams.Modulator)
+ }
+ if (zb0002Mask & 0x4) == 0 { // if not empty
+ // string "o"
+ o = append(o, 0xa1, 0x6f)
+ o = msgp.AppendByte(o, (*z).EncodingParams.Offset)
+ }
+ }
+ if (zb0001Mask & 0x10) == 0 { // if not empty
+ // string "t"
+ o = append(o, 0xa1, 0x74)
+ o = msgp.AppendByte(o, (*z).BloomFilterType)
+ }
+ }
+ return
+}
+
+func (_ *encodedBloomFilter) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedBloomFilter)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedBloomFilter) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0001 int
+ var zb0002 bool
+ zb0001, zb0002, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0001, zb0002, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0001 > 0 {
+ zb0001--
+ (*z).BloomFilterType, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BloomFilterType")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ zb0001--
+ var zb0003 int
+ var zb0004 bool
+ zb0003, zb0004, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0003, zb0004, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "EncodingParams")
+ return
+ }
+ if zb0003 > 0 {
+ zb0003--
+ (*z).EncodingParams.Offset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "EncodingParams", "struct-from-array", "Offset")
+ return
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ (*z).EncodingParams.Modulator, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "EncodingParams", "struct-from-array", "Modulator")
+ return
+ }
+ }
+ if zb0003 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0003)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "EncodingParams", "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "EncodingParams")
+ return
+ }
+ if zb0004 {
+ (*z).EncodingParams = requestParams{}
+ }
+ for zb0003 > 0 {
+ zb0003--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "EncodingParams")
+ return
+ }
+ switch string(field) {
+ case "o":
+ (*z).EncodingParams.Offset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "EncodingParams", "Offset")
+ return
+ }
+ case "m":
+ (*z).EncodingParams.Modulator, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "EncodingParams", "Modulator")
+ return
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "EncodingParams")
+ return
+ }
+ }
+ }
+ }
+ }
+ if zb0001 > 0 {
+ zb0001--
+ var zb0005 int
+ zb0005, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BloomFilter")
+ return
+ }
+ if zb0005 > maxBloomFilterSize {
+ err = msgp.ErrOverflow(uint64(zb0005), uint64(maxBloomFilterSize))
+ return
+ }
+ (*z).BloomFilter, bts, err = msgp.ReadBytesBytes(bts, (*z).BloomFilter)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BloomFilter")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ zb0001--
+ (*z).ClearPrevious, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ClearPrevious")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0001)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 {
+ (*z) = encodedBloomFilter{}
+ }
+ for zb0001 > 0 {
+ zb0001--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "t":
+ (*z).BloomFilterType, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BloomFilterType")
+ return
+ }
+ case "p":
+ var zb0006 int
+ var zb0007 bool
+ zb0006, zb0007, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0006, zb0007, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "EncodingParams")
+ return
+ }
+ if zb0006 > 0 {
+ zb0006--
+ (*z).EncodingParams.Offset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "EncodingParams", "struct-from-array", "Offset")
+ return
+ }
+ }
+ if zb0006 > 0 {
+ zb0006--
+ (*z).EncodingParams.Modulator, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "EncodingParams", "struct-from-array", "Modulator")
+ return
+ }
+ }
+ if zb0006 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0006)
+ if err != nil {
+ err = msgp.WrapError(err, "EncodingParams", "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err, "EncodingParams")
+ return
+ }
+ if zb0007 {
+ (*z).EncodingParams = requestParams{}
+ }
+ for zb0006 > 0 {
+ zb0006--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "EncodingParams")
+ return
+ }
+ switch string(field) {
+ case "o":
+ (*z).EncodingParams.Offset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "EncodingParams", "Offset")
+ return
+ }
+ case "m":
+ (*z).EncodingParams.Modulator, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "EncodingParams", "Modulator")
+ return
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err, "EncodingParams")
+ return
+ }
+ }
+ }
+ }
+ case "f":
+ var zb0008 int
+ zb0008, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BloomFilter")
+ return
+ }
+ if zb0008 > maxBloomFilterSize {
+ err = msgp.ErrOverflow(uint64(zb0008), uint64(maxBloomFilterSize))
+ return
+ }
+ (*z).BloomFilter, bts, err = msgp.ReadBytesBytes(bts, (*z).BloomFilter)
+ if err != nil {
+ err = msgp.WrapError(err, "BloomFilter")
+ return
+ }
+ case "c":
+ (*z).ClearPrevious, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ClearPrevious")
+ return
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedBloomFilter) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedBloomFilter)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedBloomFilter) Msgsize() (s int) {
+ s = 1 + 2 + msgp.ByteSize + 2 + 1 + 2 + msgp.ByteSize + 2 + msgp.ByteSize + 2 + msgp.BytesPrefixSize + len((*z).BloomFilter) + 2 + msgp.ByteSize
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedBloomFilter) MsgIsZero() bool {
+ return ((*z).BloomFilterType == 0) && (((*z).EncodingParams.Offset == 0) && ((*z).EncodingParams.Modulator == 0)) && (len((*z).BloomFilter) == 0) && ((*z).ClearPrevious == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedCert) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0009Len := uint32(10)
+ var zb0009Mask uint16 /* 11 bits */
+ if len((*z).PartProofs) == 0 {
+ zb0009Len--
+ zb0009Mask |= 0x2
+ }
+ if len((*z).BitmaskPartProofs) == 0 {
+ zb0009Len--
+ zb0009Mask |= 0x4
+ }
+ if len((*z).SigProofs) == 0 {
+ zb0009Len--
+ zb0009Mask |= 0x8
+ }
+ if len((*z).BitmaskSigProofs) == 0 {
+ zb0009Len--
+ zb0009Mask |= 0x10
+ }
+ if len((*z).SigCommit) == 0 {
+ zb0009Len--
+ zb0009Mask |= 0x20
+ }
+ if len((*z).BitmaskSigCommit) == 0 {
+ zb0009Len--
+ zb0009Mask |= 0x40
+ }
+ if len((*z).Reveals) == 0 {
+ zb0009Len--
+ zb0009Mask |= 0x80
+ }
+ if len((*z).BitmaskReveals) == 0 {
+ zb0009Len--
+ zb0009Mask |= 0x100
+ }
+ if len((*z).SignedWeight) == 0 {
+ zb0009Len--
+ zb0009Mask |= 0x200
+ }
+ if len((*z).BitmaskSignedWeight) == 0 {
+ zb0009Len--
+ zb0009Mask |= 0x400
+ }
+ // variable map header, size zb0009Len
+ o = append(o, 0x80|uint8(zb0009Len))
+ if zb0009Len != 0 {
+ if (zb0009Mask & 0x2) == 0 { // if not empty
+ // string "certP"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x50)
+ if (*z).PartProofs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).PartProofs)))
+ }
+ for zb0004 := range (*z).PartProofs {
+ if (*z).PartProofs[zb0004] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).PartProofs[zb0004])))
+ }
+ for zb0005 := range (*z).PartProofs[zb0004] {
+ o = (*z).PartProofs[zb0004][zb0005].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0009Mask & 0x4) == 0 { // if not empty
+ // string "certPbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x50, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskPartProofs))
+ }
+ if (zb0009Mask & 0x8) == 0 { // if not empty
+ // string "certS"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x53)
+ if (*z).SigProofs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).SigProofs)))
+ }
+ for zb0002 := range (*z).SigProofs {
+ if (*z).SigProofs[zb0002] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).SigProofs[zb0002])))
+ }
+ for zb0003 := range (*z).SigProofs[zb0002] {
+ o = (*z).SigProofs[zb0002][zb0003].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0009Mask & 0x10) == 0 { // if not empty
+ // string "certSbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x53, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskSigProofs))
+ }
+ if (zb0009Mask & 0x20) == 0 { // if not empty
+ // string "certc"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x63)
+ o = msgp.AppendBytes(o, (*z).SigCommit)
+ }
+ if (zb0009Mask & 0x40) == 0 { // if not empty
+ // string "certcbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskSigCommit))
+ }
+ if (zb0009Mask & 0x80) == 0 { // if not empty
+ // string "certr"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x72)
+ if (*z).Reveals == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).Reveals)))
+ }
+ for zb0006 := range (*z).Reveals {
+ if (*z).Reveals[zb0006] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendMapHeader(o, uint32(len((*z).Reveals[zb0006])))
+ }
+ zb0007_keys := make([]uint64, 0, len((*z).Reveals[zb0006]))
+ for zb0007 := range (*z).Reveals[zb0006] {
+ zb0007_keys = append(zb0007_keys, zb0007)
+ }
+ sort.Sort(SortUint64(zb0007_keys))
+ for _, zb0007 := range zb0007_keys {
+ zb0008 := (*z).Reveals[zb0006][zb0007]
+ _ = zb0008
+ o = msgp.AppendUint64(o, zb0007)
+ o = zb0008.MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0009Mask & 0x100) == 0 { // if not empty
+ // string "certrbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskReveals))
+ }
+ if (zb0009Mask & 0x200) == 0 { // if not empty
+ // string "certw"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x77)
+ if (*z).SignedWeight == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).SignedWeight)))
+ }
+ for zb0001 := range (*z).SignedWeight {
+ o = msgp.AppendUint64(o, (*z).SignedWeight[zb0001])
+ }
+ }
+ if (zb0009Mask & 0x400) == 0 { // if not empty
+ // string "certwbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x77, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskSignedWeight))
+ }
+ }
+ return
+}
+
+func (_ *encodedCert) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedCert)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedCert) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0009 int
+ var zb0010 bool
+ zb0009, zb0010, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0009, zb0010, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0009 > 0 {
+ zb0009--
+ var zb0011 int
+ zb0011, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigCommit")
+ return
+ }
+ if zb0011 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0011), uint64(maxAddressBytes))
+ return
+ }
+ (*z).SigCommit, bts, err = msgp.ReadBytesBytes(bts, (*z).SigCommit)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigCommit")
+ return
+ }
+ }
+ if zb0009 > 0 {
+ zb0009--
+ {
+ var zb0012 []byte
+ var zb0013 int
+ zb0013, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigCommit")
+ return
+ }
+ if zb0013 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0013), uint64(maxBitmaskSize))
+ return
+ }
+ zb0012, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskSigCommit))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigCommit")
+ return
+ }
+ (*z).BitmaskSigCommit = bitmask(zb0012)
+ }
+ }
+ if zb0009 > 0 {
+ zb0009--
+ var zb0014 int
+ var zb0015 bool
+ zb0014, zb0015, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight")
+ return
+ }
+ if zb0014 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0014), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight")
+ return
+ }
+ if zb0015 {
+ (*z).SignedWeight = nil
+ } else if (*z).SignedWeight != nil && cap((*z).SignedWeight) >= zb0014 {
+ (*z).SignedWeight = ((*z).SignedWeight)[:zb0014]
+ } else {
+ (*z).SignedWeight = make([]uint64, zb0014)
+ }
+ for zb0001 := range (*z).SignedWeight {
+ (*z).SignedWeight[zb0001], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight", zb0001)
+ return
+ }
+ }
+ }
+ if zb0009 > 0 {
+ zb0009--
+ {
+ var zb0016 []byte
+ var zb0017 int
+ zb0017, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSignedWeight")
+ return
+ }
+ if zb0017 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0017), uint64(maxBitmaskSize))
+ return
+ }
+ zb0016, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskSignedWeight))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSignedWeight")
+ return
+ }
+ (*z).BitmaskSignedWeight = bitmask(zb0016)
+ }
+ }
+ if zb0009 > 0 {
+ zb0009--
+ var zb0018 int
+ var zb0019 bool
+ zb0018, zb0019, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs")
+ return
+ }
+ if zb0018 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0018), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs")
+ return
+ }
+ if zb0019 {
+ (*z).SigProofs = nil
+ } else if (*z).SigProofs != nil && cap((*z).SigProofs) >= zb0018 {
+ (*z).SigProofs = ((*z).SigProofs)[:zb0018]
+ } else {
+ (*z).SigProofs = make([]certProofs, zb0018)
+ }
+ for zb0002 := range (*z).SigProofs {
+ var zb0020 int
+ var zb0021 bool
+ zb0020, zb0021, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0002)
+ return
+ }
+ if zb0020 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0020), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0002)
+ return
+ }
+ if zb0021 {
+ (*z).SigProofs[zb0002] = nil
+ } else if (*z).SigProofs[zb0002] != nil && cap((*z).SigProofs[zb0002]) >= zb0020 {
+ (*z).SigProofs[zb0002] = ((*z).SigProofs[zb0002])[:zb0020]
+ } else {
+ (*z).SigProofs[zb0002] = make(certProofs, zb0020)
+ }
+ for zb0003 := range (*z).SigProofs[zb0002] {
+ bts, err = (*z).SigProofs[zb0002][zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0002, zb0003)
+ return
+ }
+ }
+ }
+ }
+ if zb0009 > 0 {
+ zb0009--
+ {
+ var zb0022 []byte
+ var zb0023 int
+ zb0023, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigProofs")
+ return
+ }
+ if zb0023 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0023), uint64(maxBitmaskSize))
+ return
+ }
+ zb0022, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskSigProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigProofs")
+ return
+ }
+ (*z).BitmaskSigProofs = bitmask(zb0022)
+ }
+ }
+ if zb0009 > 0 {
+ zb0009--
+ var zb0024 int
+ var zb0025 bool
+ zb0024, zb0025, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs")
+ return
+ }
+ if zb0024 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0024), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs")
+ return
+ }
+ if zb0025 {
+ (*z).PartProofs = nil
+ } else if (*z).PartProofs != nil && cap((*z).PartProofs) >= zb0024 {
+ (*z).PartProofs = ((*z).PartProofs)[:zb0024]
+ } else {
+ (*z).PartProofs = make([]certProofs, zb0024)
+ }
+ for zb0004 := range (*z).PartProofs {
+ var zb0026 int
+ var zb0027 bool
+ zb0026, zb0027, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0004)
+ return
+ }
+ if zb0026 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0026), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0004)
+ return
+ }
+ if zb0027 {
+ (*z).PartProofs[zb0004] = nil
+ } else if (*z).PartProofs[zb0004] != nil && cap((*z).PartProofs[zb0004]) >= zb0026 {
+ (*z).PartProofs[zb0004] = ((*z).PartProofs[zb0004])[:zb0026]
+ } else {
+ (*z).PartProofs[zb0004] = make(certProofs, zb0026)
+ }
+ for zb0005 := range (*z).PartProofs[zb0004] {
+ bts, err = (*z).PartProofs[zb0004][zb0005].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0004, zb0005)
+ return
+ }
+ }
+ }
+ }
+ if zb0009 > 0 {
+ zb0009--
+ {
+ var zb0028 []byte
+ var zb0029 int
+ zb0029, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskPartProofs")
+ return
+ }
+ if zb0029 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0029), uint64(maxBitmaskSize))
+ return
+ }
+ zb0028, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskPartProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskPartProofs")
+ return
+ }
+ (*z).BitmaskPartProofs = bitmask(zb0028)
+ }
+ }
+ if zb0009 > 0 {
+ zb0009--
+ var zb0030 int
+ var zb0031 bool
+ zb0030, zb0031, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals")
+ return
+ }
+ if zb0030 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0030), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Reveals")
+ return
+ }
+ if zb0031 {
+ (*z).Reveals = nil
+ } else if (*z).Reveals != nil && cap((*z).Reveals) >= zb0030 {
+ (*z).Reveals = ((*z).Reveals)[:zb0030]
+ } else {
+ (*z).Reveals = make([]revealMap, zb0030)
+ }
+ for zb0006 := range (*z).Reveals {
+ var zb0032 int
+ var zb0033 bool
+ zb0032, zb0033, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0006)
+ return
+ }
+ if zb0032 > compactcert.MaxReveals {
+ err = msgp.ErrOverflow(uint64(zb0032), uint64(compactcert.MaxReveals))
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0006)
+ return
+ }
+ if zb0033 {
+ (*z).Reveals[zb0006] = nil
+ } else if (*z).Reveals[zb0006] == nil {
+ (*z).Reveals[zb0006] = make(revealMap, zb0032)
+ }
+ for zb0032 > 0 {
+ var zb0007 uint64
+ var zb0008 compactcert.Reveal
+ zb0032--
+ zb0007, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0006)
+ return
+ }
+ bts, err = zb0008.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0006, zb0007)
+ return
+ }
+ (*z).Reveals[zb0006][zb0007] = zb0008
+ }
+ }
+ }
+ if zb0009 > 0 {
+ zb0009--
+ {
+ var zb0034 []byte
+ var zb0035 int
+ zb0035, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReveals")
+ return
+ }
+ if zb0035 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0035), uint64(maxBitmaskSize))
+ return
+ }
+ zb0034, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskReveals))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReveals")
+ return
+ }
+ (*z).BitmaskReveals = bitmask(zb0034)
+ }
+ }
+ if zb0009 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0009)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0010 {
+ (*z) = encodedCert{}
+ }
+ for zb0009 > 0 {
+ zb0009--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "certc":
+ var zb0036 int
+ zb0036, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigCommit")
+ return
+ }
+ if zb0036 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0036), uint64(maxAddressBytes))
+ return
+ }
+ (*z).SigCommit, bts, err = msgp.ReadBytesBytes(bts, (*z).SigCommit)
+ if err != nil {
+ err = msgp.WrapError(err, "SigCommit")
+ return
+ }
+ case "certcbm":
+ {
+ var zb0037 []byte
+ var zb0038 int
+ zb0038, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigCommit")
+ return
+ }
+ if zb0038 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0038), uint64(maxBitmaskSize))
+ return
+ }
+ zb0037, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskSigCommit))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigCommit")
+ return
+ }
+ (*z).BitmaskSigCommit = bitmask(zb0037)
+ }
+ case "certw":
+ var zb0039 int
+ var zb0040 bool
+ zb0039, zb0040, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SignedWeight")
+ return
+ }
+ if zb0039 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0039), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "SignedWeight")
+ return
+ }
+ if zb0040 {
+ (*z).SignedWeight = nil
+ } else if (*z).SignedWeight != nil && cap((*z).SignedWeight) >= zb0039 {
+ (*z).SignedWeight = ((*z).SignedWeight)[:zb0039]
+ } else {
+ (*z).SignedWeight = make([]uint64, zb0039)
+ }
+ for zb0001 := range (*z).SignedWeight {
+ (*z).SignedWeight[zb0001], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SignedWeight", zb0001)
+ return
+ }
+ }
+ case "certwbm":
+ {
+ var zb0041 []byte
+ var zb0042 int
+ zb0042, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSignedWeight")
+ return
+ }
+ if zb0042 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0042), uint64(maxBitmaskSize))
+ return
+ }
+ zb0041, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskSignedWeight))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSignedWeight")
+ return
+ }
+ (*z).BitmaskSignedWeight = bitmask(zb0041)
+ }
+ case "certS":
+ var zb0043 int
+ var zb0044 bool
+ zb0043, zb0044, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs")
+ return
+ }
+ if zb0043 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0043), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "SigProofs")
+ return
+ }
+ if zb0044 {
+ (*z).SigProofs = nil
+ } else if (*z).SigProofs != nil && cap((*z).SigProofs) >= zb0043 {
+ (*z).SigProofs = ((*z).SigProofs)[:zb0043]
+ } else {
+ (*z).SigProofs = make([]certProofs, zb0043)
+ }
+ for zb0002 := range (*z).SigProofs {
+ var zb0045 int
+ var zb0046 bool
+ zb0045, zb0046, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs", zb0002)
+ return
+ }
+ if zb0045 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0045), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "SigProofs", zb0002)
+ return
+ }
+ if zb0046 {
+ (*z).SigProofs[zb0002] = nil
+ } else if (*z).SigProofs[zb0002] != nil && cap((*z).SigProofs[zb0002]) >= zb0045 {
+ (*z).SigProofs[zb0002] = ((*z).SigProofs[zb0002])[:zb0045]
+ } else {
+ (*z).SigProofs[zb0002] = make(certProofs, zb0045)
+ }
+ for zb0003 := range (*z).SigProofs[zb0002] {
+ bts, err = (*z).SigProofs[zb0002][zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs", zb0002, zb0003)
+ return
+ }
+ }
+ }
+ case "certSbm":
+ {
+ var zb0047 []byte
+ var zb0048 int
+ zb0048, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigProofs")
+ return
+ }
+ if zb0048 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0048), uint64(maxBitmaskSize))
+ return
+ }
+ zb0047, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskSigProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigProofs")
+ return
+ }
+ (*z).BitmaskSigProofs = bitmask(zb0047)
+ }
+ case "certP":
+ var zb0049 int
+ var zb0050 bool
+ zb0049, zb0050, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs")
+ return
+ }
+ if zb0049 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0049), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "PartProofs")
+ return
+ }
+ if zb0050 {
+ (*z).PartProofs = nil
+ } else if (*z).PartProofs != nil && cap((*z).PartProofs) >= zb0049 {
+ (*z).PartProofs = ((*z).PartProofs)[:zb0049]
+ } else {
+ (*z).PartProofs = make([]certProofs, zb0049)
+ }
+ for zb0004 := range (*z).PartProofs {
+ var zb0051 int
+ var zb0052 bool
+ zb0051, zb0052, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs", zb0004)
+ return
+ }
+ if zb0051 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0051), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "PartProofs", zb0004)
+ return
+ }
+ if zb0052 {
+ (*z).PartProofs[zb0004] = nil
+ } else if (*z).PartProofs[zb0004] != nil && cap((*z).PartProofs[zb0004]) >= zb0051 {
+ (*z).PartProofs[zb0004] = ((*z).PartProofs[zb0004])[:zb0051]
+ } else {
+ (*z).PartProofs[zb0004] = make(certProofs, zb0051)
+ }
+ for zb0005 := range (*z).PartProofs[zb0004] {
+ bts, err = (*z).PartProofs[zb0004][zb0005].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs", zb0004, zb0005)
+ return
+ }
+ }
+ }
+ case "certPbm":
+ {
+ var zb0053 []byte
+ var zb0054 int
+ zb0054, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskPartProofs")
+ return
+ }
+ if zb0054 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0054), uint64(maxBitmaskSize))
+ return
+ }
+ zb0053, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskPartProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskPartProofs")
+ return
+ }
+ (*z).BitmaskPartProofs = bitmask(zb0053)
+ }
+ case "certr":
+ var zb0055 int
+ var zb0056 bool
+ zb0055, zb0056, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals")
+ return
+ }
+ if zb0055 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0055), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Reveals")
+ return
+ }
+ if zb0056 {
+ (*z).Reveals = nil
+ } else if (*z).Reveals != nil && cap((*z).Reveals) >= zb0055 {
+ (*z).Reveals = ((*z).Reveals)[:zb0055]
+ } else {
+ (*z).Reveals = make([]revealMap, zb0055)
+ }
+ for zb0006 := range (*z).Reveals {
+ var zb0057 int
+ var zb0058 bool
+ zb0057, zb0058, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0006)
+ return
+ }
+ if zb0057 > compactcert.MaxReveals {
+ err = msgp.ErrOverflow(uint64(zb0057), uint64(compactcert.MaxReveals))
+ err = msgp.WrapError(err, "Reveals", zb0006)
+ return
+ }
+ if zb0058 {
+ (*z).Reveals[zb0006] = nil
+ } else if (*z).Reveals[zb0006] == nil {
+ (*z).Reveals[zb0006] = make(revealMap, zb0057)
+ }
+ for zb0057 > 0 {
+ var zb0007 uint64
+ var zb0008 compactcert.Reveal
+ zb0057--
+ zb0007, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0006)
+ return
+ }
+ bts, err = zb0008.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0006, zb0007)
+ return
+ }
+ (*z).Reveals[zb0006][zb0007] = zb0008
+ }
+ }
+ case "certrbm":
+ {
+ var zb0059 []byte
+ var zb0060 int
+ zb0060, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReveals")
+ return
+ }
+ if zb0060 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0060), uint64(maxBitmaskSize))
+ return
+ }
+ zb0059, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskReveals))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReveals")
+ return
+ }
+ (*z).BitmaskReveals = bitmask(zb0059)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedCert) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedCert)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedCert) Msgsize() (s int) {
+ s = 1 + 6 + msgp.BytesPrefixSize + len((*z).SigCommit) + 8 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskSigCommit)) + 6 + msgp.ArrayHeaderSize + (len((*z).SignedWeight) * (msgp.Uint64Size)) + 8 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskSignedWeight)) + 6 + msgp.ArrayHeaderSize
+ for zb0002 := range (*z).SigProofs {
+ s += msgp.ArrayHeaderSize
+ for zb0003 := range (*z).SigProofs[zb0002] {
+ s += (*z).SigProofs[zb0002][zb0003].Msgsize()
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskSigProofs)) + 6 + msgp.ArrayHeaderSize
+ for zb0004 := range (*z).PartProofs {
+ s += msgp.ArrayHeaderSize
+ for zb0005 := range (*z).PartProofs[zb0004] {
+ s += (*z).PartProofs[zb0004][zb0005].Msgsize()
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskPartProofs)) + 6 + msgp.ArrayHeaderSize
+ for zb0006 := range (*z).Reveals {
+ s += msgp.MapHeaderSize
+ if (*z).Reveals[zb0006] != nil {
+ for zb0007, zb0008 := range (*z).Reveals[zb0006] {
+ _ = zb0007
+ _ = zb0008
+ s += 0 + msgp.Uint64Size + zb0008.Msgsize()
+ }
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskReveals))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedCert) MsgIsZero() bool {
+ return (len((*z).SigCommit) == 0) && (len((*z).BitmaskSigCommit) == 0) && (len((*z).SignedWeight) == 0) && (len((*z).BitmaskSignedWeight) == 0) && (len((*z).SigProofs) == 0) && (len((*z).BitmaskSigProofs) == 0) && (len((*z).PartProofs) == 0) && (len((*z).BitmaskPartProofs) == 0) && (len((*z).Reveals) == 0) && (len((*z).BitmaskReveals) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedCompactCertTxnFields) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0011Len := uint32(14)
+ var zb0011Mask uint16 /* 16 bits */
+ if len((*z).encodedCert.PartProofs) == 0 {
+ zb0011Len--
+ zb0011Mask |= 0x4
+ }
+ if len((*z).encodedCert.BitmaskPartProofs) == 0 {
+ zb0011Len--
+ zb0011Mask |= 0x8
+ }
+ if len((*z).encodedCert.SigProofs) == 0 {
+ zb0011Len--
+ zb0011Mask |= 0x10
+ }
+ if len((*z).encodedCert.BitmaskSigProofs) == 0 {
+ zb0011Len--
+ zb0011Mask |= 0x20
+ }
+ if len((*z).encodedCert.SigCommit) == 0 {
+ zb0011Len--
+ zb0011Mask |= 0x40
+ }
+ if len((*z).encodedCert.BitmaskSigCommit) == 0 {
+ zb0011Len--
+ zb0011Mask |= 0x80
+ }
+ if len((*z).encodedCert.Reveals) == 0 {
+ zb0011Len--
+ zb0011Mask |= 0x100
+ }
+ if len((*z).encodedCert.BitmaskReveals) == 0 {
+ zb0011Len--
+ zb0011Mask |= 0x200
+ }
+ if len((*z).CertRound) == 0 {
+ zb0011Len--
+ zb0011Mask |= 0x400
+ }
+ if len((*z).BitmaskCertRound) == 0 {
+ zb0011Len--
+ zb0011Mask |= 0x800
+ }
+ if len((*z).CertType) == 0 {
+ zb0011Len--
+ zb0011Mask |= 0x1000
+ }
+ if len((*z).BitmaskCertType) == 0 {
+ zb0011Len--
+ zb0011Mask |= 0x2000
+ }
+ if len((*z).encodedCert.SignedWeight) == 0 {
+ zb0011Len--
+ zb0011Mask |= 0x4000
+ }
+ if len((*z).encodedCert.BitmaskSignedWeight) == 0 {
+ zb0011Len--
+ zb0011Mask |= 0x8000
+ }
+ // variable map header, size zb0011Len
+ o = append(o, 0x80|uint8(zb0011Len))
+ if zb0011Len != 0 {
+ if (zb0011Mask & 0x4) == 0 { // if not empty
+ // string "certP"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x50)
+ if (*z).encodedCert.PartProofs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedCert.PartProofs)))
+ }
+ for zb0006 := range (*z).encodedCert.PartProofs {
+ if (*z).encodedCert.PartProofs[zb0006] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedCert.PartProofs[zb0006])))
+ }
+ for zb0007 := range (*z).encodedCert.PartProofs[zb0006] {
+ o = (*z).encodedCert.PartProofs[zb0006][zb0007].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0011Mask & 0x8) == 0 { // if not empty
+ // string "certPbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x50, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedCert.BitmaskPartProofs))
+ }
+ if (zb0011Mask & 0x10) == 0 { // if not empty
+ // string "certS"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x53)
+ if (*z).encodedCert.SigProofs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedCert.SigProofs)))
+ }
+ for zb0004 := range (*z).encodedCert.SigProofs {
+ if (*z).encodedCert.SigProofs[zb0004] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedCert.SigProofs[zb0004])))
+ }
+ for zb0005 := range (*z).encodedCert.SigProofs[zb0004] {
+ o = (*z).encodedCert.SigProofs[zb0004][zb0005].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0011Mask & 0x20) == 0 { // if not empty
+ // string "certSbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x53, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedCert.BitmaskSigProofs))
+ }
+ if (zb0011Mask & 0x40) == 0 { // if not empty
+ // string "certc"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x63)
+ o = msgp.AppendBytes(o, (*z).encodedCert.SigCommit)
+ }
+ if (zb0011Mask & 0x80) == 0 { // if not empty
+ // string "certcbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedCert.BitmaskSigCommit))
+ }
+ if (zb0011Mask & 0x100) == 0 { // if not empty
+ // string "certr"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x72)
+ if (*z).encodedCert.Reveals == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedCert.Reveals)))
+ }
+ for zb0008 := range (*z).encodedCert.Reveals {
+ if (*z).encodedCert.Reveals[zb0008] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendMapHeader(o, uint32(len((*z).encodedCert.Reveals[zb0008])))
+ }
+ zb0009_keys := make([]uint64, 0, len((*z).encodedCert.Reveals[zb0008]))
+ for zb0009 := range (*z).encodedCert.Reveals[zb0008] {
+ zb0009_keys = append(zb0009_keys, zb0009)
+ }
+ sort.Sort(SortUint64(zb0009_keys))
+ for _, zb0009 := range zb0009_keys {
+ zb0010 := (*z).encodedCert.Reveals[zb0008][zb0009]
+ _ = zb0010
+ o = msgp.AppendUint64(o, zb0009)
+ o = zb0010.MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0011Mask & 0x200) == 0 { // if not empty
+ // string "certrbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedCert.BitmaskReveals))
+ }
+ if (zb0011Mask & 0x400) == 0 { // if not empty
+ // string "certrnd"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x72, 0x6e, 0x64)
+ if (*z).CertRound == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).CertRound)))
+ }
+ for zb0001 := range (*z).CertRound {
+ o = (*z).CertRound[zb0001].MarshalMsg(o)
+ }
+ }
+ if (zb0011Mask & 0x800) == 0 { // if not empty
+ // string "certrndbm"
+ o = append(o, 0xa9, 0x63, 0x65, 0x72, 0x74, 0x72, 0x6e, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskCertRound))
+ }
+ if (zb0011Mask & 0x1000) == 0 { // if not empty
+ // string "certtype"
+ o = append(o, 0xa8, 0x63, 0x65, 0x72, 0x74, 0x74, 0x79, 0x70, 0x65)
+ if (*z).CertType == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).CertType)))
+ }
+ for zb0002 := range (*z).CertType {
+ o = (*z).CertType[zb0002].MarshalMsg(o)
+ }
+ }
+ if (zb0011Mask & 0x2000) == 0 { // if not empty
+ // string "certtypebm"
+ o = append(o, 0xaa, 0x63, 0x65, 0x72, 0x74, 0x74, 0x79, 0x70, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskCertType))
+ }
+ if (zb0011Mask & 0x4000) == 0 { // if not empty
+ // string "certw"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x77)
+ if (*z).encodedCert.SignedWeight == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedCert.SignedWeight)))
+ }
+ for zb0003 := range (*z).encodedCert.SignedWeight {
+ o = msgp.AppendUint64(o, (*z).encodedCert.SignedWeight[zb0003])
+ }
+ }
+ if (zb0011Mask & 0x8000) == 0 { // if not empty
+ // string "certwbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x77, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedCert.BitmaskSignedWeight))
+ }
+ }
+ return
+}
+
+func (_ *encodedCompactCertTxnFields) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedCompactCertTxnFields)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedCompactCertTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0011 int
+ var zb0012 bool
+ zb0011, zb0012, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0011, zb0012, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0011 > 0 {
+ zb0011--
+ var zb0013 int
+ var zb0014 bool
+ zb0013, zb0014, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertRound")
+ return
+ }
+ if zb0013 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0013), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "CertRound")
+ return
+ }
+ if zb0014 {
+ (*z).CertRound = nil
+ } else if (*z).CertRound != nil && cap((*z).CertRound) >= zb0013 {
+ (*z).CertRound = ((*z).CertRound)[:zb0013]
+ } else {
+ (*z).CertRound = make([]basics.Round, zb0013)
+ }
+ for zb0001 := range (*z).CertRound {
+ bts, err = (*z).CertRound[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertRound", zb0001)
+ return
+ }
+ }
+ }
+ if zb0011 > 0 {
+ zb0011--
+ {
+ var zb0015 []byte
+ var zb0016 int
+ zb0016, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertRound")
+ return
+ }
+ if zb0016 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0016), uint64(maxBitmaskSize))
+ return
+ }
+ zb0015, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskCertRound))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertRound")
+ return
+ }
+ (*z).BitmaskCertRound = bitmask(zb0015)
+ }
+ }
+ if zb0011 > 0 {
+ zb0011--
+ var zb0017 int
+ var zb0018 bool
+ zb0017, zb0018, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertType")
+ return
+ }
+ if zb0017 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0017), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "CertType")
+ return
+ }
+ if zb0018 {
+ (*z).CertType = nil
+ } else if (*z).CertType != nil && cap((*z).CertType) >= zb0017 {
+ (*z).CertType = ((*z).CertType)[:zb0017]
+ } else {
+ (*z).CertType = make([]protocol.CompactCertType, zb0017)
+ }
+ for zb0002 := range (*z).CertType {
+ bts, err = (*z).CertType[zb0002].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertType", zb0002)
+ return
+ }
+ }
+ }
+ if zb0011 > 0 {
+ zb0011--
+ {
+ var zb0019 []byte
+ var zb0020 int
+ zb0020, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertType")
+ return
+ }
+ if zb0020 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0020), uint64(maxBitmaskSize))
+ return
+ }
+ zb0019, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskCertType))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertType")
+ return
+ }
+ (*z).BitmaskCertType = bitmask(zb0019)
+ }
+ }
+ if zb0011 > 0 {
+ zb0011--
+ var zb0021 int
+ zb0021, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigCommit")
+ return
+ }
+ if zb0021 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0021), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedCert.SigCommit, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedCert.SigCommit)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigCommit")
+ return
+ }
+ }
+ if zb0011 > 0 {
+ zb0011--
+ {
+ var zb0022 []byte
+ var zb0023 int
+ zb0023, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigCommit")
+ return
+ }
+ if zb0023 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0023), uint64(maxBitmaskSize))
+ return
+ }
+ zb0022, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCert.BitmaskSigCommit))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigCommit")
+ return
+ }
+ (*z).encodedCert.BitmaskSigCommit = bitmask(zb0022)
+ }
+ }
+ if zb0011 > 0 {
+ zb0011--
+ var zb0024 int
+ var zb0025 bool
+ zb0024, zb0025, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight")
+ return
+ }
+ if zb0024 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0024), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight")
+ return
+ }
+ if zb0025 {
+ (*z).encodedCert.SignedWeight = nil
+ } else if (*z).encodedCert.SignedWeight != nil && cap((*z).encodedCert.SignedWeight) >= zb0024 {
+ (*z).encodedCert.SignedWeight = ((*z).encodedCert.SignedWeight)[:zb0024]
+ } else {
+ (*z).encodedCert.SignedWeight = make([]uint64, zb0024)
+ }
+ for zb0003 := range (*z).encodedCert.SignedWeight {
+ (*z).encodedCert.SignedWeight[zb0003], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight", zb0003)
+ return
+ }
+ }
+ }
+ if zb0011 > 0 {
+ zb0011--
+ {
+ var zb0026 []byte
+ var zb0027 int
+ zb0027, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSignedWeight")
+ return
+ }
+ if zb0027 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0027), uint64(maxBitmaskSize))
+ return
+ }
+ zb0026, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCert.BitmaskSignedWeight))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSignedWeight")
+ return
+ }
+ (*z).encodedCert.BitmaskSignedWeight = bitmask(zb0026)
+ }
+ }
+ if zb0011 > 0 {
+ zb0011--
+ var zb0028 int
+ var zb0029 bool
+ zb0028, zb0029, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs")
+ return
+ }
+ if zb0028 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0028), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs")
+ return
+ }
+ if zb0029 {
+ (*z).encodedCert.SigProofs = nil
+ } else if (*z).encodedCert.SigProofs != nil && cap((*z).encodedCert.SigProofs) >= zb0028 {
+ (*z).encodedCert.SigProofs = ((*z).encodedCert.SigProofs)[:zb0028]
+ } else {
+ (*z).encodedCert.SigProofs = make([]certProofs, zb0028)
+ }
+ for zb0004 := range (*z).encodedCert.SigProofs {
+ var zb0030 int
+ var zb0031 bool
+ zb0030, zb0031, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0004)
+ return
+ }
+ if zb0030 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0030), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0004)
+ return
+ }
+ if zb0031 {
+ (*z).encodedCert.SigProofs[zb0004] = nil
+ } else if (*z).encodedCert.SigProofs[zb0004] != nil && cap((*z).encodedCert.SigProofs[zb0004]) >= zb0030 {
+ (*z).encodedCert.SigProofs[zb0004] = ((*z).encodedCert.SigProofs[zb0004])[:zb0030]
+ } else {
+ (*z).encodedCert.SigProofs[zb0004] = make(certProofs, zb0030)
+ }
+ for zb0005 := range (*z).encodedCert.SigProofs[zb0004] {
+ bts, err = (*z).encodedCert.SigProofs[zb0004][zb0005].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0004, zb0005)
+ return
+ }
+ }
+ }
+ }
+ if zb0011 > 0 {
+ zb0011--
+ {
+ var zb0032 []byte
+ var zb0033 int
+ zb0033, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigProofs")
+ return
+ }
+ if zb0033 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0033), uint64(maxBitmaskSize))
+ return
+ }
+ zb0032, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCert.BitmaskSigProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigProofs")
+ return
+ }
+ (*z).encodedCert.BitmaskSigProofs = bitmask(zb0032)
+ }
+ }
+ if zb0011 > 0 {
+ zb0011--
+ var zb0034 int
+ var zb0035 bool
+ zb0034, zb0035, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs")
+ return
+ }
+ if zb0034 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0034), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs")
+ return
+ }
+ if zb0035 {
+ (*z).encodedCert.PartProofs = nil
+ } else if (*z).encodedCert.PartProofs != nil && cap((*z).encodedCert.PartProofs) >= zb0034 {
+ (*z).encodedCert.PartProofs = ((*z).encodedCert.PartProofs)[:zb0034]
+ } else {
+ (*z).encodedCert.PartProofs = make([]certProofs, zb0034)
+ }
+ for zb0006 := range (*z).encodedCert.PartProofs {
+ var zb0036 int
+ var zb0037 bool
+ zb0036, zb0037, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0006)
+ return
+ }
+ if zb0036 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0036), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0006)
+ return
+ }
+ if zb0037 {
+ (*z).encodedCert.PartProofs[zb0006] = nil
+ } else if (*z).encodedCert.PartProofs[zb0006] != nil && cap((*z).encodedCert.PartProofs[zb0006]) >= zb0036 {
+ (*z).encodedCert.PartProofs[zb0006] = ((*z).encodedCert.PartProofs[zb0006])[:zb0036]
+ } else {
+ (*z).encodedCert.PartProofs[zb0006] = make(certProofs, zb0036)
+ }
+ for zb0007 := range (*z).encodedCert.PartProofs[zb0006] {
+ bts, err = (*z).encodedCert.PartProofs[zb0006][zb0007].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0006, zb0007)
+ return
+ }
+ }
+ }
+ }
+ if zb0011 > 0 {
+ zb0011--
+ {
+ var zb0038 []byte
+ var zb0039 int
+ zb0039, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskPartProofs")
+ return
+ }
+ if zb0039 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0039), uint64(maxBitmaskSize))
+ return
+ }
+ zb0038, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCert.BitmaskPartProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskPartProofs")
+ return
+ }
+ (*z).encodedCert.BitmaskPartProofs = bitmask(zb0038)
+ }
+ }
+ if zb0011 > 0 {
+ zb0011--
+ var zb0040 int
+ var zb0041 bool
+ zb0040, zb0041, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals")
+ return
+ }
+ if zb0040 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0040), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Reveals")
+ return
+ }
+ if zb0041 {
+ (*z).encodedCert.Reveals = nil
+ } else if (*z).encodedCert.Reveals != nil && cap((*z).encodedCert.Reveals) >= zb0040 {
+ (*z).encodedCert.Reveals = ((*z).encodedCert.Reveals)[:zb0040]
+ } else {
+ (*z).encodedCert.Reveals = make([]revealMap, zb0040)
+ }
+ for zb0008 := range (*z).encodedCert.Reveals {
+ var zb0042 int
+ var zb0043 bool
+ zb0042, zb0043, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0008)
+ return
+ }
+ if zb0042 > compactcert.MaxReveals {
+ err = msgp.ErrOverflow(uint64(zb0042), uint64(compactcert.MaxReveals))
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0008)
+ return
+ }
+ if zb0043 {
+ (*z).encodedCert.Reveals[zb0008] = nil
+ } else if (*z).encodedCert.Reveals[zb0008] == nil {
+ (*z).encodedCert.Reveals[zb0008] = make(revealMap, zb0042)
+ }
+ for zb0042 > 0 {
+ var zb0009 uint64
+ var zb0010 compactcert.Reveal
+ zb0042--
+ zb0009, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0008)
+ return
+ }
+ bts, err = zb0010.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0008, zb0009)
+ return
+ }
+ (*z).encodedCert.Reveals[zb0008][zb0009] = zb0010
+ }
+ }
+ }
+ if zb0011 > 0 {
+ zb0011--
+ {
+ var zb0044 []byte
+ var zb0045 int
+ zb0045, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReveals")
+ return
+ }
+ if zb0045 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0045), uint64(maxBitmaskSize))
+ return
+ }
+ zb0044, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCert.BitmaskReveals))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReveals")
+ return
+ }
+ (*z).encodedCert.BitmaskReveals = bitmask(zb0044)
+ }
+ }
+ if zb0011 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0011)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0012 {
+ (*z) = encodedCompactCertTxnFields{}
+ }
+ for zb0011 > 0 {
+ zb0011--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "certrnd":
+ var zb0046 int
+ var zb0047 bool
+ zb0046, zb0047, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertRound")
+ return
+ }
+ if zb0046 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0046), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "CertRound")
+ return
+ }
+ if zb0047 {
+ (*z).CertRound = nil
+ } else if (*z).CertRound != nil && cap((*z).CertRound) >= zb0046 {
+ (*z).CertRound = ((*z).CertRound)[:zb0046]
+ } else {
+ (*z).CertRound = make([]basics.Round, zb0046)
+ }
+ for zb0001 := range (*z).CertRound {
+ bts, err = (*z).CertRound[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertRound", zb0001)
+ return
+ }
+ }
+ case "certrndbm":
+ {
+ var zb0048 []byte
+ var zb0049 int
+ zb0049, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertRound")
+ return
+ }
+ if zb0049 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0049), uint64(maxBitmaskSize))
+ return
+ }
+ zb0048, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskCertRound))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertRound")
+ return
+ }
+ (*z).BitmaskCertRound = bitmask(zb0048)
+ }
+ case "certtype":
+ var zb0050 int
+ var zb0051 bool
+ zb0050, zb0051, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertType")
+ return
+ }
+ if zb0050 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0050), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "CertType")
+ return
+ }
+ if zb0051 {
+ (*z).CertType = nil
+ } else if (*z).CertType != nil && cap((*z).CertType) >= zb0050 {
+ (*z).CertType = ((*z).CertType)[:zb0050]
+ } else {
+ (*z).CertType = make([]protocol.CompactCertType, zb0050)
+ }
+ for zb0002 := range (*z).CertType {
+ bts, err = (*z).CertType[zb0002].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertType", zb0002)
+ return
+ }
+ }
+ case "certtypebm":
+ {
+ var zb0052 []byte
+ var zb0053 int
+ zb0053, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertType")
+ return
+ }
+ if zb0053 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0053), uint64(maxBitmaskSize))
+ return
+ }
+ zb0052, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskCertType))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertType")
+ return
+ }
+ (*z).BitmaskCertType = bitmask(zb0052)
+ }
+ case "certc":
+ var zb0054 int
+ zb0054, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigCommit")
+ return
+ }
+ if zb0054 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0054), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedCert.SigCommit, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedCert.SigCommit)
+ if err != nil {
+ err = msgp.WrapError(err, "SigCommit")
+ return
+ }
+ case "certcbm":
+ {
+ var zb0055 []byte
+ var zb0056 int
+ zb0056, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigCommit")
+ return
+ }
+ if zb0056 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0056), uint64(maxBitmaskSize))
+ return
+ }
+ zb0055, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCert.BitmaskSigCommit))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigCommit")
+ return
+ }
+ (*z).encodedCert.BitmaskSigCommit = bitmask(zb0055)
+ }
+ case "certw":
+ var zb0057 int
+ var zb0058 bool
+ zb0057, zb0058, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SignedWeight")
+ return
+ }
+ if zb0057 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0057), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "SignedWeight")
+ return
+ }
+ if zb0058 {
+ (*z).encodedCert.SignedWeight = nil
+ } else if (*z).encodedCert.SignedWeight != nil && cap((*z).encodedCert.SignedWeight) >= zb0057 {
+ (*z).encodedCert.SignedWeight = ((*z).encodedCert.SignedWeight)[:zb0057]
+ } else {
+ (*z).encodedCert.SignedWeight = make([]uint64, zb0057)
+ }
+ for zb0003 := range (*z).encodedCert.SignedWeight {
+ (*z).encodedCert.SignedWeight[zb0003], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SignedWeight", zb0003)
+ return
+ }
+ }
+ case "certwbm":
+ {
+ var zb0059 []byte
+ var zb0060 int
+ zb0060, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSignedWeight")
+ return
+ }
+ if zb0060 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0060), uint64(maxBitmaskSize))
+ return
+ }
+ zb0059, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCert.BitmaskSignedWeight))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSignedWeight")
+ return
+ }
+ (*z).encodedCert.BitmaskSignedWeight = bitmask(zb0059)
+ }
+ case "certS":
+ var zb0061 int
+ var zb0062 bool
+ zb0061, zb0062, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs")
+ return
+ }
+ if zb0061 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0061), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "SigProofs")
+ return
+ }
+ if zb0062 {
+ (*z).encodedCert.SigProofs = nil
+ } else if (*z).encodedCert.SigProofs != nil && cap((*z).encodedCert.SigProofs) >= zb0061 {
+ (*z).encodedCert.SigProofs = ((*z).encodedCert.SigProofs)[:zb0061]
+ } else {
+ (*z).encodedCert.SigProofs = make([]certProofs, zb0061)
+ }
+ for zb0004 := range (*z).encodedCert.SigProofs {
+ var zb0063 int
+ var zb0064 bool
+ zb0063, zb0064, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs", zb0004)
+ return
+ }
+ if zb0063 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0063), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "SigProofs", zb0004)
+ return
+ }
+ if zb0064 {
+ (*z).encodedCert.SigProofs[zb0004] = nil
+ } else if (*z).encodedCert.SigProofs[zb0004] != nil && cap((*z).encodedCert.SigProofs[zb0004]) >= zb0063 {
+ (*z).encodedCert.SigProofs[zb0004] = ((*z).encodedCert.SigProofs[zb0004])[:zb0063]
+ } else {
+ (*z).encodedCert.SigProofs[zb0004] = make(certProofs, zb0063)
+ }
+ for zb0005 := range (*z).encodedCert.SigProofs[zb0004] {
+ bts, err = (*z).encodedCert.SigProofs[zb0004][zb0005].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs", zb0004, zb0005)
+ return
+ }
+ }
+ }
+ case "certSbm":
+ {
+ var zb0065 []byte
+ var zb0066 int
+ zb0066, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigProofs")
+ return
+ }
+ if zb0066 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0066), uint64(maxBitmaskSize))
+ return
+ }
+ zb0065, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCert.BitmaskSigProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigProofs")
+ return
+ }
+ (*z).encodedCert.BitmaskSigProofs = bitmask(zb0065)
+ }
+ case "certP":
+ var zb0067 int
+ var zb0068 bool
+ zb0067, zb0068, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs")
+ return
+ }
+ if zb0067 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0067), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "PartProofs")
+ return
+ }
+ if zb0068 {
+ (*z).encodedCert.PartProofs = nil
+ } else if (*z).encodedCert.PartProofs != nil && cap((*z).encodedCert.PartProofs) >= zb0067 {
+ (*z).encodedCert.PartProofs = ((*z).encodedCert.PartProofs)[:zb0067]
+ } else {
+ (*z).encodedCert.PartProofs = make([]certProofs, zb0067)
+ }
+ for zb0006 := range (*z).encodedCert.PartProofs {
+ var zb0069 int
+ var zb0070 bool
+ zb0069, zb0070, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs", zb0006)
+ return
+ }
+ if zb0069 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0069), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "PartProofs", zb0006)
+ return
+ }
+ if zb0070 {
+ (*z).encodedCert.PartProofs[zb0006] = nil
+ } else if (*z).encodedCert.PartProofs[zb0006] != nil && cap((*z).encodedCert.PartProofs[zb0006]) >= zb0069 {
+ (*z).encodedCert.PartProofs[zb0006] = ((*z).encodedCert.PartProofs[zb0006])[:zb0069]
+ } else {
+ (*z).encodedCert.PartProofs[zb0006] = make(certProofs, zb0069)
+ }
+ for zb0007 := range (*z).encodedCert.PartProofs[zb0006] {
+ bts, err = (*z).encodedCert.PartProofs[zb0006][zb0007].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs", zb0006, zb0007)
+ return
+ }
+ }
+ }
+ case "certPbm":
+ {
+ var zb0071 []byte
+ var zb0072 int
+ zb0072, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskPartProofs")
+ return
+ }
+ if zb0072 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0072), uint64(maxBitmaskSize))
+ return
+ }
+ zb0071, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCert.BitmaskPartProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskPartProofs")
+ return
+ }
+ (*z).encodedCert.BitmaskPartProofs = bitmask(zb0071)
+ }
+ case "certr":
+ var zb0073 int
+ var zb0074 bool
+ zb0073, zb0074, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals")
+ return
+ }
+ if zb0073 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0073), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Reveals")
+ return
+ }
+ if zb0074 {
+ (*z).encodedCert.Reveals = nil
+ } else if (*z).encodedCert.Reveals != nil && cap((*z).encodedCert.Reveals) >= zb0073 {
+ (*z).encodedCert.Reveals = ((*z).encodedCert.Reveals)[:zb0073]
+ } else {
+ (*z).encodedCert.Reveals = make([]revealMap, zb0073)
+ }
+ for zb0008 := range (*z).encodedCert.Reveals {
+ var zb0075 int
+ var zb0076 bool
+ zb0075, zb0076, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0008)
+ return
+ }
+ if zb0075 > compactcert.MaxReveals {
+ err = msgp.ErrOverflow(uint64(zb0075), uint64(compactcert.MaxReveals))
+ err = msgp.WrapError(err, "Reveals", zb0008)
+ return
+ }
+ if zb0076 {
+ (*z).encodedCert.Reveals[zb0008] = nil
+ } else if (*z).encodedCert.Reveals[zb0008] == nil {
+ (*z).encodedCert.Reveals[zb0008] = make(revealMap, zb0075)
+ }
+ for zb0075 > 0 {
+ var zb0009 uint64
+ var zb0010 compactcert.Reveal
+ zb0075--
+ zb0009, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0008)
+ return
+ }
+ bts, err = zb0010.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0008, zb0009)
+ return
+ }
+ (*z).encodedCert.Reveals[zb0008][zb0009] = zb0010
+ }
+ }
+ case "certrbm":
+ {
+ var zb0077 []byte
+ var zb0078 int
+ zb0078, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReveals")
+ return
+ }
+ if zb0078 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0078), uint64(maxBitmaskSize))
+ return
+ }
+ zb0077, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCert.BitmaskReveals))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReveals")
+ return
+ }
+ (*z).encodedCert.BitmaskReveals = bitmask(zb0077)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedCompactCertTxnFields) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedCompactCertTxnFields)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedCompactCertTxnFields) Msgsize() (s int) {
+ s = 1 + 8 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).CertRound {
+ s += (*z).CertRound[zb0001].Msgsize()
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskCertRound)) + 9 + msgp.ArrayHeaderSize
+ for zb0002 := range (*z).CertType {
+ s += (*z).CertType[zb0002].Msgsize()
+ }
+ s += 11 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskCertType)) + 6 + msgp.BytesPrefixSize + len((*z).encodedCert.SigCommit) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedCert.BitmaskSigCommit)) + 6 + msgp.ArrayHeaderSize + (len((*z).encodedCert.SignedWeight) * (msgp.Uint64Size)) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedCert.BitmaskSignedWeight)) + 6 + msgp.ArrayHeaderSize
+ for zb0004 := range (*z).encodedCert.SigProofs {
+ s += msgp.ArrayHeaderSize
+ for zb0005 := range (*z).encodedCert.SigProofs[zb0004] {
+ s += (*z).encodedCert.SigProofs[zb0004][zb0005].Msgsize()
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedCert.BitmaskSigProofs)) + 6 + msgp.ArrayHeaderSize
+ for zb0006 := range (*z).encodedCert.PartProofs {
+ s += msgp.ArrayHeaderSize
+ for zb0007 := range (*z).encodedCert.PartProofs[zb0006] {
+ s += (*z).encodedCert.PartProofs[zb0006][zb0007].Msgsize()
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedCert.BitmaskPartProofs)) + 6 + msgp.ArrayHeaderSize
+ for zb0008 := range (*z).encodedCert.Reveals {
+ s += msgp.MapHeaderSize
+ if (*z).encodedCert.Reveals[zb0008] != nil {
+ for zb0009, zb0010 := range (*z).encodedCert.Reveals[zb0008] {
+ _ = zb0009
+ _ = zb0010
+ s += 0 + msgp.Uint64Size + zb0010.Msgsize()
+ }
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedCert.BitmaskReveals))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedCompactCertTxnFields) MsgIsZero() bool {
+ return (len((*z).CertRound) == 0) && (len((*z).BitmaskCertRound) == 0) && (len((*z).CertType) == 0) && (len((*z).BitmaskCertType) == 0) && (len((*z).encodedCert.SigCommit) == 0) && (len((*z).encodedCert.BitmaskSigCommit) == 0) && (len((*z).encodedCert.SignedWeight) == 0) && (len((*z).encodedCert.BitmaskSignedWeight) == 0) && (len((*z).encodedCert.SigProofs) == 0) && (len((*z).encodedCert.BitmaskSigProofs) == 0) && (len((*z).encodedCert.PartProofs) == 0) && (len((*z).encodedCert.BitmaskPartProofs) == 0) && (len((*z).encodedCert.Reveals) == 0) && (len((*z).encodedCert.BitmaskReveals) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedKeyregTxnFields) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0004Len := uint32(9)
+ var zb0004Mask uint16 /* 10 bits */
+ if len((*z).BitmaskNonparticipation) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x2
+ }
+ if len((*z).SelectionPK) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x4
+ }
+ if len((*z).VoteFirst) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x8
+ }
+ if len((*z).BitmaskVoteFirst) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x10
+ }
+ if len((*z).BitmaskKeys) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x20
+ }
+ if len((*z).VoteKeyDilution) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x40
+ }
+ if len((*z).VotePK) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x80
+ }
+ if len((*z).VoteLast) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x100
+ }
+ if len((*z).BitmaskVoteLast) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x200
+ }
+ // variable map header, size zb0004Len
+ o = append(o, 0x80|uint8(zb0004Len))
+ if zb0004Len != 0 {
+ if (zb0004Mask & 0x2) == 0 { // if not empty
+ // string "nonpartbm"
+ o = append(o, 0xa9, 0x6e, 0x6f, 0x6e, 0x70, 0x61, 0x72, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskNonparticipation))
+ }
+ if (zb0004Mask & 0x4) == 0 { // if not empty
+ // string "selkey"
+ o = append(o, 0xa6, 0x73, 0x65, 0x6c, 0x6b, 0x65, 0x79)
+ o = msgp.AppendBytes(o, (*z).SelectionPK)
+ }
+ if (zb0004Mask & 0x8) == 0 { // if not empty
+ // string "votefst"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x66, 0x73, 0x74)
+ if (*z).VoteFirst == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).VoteFirst)))
+ }
+ for zb0001 := range (*z).VoteFirst {
+ o = (*z).VoteFirst[zb0001].MarshalMsg(o)
+ }
+ }
+ if (zb0004Mask & 0x10) == 0 { // if not empty
+ // string "votefstbm"
+ o = append(o, 0xa9, 0x76, 0x6f, 0x74, 0x65, 0x66, 0x73, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskVoteFirst))
+ }
+ if (zb0004Mask & 0x20) == 0 { // if not empty
+ // string "votekbm"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x6b, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskKeys))
+ }
+ if (zb0004Mask & 0x40) == 0 { // if not empty
+ // string "votekd"
+ o = append(o, 0xa6, 0x76, 0x6f, 0x74, 0x65, 0x6b, 0x64)
+ if (*z).VoteKeyDilution == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).VoteKeyDilution)))
+ }
+ for zb0003 := range (*z).VoteKeyDilution {
+ o = msgp.AppendUint64(o, (*z).VoteKeyDilution[zb0003])
+ }
+ }
+ if (zb0004Mask & 0x80) == 0 { // if not empty
+ // string "votekey"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x6b, 0x65, 0x79)
+ o = msgp.AppendBytes(o, (*z).VotePK)
+ }
+ if (zb0004Mask & 0x100) == 0 { // if not empty
+ // string "votelst"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x6c, 0x73, 0x74)
+ if (*z).VoteLast == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).VoteLast)))
+ }
+ for zb0002 := range (*z).VoteLast {
+ o = (*z).VoteLast[zb0002].MarshalMsg(o)
+ }
+ }
+ if (zb0004Mask & 0x200) == 0 { // if not empty
+ // string "votelstbm"
+ o = append(o, 0xa9, 0x76, 0x6f, 0x74, 0x65, 0x6c, 0x73, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskVoteLast))
+ }
+ }
+ return
+}
+
+func (_ *encodedKeyregTxnFields) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedKeyregTxnFields)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedKeyregTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0004 int
+ var zb0005 bool
+ zb0004, zb0005, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0004, zb0005, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0004 > 0 {
+ zb0004--
+ var zb0006 int
+ zb0006, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VotePK")
+ return
+ }
+ if zb0006 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0006), uint64(maxAddressBytes))
+ return
+ }
+ (*z).VotePK, bts, err = msgp.ReadBytesBytes(bts, (*z).VotePK)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VotePK")
+ return
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
+ var zb0007 int
+ zb0007, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SelectionPK")
+ return
+ }
+ if zb0007 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0007), uint64(maxAddressBytes))
+ return
+ }
+ (*z).SelectionPK, bts, err = msgp.ReadBytesBytes(bts, (*z).SelectionPK)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SelectionPK")
+ return
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
+ var zb0008 int
+ var zb0009 bool
+ zb0008, zb0009, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteFirst")
+ return
+ }
+ if zb0008 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0008), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "VoteFirst")
+ return
+ }
+ if zb0009 {
+ (*z).VoteFirst = nil
+ } else if (*z).VoteFirst != nil && cap((*z).VoteFirst) >= zb0008 {
+ (*z).VoteFirst = ((*z).VoteFirst)[:zb0008]
+ } else {
+ (*z).VoteFirst = make([]basics.Round, zb0008)
+ }
+ for zb0001 := range (*z).VoteFirst {
+ bts, err = (*z).VoteFirst[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteFirst", zb0001)
+ return
+ }
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
+ {
+ var zb0010 []byte
+ var zb0011 int
+ zb0011, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteFirst")
+ return
+ }
+ if zb0011 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0011), uint64(maxBitmaskSize))
+ return
+ }
+ zb0010, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskVoteFirst))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteFirst")
+ return
+ }
+ (*z).BitmaskVoteFirst = bitmask(zb0010)
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
+ var zb0012 int
+ var zb0013 bool
+ zb0012, zb0013, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteLast")
+ return
+ }
+ if zb0012 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0012), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "VoteLast")
+ return
+ }
+ if zb0013 {
+ (*z).VoteLast = nil
+ } else if (*z).VoteLast != nil && cap((*z).VoteLast) >= zb0012 {
+ (*z).VoteLast = ((*z).VoteLast)[:zb0012]
+ } else {
+ (*z).VoteLast = make([]basics.Round, zb0012)
+ }
+ for zb0002 := range (*z).VoteLast {
+ bts, err = (*z).VoteLast[zb0002].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteLast", zb0002)
+ return
+ }
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
+ {
+ var zb0014 []byte
+ var zb0015 int
+ zb0015, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteLast")
+ return
+ }
+ if zb0015 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0015), uint64(maxBitmaskSize))
+ return
+ }
+ zb0014, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskVoteLast))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteLast")
+ return
+ }
+ (*z).BitmaskVoteLast = bitmask(zb0014)
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
+ var zb0016 int
+ var zb0017 bool
+ zb0016, zb0017, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteKeyDilution")
+ return
+ }
+ if zb0016 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0016), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "VoteKeyDilution")
+ return
+ }
+ if zb0017 {
+ (*z).VoteKeyDilution = nil
+ } else if (*z).VoteKeyDilution != nil && cap((*z).VoteKeyDilution) >= zb0016 {
+ (*z).VoteKeyDilution = ((*z).VoteKeyDilution)[:zb0016]
+ } else {
+ (*z).VoteKeyDilution = make([]uint64, zb0016)
+ }
+ for zb0003 := range (*z).VoteKeyDilution {
+ (*z).VoteKeyDilution[zb0003], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteKeyDilution", zb0003)
+ return
+ }
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
+ {
+ var zb0018 []byte
+ var zb0019 int
+ zb0019, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskKeys")
+ return
+ }
+ if zb0019 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0019), uint64(maxBitmaskSize))
+ return
+ }
+ zb0018, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskKeys))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskKeys")
+ return
+ }
+ (*z).BitmaskKeys = bitmask(zb0018)
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
+ {
+ var zb0020 []byte
+ var zb0021 int
+ zb0021, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNonparticipation")
+ return
+ }
+ if zb0021 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0021), uint64(maxBitmaskSize))
+ return
+ }
+ zb0020, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskNonparticipation))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNonparticipation")
+ return
+ }
+ (*z).BitmaskNonparticipation = bitmask(zb0020)
+ }
+ }
+ if zb0004 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0004)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0005 {
+ (*z) = encodedKeyregTxnFields{}
+ }
+ for zb0004 > 0 {
+ zb0004--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "votekey":
+ var zb0022 int
+ zb0022, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VotePK")
+ return
+ }
+ if zb0022 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0022), uint64(maxAddressBytes))
+ return
+ }
+ (*z).VotePK, bts, err = msgp.ReadBytesBytes(bts, (*z).VotePK)
+ if err != nil {
+ err = msgp.WrapError(err, "VotePK")
+ return
+ }
+ case "selkey":
+ var zb0023 int
+ zb0023, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SelectionPK")
+ return
+ }
+ if zb0023 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0023), uint64(maxAddressBytes))
+ return
+ }
+ (*z).SelectionPK, bts, err = msgp.ReadBytesBytes(bts, (*z).SelectionPK)
+ if err != nil {
+ err = msgp.WrapError(err, "SelectionPK")
+ return
+ }
+ case "votefst":
+ var zb0024 int
+ var zb0025 bool
+ zb0024, zb0025, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteFirst")
+ return
+ }
+ if zb0024 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0024), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "VoteFirst")
+ return
+ }
+ if zb0025 {
+ (*z).VoteFirst = nil
+ } else if (*z).VoteFirst != nil && cap((*z).VoteFirst) >= zb0024 {
+ (*z).VoteFirst = ((*z).VoteFirst)[:zb0024]
+ } else {
+ (*z).VoteFirst = make([]basics.Round, zb0024)
+ }
+ for zb0001 := range (*z).VoteFirst {
+ bts, err = (*z).VoteFirst[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteFirst", zb0001)
+ return
+ }
+ }
+ case "votefstbm":
+ {
+ var zb0026 []byte
+ var zb0027 int
+ zb0027, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteFirst")
+ return
+ }
+ if zb0027 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0027), uint64(maxBitmaskSize))
+ return
+ }
+ zb0026, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskVoteFirst))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteFirst")
+ return
+ }
+ (*z).BitmaskVoteFirst = bitmask(zb0026)
+ }
+ case "votelst":
+ var zb0028 int
+ var zb0029 bool
+ zb0028, zb0029, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteLast")
+ return
+ }
+ if zb0028 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0028), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "VoteLast")
+ return
+ }
+ if zb0029 {
+ (*z).VoteLast = nil
+ } else if (*z).VoteLast != nil && cap((*z).VoteLast) >= zb0028 {
+ (*z).VoteLast = ((*z).VoteLast)[:zb0028]
+ } else {
+ (*z).VoteLast = make([]basics.Round, zb0028)
+ }
+ for zb0002 := range (*z).VoteLast {
+ bts, err = (*z).VoteLast[zb0002].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteLast", zb0002)
+ return
+ }
+ }
+ case "votelstbm":
+ {
+ var zb0030 []byte
+ var zb0031 int
+ zb0031, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteLast")
+ return
+ }
+ if zb0031 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0031), uint64(maxBitmaskSize))
+ return
+ }
+ zb0030, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskVoteLast))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteLast")
+ return
+ }
+ (*z).BitmaskVoteLast = bitmask(zb0030)
+ }
+ case "votekd":
+ var zb0032 int
+ var zb0033 bool
+ zb0032, zb0033, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteKeyDilution")
+ return
+ }
+ if zb0032 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0032), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "VoteKeyDilution")
+ return
+ }
+ if zb0033 {
+ (*z).VoteKeyDilution = nil
+ } else if (*z).VoteKeyDilution != nil && cap((*z).VoteKeyDilution) >= zb0032 {
+ (*z).VoteKeyDilution = ((*z).VoteKeyDilution)[:zb0032]
+ } else {
+ (*z).VoteKeyDilution = make([]uint64, zb0032)
+ }
+ for zb0003 := range (*z).VoteKeyDilution {
+ (*z).VoteKeyDilution[zb0003], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteKeyDilution", zb0003)
+ return
+ }
+ }
+ case "votekbm":
+ {
+ var zb0034 []byte
+ var zb0035 int
+ zb0035, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskKeys")
+ return
+ }
+ if zb0035 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0035), uint64(maxBitmaskSize))
+ return
+ }
+ zb0034, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskKeys))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskKeys")
+ return
+ }
+ (*z).BitmaskKeys = bitmask(zb0034)
+ }
+ case "nonpartbm":
+ {
+ var zb0036 []byte
+ var zb0037 int
+ zb0037, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNonparticipation")
+ return
+ }
+ if zb0037 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0037), uint64(maxBitmaskSize))
+ return
+ }
+ zb0036, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskNonparticipation))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNonparticipation")
+ return
+ }
+ (*z).BitmaskNonparticipation = bitmask(zb0036)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedKeyregTxnFields) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedKeyregTxnFields)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedKeyregTxnFields) Msgsize() (s int) {
+ s = 1 + 8 + msgp.BytesPrefixSize + len((*z).VotePK) + 7 + msgp.BytesPrefixSize + len((*z).SelectionPK) + 8 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).VoteFirst {
+ s += (*z).VoteFirst[zb0001].Msgsize()
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskVoteFirst)) + 8 + msgp.ArrayHeaderSize
+ for zb0002 := range (*z).VoteLast {
+ s += (*z).VoteLast[zb0002].Msgsize()
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskVoteLast)) + 7 + msgp.ArrayHeaderSize + (len((*z).VoteKeyDilution) * (msgp.Uint64Size)) + 8 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskKeys)) + 10 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskNonparticipation))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedKeyregTxnFields) MsgIsZero() bool {
+ return (len((*z).VotePK) == 0) && (len((*z).SelectionPK) == 0) && (len((*z).VoteFirst) == 0) && (len((*z).BitmaskVoteFirst) == 0) && (len((*z).VoteLast) == 0) && (len((*z).BitmaskVoteLast) == 0) && (len((*z).VoteKeyDilution) == 0) && (len((*z).BitmaskKeys) == 0) && (len((*z).BitmaskNonparticipation) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedLsigs) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0004Len := uint32(4)
+ var zb0004Mask uint8 /* 5 bits */
+ if len((*z).LogicArgs) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x2
+ }
+ if len((*z).BitmaskLogicArgs) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x4
+ }
+ if len((*z).Logic) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x8
+ }
+ if len((*z).BitmaskLogic) == 0 {
+ zb0004Len--
+ zb0004Mask |= 0x10
+ }
+ // variable map header, size zb0004Len
+ o = append(o, 0x80|uint8(zb0004Len))
+ if zb0004Len != 0 {
+ if (zb0004Mask & 0x2) == 0 { // if not empty
+ // string "lsigarg"
+ o = append(o, 0xa7, 0x6c, 0x73, 0x69, 0x67, 0x61, 0x72, 0x67)
+ if (*z).LogicArgs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).LogicArgs)))
+ }
+ for zb0002 := range (*z).LogicArgs {
+ if (*z).LogicArgs[zb0002] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).LogicArgs[zb0002])))
+ }
+ for zb0003 := range (*z).LogicArgs[zb0002] {
+ o = msgp.AppendBytes(o, (*z).LogicArgs[zb0002][zb0003])
+ }
+ }
+ }
+ if (zb0004Mask & 0x4) == 0 { // if not empty
+ // string "lsigargbm"
+ o = append(o, 0xa9, 0x6c, 0x73, 0x69, 0x67, 0x61, 0x72, 0x67, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskLogicArgs))
+ }
+ if (zb0004Mask & 0x8) == 0 { // if not empty
+ // string "lsigl"
+ o = append(o, 0xa5, 0x6c, 0x73, 0x69, 0x67, 0x6c)
+ if (*z).Logic == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).Logic)))
+ }
+ for zb0001 := range (*z).Logic {
+ o = msgp.AppendBytes(o, (*z).Logic[zb0001])
+ }
+ }
+ if (zb0004Mask & 0x10) == 0 { // if not empty
+ // string "lsiglbm"
+ o = append(o, 0xa7, 0x6c, 0x73, 0x69, 0x67, 0x6c, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskLogic))
+ }
+ }
+ return
+}
+
+func (_ *encodedLsigs) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedLsigs)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedLsigs) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0004 int
+ var zb0005 bool
+ zb0004, zb0005, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0004, zb0005, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0004 > 0 {
+ zb0004--
+ var zb0006 int
+ var zb0007 bool
+ zb0006, zb0007, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Logic")
+ return
+ }
+ if zb0006 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0006), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Logic")
+ return
+ }
+ if zb0007 {
+ (*z).Logic = nil
+ } else if (*z).Logic != nil && cap((*z).Logic) >= zb0006 {
+ (*z).Logic = ((*z).Logic)[:zb0006]
+ } else {
+ (*z).Logic = make([][]byte, zb0006)
+ }
+ for zb0001 := range (*z).Logic {
+ var zb0008 int
+ zb0008, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Logic", zb0001)
+ return
+ }
+ if zb0008 > config.MaxLogicSigMaxSize {
+ err = msgp.ErrOverflow(uint64(zb0008), uint64(config.MaxLogicSigMaxSize))
+ return
+ }
+ (*z).Logic[zb0001], bts, err = msgp.ReadBytesBytes(bts, (*z).Logic[zb0001])
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Logic", zb0001)
+ return
+ }
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
+ {
+ var zb0009 []byte
+ var zb0010 int
+ zb0010, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLogic")
+ return
+ }
+ if zb0010 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0010), uint64(maxBitmaskSize))
+ return
+ }
+ zb0009, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskLogic))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLogic")
+ return
+ }
+ (*z).BitmaskLogic = bitmask(zb0009)
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
+ var zb0011 int
+ var zb0012 bool
+ zb0011, zb0012, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs")
+ return
+ }
+ if zb0011 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0011), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs")
+ return
+ }
+ if zb0012 {
+ (*z).LogicArgs = nil
+ } else if (*z).LogicArgs != nil && cap((*z).LogicArgs) >= zb0011 {
+ (*z).LogicArgs = ((*z).LogicArgs)[:zb0011]
+ } else {
+ (*z).LogicArgs = make([][][]byte, zb0011)
+ }
+ for zb0002 := range (*z).LogicArgs {
+ var zb0013 int
+ var zb0014 bool
+ zb0013, zb0014, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs", zb0002)
+ return
+ }
+ if zb0013 > transactions.EvalMaxArgs {
+ err = msgp.ErrOverflow(uint64(zb0013), uint64(transactions.EvalMaxArgs))
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs", zb0002)
+ return
+ }
+ if zb0014 {
+ (*z).LogicArgs[zb0002] = nil
+ } else if (*z).LogicArgs[zb0002] != nil && cap((*z).LogicArgs[zb0002]) >= zb0013 {
+ (*z).LogicArgs[zb0002] = ((*z).LogicArgs[zb0002])[:zb0013]
+ } else {
+ (*z).LogicArgs[zb0002] = make([][]byte, zb0013)
+ }
+ for zb0003 := range (*z).LogicArgs[zb0002] {
+ var zb0015 int
+ zb0015, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs", zb0002, zb0003)
+ return
+ }
+ if zb0015 > config.MaxLogicSigMaxSize {
+ err = msgp.ErrOverflow(uint64(zb0015), uint64(config.MaxLogicSigMaxSize))
+ return
+ }
+ (*z).LogicArgs[zb0002][zb0003], bts, err = msgp.ReadBytesBytes(bts, (*z).LogicArgs[zb0002][zb0003])
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs", zb0002, zb0003)
+ return
+ }
+ }
+ }
+ }
+ if zb0004 > 0 {
+ zb0004--
+ {
+ var zb0016 []byte
+ var zb0017 int
+ zb0017, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLogicArgs")
+ return
+ }
+ if zb0017 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0017), uint64(maxBitmaskSize))
+ return
+ }
+ zb0016, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskLogicArgs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLogicArgs")
+ return
+ }
+ (*z).BitmaskLogicArgs = bitmask(zb0016)
+ }
+ }
+ if zb0004 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0004)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0005 {
+ (*z) = encodedLsigs{}
+ }
+ for zb0004 > 0 {
+ zb0004--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "lsigl":
+ var zb0018 int
+ var zb0019 bool
+ zb0018, zb0019, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Logic")
+ return
+ }
+ if zb0018 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0018), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Logic")
+ return
+ }
+ if zb0019 {
+ (*z).Logic = nil
+ } else if (*z).Logic != nil && cap((*z).Logic) >= zb0018 {
+ (*z).Logic = ((*z).Logic)[:zb0018]
+ } else {
+ (*z).Logic = make([][]byte, zb0018)
+ }
+ for zb0001 := range (*z).Logic {
+ var zb0020 int
+ zb0020, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Logic", zb0001)
+ return
+ }
+ if zb0020 > config.MaxLogicSigMaxSize {
+ err = msgp.ErrOverflow(uint64(zb0020), uint64(config.MaxLogicSigMaxSize))
+ return
+ }
+ (*z).Logic[zb0001], bts, err = msgp.ReadBytesBytes(bts, (*z).Logic[zb0001])
+ if err != nil {
+ err = msgp.WrapError(err, "Logic", zb0001)
+ return
+ }
+ }
+ case "lsiglbm":
+ {
+ var zb0021 []byte
+ var zb0022 int
+ zb0022, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLogic")
+ return
+ }
+ if zb0022 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0022), uint64(maxBitmaskSize))
+ return
+ }
+ zb0021, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskLogic))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLogic")
+ return
+ }
+ (*z).BitmaskLogic = bitmask(zb0021)
+ }
+ case "lsigarg":
+ var zb0023 int
+ var zb0024 bool
+ zb0023, zb0024, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LogicArgs")
+ return
+ }
+ if zb0023 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0023), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LogicArgs")
+ return
+ }
+ if zb0024 {
+ (*z).LogicArgs = nil
+ } else if (*z).LogicArgs != nil && cap((*z).LogicArgs) >= zb0023 {
+ (*z).LogicArgs = ((*z).LogicArgs)[:zb0023]
+ } else {
+ (*z).LogicArgs = make([][][]byte, zb0023)
+ }
+ for zb0002 := range (*z).LogicArgs {
+ var zb0025 int
+ var zb0026 bool
+ zb0025, zb0026, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LogicArgs", zb0002)
+ return
+ }
+ if zb0025 > transactions.EvalMaxArgs {
+ err = msgp.ErrOverflow(uint64(zb0025), uint64(transactions.EvalMaxArgs))
+ err = msgp.WrapError(err, "LogicArgs", zb0002)
+ return
+ }
+ if zb0026 {
+ (*z).LogicArgs[zb0002] = nil
+ } else if (*z).LogicArgs[zb0002] != nil && cap((*z).LogicArgs[zb0002]) >= zb0025 {
+ (*z).LogicArgs[zb0002] = ((*z).LogicArgs[zb0002])[:zb0025]
+ } else {
+ (*z).LogicArgs[zb0002] = make([][]byte, zb0025)
+ }
+ for zb0003 := range (*z).LogicArgs[zb0002] {
+ var zb0027 int
+ zb0027, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LogicArgs", zb0002, zb0003)
+ return
+ }
+ if zb0027 > config.MaxLogicSigMaxSize {
+ err = msgp.ErrOverflow(uint64(zb0027), uint64(config.MaxLogicSigMaxSize))
+ return
+ }
+ (*z).LogicArgs[zb0002][zb0003], bts, err = msgp.ReadBytesBytes(bts, (*z).LogicArgs[zb0002][zb0003])
+ if err != nil {
+ err = msgp.WrapError(err, "LogicArgs", zb0002, zb0003)
+ return
+ }
+ }
+ }
+ case "lsigargbm":
+ {
+ var zb0028 []byte
+ var zb0029 int
+ zb0029, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLogicArgs")
+ return
+ }
+ if zb0029 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0029), uint64(maxBitmaskSize))
+ return
+ }
+ zb0028, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskLogicArgs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLogicArgs")
+ return
+ }
+ (*z).BitmaskLogicArgs = bitmask(zb0028)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedLsigs) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedLsigs)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedLsigs) Msgsize() (s int) {
+ s = 1 + 6 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).Logic {
+ s += msgp.BytesPrefixSize + len((*z).Logic[zb0001])
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskLogic)) + 8 + msgp.ArrayHeaderSize
+ for zb0002 := range (*z).LogicArgs {
+ s += msgp.ArrayHeaderSize
+ for zb0003 := range (*z).LogicArgs[zb0002] {
+ s += msgp.BytesPrefixSize + len((*z).LogicArgs[zb0002][zb0003])
+ }
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskLogicArgs))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedLsigs) MsgIsZero() bool {
+ return (len((*z).Logic) == 0) && (len((*z).BitmaskLogic) == 0) && (len((*z).LogicArgs) == 0) && (len((*z).BitmaskLogicArgs) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedMsigs) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0003Len := uint32(6)
+ var zb0003Mask uint8 /* 7 bits */
+ if len((*z).Threshold) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x2
+ }
+ if len((*z).BitmaskThreshold) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x4
+ }
+ if len((*z).Version) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x8
+ }
+ if len((*z).BitmaskVersion) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x10
+ }
+ if len((*z).Subsigs) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x20
+ }
+ if len((*z).BitmaskSubsigs) == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x40
+ }
+ // variable map header, size zb0003Len
+ o = append(o, 0x80|uint8(zb0003Len))
+ if zb0003Len != 0 {
+ if (zb0003Mask & 0x2) == 0 { // if not empty
+ // string "msigthr"
+ o = append(o, 0xa7, 0x6d, 0x73, 0x69, 0x67, 0x74, 0x68, 0x72)
+ o = msgp.AppendBytes(o, (*z).Threshold)
+ }
+ if (zb0003Mask & 0x4) == 0 { // if not empty
+ // string "msigthrbm"
+ o = append(o, 0xa9, 0x6d, 0x73, 0x69, 0x67, 0x74, 0x68, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskThreshold))
+ }
+ if (zb0003Mask & 0x8) == 0 { // if not empty
+ // string "msigv"
+ o = append(o, 0xa5, 0x6d, 0x73, 0x69, 0x67, 0x76)
+ o = msgp.AppendBytes(o, (*z).Version)
+ }
+ if (zb0003Mask & 0x10) == 0 { // if not empty
+ // string "msigvbm"
+ o = append(o, 0xa7, 0x6d, 0x73, 0x69, 0x67, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskVersion))
+ }
+ if (zb0003Mask & 0x20) == 0 { // if not empty
+ // string "subsig"
+ o = append(o, 0xa6, 0x73, 0x75, 0x62, 0x73, 0x69, 0x67)
+ if (*z).Subsigs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).Subsigs)))
+ }
+ for zb0001 := range (*z).Subsigs {
+ if (*z).Subsigs[zb0001] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).Subsigs[zb0001])))
+ }
+ for zb0002 := range (*z).Subsigs[zb0001] {
+ o = (*z).Subsigs[zb0001][zb0002].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0003Mask & 0x40) == 0 { // if not empty
+ // string "subsigsbm"
+ o = append(o, 0xa9, 0x73, 0x75, 0x62, 0x73, 0x69, 0x67, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskSubsigs))
+ }
+ }
+ return
+}
+
+func (_ *encodedMsigs) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedMsigs)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedMsigs) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0003 int
+ var zb0004 bool
+ zb0003, zb0004, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0003, zb0004, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0003 > 0 {
+ zb0003--
+ var zb0005 int
+ zb0005, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Version")
+ return
+ }
+ if zb0005 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0005), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).Version, bts, err = msgp.ReadBytesBytes(bts, (*z).Version)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Version")
+ return
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ {
+ var zb0006 []byte
+ var zb0007 int
+ zb0007, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVersion")
+ return
+ }
+ if zb0007 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0007), uint64(maxBitmaskSize))
+ return
+ }
+ zb0006, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskVersion))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVersion")
+ return
+ }
+ (*z).BitmaskVersion = bitmask(zb0006)
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ var zb0008 int
+ zb0008, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Threshold")
+ return
+ }
+ if zb0008 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0008), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).Threshold, bts, err = msgp.ReadBytesBytes(bts, (*z).Threshold)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Threshold")
+ return
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ {
+ var zb0009 []byte
+ var zb0010 int
+ zb0010, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskThreshold")
+ return
+ }
+ if zb0010 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0010), uint64(maxBitmaskSize))
+ return
+ }
+ zb0009, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskThreshold))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskThreshold")
+ return
+ }
+ (*z).BitmaskThreshold = bitmask(zb0009)
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ var zb0011 int
+ var zb0012 bool
+ zb0011, zb0012, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs")
+ return
+ }
+ if zb0011 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0011), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs")
+ return
+ }
+ if zb0012 {
+ (*z).Subsigs = nil
+ } else if (*z).Subsigs != nil && cap((*z).Subsigs) >= zb0011 {
+ (*z).Subsigs = ((*z).Subsigs)[:zb0011]
+ } else {
+ (*z).Subsigs = make([][]crypto.MultisigSubsig, zb0011)
+ }
+ for zb0001 := range (*z).Subsigs {
+ var zb0013 int
+ var zb0014 bool
+ zb0013, zb0014, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs", zb0001)
+ return
+ }
+ if zb0013 > crypto.MaxMultisig {
+ err = msgp.ErrOverflow(uint64(zb0013), uint64(crypto.MaxMultisig))
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs", zb0001)
+ return
+ }
+ if zb0014 {
+ (*z).Subsigs[zb0001] = nil
+ } else if (*z).Subsigs[zb0001] != nil && cap((*z).Subsigs[zb0001]) >= zb0013 {
+ (*z).Subsigs[zb0001] = ((*z).Subsigs[zb0001])[:zb0013]
+ } else {
+ (*z).Subsigs[zb0001] = make([]crypto.MultisigSubsig, zb0013)
+ }
+ for zb0002 := range (*z).Subsigs[zb0001] {
+ bts, err = (*z).Subsigs[zb0001][zb0002].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs", zb0001, zb0002)
+ return
+ }
+ }
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ {
+ var zb0015 []byte
+ var zb0016 int
+ zb0016, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSubsigs")
+ return
+ }
+ if zb0016 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0016), uint64(maxBitmaskSize))
+ return
+ }
+ zb0015, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskSubsigs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSubsigs")
+ return
+ }
+ (*z).BitmaskSubsigs = bitmask(zb0015)
+ }
+ }
+ if zb0003 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0003)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0004 {
+ (*z) = encodedMsigs{}
+ }
+ for zb0003 > 0 {
+ zb0003--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "msigv":
+ var zb0017 int
+ zb0017, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Version")
+ return
+ }
+ if zb0017 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0017), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).Version, bts, err = msgp.ReadBytesBytes(bts, (*z).Version)
+ if err != nil {
+ err = msgp.WrapError(err, "Version")
+ return
+ }
+ case "msigvbm":
+ {
+ var zb0018 []byte
+ var zb0019 int
+ zb0019, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVersion")
+ return
+ }
+ if zb0019 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0019), uint64(maxBitmaskSize))
+ return
+ }
+ zb0018, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskVersion))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVersion")
+ return
+ }
+ (*z).BitmaskVersion = bitmask(zb0018)
+ }
+ case "msigthr":
+ var zb0020 int
+ zb0020, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Threshold")
+ return
+ }
+ if zb0020 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0020), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).Threshold, bts, err = msgp.ReadBytesBytes(bts, (*z).Threshold)
+ if err != nil {
+ err = msgp.WrapError(err, "Threshold")
+ return
+ }
+ case "msigthrbm":
+ {
+ var zb0021 []byte
+ var zb0022 int
+ zb0022, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskThreshold")
+ return
+ }
+ if zb0022 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0022), uint64(maxBitmaskSize))
+ return
+ }
+ zb0021, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskThreshold))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskThreshold")
+ return
+ }
+ (*z).BitmaskThreshold = bitmask(zb0021)
+ }
+ case "subsig":
+ var zb0023 int
+ var zb0024 bool
+ zb0023, zb0024, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Subsigs")
+ return
+ }
+ if zb0023 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0023), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Subsigs")
+ return
+ }
+ if zb0024 {
+ (*z).Subsigs = nil
+ } else if (*z).Subsigs != nil && cap((*z).Subsigs) >= zb0023 {
+ (*z).Subsigs = ((*z).Subsigs)[:zb0023]
+ } else {
+ (*z).Subsigs = make([][]crypto.MultisigSubsig, zb0023)
+ }
+ for zb0001 := range (*z).Subsigs {
+ var zb0025 int
+ var zb0026 bool
+ zb0025, zb0026, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Subsigs", zb0001)
+ return
+ }
+ if zb0025 > crypto.MaxMultisig {
+ err = msgp.ErrOverflow(uint64(zb0025), uint64(crypto.MaxMultisig))
+ err = msgp.WrapError(err, "Subsigs", zb0001)
+ return
+ }
+ if zb0026 {
+ (*z).Subsigs[zb0001] = nil
+ } else if (*z).Subsigs[zb0001] != nil && cap((*z).Subsigs[zb0001]) >= zb0025 {
+ (*z).Subsigs[zb0001] = ((*z).Subsigs[zb0001])[:zb0025]
+ } else {
+ (*z).Subsigs[zb0001] = make([]crypto.MultisigSubsig, zb0025)
+ }
+ for zb0002 := range (*z).Subsigs[zb0001] {
+ bts, err = (*z).Subsigs[zb0001][zb0002].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Subsigs", zb0001, zb0002)
+ return
+ }
+ }
+ }
+ case "subsigsbm":
+ {
+ var zb0027 []byte
+ var zb0028 int
+ zb0028, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSubsigs")
+ return
+ }
+ if zb0028 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0028), uint64(maxBitmaskSize))
+ return
+ }
+ zb0027, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskSubsigs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSubsigs")
+ return
+ }
+ (*z).BitmaskSubsigs = bitmask(zb0027)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedMsigs) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedMsigs)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedMsigs) Msgsize() (s int) {
+ s = 1 + 6 + msgp.BytesPrefixSize + len((*z).Version) + 8 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskVersion)) + 8 + msgp.BytesPrefixSize + len((*z).Threshold) + 10 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskThreshold)) + 7 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).Subsigs {
+ s += msgp.ArrayHeaderSize
+ for zb0002 := range (*z).Subsigs[zb0001] {
+ s += (*z).Subsigs[zb0001][zb0002].Msgsize()
+ }
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskSubsigs))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedMsigs) MsgIsZero() bool {
+ return (len((*z).Version) == 0) && (len((*z).BitmaskVersion) == 0) && (len((*z).Threshold) == 0) && (len((*z).BitmaskThreshold) == 0) && (len((*z).Subsigs) == 0) && (len((*z).BitmaskSubsigs) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedPaymentTxnFields) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0002Len := uint32(6)
+ var zb0002Mask uint8 /* 7 bits */
+ if len((*z).Amount) == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x2
+ }
+ if len((*z).BitmaskAmount) == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x4
+ }
+ if len((*z).CloseRemainderTo) == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x8
+ }
+ if len((*z).BitmaskCloseRemainderTo) == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x10
+ }
+ if len((*z).Receiver) == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x20
+ }
+ if len((*z).BitmaskReceiver) == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x40
+ }
+ // variable map header, size zb0002Len
+ o = append(o, 0x80|uint8(zb0002Len))
+ if zb0002Len != 0 {
+ if (zb0002Mask & 0x2) == 0 { // if not empty
+ // string "amt"
+ o = append(o, 0xa3, 0x61, 0x6d, 0x74)
+ if (*z).Amount == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).Amount)))
+ }
+ for zb0001 := range (*z).Amount {
+ o = (*z).Amount[zb0001].MarshalMsg(o)
+ }
+ }
+ if (zb0002Mask & 0x4) == 0 { // if not empty
+ // string "amtbm"
+ o = append(o, 0xa5, 0x61, 0x6d, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskAmount))
+ }
+ if (zb0002Mask & 0x8) == 0 { // if not empty
+ // string "close"
+ o = append(o, 0xa5, 0x63, 0x6c, 0x6f, 0x73, 0x65)
+ o = msgp.AppendBytes(o, (*z).CloseRemainderTo)
+ }
+ if (zb0002Mask & 0x10) == 0 { // if not empty
+ // string "closebm"
+ o = append(o, 0xa7, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskCloseRemainderTo))
+ }
+ if (zb0002Mask & 0x20) == 0 { // if not empty
+ // string "rcv"
+ o = append(o, 0xa3, 0x72, 0x63, 0x76)
+ o = msgp.AppendBytes(o, (*z).Receiver)
+ }
+ if (zb0002Mask & 0x40) == 0 { // if not empty
+ // string "rcvbm"
+ o = append(o, 0xa5, 0x72, 0x63, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskReceiver))
+ }
+ }
+ return
+}
+
+func (_ *encodedPaymentTxnFields) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedPaymentTxnFields)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedPaymentTxnFields) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0002 int
+ var zb0003 bool
+ zb0002, zb0003, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0002, zb0003, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 > 0 {
+ zb0002--
+ var zb0004 int
+ zb0004, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Receiver")
+ return
+ }
+ if zb0004 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0004), uint64(maxAddressBytes))
+ return
+ }
+ (*z).Receiver, bts, err = msgp.ReadBytesBytes(bts, (*z).Receiver)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Receiver")
+ return
+ }
+ }
+ if zb0002 > 0 {
+ zb0002--
+ {
+ var zb0005 []byte
+ var zb0006 int
+ zb0006, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReceiver")
+ return
+ }
+ if zb0006 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0006), uint64(maxBitmaskSize))
+ return
+ }
+ zb0005, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReceiver")
+ return
+ }
+ (*z).BitmaskReceiver = bitmask(zb0005)
+ }
+ }
+ if zb0002 > 0 {
+ zb0002--
+ var zb0007 int
+ var zb0008 bool
+ zb0007, zb0008, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Amount")
+ return
+ }
+ if zb0007 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0007), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Amount")
+ return
+ }
+ if zb0008 {
+ (*z).Amount = nil
+ } else if (*z).Amount != nil && cap((*z).Amount) >= zb0007 {
+ (*z).Amount = ((*z).Amount)[:zb0007]
+ } else {
+ (*z).Amount = make([]basics.MicroAlgos, zb0007)
+ }
+ for zb0001 := range (*z).Amount {
+ bts, err = (*z).Amount[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Amount", zb0001)
+ return
+ }
+ }
+ }
+ if zb0002 > 0 {
+ zb0002--
+ {
+ var zb0009 []byte
+ var zb0010 int
+ zb0010, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAmount")
+ return
+ }
+ if zb0010 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0010), uint64(maxBitmaskSize))
+ return
+ }
+ zb0009, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAmount")
+ return
+ }
+ (*z).BitmaskAmount = bitmask(zb0009)
+ }
+ }
+ if zb0002 > 0 {
+ zb0002--
+ var zb0011 int
+ zb0011, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CloseRemainderTo")
+ return
+ }
+ if zb0011 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0011), uint64(maxAddressBytes))
+ return
+ }
+ (*z).CloseRemainderTo, bts, err = msgp.ReadBytesBytes(bts, (*z).CloseRemainderTo)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CloseRemainderTo")
+ return
+ }
+ }
+ if zb0002 > 0 {
+ zb0002--
+ {
+ var zb0012 []byte
+ var zb0013 int
+ zb0013, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCloseRemainderTo")
+ return
+ }
+ if zb0013 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0013), uint64(maxBitmaskSize))
+ return
+ }
+ zb0012, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskCloseRemainderTo))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCloseRemainderTo")
+ return
+ }
+ (*z).BitmaskCloseRemainderTo = bitmask(zb0012)
+ }
+ }
+ if zb0002 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0002)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0003 {
+ (*z) = encodedPaymentTxnFields{}
+ }
+ for zb0002 > 0 {
+ zb0002--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "rcv":
+ var zb0014 int
+ zb0014, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Receiver")
+ return
+ }
+ if zb0014 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0014), uint64(maxAddressBytes))
+ return
+ }
+ (*z).Receiver, bts, err = msgp.ReadBytesBytes(bts, (*z).Receiver)
+ if err != nil {
+ err = msgp.WrapError(err, "Receiver")
+ return
+ }
+ case "rcvbm":
+ {
+ var zb0015 []byte
+ var zb0016 int
+ zb0016, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReceiver")
+ return
+ }
+ if zb0016 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0016), uint64(maxBitmaskSize))
+ return
+ }
+ zb0015, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReceiver")
+ return
+ }
+ (*z).BitmaskReceiver = bitmask(zb0015)
+ }
+ case "amt":
+ var zb0017 int
+ var zb0018 bool
+ zb0017, zb0018, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Amount")
+ return
+ }
+ if zb0017 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0017), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Amount")
+ return
+ }
+ if zb0018 {
+ (*z).Amount = nil
+ } else if (*z).Amount != nil && cap((*z).Amount) >= zb0017 {
+ (*z).Amount = ((*z).Amount)[:zb0017]
+ } else {
+ (*z).Amount = make([]basics.MicroAlgos, zb0017)
+ }
+ for zb0001 := range (*z).Amount {
+ bts, err = (*z).Amount[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Amount", zb0001)
+ return
+ }
+ }
+ case "amtbm":
+ {
+ var zb0019 []byte
+ var zb0020 int
+ zb0020, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAmount")
+ return
+ }
+ if zb0020 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0020), uint64(maxBitmaskSize))
+ return
+ }
+ zb0019, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAmount")
+ return
+ }
+ (*z).BitmaskAmount = bitmask(zb0019)
+ }
+ case "close":
+ var zb0021 int
+ zb0021, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CloseRemainderTo")
+ return
+ }
+ if zb0021 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0021), uint64(maxAddressBytes))
+ return
+ }
+ (*z).CloseRemainderTo, bts, err = msgp.ReadBytesBytes(bts, (*z).CloseRemainderTo)
+ if err != nil {
+ err = msgp.WrapError(err, "CloseRemainderTo")
+ return
+ }
+ case "closebm":
+ {
+ var zb0022 []byte
+ var zb0023 int
+ zb0023, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCloseRemainderTo")
+ return
+ }
+ if zb0023 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0023), uint64(maxBitmaskSize))
+ return
+ }
+ zb0022, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskCloseRemainderTo))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCloseRemainderTo")
+ return
+ }
+ (*z).BitmaskCloseRemainderTo = bitmask(zb0022)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedPaymentTxnFields) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedPaymentTxnFields)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedPaymentTxnFields) Msgsize() (s int) {
+ s = 1 + 4 + msgp.BytesPrefixSize + len((*z).Receiver) + 6 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskReceiver)) + 4 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).Amount {
+ s += (*z).Amount[zb0001].Msgsize()
+ }
+ s += 6 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskAmount)) + 6 + msgp.BytesPrefixSize + len((*z).CloseRemainderTo) + 8 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskCloseRemainderTo))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedPaymentTxnFields) MsgIsZero() bool {
+ return (len((*z).Receiver) == 0) && (len((*z).BitmaskReceiver) == 0) && (len((*z).Amount) == 0) && (len((*z).BitmaskAmount) == 0) && (len((*z).CloseRemainderTo) == 0) && (len((*z).BitmaskCloseRemainderTo) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedSignedTxns) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0049Len := uint32(126)
+ var zb0049Mask [3]uint64 /* 140 bits */
+ if len((*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x4000
+ }
+ if len((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x8000
+ }
+ if len((*z).encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x10000
+ }
+ if len((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x20000
+ }
+ if len((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x40000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x80000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x100000
+ }
+ if len((*z).encodedTxns.encodedPaymentTxnFields.Amount) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x200000
+ }
+ if len((*z).encodedTxns.encodedPaymentTxnFields.BitmaskAmount) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x400000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x800000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x1000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x2000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x4000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.OnCompletion) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x8000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x10000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x20000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x40000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x80000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x100000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.Accounts) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x200000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x400000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x800000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x1000000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x2000000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x4000000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x8000000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x10000000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x20000000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x40000000000
+ }
+ if len((*z).encodedTxns.encodedAssetTransferTxnFields.AssetReceiver) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x80000000000
+ }
+ if len((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x100000000000
+ }
+ if len((*z).encodedTxns.encodedAssetTransferTxnFields.AssetSender) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x200000000000
+ }
+ if len((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x400000000000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x800000000000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x1000000000000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x2000000000000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x4000000000000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x8000000000000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x10000000000000
+ }
+ if len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x20000000000000
+ }
+ if len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x40000000000000
+ }
+ if len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x80000000000000
+ }
+ if len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x100000000000000
+ }
+ if len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x200000000000000
+ }
+ if len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x400000000000000
+ }
+ if len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x800000000000000
+ }
+ if len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x1000000000000000
+ }
+ if len((*z).encodedTxns.encodedCompactCertTxnFields.CertRound) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x2000000000000000
+ }
+ if len((*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x4000000000000000
+ }
+ if len((*z).encodedTxns.encodedCompactCertTxnFields.CertType) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x8000000000000000
+ }
+ if len((*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertType) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x1
+ }
+ if len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x2
+ }
+ if len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x4
+ }
+ if len((*z).encodedTxns.encodedPaymentTxnFields.CloseRemainderTo) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x8
+ }
+ if len((*z).encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x10
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x20
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x40
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x80
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x100
+ }
+ if len((*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x200
+ }
+ if len((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x400
+ }
+ if len((*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x800
+ }
+ if len((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x1000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x2000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.Fee) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x4000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.BitmaskFee) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x8000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.FirstValid) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x10000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.BitmaskFirstValid) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x20000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.BitmaskGenesisID) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x40000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x80000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x100000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x200000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x400000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.BitmaskGroup) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x800000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x1000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x2000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x4000000
+ }
+ if len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x8000000
+ }
+ if len((*z).encodedLsigs.LogicArgs) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x10000000
+ }
+ if len((*z).encodedLsigs.BitmaskLogicArgs) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x20000000
+ }
+ if len((*z).encodedLsigs.Logic) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x40000000
+ }
+ if len((*z).encodedLsigs.BitmaskLogic) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x80000000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.LastValid) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x100000000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.BitmaskLastValid) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x200000000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.Lease) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x400000000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.BitmaskLease) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x800000000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x1000000000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x2000000000
+ }
+ if len((*z).encodedMsigs.Threshold) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x4000000000
+ }
+ if len((*z).encodedMsigs.BitmaskThreshold) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x8000000000
+ }
+ if len((*z).encodedMsigs.Version) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x10000000000
+ }
+ if len((*z).encodedMsigs.BitmaskVersion) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x20000000000
+ }
+ if len((*z).encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x40000000000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.Note) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x80000000000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.BitmaskNote) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x100000000000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x200000000000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x400000000000
+ }
+ if len((*z).encodedTxns.encodedPaymentTxnFields.Receiver) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x800000000000
+ }
+ if len((*z).encodedTxns.encodedPaymentTxnFields.BitmaskReceiver) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x1000000000000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.RekeyTo) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x2000000000000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.BitmaskRekeyTo) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x4000000000000
+ }
+ if len((*z).encodedTxns.encodedKeyregTxnFields.SelectionPK) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x8000000000000
+ }
+ if len((*z).AuthAddr) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x10000000000000
+ }
+ if len((*z).BitmaskAuthAddr) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x20000000000000
+ }
+ if len((*z).Sig) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x40000000000000
+ }
+ if len((*z).BitmaskSig) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x80000000000000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.Sender) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x100000000000000
+ }
+ if len((*z).encodedTxns.encodedTxnHeaders.BitmaskSender) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x200000000000000
+ }
+ if len((*z).encodedMsigs.Subsigs) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x400000000000000
+ }
+ if len((*z).encodedMsigs.BitmaskSubsigs) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x800000000000000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x1000000000000000
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x2000000000000000
+ }
+ if len((*z).encodedTxns.TxType) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x4000000000000000
+ }
+ if len((*z).encodedTxns.BitmaskTxType) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x8000000000000000
+ }
+ if (*z).encodedTxns.TxTypeOffset == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x1
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x2
+ }
+ if len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x4
+ }
+ if len((*z).encodedTxns.encodedKeyregTxnFields.VoteFirst) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x8
+ }
+ if len((*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x10
+ }
+ if len((*z).encodedTxns.encodedKeyregTxnFields.BitmaskKeys) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x20
+ }
+ if len((*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x40
+ }
+ if len((*z).encodedTxns.encodedKeyregTxnFields.VotePK) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x80
+ }
+ if len((*z).encodedTxns.encodedKeyregTxnFields.VoteLast) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x100
+ }
+ if len((*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x200
+ }
+ if len((*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x400
+ }
+ if len((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x800
+ }
+ // variable map header, size zb0049Len
+ o = msgp.AppendMapHeader(o, zb0049Len)
+ if zb0049Len != 0 {
+ if (zb0049Mask[0] & 0x4000) == 0 { // if not empty
+ // string "aamt"
+ o = append(o, 0xa4, 0x61, 0x61, 0x6d, 0x74)
+ if (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount)))
+ }
+ for zb0021 := range (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount {
+ o = msgp.AppendUint64(o, (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount[zb0021])
+ }
+ }
+ if (zb0049Mask[0] & 0x8000) == 0 { // if not empty
+ // string "aamtbm"
+ o = append(o, 0xa6, 0x61, 0x61, 0x6d, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount))
+ }
+ if (zb0049Mask[0] & 0x10000) == 0 { // if not empty
+ // string "aclose"
+ o = append(o, 0xa6, 0x61, 0x63, 0x6c, 0x6f, 0x73, 0x65)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo)
+ }
+ if (zb0049Mask[0] & 0x20000) == 0 { // if not empty
+ // string "aclosebm"
+ o = append(o, 0xa8, 0x61, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo))
+ }
+ if (zb0049Mask[0] & 0x40000) == 0 { // if not empty
+ // string "afrzbm"
+ o = append(o, 0xa6, 0x61, 0x66, 0x72, 0x7a, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen))
+ }
+ if (zb0049Mask[0] & 0x80000) == 0 { // if not empty
+ // string "am"
+ o = append(o, 0xa2, 0x61, 0x6d)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash)
+ }
+ if (zb0049Mask[0] & 0x100000) == 0 { // if not empty
+ // string "ambm"
+ o = append(o, 0xa4, 0x61, 0x6d, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash))
+ }
+ if (zb0049Mask[0] & 0x200000) == 0 { // if not empty
+ // string "amt"
+ o = append(o, 0xa3, 0x61, 0x6d, 0x74)
+ if (*z).encodedTxns.encodedPaymentTxnFields.Amount == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedPaymentTxnFields.Amount)))
+ }
+ for zb0013 := range (*z).encodedTxns.encodedPaymentTxnFields.Amount {
+ o = (*z).encodedTxns.encodedPaymentTxnFields.Amount[zb0013].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[0] & 0x400000) == 0 { // if not empty
+ // string "amtbm"
+ o = append(o, 0xa5, 0x61, 0x6d, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedPaymentTxnFields.BitmaskAmount))
+ }
+ if (zb0049Mask[0] & 0x800000) == 0 { // if not empty
+ // string "an"
+ o = append(o, 0xa2, 0x61, 0x6e)
+ if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName)))
+ }
+ for zb0018 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName {
+ o = msgp.AppendString(o, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName[zb0018])
+ }
+ }
+ if (zb0049Mask[0] & 0x1000000) == 0 { // if not empty
+ // string "anbm"
+ o = append(o, 0xa4, 0x61, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName))
+ }
+ if (zb0049Mask[0] & 0x2000000) == 0 { // if not empty
+ // string "apaa"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x61)
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs)))
+ }
+ for zb0024 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs {
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024])))
+ }
+ for zb0025 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] {
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024][zb0025])
+ }
+ }
+ }
+ if (zb0049Mask[0] & 0x4000000) == 0 { // if not empty
+ // string "apaabm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x61, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs))
+ }
+ if (zb0049Mask[0] & 0x8000000) == 0 { // if not empty
+ // string "apan"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x6e)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedApplicationCallTxnFields.OnCompletion)
+ }
+ if (zb0049Mask[0] & 0x10000000) == 0 { // if not empty
+ // string "apanbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion))
+ }
+ if (zb0049Mask[0] & 0x20000000) == 0 { // if not empty
+ // string "apap"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x70)
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram)))
+ }
+ for zb0036 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram {
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram[zb0036]))
+ }
+ }
+ if (zb0049Mask[0] & 0x40000000) == 0 { // if not empty
+ // string "apapbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x70, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram))
+ }
+ if (zb0049Mask[0] & 0x80000000) == 0 { // if not empty
+ // string "apas"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x73)
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets)))
+ }
+ for zb0030 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets {
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030])))
+ }
+ for zb0031 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] {
+ o = (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030][zb0031].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0049Mask[0] & 0x100000000) == 0 { // if not empty
+ // string "apasbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets))
+ }
+ if (zb0049Mask[0] & 0x200000000) == 0 { // if not empty
+ // string "apat"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x74)
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.Accounts)))
+ }
+ for zb0026 := range (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts {
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026])))
+ }
+ for zb0027 := range (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] {
+ o = (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026][zb0027].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0049Mask[0] & 0x400000000) == 0 { // if not empty
+ // string "apatbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts))
+ }
+ if (zb0049Mask[0] & 0x800000000) == 0 { // if not empty
+ // string "apep"
+ o = append(o, 0xa4, 0x61, 0x70, 0x65, 0x70)
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages)))
+ }
+ for zb0038 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages {
+ o = msgp.AppendUint32(o, (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages[zb0038])
+ }
+ }
+ if (zb0049Mask[0] & 0x1000000000) == 0 { // if not empty
+ // string "apepbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x65, 0x70, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages))
+ }
+ if (zb0049Mask[0] & 0x2000000000) == 0 { // if not empty
+ // string "apfa"
+ o = append(o, 0xa4, 0x61, 0x70, 0x66, 0x61)
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps)))
+ }
+ for zb0028 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps {
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028])))
+ }
+ for zb0029 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] {
+ o = (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028][zb0029].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0049Mask[0] & 0x4000000000) == 0 { // if not empty
+ // string "apfabm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x66, 0x61, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps))
+ }
+ if (zb0049Mask[0] & 0x8000000000) == 0 { // if not empty
+ // string "apid"
+ o = append(o, 0xa4, 0x61, 0x70, 0x69, 0x64)
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID)))
+ }
+ for zb0023 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID {
+ o = (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID[zb0023].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[0] & 0x10000000000) == 0 { // if not empty
+ // string "apidbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID))
+ }
+ if (zb0049Mask[0] & 0x20000000000) == 0 { // if not empty
+ // string "apsu"
+ o = append(o, 0xa4, 0x61, 0x70, 0x73, 0x75)
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram)))
+ }
+ for zb0037 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram {
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram[zb0037]))
+ }
+ }
+ if (zb0049Mask[0] & 0x40000000000) == 0 { // if not empty
+ // string "apsubm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x73, 0x75, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram))
+ }
+ if (zb0049Mask[0] & 0x80000000000) == 0 { // if not empty
+ // string "arcv"
+ o = append(o, 0xa4, 0x61, 0x72, 0x63, 0x76)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedAssetTransferTxnFields.AssetReceiver)
+ }
+ if (zb0049Mask[0] & 0x100000000000) == 0 { // if not empty
+ // string "arcvbm"
+ o = append(o, 0xa6, 0x61, 0x72, 0x63, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver))
+ }
+ if (zb0049Mask[0] & 0x200000000000) == 0 { // if not empty
+ // string "asnd"
+ o = append(o, 0xa4, 0x61, 0x73, 0x6e, 0x64)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedAssetTransferTxnFields.AssetSender)
+ }
+ if (zb0049Mask[0] & 0x400000000000) == 0 { // if not empty
+ // string "asndbm"
+ o = append(o, 0xa6, 0x61, 0x73, 0x6e, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender))
+ }
+ if (zb0049Mask[0] & 0x800000000000) == 0 { // if not empty
+ // string "au"
+ o = append(o, 0xa2, 0x61, 0x75)
+ if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL)))
+ }
+ for zb0019 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL {
+ o = msgp.AppendString(o, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL[zb0019])
+ }
+ }
+ if (zb0049Mask[0] & 0x1000000000000) == 0 { // if not empty
+ // string "aubm"
+ o = append(o, 0xa4, 0x61, 0x75, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL))
+ }
+ if (zb0049Mask[0] & 0x2000000000000) == 0 { // if not empty
+ // string "c"
+ o = append(o, 0xa1, 0x63)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback)
+ }
+ if (zb0049Mask[0] & 0x4000000000000) == 0 { // if not empty
+ // string "caid"
+ o = append(o, 0xa4, 0x63, 0x61, 0x69, 0x64)
+ if (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset)))
+ }
+ for zb0014 := range (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset {
+ o = (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset[zb0014].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[0] & 0x8000000000000) == 0 { // if not empty
+ // string "caidbm"
+ o = append(o, 0xa6, 0x63, 0x61, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset))
+ }
+ if (zb0049Mask[0] & 0x10000000000000) == 0 { // if not empty
+ // string "cbm"
+ o = append(o, 0xa3, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback))
+ }
+ if (zb0049Mask[0] & 0x20000000000000) == 0 { // if not empty
+ // string "certP"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x50)
+ if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs)))
+ }
+ for zb0044 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs {
+ if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044])))
+ }
+ for zb0045 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] {
+ o = (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044][zb0045].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0049Mask[0] & 0x40000000000000) == 0 { // if not empty
+ // string "certPbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x50, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs))
+ }
+ if (zb0049Mask[0] & 0x80000000000000) == 0 { // if not empty
+ // string "certS"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x53)
+ if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs)))
+ }
+ for zb0042 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs {
+ if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042])))
+ }
+ for zb0043 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] {
+ o = (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042][zb0043].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0049Mask[0] & 0x100000000000000) == 0 { // if not empty
+ // string "certSbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x53, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs))
+ }
+ if (zb0049Mask[0] & 0x200000000000000) == 0 { // if not empty
+ // string "certc"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x63)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit)
+ }
+ if (zb0049Mask[0] & 0x400000000000000) == 0 { // if not empty
+ // string "certcbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit))
+ }
+ if (zb0049Mask[0] & 0x800000000000000) == 0 { // if not empty
+ // string "certr"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x72)
+ if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals)))
+ }
+ for zb0046 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals {
+ if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendMapHeader(o, uint32(len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046])))
+ }
+ zb0047_keys := make([]uint64, 0, len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046]))
+ for zb0047 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] {
+ zb0047_keys = append(zb0047_keys, zb0047)
+ }
+ sort.Sort(SortUint64(zb0047_keys))
+ for _, zb0047 := range zb0047_keys {
+ zb0048 := (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046][zb0047]
+ _ = zb0048
+ o = msgp.AppendUint64(o, zb0047)
+ o = zb0048.MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0049Mask[0] & 0x1000000000000000) == 0 { // if not empty
+ // string "certrbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals))
+ }
+ if (zb0049Mask[0] & 0x2000000000000000) == 0 { // if not empty
+ // string "certrnd"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x72, 0x6e, 0x64)
+ if (*z).encodedTxns.encodedCompactCertTxnFields.CertRound == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedCompactCertTxnFields.CertRound)))
+ }
+ for zb0039 := range (*z).encodedTxns.encodedCompactCertTxnFields.CertRound {
+ o = (*z).encodedTxns.encodedCompactCertTxnFields.CertRound[zb0039].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[0] & 0x4000000000000000) == 0 { // if not empty
+ // string "certrndbm"
+ o = append(o, 0xa9, 0x63, 0x65, 0x72, 0x74, 0x72, 0x6e, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound))
+ }
+ if (zb0049Mask[0] & 0x8000000000000000) == 0 { // if not empty
+ // string "certtype"
+ o = append(o, 0xa8, 0x63, 0x65, 0x72, 0x74, 0x74, 0x79, 0x70, 0x65)
+ if (*z).encodedTxns.encodedCompactCertTxnFields.CertType == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedCompactCertTxnFields.CertType)))
+ }
+ for zb0040 := range (*z).encodedTxns.encodedCompactCertTxnFields.CertType {
+ o = (*z).encodedTxns.encodedCompactCertTxnFields.CertType[zb0040].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[1] & 0x1) == 0 { // if not empty
+ // string "certtypebm"
+ o = append(o, 0xaa, 0x63, 0x65, 0x72, 0x74, 0x74, 0x79, 0x70, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertType))
+ }
+ if (zb0049Mask[1] & 0x2) == 0 { // if not empty
+ // string "certw"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x77)
+ if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight)))
+ }
+ for zb0041 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight {
+ o = msgp.AppendUint64(o, (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight[zb0041])
+ }
+ }
+ if (zb0049Mask[1] & 0x4) == 0 { // if not empty
+ // string "certwbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x77, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight))
+ }
+ if (zb0049Mask[1] & 0x8) == 0 { // if not empty
+ // string "close"
+ o = append(o, 0xa5, 0x63, 0x6c, 0x6f, 0x73, 0x65)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedPaymentTxnFields.CloseRemainderTo)
+ }
+ if (zb0049Mask[1] & 0x10) == 0 { // if not empty
+ // string "closebm"
+ o = append(o, 0xa7, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo))
+ }
+ if (zb0049Mask[1] & 0x20) == 0 { // if not empty
+ // string "dc"
+ o = append(o, 0xa2, 0x64, 0x63)
+ if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals)))
+ }
+ for zb0016 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals {
+ o = msgp.AppendUint32(o, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals[zb0016])
+ }
+ }
+ if (zb0049Mask[1] & 0x40) == 0 { // if not empty
+ // string "dcbm"
+ o = append(o, 0xa4, 0x64, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals))
+ }
+ if (zb0049Mask[1] & 0x80) == 0 { // if not empty
+ // string "dfbm"
+ o = append(o, 0xa4, 0x64, 0x66, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen))
+ }
+ if (zb0049Mask[1] & 0x100) == 0 { // if not empty
+ // string "f"
+ o = append(o, 0xa1, 0x66)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze)
+ }
+ if (zb0049Mask[1] & 0x200) == 0 { // if not empty
+ // string "fadd"
+ o = append(o, 0xa4, 0x66, 0x61, 0x64, 0x64)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount)
+ }
+ if (zb0049Mask[1] & 0x400) == 0 { // if not empty
+ // string "faddbm"
+ o = append(o, 0xa6, 0x66, 0x61, 0x64, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount))
+ }
+ if (zb0049Mask[1] & 0x800) == 0 { // if not empty
+ // string "faid"
+ o = append(o, 0xa4, 0x66, 0x61, 0x69, 0x64)
+ if (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset)))
+ }
+ for zb0022 := range (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset {
+ o = (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset[zb0022].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[1] & 0x1000) == 0 { // if not empty
+ // string "faidbm"
+ o = append(o, 0xa6, 0x66, 0x61, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset))
+ }
+ if (zb0049Mask[1] & 0x2000) == 0 { // if not empty
+ // string "fbm"
+ o = append(o, 0xa3, 0x66, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze))
+ }
+ if (zb0049Mask[1] & 0x4000) == 0 { // if not empty
+ // string "fee"
+ o = append(o, 0xa3, 0x66, 0x65, 0x65)
+ if (*z).encodedTxns.encodedTxnHeaders.Fee == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedTxnHeaders.Fee)))
+ }
+ for zb0006 := range (*z).encodedTxns.encodedTxnHeaders.Fee {
+ o = (*z).encodedTxns.encodedTxnHeaders.Fee[zb0006].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[1] & 0x8000) == 0 { // if not empty
+ // string "feebm"
+ o = append(o, 0xa5, 0x66, 0x65, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskFee))
+ }
+ if (zb0049Mask[1] & 0x10000) == 0 { // if not empty
+ // string "fv"
+ o = append(o, 0xa2, 0x66, 0x76)
+ if (*z).encodedTxns.encodedTxnHeaders.FirstValid == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedTxnHeaders.FirstValid)))
+ }
+ for zb0007 := range (*z).encodedTxns.encodedTxnHeaders.FirstValid {
+ o = (*z).encodedTxns.encodedTxnHeaders.FirstValid[zb0007].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[1] & 0x20000) == 0 { // if not empty
+ // string "fvbm"
+ o = append(o, 0xa4, 0x66, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskFirstValid))
+ }
+ if (zb0049Mask[1] & 0x40000) == 0 { // if not empty
+ // string "genbm"
+ o = append(o, 0xa5, 0x67, 0x65, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskGenesisID))
+ }
+ if (zb0049Mask[1] & 0x80000) == 0 { // if not empty
+ // string "gnbs"
+ o = append(o, 0xa4, 0x67, 0x6e, 0x62, 0x73)
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice)))
+ }
+ for zb0035 := range (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice {
+ o = msgp.AppendUint64(o, (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice[zb0035])
+ }
+ }
+ if (zb0049Mask[1] & 0x100000) == 0 { // if not empty
+ // string "gnbsbm"
+ o = append(o, 0xa6, 0x67, 0x6e, 0x62, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice))
+ }
+ if (zb0049Mask[1] & 0x200000) == 0 { // if not empty
+ // string "gnui"
+ o = append(o, 0xa4, 0x67, 0x6e, 0x75, 0x69)
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint)))
+ }
+ for zb0034 := range (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint {
+ o = msgp.AppendUint64(o, (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint[zb0034])
+ }
+ }
+ if (zb0049Mask[1] & 0x400000) == 0 { // if not empty
+ // string "gnuibm"
+ o = append(o, 0xa6, 0x67, 0x6e, 0x75, 0x69, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint))
+ }
+ if (zb0049Mask[1] & 0x800000) == 0 { // if not empty
+ // string "grpbm"
+ o = append(o, 0xa5, 0x67, 0x72, 0x70, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskGroup))
+ }
+ if (zb0049Mask[1] & 0x1000000) == 0 { // if not empty
+ // string "lnbs"
+ o = append(o, 0xa4, 0x6c, 0x6e, 0x62, 0x73)
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice)))
+ }
+ for zb0033 := range (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice {
+ o = msgp.AppendUint64(o, (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice[zb0033])
+ }
+ }
+ if (zb0049Mask[1] & 0x2000000) == 0 { // if not empty
+ // string "lnbsbm"
+ o = append(o, 0xa6, 0x6c, 0x6e, 0x62, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice))
+ }
+ if (zb0049Mask[1] & 0x4000000) == 0 { // if not empty
+ // string "lnui"
+ o = append(o, 0xa4, 0x6c, 0x6e, 0x75, 0x69)
+ if (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint)))
+ }
+ for zb0032 := range (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint {
+ o = msgp.AppendUint64(o, (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint[zb0032])
+ }
+ }
+ if (zb0049Mask[1] & 0x8000000) == 0 { // if not empty
+ // string "lnuibm"
+ o = append(o, 0xa6, 0x6c, 0x6e, 0x75, 0x69, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint))
+ }
+ if (zb0049Mask[1] & 0x10000000) == 0 { // if not empty
+ // string "lsigarg"
+ o = append(o, 0xa7, 0x6c, 0x73, 0x69, 0x67, 0x61, 0x72, 0x67)
+ if (*z).encodedLsigs.LogicArgs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedLsigs.LogicArgs)))
+ }
+ for zb0004 := range (*z).encodedLsigs.LogicArgs {
+ if (*z).encodedLsigs.LogicArgs[zb0004] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedLsigs.LogicArgs[zb0004])))
+ }
+ for zb0005 := range (*z).encodedLsigs.LogicArgs[zb0004] {
+ o = msgp.AppendBytes(o, (*z).encodedLsigs.LogicArgs[zb0004][zb0005])
+ }
+ }
+ }
+ if (zb0049Mask[1] & 0x20000000) == 0 { // if not empty
+ // string "lsigargbm"
+ o = append(o, 0xa9, 0x6c, 0x73, 0x69, 0x67, 0x61, 0x72, 0x67, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedLsigs.BitmaskLogicArgs))
+ }
+ if (zb0049Mask[1] & 0x40000000) == 0 { // if not empty
+ // string "lsigl"
+ o = append(o, 0xa5, 0x6c, 0x73, 0x69, 0x67, 0x6c)
+ if (*z).encodedLsigs.Logic == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedLsigs.Logic)))
+ }
+ for zb0003 := range (*z).encodedLsigs.Logic {
+ o = msgp.AppendBytes(o, (*z).encodedLsigs.Logic[zb0003])
+ }
+ }
+ if (zb0049Mask[1] & 0x80000000) == 0 { // if not empty
+ // string "lsiglbm"
+ o = append(o, 0xa7, 0x6c, 0x73, 0x69, 0x67, 0x6c, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedLsigs.BitmaskLogic))
+ }
+ if (zb0049Mask[1] & 0x100000000) == 0 { // if not empty
+ // string "lv"
+ o = append(o, 0xa2, 0x6c, 0x76)
+ if (*z).encodedTxns.encodedTxnHeaders.LastValid == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedTxnHeaders.LastValid)))
+ }
+ for zb0008 := range (*z).encodedTxns.encodedTxnHeaders.LastValid {
+ o = (*z).encodedTxns.encodedTxnHeaders.LastValid[zb0008].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[1] & 0x200000000) == 0 { // if not empty
+ // string "lvbm"
+ o = append(o, 0xa4, 0x6c, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskLastValid))
+ }
+ if (zb0049Mask[1] & 0x400000000) == 0 { // if not empty
+ // string "lx"
+ o = append(o, 0xa2, 0x6c, 0x78)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedTxnHeaders.Lease)
+ }
+ if (zb0049Mask[1] & 0x800000000) == 0 { // if not empty
+ // string "lxbm"
+ o = append(o, 0xa4, 0x6c, 0x78, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskLease))
+ }
+ if (zb0049Mask[1] & 0x1000000000) == 0 { // if not empty
+ // string "m"
+ o = append(o, 0xa1, 0x6d)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager)
+ }
+ if (zb0049Mask[1] & 0x2000000000) == 0 { // if not empty
+ // string "mbm"
+ o = append(o, 0xa3, 0x6d, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager))
+ }
+ if (zb0049Mask[1] & 0x4000000000) == 0 { // if not empty
+ // string "msigthr"
+ o = append(o, 0xa7, 0x6d, 0x73, 0x69, 0x67, 0x74, 0x68, 0x72)
+ o = msgp.AppendBytes(o, (*z).encodedMsigs.Threshold)
+ }
+ if (zb0049Mask[1] & 0x8000000000) == 0 { // if not empty
+ // string "msigthrbm"
+ o = append(o, 0xa9, 0x6d, 0x73, 0x69, 0x67, 0x74, 0x68, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedMsigs.BitmaskThreshold))
+ }
+ if (zb0049Mask[1] & 0x10000000000) == 0 { // if not empty
+ // string "msigv"
+ o = append(o, 0xa5, 0x6d, 0x73, 0x69, 0x67, 0x76)
+ o = msgp.AppendBytes(o, (*z).encodedMsigs.Version)
+ }
+ if (zb0049Mask[1] & 0x20000000000) == 0 { // if not empty
+ // string "msigvbm"
+ o = append(o, 0xa7, 0x6d, 0x73, 0x69, 0x67, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedMsigs.BitmaskVersion))
+ }
+ if (zb0049Mask[1] & 0x40000000000) == 0 { // if not empty
+ // string "nonpartbm"
+ o = append(o, 0xa9, 0x6e, 0x6f, 0x6e, 0x70, 0x61, 0x72, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation))
+ }
+ if (zb0049Mask[1] & 0x80000000000) == 0 { // if not empty
+ // string "note"
+ o = append(o, 0xa4, 0x6e, 0x6f, 0x74, 0x65)
+ if (*z).encodedTxns.encodedTxnHeaders.Note == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedTxnHeaders.Note)))
+ }
+ for zb0009 := range (*z).encodedTxns.encodedTxnHeaders.Note {
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedTxnHeaders.Note[zb0009])
+ }
+ }
+ if (zb0049Mask[1] & 0x100000000000) == 0 { // if not empty
+ // string "notebm"
+ o = append(o, 0xa6, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskNote))
+ }
+ if (zb0049Mask[1] & 0x200000000000) == 0 { // if not empty
+ // string "r"
+ o = append(o, 0xa1, 0x72)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve)
+ }
+ if (zb0049Mask[1] & 0x400000000000) == 0 { // if not empty
+ // string "rbm"
+ o = append(o, 0xa3, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve))
+ }
+ if (zb0049Mask[1] & 0x800000000000) == 0 { // if not empty
+ // string "rcv"
+ o = append(o, 0xa3, 0x72, 0x63, 0x76)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedPaymentTxnFields.Receiver)
+ }
+ if (zb0049Mask[1] & 0x1000000000000) == 0 { // if not empty
+ // string "rcvbm"
+ o = append(o, 0xa5, 0x72, 0x63, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedPaymentTxnFields.BitmaskReceiver))
+ }
+ if (zb0049Mask[1] & 0x2000000000000) == 0 { // if not empty
+ // string "rekey"
+ o = append(o, 0xa5, 0x72, 0x65, 0x6b, 0x65, 0x79)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedTxnHeaders.RekeyTo)
+ }
+ if (zb0049Mask[1] & 0x4000000000000) == 0 { // if not empty
+ // string "rekeybm"
+ o = append(o, 0xa7, 0x72, 0x65, 0x6b, 0x65, 0x79, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskRekeyTo))
+ }
+ if (zb0049Mask[1] & 0x8000000000000) == 0 { // if not empty
+ // string "selkey"
+ o = append(o, 0xa6, 0x73, 0x65, 0x6c, 0x6b, 0x65, 0x79)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedKeyregTxnFields.SelectionPK)
+ }
+ if (zb0049Mask[1] & 0x10000000000000) == 0 { // if not empty
+ // string "sgnr"
+ o = append(o, 0xa4, 0x73, 0x67, 0x6e, 0x72)
+ o = msgp.AppendBytes(o, (*z).AuthAddr)
+ }
+ if (zb0049Mask[1] & 0x20000000000000) == 0 { // if not empty
+ // string "sgnrbm"
+ o = append(o, 0xa6, 0x73, 0x67, 0x6e, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskAuthAddr))
+ }
+ if (zb0049Mask[1] & 0x40000000000000) == 0 { // if not empty
+ // string "sig"
+ o = append(o, 0xa3, 0x73, 0x69, 0x67)
+ o = msgp.AppendBytes(o, (*z).Sig)
+ }
+ if (zb0049Mask[1] & 0x80000000000000) == 0 { // if not empty
+ // string "sigbm"
+ o = append(o, 0xa5, 0x73, 0x69, 0x67, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskSig))
+ }
+ if (zb0049Mask[1] & 0x100000000000000) == 0 { // if not empty
+ // string "snd"
+ o = append(o, 0xa3, 0x73, 0x6e, 0x64)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedTxnHeaders.Sender)
+ }
+ if (zb0049Mask[1] & 0x200000000000000) == 0 { // if not empty
+ // string "sndbm"
+ o = append(o, 0xa5, 0x73, 0x6e, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskSender))
+ }
+ if (zb0049Mask[1] & 0x400000000000000) == 0 { // if not empty
+ // string "subsig"
+ o = append(o, 0xa6, 0x73, 0x75, 0x62, 0x73, 0x69, 0x67)
+ if (*z).encodedMsigs.Subsigs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedMsigs.Subsigs)))
+ }
+ for zb0001 := range (*z).encodedMsigs.Subsigs {
+ if (*z).encodedMsigs.Subsigs[zb0001] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedMsigs.Subsigs[zb0001])))
+ }
+ for zb0002 := range (*z).encodedMsigs.Subsigs[zb0001] {
+ o = (*z).encodedMsigs.Subsigs[zb0001][zb0002].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0049Mask[1] & 0x800000000000000) == 0 { // if not empty
+ // string "subsigsbm"
+ o = append(o, 0xa9, 0x73, 0x75, 0x62, 0x73, 0x69, 0x67, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedMsigs.BitmaskSubsigs))
+ }
+ if (zb0049Mask[1] & 0x1000000000000000) == 0 { // if not empty
+ // string "t"
+ o = append(o, 0xa1, 0x74)
+ if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total)))
+ }
+ for zb0015 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total {
+ o = msgp.AppendUint64(o, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total[zb0015])
+ }
+ }
+ if (zb0049Mask[1] & 0x2000000000000000) == 0 { // if not empty
+ // string "tbm"
+ o = append(o, 0xa3, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal))
+ }
+ if (zb0049Mask[1] & 0x4000000000000000) == 0 { // if not empty
+ // string "type"
+ o = append(o, 0xa4, 0x74, 0x79, 0x70, 0x65)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.TxType)
+ }
+ if (zb0049Mask[1] & 0x8000000000000000) == 0 { // if not empty
+ // string "typebm"
+ o = append(o, 0xa6, 0x74, 0x79, 0x70, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.BitmaskTxType))
+ }
+ if (zb0049Mask[2] & 0x1) == 0 { // if not empty
+ // string "typeo"
+ o = append(o, 0xa5, 0x74, 0x79, 0x70, 0x65, 0x6f)
+ o = msgp.AppendByte(o, (*z).encodedTxns.TxTypeOffset)
+ }
+ if (zb0049Mask[2] & 0x2) == 0 { // if not empty
+ // string "un"
+ o = append(o, 0xa2, 0x75, 0x6e)
+ if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName)))
+ }
+ for zb0017 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName {
+ o = msgp.AppendString(o, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName[zb0017])
+ }
+ }
+ if (zb0049Mask[2] & 0x4) == 0 { // if not empty
+ // string "unbm"
+ o = append(o, 0xa4, 0x75, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName))
+ }
+ if (zb0049Mask[2] & 0x8) == 0 { // if not empty
+ // string "votefst"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x66, 0x73, 0x74)
+ if (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedKeyregTxnFields.VoteFirst)))
+ }
+ for zb0010 := range (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst {
+ o = (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst[zb0010].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[2] & 0x10) == 0 { // if not empty
+ // string "votefstbm"
+ o = append(o, 0xa9, 0x76, 0x6f, 0x74, 0x65, 0x66, 0x73, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst))
+ }
+ if (zb0049Mask[2] & 0x20) == 0 { // if not empty
+ // string "votekbm"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x6b, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskKeys))
+ }
+ if (zb0049Mask[2] & 0x40) == 0 { // if not empty
+ // string "votekd"
+ o = append(o, 0xa6, 0x76, 0x6f, 0x74, 0x65, 0x6b, 0x64)
+ if (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution)))
+ }
+ for zb0012 := range (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution {
+ o = msgp.AppendUint64(o, (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution[zb0012])
+ }
+ }
+ if (zb0049Mask[2] & 0x80) == 0 { // if not empty
+ // string "votekey"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x6b, 0x65, 0x79)
+ o = msgp.AppendBytes(o, (*z).encodedTxns.encodedKeyregTxnFields.VotePK)
+ }
+ if (zb0049Mask[2] & 0x100) == 0 { // if not empty
+ // string "votelst"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x6c, 0x73, 0x74)
+ if (*z).encodedTxns.encodedKeyregTxnFields.VoteLast == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedKeyregTxnFields.VoteLast)))
+ }
+ for zb0011 := range (*z).encodedTxns.encodedKeyregTxnFields.VoteLast {
+ o = (*z).encodedTxns.encodedKeyregTxnFields.VoteLast[zb0011].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[2] & 0x200) == 0 { // if not empty
+ // string "votelstbm"
+ o = append(o, 0xa9, 0x76, 0x6f, 0x74, 0x65, 0x6c, 0x73, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast))
+ }
+ if (zb0049Mask[2] & 0x400) == 0 { // if not empty
+ // string "xaid"
+ o = append(o, 0xa4, 0x78, 0x61, 0x69, 0x64)
+ if (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset)))
+ }
+ for zb0020 := range (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset {
+ o = (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset[zb0020].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[2] & 0x800) == 0 { // if not empty
+ // string "xaidbm"
+ o = append(o, 0xa6, 0x78, 0x61, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset))
+ }
+ }
+ return
+}
+
+func (_ *encodedSignedTxns) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedSignedTxns)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedSignedTxns) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0049 int
+ var zb0050 bool
+ zb0049, zb0050, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0049, zb0050, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0051 int
+ zb0051, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Sig")
+ return
+ }
+ if zb0051 > maxSignatureBytes {
+ err = msgp.ErrOverflow(uint64(zb0051), uint64(maxSignatureBytes))
+ return
+ }
+ (*z).Sig, bts, err = msgp.ReadBytesBytes(bts, (*z).Sig)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Sig")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0052 []byte
+ var zb0053 int
+ zb0053, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSig")
+ return
+ }
+ if zb0053 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0053), uint64(maxBitmaskSize))
+ return
+ }
+ zb0052, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskSig))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSig")
+ return
+ }
+ (*z).BitmaskSig = bitmask(zb0052)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0054 int
+ zb0054, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Version")
+ return
+ }
+ if zb0054 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0054), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedMsigs.Version, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedMsigs.Version)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Version")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0055 []byte
+ var zb0056 int
+ zb0056, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVersion")
+ return
+ }
+ if zb0056 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0056), uint64(maxBitmaskSize))
+ return
+ }
+ zb0055, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedMsigs.BitmaskVersion))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVersion")
+ return
+ }
+ (*z).encodedMsigs.BitmaskVersion = bitmask(zb0055)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0057 int
+ zb0057, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Threshold")
+ return
+ }
+ if zb0057 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0057), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedMsigs.Threshold, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedMsigs.Threshold)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Threshold")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0058 []byte
+ var zb0059 int
+ zb0059, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskThreshold")
+ return
+ }
+ if zb0059 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0059), uint64(maxBitmaskSize))
+ return
+ }
+ zb0058, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedMsigs.BitmaskThreshold))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskThreshold")
+ return
+ }
+ (*z).encodedMsigs.BitmaskThreshold = bitmask(zb0058)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0060 int
+ var zb0061 bool
+ zb0060, zb0061, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs")
+ return
+ }
+ if zb0060 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0060), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs")
+ return
+ }
+ if zb0061 {
+ (*z).encodedMsigs.Subsigs = nil
+ } else if (*z).encodedMsigs.Subsigs != nil && cap((*z).encodedMsigs.Subsigs) >= zb0060 {
+ (*z).encodedMsigs.Subsigs = ((*z).encodedMsigs.Subsigs)[:zb0060]
+ } else {
+ (*z).encodedMsigs.Subsigs = make([][]crypto.MultisigSubsig, zb0060)
+ }
+ for zb0001 := range (*z).encodedMsigs.Subsigs {
+ var zb0062 int
+ var zb0063 bool
+ zb0062, zb0063, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs", zb0001)
+ return
+ }
+ if zb0062 > crypto.MaxMultisig {
+ err = msgp.ErrOverflow(uint64(zb0062), uint64(crypto.MaxMultisig))
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs", zb0001)
+ return
+ }
+ if zb0063 {
+ (*z).encodedMsigs.Subsigs[zb0001] = nil
+ } else if (*z).encodedMsigs.Subsigs[zb0001] != nil && cap((*z).encodedMsigs.Subsigs[zb0001]) >= zb0062 {
+ (*z).encodedMsigs.Subsigs[zb0001] = ((*z).encodedMsigs.Subsigs[zb0001])[:zb0062]
+ } else {
+ (*z).encodedMsigs.Subsigs[zb0001] = make([]crypto.MultisigSubsig, zb0062)
+ }
+ for zb0002 := range (*z).encodedMsigs.Subsigs[zb0001] {
+ bts, err = (*z).encodedMsigs.Subsigs[zb0001][zb0002].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs", zb0001, zb0002)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0064 []byte
+ var zb0065 int
+ zb0065, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSubsigs")
+ return
+ }
+ if zb0065 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0065), uint64(maxBitmaskSize))
+ return
+ }
+ zb0064, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedMsigs.BitmaskSubsigs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSubsigs")
+ return
+ }
+ (*z).encodedMsigs.BitmaskSubsigs = bitmask(zb0064)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0066 int
+ var zb0067 bool
+ zb0066, zb0067, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Logic")
+ return
+ }
+ if zb0066 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0066), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Logic")
+ return
+ }
+ if zb0067 {
+ (*z).encodedLsigs.Logic = nil
+ } else if (*z).encodedLsigs.Logic != nil && cap((*z).encodedLsigs.Logic) >= zb0066 {
+ (*z).encodedLsigs.Logic = ((*z).encodedLsigs.Logic)[:zb0066]
+ } else {
+ (*z).encodedLsigs.Logic = make([][]byte, zb0066)
+ }
+ for zb0003 := range (*z).encodedLsigs.Logic {
+ var zb0068 int
+ zb0068, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Logic", zb0003)
+ return
+ }
+ if zb0068 > config.MaxLogicSigMaxSize {
+ err = msgp.ErrOverflow(uint64(zb0068), uint64(config.MaxLogicSigMaxSize))
+ return
+ }
+ (*z).encodedLsigs.Logic[zb0003], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedLsigs.Logic[zb0003])
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Logic", zb0003)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0069 []byte
+ var zb0070 int
+ zb0070, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLogic")
+ return
+ }
+ if zb0070 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0070), uint64(maxBitmaskSize))
+ return
+ }
+ zb0069, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedLsigs.BitmaskLogic))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLogic")
+ return
+ }
+ (*z).encodedLsigs.BitmaskLogic = bitmask(zb0069)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0071 int
+ var zb0072 bool
+ zb0071, zb0072, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs")
+ return
+ }
+ if zb0071 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0071), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs")
+ return
+ }
+ if zb0072 {
+ (*z).encodedLsigs.LogicArgs = nil
+ } else if (*z).encodedLsigs.LogicArgs != nil && cap((*z).encodedLsigs.LogicArgs) >= zb0071 {
+ (*z).encodedLsigs.LogicArgs = ((*z).encodedLsigs.LogicArgs)[:zb0071]
+ } else {
+ (*z).encodedLsigs.LogicArgs = make([][][]byte, zb0071)
+ }
+ for zb0004 := range (*z).encodedLsigs.LogicArgs {
+ var zb0073 int
+ var zb0074 bool
+ zb0073, zb0074, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs", zb0004)
+ return
+ }
+ if zb0073 > transactions.EvalMaxArgs {
+ err = msgp.ErrOverflow(uint64(zb0073), uint64(transactions.EvalMaxArgs))
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs", zb0004)
+ return
+ }
+ if zb0074 {
+ (*z).encodedLsigs.LogicArgs[zb0004] = nil
+ } else if (*z).encodedLsigs.LogicArgs[zb0004] != nil && cap((*z).encodedLsigs.LogicArgs[zb0004]) >= zb0073 {
+ (*z).encodedLsigs.LogicArgs[zb0004] = ((*z).encodedLsigs.LogicArgs[zb0004])[:zb0073]
+ } else {
+ (*z).encodedLsigs.LogicArgs[zb0004] = make([][]byte, zb0073)
+ }
+ for zb0005 := range (*z).encodedLsigs.LogicArgs[zb0004] {
+ var zb0075 int
+ zb0075, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs", zb0004, zb0005)
+ return
+ }
+ if zb0075 > config.MaxLogicSigMaxSize {
+ err = msgp.ErrOverflow(uint64(zb0075), uint64(config.MaxLogicSigMaxSize))
+ return
+ }
+ (*z).encodedLsigs.LogicArgs[zb0004][zb0005], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedLsigs.LogicArgs[zb0004][zb0005])
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs", zb0004, zb0005)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0076 []byte
+ var zb0077 int
+ zb0077, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLogicArgs")
+ return
+ }
+ if zb0077 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0077), uint64(maxBitmaskSize))
+ return
+ }
+ zb0076, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedLsigs.BitmaskLogicArgs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLogicArgs")
+ return
+ }
+ (*z).encodedLsigs.BitmaskLogicArgs = bitmask(zb0076)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0078 int
+ zb0078, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AuthAddr")
+ return
+ }
+ if zb0078 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0078), uint64(maxAddressBytes))
+ return
+ }
+ (*z).AuthAddr, bts, err = msgp.ReadBytesBytes(bts, (*z).AuthAddr)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AuthAddr")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0079 []byte
+ var zb0080 int
+ zb0080, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAuthAddr")
+ return
+ }
+ if zb0080 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0080), uint64(maxBitmaskSize))
+ return
+ }
+ zb0079, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAuthAddr))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAuthAddr")
+ return
+ }
+ (*z).BitmaskAuthAddr = bitmask(zb0079)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0081 int
+ zb0081, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TxType")
+ return
+ }
+ if zb0081 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0081), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedTxns.TxType, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.TxType)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TxType")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0082 []byte
+ var zb0083 int
+ zb0083, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTxType")
+ return
+ }
+ if zb0083 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0083), uint64(maxBitmaskSize))
+ return
+ }
+ zb0082, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.BitmaskTxType))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTxType")
+ return
+ }
+ (*z).encodedTxns.BitmaskTxType = bitmask(zb0082)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ (*z).encodedTxns.TxTypeOffset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TxTypeOffset")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0084 int
+ zb0084, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Sender")
+ return
+ }
+ if zb0084 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0084), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.Sender, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedTxnHeaders.Sender)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Sender")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0085 []byte
+ var zb0086 int
+ zb0086, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSender")
+ return
+ }
+ if zb0086 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0086), uint64(maxBitmaskSize))
+ return
+ }
+ zb0085, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskSender))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSender")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskSender = bitmask(zb0085)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0087 int
+ var zb0088 bool
+ zb0087, zb0088, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Fee")
+ return
+ }
+ if zb0087 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0087), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Fee")
+ return
+ }
+ if zb0088 {
+ (*z).encodedTxns.encodedTxnHeaders.Fee = nil
+ } else if (*z).encodedTxns.encodedTxnHeaders.Fee != nil && cap((*z).encodedTxns.encodedTxnHeaders.Fee) >= zb0087 {
+ (*z).encodedTxns.encodedTxnHeaders.Fee = ((*z).encodedTxns.encodedTxnHeaders.Fee)[:zb0087]
+ } else {
+ (*z).encodedTxns.encodedTxnHeaders.Fee = make([]basics.MicroAlgos, zb0087)
+ }
+ for zb0006 := range (*z).encodedTxns.encodedTxnHeaders.Fee {
+ bts, err = (*z).encodedTxns.encodedTxnHeaders.Fee[zb0006].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Fee", zb0006)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0089 []byte
+ var zb0090 int
+ zb0090, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFee")
+ return
+ }
+ if zb0090 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0090), uint64(maxBitmaskSize))
+ return
+ }
+ zb0089, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskFee))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFee")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskFee = bitmask(zb0089)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0091 int
+ var zb0092 bool
+ zb0091, zb0092, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FirstValid")
+ return
+ }
+ if zb0091 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0091), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "FirstValid")
+ return
+ }
+ if zb0092 {
+ (*z).encodedTxns.encodedTxnHeaders.FirstValid = nil
+ } else if (*z).encodedTxns.encodedTxnHeaders.FirstValid != nil && cap((*z).encodedTxns.encodedTxnHeaders.FirstValid) >= zb0091 {
+ (*z).encodedTxns.encodedTxnHeaders.FirstValid = ((*z).encodedTxns.encodedTxnHeaders.FirstValid)[:zb0091]
+ } else {
+ (*z).encodedTxns.encodedTxnHeaders.FirstValid = make([]basics.Round, zb0091)
+ }
+ for zb0007 := range (*z).encodedTxns.encodedTxnHeaders.FirstValid {
+ bts, err = (*z).encodedTxns.encodedTxnHeaders.FirstValid[zb0007].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FirstValid", zb0007)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0093 []byte
+ var zb0094 int
+ zb0094, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFirstValid")
+ return
+ }
+ if zb0094 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0094), uint64(maxBitmaskSize))
+ return
+ }
+ zb0093, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskFirstValid))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFirstValid")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskFirstValid = bitmask(zb0093)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0095 int
+ var zb0096 bool
+ zb0095, zb0096, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LastValid")
+ return
+ }
+ if zb0095 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0095), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LastValid")
+ return
+ }
+ if zb0096 {
+ (*z).encodedTxns.encodedTxnHeaders.LastValid = nil
+ } else if (*z).encodedTxns.encodedTxnHeaders.LastValid != nil && cap((*z).encodedTxns.encodedTxnHeaders.LastValid) >= zb0095 {
+ (*z).encodedTxns.encodedTxnHeaders.LastValid = ((*z).encodedTxns.encodedTxnHeaders.LastValid)[:zb0095]
+ } else {
+ (*z).encodedTxns.encodedTxnHeaders.LastValid = make([]basics.Round, zb0095)
+ }
+ for zb0008 := range (*z).encodedTxns.encodedTxnHeaders.LastValid {
+ bts, err = (*z).encodedTxns.encodedTxnHeaders.LastValid[zb0008].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LastValid", zb0008)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0097 []byte
+ var zb0098 int
+ zb0098, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLastValid")
+ return
+ }
+ if zb0098 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0098), uint64(maxBitmaskSize))
+ return
+ }
+ zb0097, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskLastValid))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLastValid")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskLastValid = bitmask(zb0097)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0099 int
+ var zb0100 bool
+ zb0099, zb0100, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Note")
+ return
+ }
+ if zb0099 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0099), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Note")
+ return
+ }
+ if zb0100 {
+ (*z).encodedTxns.encodedTxnHeaders.Note = nil
+ } else if (*z).encodedTxns.encodedTxnHeaders.Note != nil && cap((*z).encodedTxns.encodedTxnHeaders.Note) >= zb0099 {
+ (*z).encodedTxns.encodedTxnHeaders.Note = ((*z).encodedTxns.encodedTxnHeaders.Note)[:zb0099]
+ } else {
+ (*z).encodedTxns.encodedTxnHeaders.Note = make([][]byte, zb0099)
+ }
+ for zb0009 := range (*z).encodedTxns.encodedTxnHeaders.Note {
+ var zb0101 int
+ zb0101, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Note", zb0009)
+ return
+ }
+ if zb0101 > config.MaxTxnNoteBytes {
+ err = msgp.ErrOverflow(uint64(zb0101), uint64(config.MaxTxnNoteBytes))
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.Note[zb0009], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedTxnHeaders.Note[zb0009])
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Note", zb0009)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0102 []byte
+ var zb0103 int
+ zb0103, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNote")
+ return
+ }
+ if zb0103 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0103), uint64(maxBitmaskSize))
+ return
+ }
+ zb0102, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskNote))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNote")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskNote = bitmask(zb0102)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0104 []byte
+ var zb0105 int
+ zb0105, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGenesisID")
+ return
+ }
+ if zb0105 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0105), uint64(maxBitmaskSize))
+ return
+ }
+ zb0104, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskGenesisID))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGenesisID")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskGenesisID = bitmask(zb0104)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0106 []byte
+ var zb0107 int
+ zb0107, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGroup")
+ return
+ }
+ if zb0107 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0107), uint64(maxBitmaskSize))
+ return
+ }
+ zb0106, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskGroup))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGroup")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskGroup = bitmask(zb0106)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0108 int
+ zb0108, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Lease")
+ return
+ }
+ if zb0108 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0108), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.Lease, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedTxnHeaders.Lease)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Lease")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0109 []byte
+ var zb0110 int
+ zb0110, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLease")
+ return
+ }
+ if zb0110 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0110), uint64(maxBitmaskSize))
+ return
+ }
+ zb0109, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskLease))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLease")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskLease = bitmask(zb0109)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0111 int
+ zb0111, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "RekeyTo")
+ return
+ }
+ if zb0111 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0111), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.RekeyTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedTxnHeaders.RekeyTo)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "RekeyTo")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0112 []byte
+ var zb0113 int
+ zb0113, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskRekeyTo")
+ return
+ }
+ if zb0113 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0113), uint64(maxBitmaskSize))
+ return
+ }
+ zb0112, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskRekeyTo))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskRekeyTo")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskRekeyTo = bitmask(zb0112)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0114 int
+ zb0114, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VotePK")
+ return
+ }
+ if zb0114 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0114), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedKeyregTxnFields.VotePK, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedKeyregTxnFields.VotePK)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VotePK")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0115 int
+ zb0115, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SelectionPK")
+ return
+ }
+ if zb0115 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0115), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedKeyregTxnFields.SelectionPK, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedKeyregTxnFields.SelectionPK)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SelectionPK")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0116 int
+ var zb0117 bool
+ zb0116, zb0117, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteFirst")
+ return
+ }
+ if zb0116 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0116), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "VoteFirst")
+ return
+ }
+ if zb0117 {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst = nil
+ } else if (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst != nil && cap((*z).encodedTxns.encodedKeyregTxnFields.VoteFirst) >= zb0116 {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst = ((*z).encodedTxns.encodedKeyregTxnFields.VoteFirst)[:zb0116]
+ } else {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst = make([]basics.Round, zb0116)
+ }
+ for zb0010 := range (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst {
+ bts, err = (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst[zb0010].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteFirst", zb0010)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0118 []byte
+ var zb0119 int
+ zb0119, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteFirst")
+ return
+ }
+ if zb0119 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0119), uint64(maxBitmaskSize))
+ return
+ }
+ zb0118, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteFirst")
+ return
+ }
+ (*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst = bitmask(zb0118)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0120 int
+ var zb0121 bool
+ zb0120, zb0121, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteLast")
+ return
+ }
+ if zb0120 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0120), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "VoteLast")
+ return
+ }
+ if zb0121 {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteLast = nil
+ } else if (*z).encodedTxns.encodedKeyregTxnFields.VoteLast != nil && cap((*z).encodedTxns.encodedKeyregTxnFields.VoteLast) >= zb0120 {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteLast = ((*z).encodedTxns.encodedKeyregTxnFields.VoteLast)[:zb0120]
+ } else {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteLast = make([]basics.Round, zb0120)
+ }
+ for zb0011 := range (*z).encodedTxns.encodedKeyregTxnFields.VoteLast {
+ bts, err = (*z).encodedTxns.encodedKeyregTxnFields.VoteLast[zb0011].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteLast", zb0011)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0122 []byte
+ var zb0123 int
+ zb0123, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteLast")
+ return
+ }
+ if zb0123 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0123), uint64(maxBitmaskSize))
+ return
+ }
+ zb0122, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteLast")
+ return
+ }
+ (*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast = bitmask(zb0122)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0124 int
+ var zb0125 bool
+ zb0124, zb0125, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteKeyDilution")
+ return
+ }
+ if zb0124 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0124), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "VoteKeyDilution")
+ return
+ }
+ if zb0125 {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution = nil
+ } else if (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution != nil && cap((*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution) >= zb0124 {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution = ((*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution)[:zb0124]
+ } else {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution = make([]uint64, zb0124)
+ }
+ for zb0012 := range (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution[zb0012], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteKeyDilution", zb0012)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0126 []byte
+ var zb0127 int
+ zb0127, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskKeys")
+ return
+ }
+ if zb0127 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0127), uint64(maxBitmaskSize))
+ return
+ }
+ zb0126, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskKeys))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskKeys")
+ return
+ }
+ (*z).encodedTxns.encodedKeyregTxnFields.BitmaskKeys = bitmask(zb0126)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0128 []byte
+ var zb0129 int
+ zb0129, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNonparticipation")
+ return
+ }
+ if zb0129 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0129), uint64(maxBitmaskSize))
+ return
+ }
+ zb0128, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNonparticipation")
+ return
+ }
+ (*z).encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation = bitmask(zb0128)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0130 int
+ zb0130, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Receiver")
+ return
+ }
+ if zb0130 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0130), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedPaymentTxnFields.Receiver, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedPaymentTxnFields.Receiver)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Receiver")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0131 []byte
+ var zb0132 int
+ zb0132, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReceiver")
+ return
+ }
+ if zb0132 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0132), uint64(maxBitmaskSize))
+ return
+ }
+ zb0131, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedPaymentTxnFields.BitmaskReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReceiver")
+ return
+ }
+ (*z).encodedTxns.encodedPaymentTxnFields.BitmaskReceiver = bitmask(zb0131)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0133 int
+ var zb0134 bool
+ zb0133, zb0134, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Amount")
+ return
+ }
+ if zb0133 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0133), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Amount")
+ return
+ }
+ if zb0134 {
+ (*z).encodedTxns.encodedPaymentTxnFields.Amount = nil
+ } else if (*z).encodedTxns.encodedPaymentTxnFields.Amount != nil && cap((*z).encodedTxns.encodedPaymentTxnFields.Amount) >= zb0133 {
+ (*z).encodedTxns.encodedPaymentTxnFields.Amount = ((*z).encodedTxns.encodedPaymentTxnFields.Amount)[:zb0133]
+ } else {
+ (*z).encodedTxns.encodedPaymentTxnFields.Amount = make([]basics.MicroAlgos, zb0133)
+ }
+ for zb0013 := range (*z).encodedTxns.encodedPaymentTxnFields.Amount {
+ bts, err = (*z).encodedTxns.encodedPaymentTxnFields.Amount[zb0013].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Amount", zb0013)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0135 []byte
+ var zb0136 int
+ zb0136, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAmount")
+ return
+ }
+ if zb0136 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0136), uint64(maxBitmaskSize))
+ return
+ }
+ zb0135, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedPaymentTxnFields.BitmaskAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAmount")
+ return
+ }
+ (*z).encodedTxns.encodedPaymentTxnFields.BitmaskAmount = bitmask(zb0135)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0137 int
+ zb0137, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CloseRemainderTo")
+ return
+ }
+ if zb0137 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0137), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedPaymentTxnFields.CloseRemainderTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedPaymentTxnFields.CloseRemainderTo)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CloseRemainderTo")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0138 []byte
+ var zb0139 int
+ zb0139, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCloseRemainderTo")
+ return
+ }
+ if zb0139 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0139), uint64(maxBitmaskSize))
+ return
+ }
+ zb0138, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCloseRemainderTo")
+ return
+ }
+ (*z).encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo = bitmask(zb0138)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0140 int
+ var zb0141 bool
+ zb0140, zb0141, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ConfigAsset")
+ return
+ }
+ if zb0140 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0140), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ConfigAsset")
+ return
+ }
+ if zb0141 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset = nil
+ } else if (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset != nil && cap((*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset) >= zb0140 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset = ((*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset)[:zb0140]
+ } else {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset = make([]basics.AssetIndex, zb0140)
+ }
+ for zb0014 := range (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset {
+ bts, err = (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset[zb0014].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ConfigAsset", zb0014)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0142 []byte
+ var zb0143 int
+ zb0143, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskConfigAsset")
+ return
+ }
+ if zb0143 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0143), uint64(maxBitmaskSize))
+ return
+ }
+ zb0142, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskConfigAsset")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset = bitmask(zb0142)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0144 int
+ var zb0145 bool
+ zb0144, zb0145, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Total")
+ return
+ }
+ if zb0144 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0144), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Total")
+ return
+ }
+ if zb0145 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total = nil
+ } else if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total != nil && cap((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total) >= zb0144 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total = ((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total)[:zb0144]
+ } else {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total = make([]uint64, zb0144)
+ }
+ for zb0015 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total[zb0015], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Total", zb0015)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0146 []byte
+ var zb0147 int
+ zb0147, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTotal")
+ return
+ }
+ if zb0147 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0147), uint64(maxBitmaskSize))
+ return
+ }
+ zb0146, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTotal")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal = bitmask(zb0146)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0148 int
+ var zb0149 bool
+ zb0148, zb0149, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Decimals")
+ return
+ }
+ if zb0148 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0148), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Decimals")
+ return
+ }
+ if zb0149 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals = nil
+ } else if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals != nil && cap((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals) >= zb0148 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals = ((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals)[:zb0148]
+ } else {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals = make([]uint32, zb0148)
+ }
+ for zb0016 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals[zb0016], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Decimals", zb0016)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0150 []byte
+ var zb0151 int
+ zb0151, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDecimals")
+ return
+ }
+ if zb0151 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0151), uint64(maxBitmaskSize))
+ return
+ }
+ zb0150, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDecimals")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals = bitmask(zb0150)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0152 []byte
+ var zb0153 int
+ zb0153, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDefaultFrozen")
+ return
+ }
+ if zb0153 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0153), uint64(maxBitmaskSize))
+ return
+ }
+ zb0152, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDefaultFrozen")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen = bitmask(zb0152)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0154 int
+ var zb0155 bool
+ zb0154, zb0155, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UnitName")
+ return
+ }
+ if zb0154 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0154), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "UnitName")
+ return
+ }
+ if zb0155 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName = nil
+ } else if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName != nil && cap((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName) >= zb0154 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName = ((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName)[:zb0154]
+ } else {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName = make([]string, zb0154)
+ }
+ for zb0017 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName[zb0017], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UnitName", zb0017)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0156 []byte
+ var zb0157 int
+ zb0157, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskUnitName")
+ return
+ }
+ if zb0157 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0157), uint64(maxBitmaskSize))
+ return
+ }
+ zb0156, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskUnitName")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName = bitmask(zb0156)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0158 int
+ var zb0159 bool
+ zb0158, zb0159, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetName")
+ return
+ }
+ if zb0158 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0158), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "AssetName")
+ return
+ }
+ if zb0159 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName = nil
+ } else if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName != nil && cap((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName) >= zb0158 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName = ((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName)[:zb0158]
+ } else {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName = make([]string, zb0158)
+ }
+ for zb0018 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName[zb0018], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetName", zb0018)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0160 []byte
+ var zb0161 int
+ zb0161, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetName")
+ return
+ }
+ if zb0161 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0161), uint64(maxBitmaskSize))
+ return
+ }
+ zb0160, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetName")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName = bitmask(zb0160)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0162 int
+ var zb0163 bool
+ zb0162, zb0163, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "URL")
+ return
+ }
+ if zb0162 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0162), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "URL")
+ return
+ }
+ if zb0163 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL = nil
+ } else if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL != nil && cap((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL) >= zb0162 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL = ((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL)[:zb0162]
+ } else {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL = make([]string, zb0162)
+ }
+ for zb0019 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL[zb0019], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "URL", zb0019)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0164 []byte
+ var zb0165 int
+ zb0165, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskURL")
+ return
+ }
+ if zb0165 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0165), uint64(maxBitmaskSize))
+ return
+ }
+ zb0164, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskURL")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL = bitmask(zb0164)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0166 int
+ zb0166, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "MetadataHash")
+ return
+ }
+ if zb0166 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0166), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "MetadataHash")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0167 []byte
+ var zb0168 int
+ zb0168, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskMetadataHash")
+ return
+ }
+ if zb0168 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0168), uint64(maxBitmaskSize))
+ return
+ }
+ zb0167, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskMetadataHash")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash = bitmask(zb0167)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0169 int
+ zb0169, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Manager")
+ return
+ }
+ if zb0169 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0169), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Manager")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0170 []byte
+ var zb0171 int
+ zb0171, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskManager")
+ return
+ }
+ if zb0171 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0171), uint64(maxBitmaskSize))
+ return
+ }
+ zb0170, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskManager")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager = bitmask(zb0170)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0172 int
+ zb0172, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reserve")
+ return
+ }
+ if zb0172 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0172), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reserve")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0173 []byte
+ var zb0174 int
+ zb0174, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReserve")
+ return
+ }
+ if zb0174 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0174), uint64(maxBitmaskSize))
+ return
+ }
+ zb0173, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReserve")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve = bitmask(zb0173)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0175 int
+ zb0175, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Freeze")
+ return
+ }
+ if zb0175 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0175), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Freeze")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0176 []byte
+ var zb0177 int
+ zb0177, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreeze")
+ return
+ }
+ if zb0177 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0177), uint64(maxBitmaskSize))
+ return
+ }
+ zb0176, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreeze")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze = bitmask(zb0176)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0178 int
+ zb0178, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Clawback")
+ return
+ }
+ if zb0178 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0178), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Clawback")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0179 []byte
+ var zb0180 int
+ zb0180, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClawback")
+ return
+ }
+ if zb0180 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0180), uint64(maxBitmaskSize))
+ return
+ }
+ zb0179, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClawback")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback = bitmask(zb0179)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0181 int
+ var zb0182 bool
+ zb0181, zb0182, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "XferAsset")
+ return
+ }
+ if zb0181 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0181), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "XferAsset")
+ return
+ }
+ if zb0182 {
+ (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset = nil
+ } else if (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset != nil && cap((*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset) >= zb0181 {
+ (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset = ((*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset)[:zb0181]
+ } else {
+ (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset = make([]basics.AssetIndex, zb0181)
+ }
+ for zb0020 := range (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset {
+ bts, err = (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset[zb0020].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "XferAsset", zb0020)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0183 []byte
+ var zb0184 int
+ zb0184, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskXferAsset")
+ return
+ }
+ if zb0184 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0184), uint64(maxBitmaskSize))
+ return
+ }
+ zb0183, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskXferAsset")
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset = bitmask(zb0183)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0185 int
+ var zb0186 bool
+ zb0185, zb0186, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetAmount")
+ return
+ }
+ if zb0185 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0185), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "AssetAmount")
+ return
+ }
+ if zb0186 {
+ (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount = nil
+ } else if (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount != nil && cap((*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount) >= zb0185 {
+ (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount = ((*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount)[:zb0185]
+ } else {
+ (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount = make([]uint64, zb0185)
+ }
+ for zb0021 := range (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount {
+ (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount[zb0021], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetAmount", zb0021)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0187 []byte
+ var zb0188 int
+ zb0188, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetAmount")
+ return
+ }
+ if zb0188 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0188), uint64(maxBitmaskSize))
+ return
+ }
+ zb0187, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetAmount")
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount = bitmask(zb0187)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0189 int
+ zb0189, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetSender")
+ return
+ }
+ if zb0189 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0189), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.AssetSender, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetTransferTxnFields.AssetSender)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetSender")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0190 []byte
+ var zb0191 int
+ zb0191, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetSender")
+ return
+ }
+ if zb0191 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0191), uint64(maxBitmaskSize))
+ return
+ }
+ zb0190, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetSender")
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender = bitmask(zb0190)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0192 int
+ zb0192, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetReceiver")
+ return
+ }
+ if zb0192 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0192), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.AssetReceiver, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetTransferTxnFields.AssetReceiver)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetReceiver")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0193 []byte
+ var zb0194 int
+ zb0194, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetReceiver")
+ return
+ }
+ if zb0194 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0194), uint64(maxBitmaskSize))
+ return
+ }
+ zb0193, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetReceiver")
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver = bitmask(zb0193)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0195 int
+ zb0195, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetCloseTo")
+ return
+ }
+ if zb0195 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0195), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetCloseTo")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0196 []byte
+ var zb0197 int
+ zb0197, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetCloseTo")
+ return
+ }
+ if zb0197 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0197), uint64(maxBitmaskSize))
+ return
+ }
+ zb0196, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetCloseTo")
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo = bitmask(zb0196)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0198 int
+ zb0198, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAccount")
+ return
+ }
+ if zb0198 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0198), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAccount")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0199 []byte
+ var zb0200 int
+ zb0200, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAccount")
+ return
+ }
+ if zb0200 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0200), uint64(maxBitmaskSize))
+ return
+ }
+ zb0199, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAccount")
+ return
+ }
+ (*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount = bitmask(zb0199)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0201 int
+ var zb0202 bool
+ zb0201, zb0202, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAsset")
+ return
+ }
+ if zb0201 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0201), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAsset")
+ return
+ }
+ if zb0202 {
+ (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset = nil
+ } else if (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset != nil && cap((*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset) >= zb0201 {
+ (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset = ((*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset)[:zb0201]
+ } else {
+ (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset = make([]basics.AssetIndex, zb0201)
+ }
+ for zb0022 := range (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset {
+ bts, err = (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset[zb0022].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAsset", zb0022)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0203 []byte
+ var zb0204 int
+ zb0204, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAsset")
+ return
+ }
+ if zb0204 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0204), uint64(maxBitmaskSize))
+ return
+ }
+ zb0203, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAsset")
+ return
+ }
+ (*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset = bitmask(zb0203)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0205 []byte
+ var zb0206 int
+ zb0206, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetFrozen")
+ return
+ }
+ if zb0206 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0206), uint64(maxBitmaskSize))
+ return
+ }
+ zb0205, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetFrozen")
+ return
+ }
+ (*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen = bitmask(zb0205)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0207 int
+ var zb0208 bool
+ zb0207, zb0208, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationID")
+ return
+ }
+ if zb0207 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0207), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationID")
+ return
+ }
+ if zb0208 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID) >= zb0207 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID = ((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID)[:zb0207]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID = make([]basics.AppIndex, zb0207)
+ }
+ for zb0023 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID {
+ bts, err = (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID[zb0023].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationID", zb0023)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0209 []byte
+ var zb0210 int
+ zb0210, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationID")
+ return
+ }
+ if zb0210 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0210), uint64(maxBitmaskSize))
+ return
+ }
+ zb0209, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationID")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID = bitmask(zb0209)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0211 int
+ zb0211, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "OnCompletion")
+ return
+ }
+ if zb0211 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0211), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.OnCompletion, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedApplicationCallTxnFields.OnCompletion)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "OnCompletion")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0212 []byte
+ var zb0213 int
+ zb0213, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskOnCompletion")
+ return
+ }
+ if zb0213 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0213), uint64(maxBitmaskSize))
+ return
+ }
+ zb0212, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskOnCompletion")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion = bitmask(zb0212)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0214 int
+ var zb0215 bool
+ zb0214, zb0215, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs")
+ return
+ }
+ if zb0214 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0214), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs")
+ return
+ }
+ if zb0215 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs) >= zb0214 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs = ((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs)[:zb0214]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs = make([]applicationArgs, zb0214)
+ }
+ for zb0024 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs {
+ var zb0216 int
+ var zb0217 bool
+ zb0216, zb0217, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs", zb0024)
+ return
+ }
+ if zb0216 > transactions.EncodedMaxApplicationArgs {
+ err = msgp.ErrOverflow(uint64(zb0216), uint64(transactions.EncodedMaxApplicationArgs))
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs", zb0024)
+ return
+ }
+ if zb0217 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024]) >= zb0216 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] = ((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024])[:zb0216]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] = make(applicationArgs, zb0216)
+ }
+ for zb0025 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024][zb0025], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024][zb0025])
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs", zb0024, zb0025)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0218 []byte
+ var zb0219 int
+ zb0219, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationArgs")
+ return
+ }
+ if zb0219 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0219), uint64(maxBitmaskSize))
+ return
+ }
+ zb0218, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationArgs")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs = bitmask(zb0218)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0220 int
+ var zb0221 bool
+ zb0220, zb0221, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Accounts")
+ return
+ }
+ if zb0220 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0220), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Accounts")
+ return
+ }
+ if zb0221 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.Accounts) >= zb0220 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts = ((*z).encodedTxns.encodedApplicationCallTxnFields.Accounts)[:zb0220]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts = make([]addresses, zb0220)
+ }
+ for zb0026 := range (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts {
+ var zb0222 int
+ var zb0223 bool
+ zb0222, zb0223, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Accounts", zb0026)
+ return
+ }
+ if zb0222 > transactions.EncodedMaxAccounts {
+ err = msgp.ErrOverflow(uint64(zb0222), uint64(transactions.EncodedMaxAccounts))
+ err = msgp.WrapError(err, "struct-from-array", "Accounts", zb0026)
+ return
+ }
+ if zb0223 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026]) >= zb0222 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] = ((*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026])[:zb0222]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] = make(addresses, zb0222)
+ }
+ for zb0027 := range (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] {
+ bts, err = (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026][zb0027].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Accounts", zb0026, zb0027)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0224 []byte
+ var zb0225 int
+ zb0225, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAccounts")
+ return
+ }
+ if zb0225 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0225), uint64(maxBitmaskSize))
+ return
+ }
+ zb0224, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAccounts")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts = bitmask(zb0224)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0226 int
+ var zb0227 bool
+ zb0226, zb0227, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps")
+ return
+ }
+ if zb0226 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0226), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps")
+ return
+ }
+ if zb0227 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps) >= zb0226 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps = ((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps)[:zb0226]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps = make([]appIndices, zb0226)
+ }
+ for zb0028 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps {
+ var zb0228 int
+ var zb0229 bool
+ zb0228, zb0229, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps", zb0028)
+ return
+ }
+ if zb0228 > transactions.EncodedMaxForeignApps {
+ err = msgp.ErrOverflow(uint64(zb0228), uint64(transactions.EncodedMaxForeignApps))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps", zb0028)
+ return
+ }
+ if zb0229 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028]) >= zb0228 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] = ((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028])[:zb0228]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] = make(appIndices, zb0228)
+ }
+ for zb0029 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] {
+ bts, err = (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028][zb0029].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps", zb0028, zb0029)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0230 []byte
+ var zb0231 int
+ zb0231, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignApps")
+ return
+ }
+ if zb0231 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0231), uint64(maxBitmaskSize))
+ return
+ }
+ zb0230, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignApps")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps = bitmask(zb0230)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0232 int
+ var zb0233 bool
+ zb0232, zb0233, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets")
+ return
+ }
+ if zb0232 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0232), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets")
+ return
+ }
+ if zb0233 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets) >= zb0232 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets = ((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets)[:zb0232]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets = make([]assetIndices, zb0232)
+ }
+ for zb0030 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets {
+ var zb0234 int
+ var zb0235 bool
+ zb0234, zb0235, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets", zb0030)
+ return
+ }
+ if zb0234 > transactions.EncodedMaxForeignAssets {
+ err = msgp.ErrOverflow(uint64(zb0234), uint64(transactions.EncodedMaxForeignAssets))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets", zb0030)
+ return
+ }
+ if zb0235 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030]) >= zb0234 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] = ((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030])[:zb0234]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] = make(assetIndices, zb0234)
+ }
+ for zb0031 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] {
+ bts, err = (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030][zb0031].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets", zb0030, zb0031)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0236 []byte
+ var zb0237 int
+ zb0237, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignAssets")
+ return
+ }
+ if zb0237 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0237), uint64(maxBitmaskSize))
+ return
+ }
+ zb0236, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignAssets")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets = bitmask(zb0236)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0238 int
+ var zb0239 bool
+ zb0238, zb0239, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumUint")
+ return
+ }
+ if zb0238 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0238), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumUint")
+ return
+ }
+ if zb0239 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint) >= zb0238 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint = ((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint)[:zb0238]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint = make([]uint64, zb0238)
+ }
+ for zb0032 := range (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint[zb0032], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumUint", zb0032)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0240 []byte
+ var zb0241 int
+ zb0241, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumUint")
+ return
+ }
+ if zb0241 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0241), uint64(maxBitmaskSize))
+ return
+ }
+ zb0240, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumUint")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint = bitmask(zb0240)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0242 int
+ var zb0243 bool
+ zb0242, zb0243, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumByteSlice")
+ return
+ }
+ if zb0242 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0242), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumByteSlice")
+ return
+ }
+ if zb0243 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice) >= zb0242 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice = ((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice)[:zb0242]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice = make([]uint64, zb0242)
+ }
+ for zb0033 := range (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice[zb0033], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumByteSlice", zb0033)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0244 []byte
+ var zb0245 int
+ zb0245, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumByteSlice")
+ return
+ }
+ if zb0245 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0245), uint64(maxBitmaskSize))
+ return
+ }
+ zb0244, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumByteSlice")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice = bitmask(zb0244)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0246 int
+ var zb0247 bool
+ zb0246, zb0247, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumUint")
+ return
+ }
+ if zb0246 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0246), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumUint")
+ return
+ }
+ if zb0247 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint) >= zb0246 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint = ((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint)[:zb0246]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint = make([]uint64, zb0246)
+ }
+ for zb0034 := range (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint[zb0034], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumUint", zb0034)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0248 []byte
+ var zb0249 int
+ zb0249, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumUint")
+ return
+ }
+ if zb0249 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0249), uint64(maxBitmaskSize))
+ return
+ }
+ zb0248, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumUint")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint = bitmask(zb0248)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0250 int
+ var zb0251 bool
+ zb0250, zb0251, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumByteSlice")
+ return
+ }
+ if zb0250 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0250), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumByteSlice")
+ return
+ }
+ if zb0251 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice) >= zb0250 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice = ((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice)[:zb0250]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice = make([]uint64, zb0250)
+ }
+ for zb0035 := range (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice[zb0035], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumByteSlice", zb0035)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0252 []byte
+ var zb0253 int
+ zb0253, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumByteSlice")
+ return
+ }
+ if zb0253 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0253), uint64(maxBitmaskSize))
+ return
+ }
+ zb0252, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumByteSlice")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice = bitmask(zb0252)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0254 int
+ var zb0255 bool
+ zb0254, zb0255, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram")
+ return
+ }
+ if zb0254 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0254), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram")
+ return
+ }
+ if zb0255 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram) >= zb0254 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram = ((*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram)[:zb0254]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram = make([]program, zb0254)
+ }
+ for zb0036 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram {
+ {
+ var zb0256 []byte
+ var zb0257 int
+ zb0257, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram", zb0036)
+ return
+ }
+ if zb0257 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0257), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0256, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram[zb0036]))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram", zb0036)
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram[zb0036] = program(zb0256)
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0258 []byte
+ var zb0259 int
+ zb0259, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApprovalProgram")
+ return
+ }
+ if zb0259 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0259), uint64(maxBitmaskSize))
+ return
+ }
+ zb0258, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApprovalProgram")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram = bitmask(zb0258)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0260 int
+ var zb0261 bool
+ zb0260, zb0261, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram")
+ return
+ }
+ if zb0260 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0260), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram")
+ return
+ }
+ if zb0261 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram) >= zb0260 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram = ((*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram)[:zb0260]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram = make([]program, zb0260)
+ }
+ for zb0037 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram {
+ {
+ var zb0262 []byte
+ var zb0263 int
+ zb0263, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram", zb0037)
+ return
+ }
+ if zb0263 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0263), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0262, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram[zb0037]))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram", zb0037)
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram[zb0037] = program(zb0262)
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0264 []byte
+ var zb0265 int
+ zb0265, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClearStateProgram")
+ return
+ }
+ if zb0265 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0265), uint64(maxBitmaskSize))
+ return
+ }
+ zb0264, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClearStateProgram")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram = bitmask(zb0264)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0266 int
+ var zb0267 bool
+ zb0266, zb0267, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExtraProgramPages")
+ return
+ }
+ if zb0266 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0266), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ExtraProgramPages")
+ return
+ }
+ if zb0267 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages) >= zb0266 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages = ((*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages)[:zb0266]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages = make([]uint32, zb0266)
+ }
+ for zb0038 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages[zb0038], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExtraProgramPages", zb0038)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0268 []byte
+ var zb0269 int
+ zb0269, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskExtraProgramPages")
+ return
+ }
+ if zb0269 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0269), uint64(maxBitmaskSize))
+ return
+ }
+ zb0268, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskExtraProgramPages")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages = bitmask(zb0268)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0270 int
+ var zb0271 bool
+ zb0270, zb0271, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertRound")
+ return
+ }
+ if zb0270 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0270), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "CertRound")
+ return
+ }
+ if zb0271 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.CertRound = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.CertRound != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.CertRound) >= zb0270 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.CertRound = ((*z).encodedTxns.encodedCompactCertTxnFields.CertRound)[:zb0270]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.CertRound = make([]basics.Round, zb0270)
+ }
+ for zb0039 := range (*z).encodedTxns.encodedCompactCertTxnFields.CertRound {
+ bts, err = (*z).encodedTxns.encodedCompactCertTxnFields.CertRound[zb0039].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertRound", zb0039)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0272 []byte
+ var zb0273 int
+ zb0273, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertRound")
+ return
+ }
+ if zb0273 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0273), uint64(maxBitmaskSize))
+ return
+ }
+ zb0272, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertRound")
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound = bitmask(zb0272)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0274 int
+ var zb0275 bool
+ zb0274, zb0275, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertType")
+ return
+ }
+ if zb0274 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0274), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "CertType")
+ return
+ }
+ if zb0275 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.CertType = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.CertType != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.CertType) >= zb0274 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.CertType = ((*z).encodedTxns.encodedCompactCertTxnFields.CertType)[:zb0274]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.CertType = make([]protocol.CompactCertType, zb0274)
+ }
+ for zb0040 := range (*z).encodedTxns.encodedCompactCertTxnFields.CertType {
+ bts, err = (*z).encodedTxns.encodedCompactCertTxnFields.CertType[zb0040].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertType", zb0040)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0276 []byte
+ var zb0277 int
+ zb0277, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertType")
+ return
+ }
+ if zb0277 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0277), uint64(maxBitmaskSize))
+ return
+ }
+ zb0276, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertType))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertType")
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertType = bitmask(zb0276)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0278 int
+ zb0278, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigCommit")
+ return
+ }
+ if zb0278 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0278), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigCommit")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0279 []byte
+ var zb0280 int
+ zb0280, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigCommit")
+ return
+ }
+ if zb0280 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0280), uint64(maxBitmaskSize))
+ return
+ }
+ zb0279, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigCommit")
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit = bitmask(zb0279)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0281 int
+ var zb0282 bool
+ zb0281, zb0282, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight")
+ return
+ }
+ if zb0281 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0281), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight")
+ return
+ }
+ if zb0282 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight) >= zb0281 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight = ((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight)[:zb0281]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight = make([]uint64, zb0281)
+ }
+ for zb0041 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight[zb0041], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight", zb0041)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0283 []byte
+ var zb0284 int
+ zb0284, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSignedWeight")
+ return
+ }
+ if zb0284 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0284), uint64(maxBitmaskSize))
+ return
+ }
+ zb0283, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSignedWeight")
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight = bitmask(zb0283)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0285 int
+ var zb0286 bool
+ zb0285, zb0286, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs")
+ return
+ }
+ if zb0285 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0285), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs")
+ return
+ }
+ if zb0286 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs) >= zb0285 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs = ((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs)[:zb0285]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs = make([]certProofs, zb0285)
+ }
+ for zb0042 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs {
+ var zb0287 int
+ var zb0288 bool
+ zb0287, zb0288, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0042)
+ return
+ }
+ if zb0287 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0287), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0042)
+ return
+ }
+ if zb0288 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042]) >= zb0287 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] = ((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042])[:zb0287]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] = make(certProofs, zb0287)
+ }
+ for zb0043 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] {
+ bts, err = (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042][zb0043].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0042, zb0043)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0289 []byte
+ var zb0290 int
+ zb0290, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigProofs")
+ return
+ }
+ if zb0290 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0290), uint64(maxBitmaskSize))
+ return
+ }
+ zb0289, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigProofs")
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs = bitmask(zb0289)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0291 int
+ var zb0292 bool
+ zb0291, zb0292, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs")
+ return
+ }
+ if zb0291 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0291), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs")
+ return
+ }
+ if zb0292 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs) >= zb0291 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs = ((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs)[:zb0291]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs = make([]certProofs, zb0291)
+ }
+ for zb0044 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs {
+ var zb0293 int
+ var zb0294 bool
+ zb0293, zb0294, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0044)
+ return
+ }
+ if zb0293 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0293), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0044)
+ return
+ }
+ if zb0294 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044]) >= zb0293 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] = ((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044])[:zb0293]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] = make(certProofs, zb0293)
+ }
+ for zb0045 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] {
+ bts, err = (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044][zb0045].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0044, zb0045)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0295 []byte
+ var zb0296 int
+ zb0296, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskPartProofs")
+ return
+ }
+ if zb0296 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0296), uint64(maxBitmaskSize))
+ return
+ }
+ zb0295, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskPartProofs")
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs = bitmask(zb0295)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0297 int
+ var zb0298 bool
+ zb0297, zb0298, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals")
+ return
+ }
+ if zb0297 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0297), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Reveals")
+ return
+ }
+ if zb0298 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals) >= zb0297 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals = ((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals)[:zb0297]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals = make([]revealMap, zb0297)
+ }
+ for zb0046 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals {
+ var zb0299 int
+ var zb0300 bool
+ zb0299, zb0300, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0046)
+ return
+ }
+ if zb0299 > compactcert.MaxReveals {
+ err = msgp.ErrOverflow(uint64(zb0299), uint64(compactcert.MaxReveals))
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0046)
+ return
+ }
+ if zb0300 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] == nil {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] = make(revealMap, zb0299)
+ }
+ for zb0299 > 0 {
+ var zb0047 uint64
+ var zb0048 compactcert.Reveal
+ zb0299--
+ zb0047, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0046)
+ return
+ }
+ bts, err = zb0048.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0046, zb0047)
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046][zb0047] = zb0048
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0301 []byte
+ var zb0302 int
+ zb0302, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReveals")
+ return
+ }
+ if zb0302 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0302), uint64(maxBitmaskSize))
+ return
+ }
+ zb0301, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReveals")
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals = bitmask(zb0301)
+ }
+ }
+ if zb0049 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0049)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0050 {
+ (*z) = encodedSignedTxns{}
+ }
+ for zb0049 > 0 {
+ zb0049--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "sig":
+ var zb0303 int
+ zb0303, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Sig")
+ return
+ }
+ if zb0303 > maxSignatureBytes {
+ err = msgp.ErrOverflow(uint64(zb0303), uint64(maxSignatureBytes))
+ return
+ }
+ (*z).Sig, bts, err = msgp.ReadBytesBytes(bts, (*z).Sig)
+ if err != nil {
+ err = msgp.WrapError(err, "Sig")
+ return
+ }
+ case "sigbm":
+ {
+ var zb0304 []byte
+ var zb0305 int
+ zb0305, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSig")
+ return
+ }
+ if zb0305 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0305), uint64(maxBitmaskSize))
+ return
+ }
+ zb0304, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskSig))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSig")
+ return
+ }
+ (*z).BitmaskSig = bitmask(zb0304)
+ }
+ case "msigv":
+ var zb0306 int
+ zb0306, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Version")
+ return
+ }
+ if zb0306 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0306), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedMsigs.Version, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedMsigs.Version)
+ if err != nil {
+ err = msgp.WrapError(err, "Version")
+ return
+ }
+ case "msigvbm":
+ {
+ var zb0307 []byte
+ var zb0308 int
+ zb0308, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVersion")
+ return
+ }
+ if zb0308 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0308), uint64(maxBitmaskSize))
+ return
+ }
+ zb0307, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedMsigs.BitmaskVersion))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVersion")
+ return
+ }
+ (*z).encodedMsigs.BitmaskVersion = bitmask(zb0307)
+ }
+ case "msigthr":
+ var zb0309 int
+ zb0309, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Threshold")
+ return
+ }
+ if zb0309 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0309), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedMsigs.Threshold, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedMsigs.Threshold)
+ if err != nil {
+ err = msgp.WrapError(err, "Threshold")
+ return
+ }
+ case "msigthrbm":
+ {
+ var zb0310 []byte
+ var zb0311 int
+ zb0311, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskThreshold")
+ return
+ }
+ if zb0311 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0311), uint64(maxBitmaskSize))
+ return
+ }
+ zb0310, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedMsigs.BitmaskThreshold))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskThreshold")
+ return
+ }
+ (*z).encodedMsigs.BitmaskThreshold = bitmask(zb0310)
+ }
+ case "subsig":
+ var zb0312 int
+ var zb0313 bool
+ zb0312, zb0313, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Subsigs")
+ return
+ }
+ if zb0312 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0312), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Subsigs")
+ return
+ }
+ if zb0313 {
+ (*z).encodedMsigs.Subsigs = nil
+ } else if (*z).encodedMsigs.Subsigs != nil && cap((*z).encodedMsigs.Subsigs) >= zb0312 {
+ (*z).encodedMsigs.Subsigs = ((*z).encodedMsigs.Subsigs)[:zb0312]
+ } else {
+ (*z).encodedMsigs.Subsigs = make([][]crypto.MultisigSubsig, zb0312)
+ }
+ for zb0001 := range (*z).encodedMsigs.Subsigs {
+ var zb0314 int
+ var zb0315 bool
+ zb0314, zb0315, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Subsigs", zb0001)
+ return
+ }
+ if zb0314 > crypto.MaxMultisig {
+ err = msgp.ErrOverflow(uint64(zb0314), uint64(crypto.MaxMultisig))
+ err = msgp.WrapError(err, "Subsigs", zb0001)
+ return
+ }
+ if zb0315 {
+ (*z).encodedMsigs.Subsigs[zb0001] = nil
+ } else if (*z).encodedMsigs.Subsigs[zb0001] != nil && cap((*z).encodedMsigs.Subsigs[zb0001]) >= zb0314 {
+ (*z).encodedMsigs.Subsigs[zb0001] = ((*z).encodedMsigs.Subsigs[zb0001])[:zb0314]
+ } else {
+ (*z).encodedMsigs.Subsigs[zb0001] = make([]crypto.MultisigSubsig, zb0314)
+ }
+ for zb0002 := range (*z).encodedMsigs.Subsigs[zb0001] {
+ bts, err = (*z).encodedMsigs.Subsigs[zb0001][zb0002].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Subsigs", zb0001, zb0002)
+ return
+ }
+ }
+ }
+ case "subsigsbm":
+ {
+ var zb0316 []byte
+ var zb0317 int
+ zb0317, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSubsigs")
+ return
+ }
+ if zb0317 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0317), uint64(maxBitmaskSize))
+ return
+ }
+ zb0316, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedMsigs.BitmaskSubsigs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSubsigs")
+ return
+ }
+ (*z).encodedMsigs.BitmaskSubsigs = bitmask(zb0316)
+ }
+ case "lsigl":
+ var zb0318 int
+ var zb0319 bool
+ zb0318, zb0319, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Logic")
+ return
+ }
+ if zb0318 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0318), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Logic")
+ return
+ }
+ if zb0319 {
+ (*z).encodedLsigs.Logic = nil
+ } else if (*z).encodedLsigs.Logic != nil && cap((*z).encodedLsigs.Logic) >= zb0318 {
+ (*z).encodedLsigs.Logic = ((*z).encodedLsigs.Logic)[:zb0318]
+ } else {
+ (*z).encodedLsigs.Logic = make([][]byte, zb0318)
+ }
+ for zb0003 := range (*z).encodedLsigs.Logic {
+ var zb0320 int
+ zb0320, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Logic", zb0003)
+ return
+ }
+ if zb0320 > config.MaxLogicSigMaxSize {
+ err = msgp.ErrOverflow(uint64(zb0320), uint64(config.MaxLogicSigMaxSize))
+ return
+ }
+ (*z).encodedLsigs.Logic[zb0003], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedLsigs.Logic[zb0003])
+ if err != nil {
+ err = msgp.WrapError(err, "Logic", zb0003)
+ return
+ }
+ }
+ case "lsiglbm":
+ {
+ var zb0321 []byte
+ var zb0322 int
+ zb0322, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLogic")
+ return
+ }
+ if zb0322 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0322), uint64(maxBitmaskSize))
+ return
+ }
+ zb0321, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedLsigs.BitmaskLogic))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLogic")
+ return
+ }
+ (*z).encodedLsigs.BitmaskLogic = bitmask(zb0321)
+ }
+ case "lsigarg":
+ var zb0323 int
+ var zb0324 bool
+ zb0323, zb0324, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LogicArgs")
+ return
+ }
+ if zb0323 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0323), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LogicArgs")
+ return
+ }
+ if zb0324 {
+ (*z).encodedLsigs.LogicArgs = nil
+ } else if (*z).encodedLsigs.LogicArgs != nil && cap((*z).encodedLsigs.LogicArgs) >= zb0323 {
+ (*z).encodedLsigs.LogicArgs = ((*z).encodedLsigs.LogicArgs)[:zb0323]
+ } else {
+ (*z).encodedLsigs.LogicArgs = make([][][]byte, zb0323)
+ }
+ for zb0004 := range (*z).encodedLsigs.LogicArgs {
+ var zb0325 int
+ var zb0326 bool
+ zb0325, zb0326, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LogicArgs", zb0004)
+ return
+ }
+ if zb0325 > transactions.EvalMaxArgs {
+ err = msgp.ErrOverflow(uint64(zb0325), uint64(transactions.EvalMaxArgs))
+ err = msgp.WrapError(err, "LogicArgs", zb0004)
+ return
+ }
+ if zb0326 {
+ (*z).encodedLsigs.LogicArgs[zb0004] = nil
+ } else if (*z).encodedLsigs.LogicArgs[zb0004] != nil && cap((*z).encodedLsigs.LogicArgs[zb0004]) >= zb0325 {
+ (*z).encodedLsigs.LogicArgs[zb0004] = ((*z).encodedLsigs.LogicArgs[zb0004])[:zb0325]
+ } else {
+ (*z).encodedLsigs.LogicArgs[zb0004] = make([][]byte, zb0325)
+ }
+ for zb0005 := range (*z).encodedLsigs.LogicArgs[zb0004] {
+ var zb0327 int
+ zb0327, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LogicArgs", zb0004, zb0005)
+ return
+ }
+ if zb0327 > config.MaxLogicSigMaxSize {
+ err = msgp.ErrOverflow(uint64(zb0327), uint64(config.MaxLogicSigMaxSize))
+ return
+ }
+ (*z).encodedLsigs.LogicArgs[zb0004][zb0005], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedLsigs.LogicArgs[zb0004][zb0005])
+ if err != nil {
+ err = msgp.WrapError(err, "LogicArgs", zb0004, zb0005)
+ return
+ }
+ }
+ }
+ case "lsigargbm":
+ {
+ var zb0328 []byte
+ var zb0329 int
+ zb0329, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLogicArgs")
+ return
+ }
+ if zb0329 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0329), uint64(maxBitmaskSize))
+ return
+ }
+ zb0328, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedLsigs.BitmaskLogicArgs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLogicArgs")
+ return
+ }
+ (*z).encodedLsigs.BitmaskLogicArgs = bitmask(zb0328)
+ }
+ case "sgnr":
+ var zb0330 int
+ zb0330, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AuthAddr")
+ return
+ }
+ if zb0330 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0330), uint64(maxAddressBytes))
+ return
+ }
+ (*z).AuthAddr, bts, err = msgp.ReadBytesBytes(bts, (*z).AuthAddr)
+ if err != nil {
+ err = msgp.WrapError(err, "AuthAddr")
+ return
+ }
+ case "sgnrbm":
+ {
+ var zb0331 []byte
+ var zb0332 int
+ zb0332, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAuthAddr")
+ return
+ }
+ if zb0332 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0332), uint64(maxBitmaskSize))
+ return
+ }
+ zb0331, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskAuthAddr))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAuthAddr")
+ return
+ }
+ (*z).BitmaskAuthAddr = bitmask(zb0331)
+ }
+ case "type":
+ var zb0333 int
+ zb0333, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "TxType")
+ return
+ }
+ if zb0333 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0333), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedTxns.TxType, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.TxType)
+ if err != nil {
+ err = msgp.WrapError(err, "TxType")
+ return
+ }
+ case "typebm":
+ {
+ var zb0334 []byte
+ var zb0335 int
+ zb0335, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTxType")
+ return
+ }
+ if zb0335 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0335), uint64(maxBitmaskSize))
+ return
+ }
+ zb0334, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.BitmaskTxType))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTxType")
+ return
+ }
+ (*z).encodedTxns.BitmaskTxType = bitmask(zb0334)
+ }
+ case "typeo":
+ (*z).encodedTxns.TxTypeOffset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "TxTypeOffset")
+ return
+ }
+ case "snd":
+ var zb0336 int
+ zb0336, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Sender")
+ return
+ }
+ if zb0336 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0336), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.Sender, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedTxnHeaders.Sender)
+ if err != nil {
+ err = msgp.WrapError(err, "Sender")
+ return
+ }
+ case "sndbm":
+ {
+ var zb0337 []byte
+ var zb0338 int
+ zb0338, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSender")
+ return
+ }
+ if zb0338 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0338), uint64(maxBitmaskSize))
+ return
+ }
+ zb0337, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskSender))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSender")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskSender = bitmask(zb0337)
+ }
+ case "fee":
+ var zb0339 int
+ var zb0340 bool
+ zb0339, zb0340, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Fee")
+ return
+ }
+ if zb0339 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0339), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Fee")
+ return
+ }
+ if zb0340 {
+ (*z).encodedTxns.encodedTxnHeaders.Fee = nil
+ } else if (*z).encodedTxns.encodedTxnHeaders.Fee != nil && cap((*z).encodedTxns.encodedTxnHeaders.Fee) >= zb0339 {
+ (*z).encodedTxns.encodedTxnHeaders.Fee = ((*z).encodedTxns.encodedTxnHeaders.Fee)[:zb0339]
+ } else {
+ (*z).encodedTxns.encodedTxnHeaders.Fee = make([]basics.MicroAlgos, zb0339)
+ }
+ for zb0006 := range (*z).encodedTxns.encodedTxnHeaders.Fee {
+ bts, err = (*z).encodedTxns.encodedTxnHeaders.Fee[zb0006].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Fee", zb0006)
+ return
+ }
+ }
+ case "feebm":
+ {
+ var zb0341 []byte
+ var zb0342 int
+ zb0342, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFee")
+ return
+ }
+ if zb0342 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0342), uint64(maxBitmaskSize))
+ return
+ }
+ zb0341, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskFee))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFee")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskFee = bitmask(zb0341)
+ }
+ case "fv":
+ var zb0343 int
+ var zb0344 bool
+ zb0343, zb0344, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FirstValid")
+ return
+ }
+ if zb0343 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0343), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "FirstValid")
+ return
+ }
+ if zb0344 {
+ (*z).encodedTxns.encodedTxnHeaders.FirstValid = nil
+ } else if (*z).encodedTxns.encodedTxnHeaders.FirstValid != nil && cap((*z).encodedTxns.encodedTxnHeaders.FirstValid) >= zb0343 {
+ (*z).encodedTxns.encodedTxnHeaders.FirstValid = ((*z).encodedTxns.encodedTxnHeaders.FirstValid)[:zb0343]
+ } else {
+ (*z).encodedTxns.encodedTxnHeaders.FirstValid = make([]basics.Round, zb0343)
+ }
+ for zb0007 := range (*z).encodedTxns.encodedTxnHeaders.FirstValid {
+ bts, err = (*z).encodedTxns.encodedTxnHeaders.FirstValid[zb0007].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FirstValid", zb0007)
+ return
+ }
+ }
+ case "fvbm":
+ {
+ var zb0345 []byte
+ var zb0346 int
+ zb0346, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFirstValid")
+ return
+ }
+ if zb0346 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0346), uint64(maxBitmaskSize))
+ return
+ }
+ zb0345, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskFirstValid))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFirstValid")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskFirstValid = bitmask(zb0345)
+ }
+ case "lv":
+ var zb0347 int
+ var zb0348 bool
+ zb0347, zb0348, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LastValid")
+ return
+ }
+ if zb0347 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0347), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LastValid")
+ return
+ }
+ if zb0348 {
+ (*z).encodedTxns.encodedTxnHeaders.LastValid = nil
+ } else if (*z).encodedTxns.encodedTxnHeaders.LastValid != nil && cap((*z).encodedTxns.encodedTxnHeaders.LastValid) >= zb0347 {
+ (*z).encodedTxns.encodedTxnHeaders.LastValid = ((*z).encodedTxns.encodedTxnHeaders.LastValid)[:zb0347]
+ } else {
+ (*z).encodedTxns.encodedTxnHeaders.LastValid = make([]basics.Round, zb0347)
+ }
+ for zb0008 := range (*z).encodedTxns.encodedTxnHeaders.LastValid {
+ bts, err = (*z).encodedTxns.encodedTxnHeaders.LastValid[zb0008].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LastValid", zb0008)
+ return
+ }
+ }
+ case "lvbm":
+ {
+ var zb0349 []byte
+ var zb0350 int
+ zb0350, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLastValid")
+ return
+ }
+ if zb0350 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0350), uint64(maxBitmaskSize))
+ return
+ }
+ zb0349, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskLastValid))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLastValid")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskLastValid = bitmask(zb0349)
+ }
+ case "note":
+ var zb0351 int
+ var zb0352 bool
+ zb0351, zb0352, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Note")
+ return
+ }
+ if zb0351 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0351), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Note")
+ return
+ }
+ if zb0352 {
+ (*z).encodedTxns.encodedTxnHeaders.Note = nil
+ } else if (*z).encodedTxns.encodedTxnHeaders.Note != nil && cap((*z).encodedTxns.encodedTxnHeaders.Note) >= zb0351 {
+ (*z).encodedTxns.encodedTxnHeaders.Note = ((*z).encodedTxns.encodedTxnHeaders.Note)[:zb0351]
+ } else {
+ (*z).encodedTxns.encodedTxnHeaders.Note = make([][]byte, zb0351)
+ }
+ for zb0009 := range (*z).encodedTxns.encodedTxnHeaders.Note {
+ var zb0353 int
+ zb0353, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Note", zb0009)
+ return
+ }
+ if zb0353 > config.MaxTxnNoteBytes {
+ err = msgp.ErrOverflow(uint64(zb0353), uint64(config.MaxTxnNoteBytes))
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.Note[zb0009], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedTxnHeaders.Note[zb0009])
+ if err != nil {
+ err = msgp.WrapError(err, "Note", zb0009)
+ return
+ }
+ }
+ case "notebm":
+ {
+ var zb0354 []byte
+ var zb0355 int
+ zb0355, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNote")
+ return
+ }
+ if zb0355 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0355), uint64(maxBitmaskSize))
+ return
+ }
+ zb0354, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskNote))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNote")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskNote = bitmask(zb0354)
+ }
+ case "genbm":
+ {
+ var zb0356 []byte
+ var zb0357 int
+ zb0357, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGenesisID")
+ return
+ }
+ if zb0357 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0357), uint64(maxBitmaskSize))
+ return
+ }
+ zb0356, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskGenesisID))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGenesisID")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskGenesisID = bitmask(zb0356)
+ }
+ case "grpbm":
+ {
+ var zb0358 []byte
+ var zb0359 int
+ zb0359, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGroup")
+ return
+ }
+ if zb0359 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0359), uint64(maxBitmaskSize))
+ return
+ }
+ zb0358, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskGroup))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGroup")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskGroup = bitmask(zb0358)
+ }
+ case "lx":
+ var zb0360 int
+ zb0360, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Lease")
+ return
+ }
+ if zb0360 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0360), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.Lease, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedTxnHeaders.Lease)
+ if err != nil {
+ err = msgp.WrapError(err, "Lease")
+ return
+ }
+ case "lxbm":
+ {
+ var zb0361 []byte
+ var zb0362 int
+ zb0362, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLease")
+ return
+ }
+ if zb0362 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0362), uint64(maxBitmaskSize))
+ return
+ }
+ zb0361, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskLease))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLease")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskLease = bitmask(zb0361)
+ }
+ case "rekey":
+ var zb0363 int
+ zb0363, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "RekeyTo")
+ return
+ }
+ if zb0363 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0363), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.RekeyTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedTxnHeaders.RekeyTo)
+ if err != nil {
+ err = msgp.WrapError(err, "RekeyTo")
+ return
+ }
+ case "rekeybm":
+ {
+ var zb0364 []byte
+ var zb0365 int
+ zb0365, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskRekeyTo")
+ return
+ }
+ if zb0365 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0365), uint64(maxBitmaskSize))
+ return
+ }
+ zb0364, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedTxnHeaders.BitmaskRekeyTo))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskRekeyTo")
+ return
+ }
+ (*z).encodedTxns.encodedTxnHeaders.BitmaskRekeyTo = bitmask(zb0364)
+ }
+ case "votekey":
+ var zb0366 int
+ zb0366, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VotePK")
+ return
+ }
+ if zb0366 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0366), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedKeyregTxnFields.VotePK, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedKeyregTxnFields.VotePK)
+ if err != nil {
+ err = msgp.WrapError(err, "VotePK")
+ return
+ }
+ case "selkey":
+ var zb0367 int
+ zb0367, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SelectionPK")
+ return
+ }
+ if zb0367 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0367), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedKeyregTxnFields.SelectionPK, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedKeyregTxnFields.SelectionPK)
+ if err != nil {
+ err = msgp.WrapError(err, "SelectionPK")
+ return
+ }
+ case "votefst":
+ var zb0368 int
+ var zb0369 bool
+ zb0368, zb0369, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteFirst")
+ return
+ }
+ if zb0368 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0368), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "VoteFirst")
+ return
+ }
+ if zb0369 {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst = nil
+ } else if (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst != nil && cap((*z).encodedTxns.encodedKeyregTxnFields.VoteFirst) >= zb0368 {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst = ((*z).encodedTxns.encodedKeyregTxnFields.VoteFirst)[:zb0368]
+ } else {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst = make([]basics.Round, zb0368)
+ }
+ for zb0010 := range (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst {
+ bts, err = (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst[zb0010].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteFirst", zb0010)
+ return
+ }
+ }
+ case "votefstbm":
+ {
+ var zb0370 []byte
+ var zb0371 int
+ zb0371, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteFirst")
+ return
+ }
+ if zb0371 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0371), uint64(maxBitmaskSize))
+ return
+ }
+ zb0370, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteFirst")
+ return
+ }
+ (*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst = bitmask(zb0370)
+ }
+ case "votelst":
+ var zb0372 int
+ var zb0373 bool
+ zb0372, zb0373, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteLast")
+ return
+ }
+ if zb0372 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0372), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "VoteLast")
+ return
+ }
+ if zb0373 {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteLast = nil
+ } else if (*z).encodedTxns.encodedKeyregTxnFields.VoteLast != nil && cap((*z).encodedTxns.encodedKeyregTxnFields.VoteLast) >= zb0372 {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteLast = ((*z).encodedTxns.encodedKeyregTxnFields.VoteLast)[:zb0372]
+ } else {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteLast = make([]basics.Round, zb0372)
+ }
+ for zb0011 := range (*z).encodedTxns.encodedKeyregTxnFields.VoteLast {
+ bts, err = (*z).encodedTxns.encodedKeyregTxnFields.VoteLast[zb0011].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteLast", zb0011)
+ return
+ }
+ }
+ case "votelstbm":
+ {
+ var zb0374 []byte
+ var zb0375 int
+ zb0375, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteLast")
+ return
+ }
+ if zb0375 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0375), uint64(maxBitmaskSize))
+ return
+ }
+ zb0374, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteLast")
+ return
+ }
+ (*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast = bitmask(zb0374)
+ }
+ case "votekd":
+ var zb0376 int
+ var zb0377 bool
+ zb0376, zb0377, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteKeyDilution")
+ return
+ }
+ if zb0376 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0376), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "VoteKeyDilution")
+ return
+ }
+ if zb0377 {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution = nil
+ } else if (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution != nil && cap((*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution) >= zb0376 {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution = ((*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution)[:zb0376]
+ } else {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution = make([]uint64, zb0376)
+ }
+ for zb0012 := range (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution {
+ (*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution[zb0012], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteKeyDilution", zb0012)
+ return
+ }
+ }
+ case "votekbm":
+ {
+ var zb0378 []byte
+ var zb0379 int
+ zb0379, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskKeys")
+ return
+ }
+ if zb0379 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0379), uint64(maxBitmaskSize))
+ return
+ }
+ zb0378, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskKeys))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskKeys")
+ return
+ }
+ (*z).encodedTxns.encodedKeyregTxnFields.BitmaskKeys = bitmask(zb0378)
+ }
+ case "nonpartbm":
+ {
+ var zb0380 []byte
+ var zb0381 int
+ zb0381, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNonparticipation")
+ return
+ }
+ if zb0381 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0381), uint64(maxBitmaskSize))
+ return
+ }
+ zb0380, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNonparticipation")
+ return
+ }
+ (*z).encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation = bitmask(zb0380)
+ }
+ case "rcv":
+ var zb0382 int
+ zb0382, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Receiver")
+ return
+ }
+ if zb0382 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0382), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedPaymentTxnFields.Receiver, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedPaymentTxnFields.Receiver)
+ if err != nil {
+ err = msgp.WrapError(err, "Receiver")
+ return
+ }
+ case "rcvbm":
+ {
+ var zb0383 []byte
+ var zb0384 int
+ zb0384, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReceiver")
+ return
+ }
+ if zb0384 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0384), uint64(maxBitmaskSize))
+ return
+ }
+ zb0383, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedPaymentTxnFields.BitmaskReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReceiver")
+ return
+ }
+ (*z).encodedTxns.encodedPaymentTxnFields.BitmaskReceiver = bitmask(zb0383)
+ }
+ case "amt":
+ var zb0385 int
+ var zb0386 bool
+ zb0385, zb0386, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Amount")
+ return
+ }
+ if zb0385 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0385), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Amount")
+ return
+ }
+ if zb0386 {
+ (*z).encodedTxns.encodedPaymentTxnFields.Amount = nil
+ } else if (*z).encodedTxns.encodedPaymentTxnFields.Amount != nil && cap((*z).encodedTxns.encodedPaymentTxnFields.Amount) >= zb0385 {
+ (*z).encodedTxns.encodedPaymentTxnFields.Amount = ((*z).encodedTxns.encodedPaymentTxnFields.Amount)[:zb0385]
+ } else {
+ (*z).encodedTxns.encodedPaymentTxnFields.Amount = make([]basics.MicroAlgos, zb0385)
+ }
+ for zb0013 := range (*z).encodedTxns.encodedPaymentTxnFields.Amount {
+ bts, err = (*z).encodedTxns.encodedPaymentTxnFields.Amount[zb0013].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Amount", zb0013)
+ return
+ }
+ }
+ case "amtbm":
+ {
+ var zb0387 []byte
+ var zb0388 int
+ zb0388, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAmount")
+ return
+ }
+ if zb0388 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0388), uint64(maxBitmaskSize))
+ return
+ }
+ zb0387, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedPaymentTxnFields.BitmaskAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAmount")
+ return
+ }
+ (*z).encodedTxns.encodedPaymentTxnFields.BitmaskAmount = bitmask(zb0387)
+ }
+ case "close":
+ var zb0389 int
+ zb0389, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CloseRemainderTo")
+ return
+ }
+ if zb0389 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0389), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedPaymentTxnFields.CloseRemainderTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedPaymentTxnFields.CloseRemainderTo)
+ if err != nil {
+ err = msgp.WrapError(err, "CloseRemainderTo")
+ return
+ }
+ case "closebm":
+ {
+ var zb0390 []byte
+ var zb0391 int
+ zb0391, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCloseRemainderTo")
+ return
+ }
+ if zb0391 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0391), uint64(maxBitmaskSize))
+ return
+ }
+ zb0390, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCloseRemainderTo")
+ return
+ }
+ (*z).encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo = bitmask(zb0390)
+ }
+ case "caid":
+ var zb0392 int
+ var zb0393 bool
+ zb0392, zb0393, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ConfigAsset")
+ return
+ }
+ if zb0392 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0392), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ConfigAsset")
+ return
+ }
+ if zb0393 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset = nil
+ } else if (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset != nil && cap((*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset) >= zb0392 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset = ((*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset)[:zb0392]
+ } else {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset = make([]basics.AssetIndex, zb0392)
+ }
+ for zb0014 := range (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset {
+ bts, err = (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset[zb0014].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ConfigAsset", zb0014)
+ return
+ }
+ }
+ case "caidbm":
+ {
+ var zb0394 []byte
+ var zb0395 int
+ zb0395, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskConfigAsset")
+ return
+ }
+ if zb0395 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0395), uint64(maxBitmaskSize))
+ return
+ }
+ zb0394, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskConfigAsset")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset = bitmask(zb0394)
+ }
+ case "t":
+ var zb0396 int
+ var zb0397 bool
+ zb0396, zb0397, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Total")
+ return
+ }
+ if zb0396 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0396), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Total")
+ return
+ }
+ if zb0397 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total = nil
+ } else if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total != nil && cap((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total) >= zb0396 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total = ((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total)[:zb0396]
+ } else {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total = make([]uint64, zb0396)
+ }
+ for zb0015 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total[zb0015], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Total", zb0015)
+ return
+ }
+ }
+ case "tbm":
+ {
+ var zb0398 []byte
+ var zb0399 int
+ zb0399, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTotal")
+ return
+ }
+ if zb0399 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0399), uint64(maxBitmaskSize))
+ return
+ }
+ zb0398, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTotal")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal = bitmask(zb0398)
+ }
+ case "dc":
+ var zb0400 int
+ var zb0401 bool
+ zb0400, zb0401, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Decimals")
+ return
+ }
+ if zb0400 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0400), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Decimals")
+ return
+ }
+ if zb0401 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals = nil
+ } else if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals != nil && cap((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals) >= zb0400 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals = ((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals)[:zb0400]
+ } else {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals = make([]uint32, zb0400)
+ }
+ for zb0016 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals[zb0016], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Decimals", zb0016)
+ return
+ }
+ }
+ case "dcbm":
+ {
+ var zb0402 []byte
+ var zb0403 int
+ zb0403, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDecimals")
+ return
+ }
+ if zb0403 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0403), uint64(maxBitmaskSize))
+ return
+ }
+ zb0402, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDecimals")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals = bitmask(zb0402)
+ }
+ case "dfbm":
+ {
+ var zb0404 []byte
+ var zb0405 int
+ zb0405, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDefaultFrozen")
+ return
+ }
+ if zb0405 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0405), uint64(maxBitmaskSize))
+ return
+ }
+ zb0404, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDefaultFrozen")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen = bitmask(zb0404)
+ }
+ case "un":
+ var zb0406 int
+ var zb0407 bool
+ zb0406, zb0407, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UnitName")
+ return
+ }
+ if zb0406 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0406), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "UnitName")
+ return
+ }
+ if zb0407 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName = nil
+ } else if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName != nil && cap((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName) >= zb0406 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName = ((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName)[:zb0406]
+ } else {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName = make([]string, zb0406)
+ }
+ for zb0017 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName[zb0017], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UnitName", zb0017)
+ return
+ }
+ }
+ case "unbm":
+ {
+ var zb0408 []byte
+ var zb0409 int
+ zb0409, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskUnitName")
+ return
+ }
+ if zb0409 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0409), uint64(maxBitmaskSize))
+ return
+ }
+ zb0408, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskUnitName")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName = bitmask(zb0408)
+ }
+ case "an":
+ var zb0410 int
+ var zb0411 bool
+ zb0410, zb0411, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetName")
+ return
+ }
+ if zb0410 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0410), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "AssetName")
+ return
+ }
+ if zb0411 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName = nil
+ } else if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName != nil && cap((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName) >= zb0410 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName = ((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName)[:zb0410]
+ } else {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName = make([]string, zb0410)
+ }
+ for zb0018 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName[zb0018], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetName", zb0018)
+ return
+ }
+ }
+ case "anbm":
+ {
+ var zb0412 []byte
+ var zb0413 int
+ zb0413, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetName")
+ return
+ }
+ if zb0413 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0413), uint64(maxBitmaskSize))
+ return
+ }
+ zb0412, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetName")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName = bitmask(zb0412)
+ }
+ case "au":
+ var zb0414 int
+ var zb0415 bool
+ zb0414, zb0415, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "URL")
+ return
+ }
+ if zb0414 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0414), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "URL")
+ return
+ }
+ if zb0415 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL = nil
+ } else if (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL != nil && cap((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL) >= zb0414 {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL = ((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL)[:zb0414]
+ } else {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL = make([]string, zb0414)
+ }
+ for zb0019 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL {
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL[zb0019], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "URL", zb0019)
+ return
+ }
+ }
+ case "aubm":
+ {
+ var zb0416 []byte
+ var zb0417 int
+ zb0417, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskURL")
+ return
+ }
+ if zb0417 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0417), uint64(maxBitmaskSize))
+ return
+ }
+ zb0416, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskURL")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL = bitmask(zb0416)
+ }
+ case "am":
+ var zb0418 int
+ zb0418, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "MetadataHash")
+ return
+ }
+ if zb0418 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0418), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash)
+ if err != nil {
+ err = msgp.WrapError(err, "MetadataHash")
+ return
+ }
+ case "ambm":
+ {
+ var zb0419 []byte
+ var zb0420 int
+ zb0420, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskMetadataHash")
+ return
+ }
+ if zb0420 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0420), uint64(maxBitmaskSize))
+ return
+ }
+ zb0419, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskMetadataHash")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash = bitmask(zb0419)
+ }
+ case "m":
+ var zb0421 int
+ zb0421, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Manager")
+ return
+ }
+ if zb0421 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0421), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager)
+ if err != nil {
+ err = msgp.WrapError(err, "Manager")
+ return
+ }
+ case "mbm":
+ {
+ var zb0422 []byte
+ var zb0423 int
+ zb0423, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskManager")
+ return
+ }
+ if zb0423 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0423), uint64(maxBitmaskSize))
+ return
+ }
+ zb0422, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskManager")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager = bitmask(zb0422)
+ }
+ case "r":
+ var zb0424 int
+ zb0424, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reserve")
+ return
+ }
+ if zb0424 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0424), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve)
+ if err != nil {
+ err = msgp.WrapError(err, "Reserve")
+ return
+ }
+ case "rbm":
+ {
+ var zb0425 []byte
+ var zb0426 int
+ zb0426, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReserve")
+ return
+ }
+ if zb0426 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0426), uint64(maxBitmaskSize))
+ return
+ }
+ zb0425, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReserve")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve = bitmask(zb0425)
+ }
+ case "f":
+ var zb0427 int
+ zb0427, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Freeze")
+ return
+ }
+ if zb0427 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0427), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze)
+ if err != nil {
+ err = msgp.WrapError(err, "Freeze")
+ return
+ }
+ case "fbm":
+ {
+ var zb0428 []byte
+ var zb0429 int
+ zb0429, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreeze")
+ return
+ }
+ if zb0429 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0429), uint64(maxBitmaskSize))
+ return
+ }
+ zb0428, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreeze")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze = bitmask(zb0428)
+ }
+ case "c":
+ var zb0430 int
+ zb0430, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Clawback")
+ return
+ }
+ if zb0430 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0430), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback)
+ if err != nil {
+ err = msgp.WrapError(err, "Clawback")
+ return
+ }
+ case "cbm":
+ {
+ var zb0431 []byte
+ var zb0432 int
+ zb0432, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClawback")
+ return
+ }
+ if zb0432 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0432), uint64(maxBitmaskSize))
+ return
+ }
+ zb0431, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClawback")
+ return
+ }
+ (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback = bitmask(zb0431)
+ }
+ case "xaid":
+ var zb0433 int
+ var zb0434 bool
+ zb0433, zb0434, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "XferAsset")
+ return
+ }
+ if zb0433 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0433), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "XferAsset")
+ return
+ }
+ if zb0434 {
+ (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset = nil
+ } else if (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset != nil && cap((*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset) >= zb0433 {
+ (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset = ((*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset)[:zb0433]
+ } else {
+ (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset = make([]basics.AssetIndex, zb0433)
+ }
+ for zb0020 := range (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset {
+ bts, err = (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset[zb0020].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "XferAsset", zb0020)
+ return
+ }
+ }
+ case "xaidbm":
+ {
+ var zb0435 []byte
+ var zb0436 int
+ zb0436, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskXferAsset")
+ return
+ }
+ if zb0436 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0436), uint64(maxBitmaskSize))
+ return
+ }
+ zb0435, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskXferAsset")
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset = bitmask(zb0435)
+ }
+ case "aamt":
+ var zb0437 int
+ var zb0438 bool
+ zb0437, zb0438, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetAmount")
+ return
+ }
+ if zb0437 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0437), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "AssetAmount")
+ return
+ }
+ if zb0438 {
+ (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount = nil
+ } else if (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount != nil && cap((*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount) >= zb0437 {
+ (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount = ((*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount)[:zb0437]
+ } else {
+ (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount = make([]uint64, zb0437)
+ }
+ for zb0021 := range (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount {
+ (*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount[zb0021], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetAmount", zb0021)
+ return
+ }
+ }
+ case "aamtbm":
+ {
+ var zb0439 []byte
+ var zb0440 int
+ zb0440, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetAmount")
+ return
+ }
+ if zb0440 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0440), uint64(maxBitmaskSize))
+ return
+ }
+ zb0439, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetAmount")
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount = bitmask(zb0439)
+ }
+ case "asnd":
+ var zb0441 int
+ zb0441, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetSender")
+ return
+ }
+ if zb0441 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0441), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.AssetSender, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetTransferTxnFields.AssetSender)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetSender")
+ return
+ }
+ case "asndbm":
+ {
+ var zb0442 []byte
+ var zb0443 int
+ zb0443, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetSender")
+ return
+ }
+ if zb0443 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0443), uint64(maxBitmaskSize))
+ return
+ }
+ zb0442, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetSender")
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender = bitmask(zb0442)
+ }
+ case "arcv":
+ var zb0444 int
+ zb0444, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetReceiver")
+ return
+ }
+ if zb0444 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0444), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.AssetReceiver, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetTransferTxnFields.AssetReceiver)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetReceiver")
+ return
+ }
+ case "arcvbm":
+ {
+ var zb0445 []byte
+ var zb0446 int
+ zb0446, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetReceiver")
+ return
+ }
+ if zb0446 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0446), uint64(maxBitmaskSize))
+ return
+ }
+ zb0445, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetReceiver")
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver = bitmask(zb0445)
+ }
+ case "aclose":
+ var zb0447 int
+ zb0447, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetCloseTo")
+ return
+ }
+ if zb0447 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0447), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetCloseTo")
+ return
+ }
+ case "aclosebm":
+ {
+ var zb0448 []byte
+ var zb0449 int
+ zb0449, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetCloseTo")
+ return
+ }
+ if zb0449 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0449), uint64(maxBitmaskSize))
+ return
+ }
+ zb0448, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetCloseTo")
+ return
+ }
+ (*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo = bitmask(zb0448)
+ }
+ case "fadd":
+ var zb0450 int
+ zb0450, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAccount")
+ return
+ }
+ if zb0450 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0450), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAccount")
+ return
+ }
+ case "faddbm":
+ {
+ var zb0451 []byte
+ var zb0452 int
+ zb0452, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAccount")
+ return
+ }
+ if zb0452 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0452), uint64(maxBitmaskSize))
+ return
+ }
+ zb0451, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAccount")
+ return
+ }
+ (*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount = bitmask(zb0451)
+ }
+ case "faid":
+ var zb0453 int
+ var zb0454 bool
+ zb0453, zb0454, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAsset")
+ return
+ }
+ if zb0453 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0453), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "FreezeAsset")
+ return
+ }
+ if zb0454 {
+ (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset = nil
+ } else if (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset != nil && cap((*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset) >= zb0453 {
+ (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset = ((*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset)[:zb0453]
+ } else {
+ (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset = make([]basics.AssetIndex, zb0453)
+ }
+ for zb0022 := range (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset {
+ bts, err = (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset[zb0022].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAsset", zb0022)
+ return
+ }
+ }
+ case "faidbm":
+ {
+ var zb0455 []byte
+ var zb0456 int
+ zb0456, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAsset")
+ return
+ }
+ if zb0456 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0456), uint64(maxBitmaskSize))
+ return
+ }
+ zb0455, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAsset")
+ return
+ }
+ (*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset = bitmask(zb0455)
+ }
+ case "afrzbm":
+ {
+ var zb0457 []byte
+ var zb0458 int
+ zb0458, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetFrozen")
+ return
+ }
+ if zb0458 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0458), uint64(maxBitmaskSize))
+ return
+ }
+ zb0457, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetFrozen")
+ return
+ }
+ (*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen = bitmask(zb0457)
+ }
+ case "apid":
+ var zb0459 int
+ var zb0460 bool
+ zb0459, zb0460, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationID")
+ return
+ }
+ if zb0459 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0459), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ApplicationID")
+ return
+ }
+ if zb0460 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID) >= zb0459 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID = ((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID)[:zb0459]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID = make([]basics.AppIndex, zb0459)
+ }
+ for zb0023 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID {
+ bts, err = (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID[zb0023].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationID", zb0023)
+ return
+ }
+ }
+ case "apidbm":
+ {
+ var zb0461 []byte
+ var zb0462 int
+ zb0462, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationID")
+ return
+ }
+ if zb0462 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0462), uint64(maxBitmaskSize))
+ return
+ }
+ zb0461, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationID")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID = bitmask(zb0461)
+ }
+ case "apan":
+ var zb0463 int
+ zb0463, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "OnCompletion")
+ return
+ }
+ if zb0463 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0463), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.OnCompletion, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedApplicationCallTxnFields.OnCompletion)
+ if err != nil {
+ err = msgp.WrapError(err, "OnCompletion")
+ return
+ }
+ case "apanbm":
+ {
+ var zb0464 []byte
+ var zb0465 int
+ zb0465, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskOnCompletion")
+ return
+ }
+ if zb0465 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0465), uint64(maxBitmaskSize))
+ return
+ }
+ zb0464, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskOnCompletion")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion = bitmask(zb0464)
+ }
+ case "apaa":
+ var zb0466 int
+ var zb0467 bool
+ zb0466, zb0467, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationArgs")
+ return
+ }
+ if zb0466 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0466), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ApplicationArgs")
+ return
+ }
+ if zb0467 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs) >= zb0466 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs = ((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs)[:zb0466]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs = make([]applicationArgs, zb0466)
+ }
+ for zb0024 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs {
+ var zb0468 int
+ var zb0469 bool
+ zb0468, zb0469, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationArgs", zb0024)
+ return
+ }
+ if zb0468 > transactions.EncodedMaxApplicationArgs {
+ err = msgp.ErrOverflow(uint64(zb0468), uint64(transactions.EncodedMaxApplicationArgs))
+ err = msgp.WrapError(err, "ApplicationArgs", zb0024)
+ return
+ }
+ if zb0469 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024]) >= zb0468 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] = ((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024])[:zb0468]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] = make(applicationArgs, zb0468)
+ }
+ for zb0025 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024][zb0025], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024][zb0025])
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationArgs", zb0024, zb0025)
+ return
+ }
+ }
+ }
+ case "apaabm":
+ {
+ var zb0470 []byte
+ var zb0471 int
+ zb0471, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationArgs")
+ return
+ }
+ if zb0471 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0471), uint64(maxBitmaskSize))
+ return
+ }
+ zb0470, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationArgs")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs = bitmask(zb0470)
+ }
+ case "apat":
+ var zb0472 int
+ var zb0473 bool
+ zb0472, zb0473, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Accounts")
+ return
+ }
+ if zb0472 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0472), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Accounts")
+ return
+ }
+ if zb0473 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.Accounts) >= zb0472 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts = ((*z).encodedTxns.encodedApplicationCallTxnFields.Accounts)[:zb0472]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts = make([]addresses, zb0472)
+ }
+ for zb0026 := range (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts {
+ var zb0474 int
+ var zb0475 bool
+ zb0474, zb0475, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Accounts", zb0026)
+ return
+ }
+ if zb0474 > transactions.EncodedMaxAccounts {
+ err = msgp.ErrOverflow(uint64(zb0474), uint64(transactions.EncodedMaxAccounts))
+ err = msgp.WrapError(err, "Accounts", zb0026)
+ return
+ }
+ if zb0475 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026]) >= zb0474 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] = ((*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026])[:zb0474]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] = make(addresses, zb0474)
+ }
+ for zb0027 := range (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] {
+ bts, err = (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026][zb0027].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Accounts", zb0026, zb0027)
+ return
+ }
+ }
+ }
+ case "apatbm":
+ {
+ var zb0476 []byte
+ var zb0477 int
+ zb0477, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAccounts")
+ return
+ }
+ if zb0477 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0477), uint64(maxBitmaskSize))
+ return
+ }
+ zb0476, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAccounts")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts = bitmask(zb0476)
+ }
+ case "apfa":
+ var zb0478 int
+ var zb0479 bool
+ zb0478, zb0479, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignApps")
+ return
+ }
+ if zb0478 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0478), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ForeignApps")
+ return
+ }
+ if zb0479 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps) >= zb0478 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps = ((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps)[:zb0478]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps = make([]appIndices, zb0478)
+ }
+ for zb0028 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps {
+ var zb0480 int
+ var zb0481 bool
+ zb0480, zb0481, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignApps", zb0028)
+ return
+ }
+ if zb0480 > transactions.EncodedMaxForeignApps {
+ err = msgp.ErrOverflow(uint64(zb0480), uint64(transactions.EncodedMaxForeignApps))
+ err = msgp.WrapError(err, "ForeignApps", zb0028)
+ return
+ }
+ if zb0481 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028]) >= zb0480 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] = ((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028])[:zb0480]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] = make(appIndices, zb0480)
+ }
+ for zb0029 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] {
+ bts, err = (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028][zb0029].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignApps", zb0028, zb0029)
+ return
+ }
+ }
+ }
+ case "apfabm":
+ {
+ var zb0482 []byte
+ var zb0483 int
+ zb0483, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignApps")
+ return
+ }
+ if zb0483 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0483), uint64(maxBitmaskSize))
+ return
+ }
+ zb0482, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignApps")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps = bitmask(zb0482)
+ }
+ case "apas":
+ var zb0484 int
+ var zb0485 bool
+ zb0484, zb0485, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignAssets")
+ return
+ }
+ if zb0484 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0484), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ForeignAssets")
+ return
+ }
+ if zb0485 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets) >= zb0484 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets = ((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets)[:zb0484]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets = make([]assetIndices, zb0484)
+ }
+ for zb0030 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets {
+ var zb0486 int
+ var zb0487 bool
+ zb0486, zb0487, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignAssets", zb0030)
+ return
+ }
+ if zb0486 > transactions.EncodedMaxForeignAssets {
+ err = msgp.ErrOverflow(uint64(zb0486), uint64(transactions.EncodedMaxForeignAssets))
+ err = msgp.WrapError(err, "ForeignAssets", zb0030)
+ return
+ }
+ if zb0487 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030]) >= zb0486 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] = ((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030])[:zb0486]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] = make(assetIndices, zb0486)
+ }
+ for zb0031 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] {
+ bts, err = (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030][zb0031].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignAssets", zb0030, zb0031)
+ return
+ }
+ }
+ }
+ case "apasbm":
+ {
+ var zb0488 []byte
+ var zb0489 int
+ zb0489, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignAssets")
+ return
+ }
+ if zb0489 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0489), uint64(maxBitmaskSize))
+ return
+ }
+ zb0488, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignAssets")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets = bitmask(zb0488)
+ }
+ case "lnui":
+ var zb0490 int
+ var zb0491 bool
+ zb0490, zb0491, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumUint")
+ return
+ }
+ if zb0490 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0490), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LocalNumUint")
+ return
+ }
+ if zb0491 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint) >= zb0490 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint = ((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint)[:zb0490]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint = make([]uint64, zb0490)
+ }
+ for zb0032 := range (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint[zb0032], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumUint", zb0032)
+ return
+ }
+ }
+ case "lnuibm":
+ {
+ var zb0492 []byte
+ var zb0493 int
+ zb0493, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumUint")
+ return
+ }
+ if zb0493 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0493), uint64(maxBitmaskSize))
+ return
+ }
+ zb0492, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumUint")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint = bitmask(zb0492)
+ }
+ case "lnbs":
+ var zb0494 int
+ var zb0495 bool
+ zb0494, zb0495, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumByteSlice")
+ return
+ }
+ if zb0494 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0494), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LocalNumByteSlice")
+ return
+ }
+ if zb0495 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice) >= zb0494 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice = ((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice)[:zb0494]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice = make([]uint64, zb0494)
+ }
+ for zb0033 := range (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice[zb0033], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumByteSlice", zb0033)
+ return
+ }
+ }
+ case "lnbsbm":
+ {
+ var zb0496 []byte
+ var zb0497 int
+ zb0497, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumByteSlice")
+ return
+ }
+ if zb0497 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0497), uint64(maxBitmaskSize))
+ return
+ }
+ zb0496, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumByteSlice")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice = bitmask(zb0496)
+ }
+ case "gnui":
+ var zb0498 int
+ var zb0499 bool
+ zb0498, zb0499, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumUint")
+ return
+ }
+ if zb0498 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0498), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "GlobalNumUint")
+ return
+ }
+ if zb0499 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint) >= zb0498 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint = ((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint)[:zb0498]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint = make([]uint64, zb0498)
+ }
+ for zb0034 := range (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint[zb0034], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumUint", zb0034)
+ return
+ }
+ }
+ case "gnuibm":
+ {
+ var zb0500 []byte
+ var zb0501 int
+ zb0501, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumUint")
+ return
+ }
+ if zb0501 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0501), uint64(maxBitmaskSize))
+ return
+ }
+ zb0500, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumUint")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint = bitmask(zb0500)
+ }
+ case "gnbs":
+ var zb0502 int
+ var zb0503 bool
+ zb0502, zb0503, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumByteSlice")
+ return
+ }
+ if zb0502 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0502), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "GlobalNumByteSlice")
+ return
+ }
+ if zb0503 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice) >= zb0502 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice = ((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice)[:zb0502]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice = make([]uint64, zb0502)
+ }
+ for zb0035 := range (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice[zb0035], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumByteSlice", zb0035)
+ return
+ }
+ }
+ case "gnbsbm":
+ {
+ var zb0504 []byte
+ var zb0505 int
+ zb0505, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumByteSlice")
+ return
+ }
+ if zb0505 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0505), uint64(maxBitmaskSize))
+ return
+ }
+ zb0504, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumByteSlice")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice = bitmask(zb0504)
+ }
+ case "apap":
+ var zb0506 int
+ var zb0507 bool
+ zb0506, zb0507, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApprovalProgram")
+ return
+ }
+ if zb0506 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0506), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ApprovalProgram")
+ return
+ }
+ if zb0507 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram) >= zb0506 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram = ((*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram)[:zb0506]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram = make([]program, zb0506)
+ }
+ for zb0036 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram {
+ {
+ var zb0508 []byte
+ var zb0509 int
+ zb0509, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApprovalProgram", zb0036)
+ return
+ }
+ if zb0509 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0509), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0508, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram[zb0036]))
+ if err != nil {
+ err = msgp.WrapError(err, "ApprovalProgram", zb0036)
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram[zb0036] = program(zb0508)
+ }
+ }
+ case "apapbm":
+ {
+ var zb0510 []byte
+ var zb0511 int
+ zb0511, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApprovalProgram")
+ return
+ }
+ if zb0511 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0511), uint64(maxBitmaskSize))
+ return
+ }
+ zb0510, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApprovalProgram")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram = bitmask(zb0510)
+ }
+ case "apsu":
+ var zb0512 int
+ var zb0513 bool
+ zb0512, zb0513, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ClearStateProgram")
+ return
+ }
+ if zb0512 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0512), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ClearStateProgram")
+ return
+ }
+ if zb0513 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram) >= zb0512 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram = ((*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram)[:zb0512]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram = make([]program, zb0512)
+ }
+ for zb0037 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram {
+ {
+ var zb0514 []byte
+ var zb0515 int
+ zb0515, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ClearStateProgram", zb0037)
+ return
+ }
+ if zb0515 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0515), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0514, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram[zb0037]))
+ if err != nil {
+ err = msgp.WrapError(err, "ClearStateProgram", zb0037)
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram[zb0037] = program(zb0514)
+ }
+ }
+ case "apsubm":
+ {
+ var zb0516 []byte
+ var zb0517 int
+ zb0517, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClearStateProgram")
+ return
+ }
+ if zb0517 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0517), uint64(maxBitmaskSize))
+ return
+ }
+ zb0516, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClearStateProgram")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram = bitmask(zb0516)
+ }
+ case "apep":
+ var zb0518 int
+ var zb0519 bool
+ zb0518, zb0519, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExtraProgramPages")
+ return
+ }
+ if zb0518 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0518), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ExtraProgramPages")
+ return
+ }
+ if zb0519 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages = nil
+ } else if (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages != nil && cap((*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages) >= zb0518 {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages = ((*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages)[:zb0518]
+ } else {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages = make([]uint32, zb0518)
+ }
+ for zb0038 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages {
+ (*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages[zb0038], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExtraProgramPages", zb0038)
+ return
+ }
+ }
+ case "apepbm":
+ {
+ var zb0520 []byte
+ var zb0521 int
+ zb0521, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskExtraProgramPages")
+ return
+ }
+ if zb0521 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0521), uint64(maxBitmaskSize))
+ return
+ }
+ zb0520, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskExtraProgramPages")
+ return
+ }
+ (*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages = bitmask(zb0520)
+ }
+ case "certrnd":
+ var zb0522 int
+ var zb0523 bool
+ zb0522, zb0523, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertRound")
+ return
+ }
+ if zb0522 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0522), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "CertRound")
+ return
+ }
+ if zb0523 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.CertRound = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.CertRound != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.CertRound) >= zb0522 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.CertRound = ((*z).encodedTxns.encodedCompactCertTxnFields.CertRound)[:zb0522]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.CertRound = make([]basics.Round, zb0522)
+ }
+ for zb0039 := range (*z).encodedTxns.encodedCompactCertTxnFields.CertRound {
+ bts, err = (*z).encodedTxns.encodedCompactCertTxnFields.CertRound[zb0039].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertRound", zb0039)
+ return
+ }
+ }
+ case "certrndbm":
+ {
+ var zb0524 []byte
+ var zb0525 int
+ zb0525, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertRound")
+ return
+ }
+ if zb0525 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0525), uint64(maxBitmaskSize))
+ return
+ }
+ zb0524, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertRound")
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound = bitmask(zb0524)
+ }
+ case "certtype":
+ var zb0526 int
+ var zb0527 bool
+ zb0526, zb0527, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertType")
+ return
+ }
+ if zb0526 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0526), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "CertType")
+ return
+ }
+ if zb0527 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.CertType = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.CertType != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.CertType) >= zb0526 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.CertType = ((*z).encodedTxns.encodedCompactCertTxnFields.CertType)[:zb0526]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.CertType = make([]protocol.CompactCertType, zb0526)
+ }
+ for zb0040 := range (*z).encodedTxns.encodedCompactCertTxnFields.CertType {
+ bts, err = (*z).encodedTxns.encodedCompactCertTxnFields.CertType[zb0040].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertType", zb0040)
+ return
+ }
+ }
+ case "certtypebm":
+ {
+ var zb0528 []byte
+ var zb0529 int
+ zb0529, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertType")
+ return
+ }
+ if zb0529 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0529), uint64(maxBitmaskSize))
+ return
+ }
+ zb0528, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertType))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertType")
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertType = bitmask(zb0528)
+ }
+ case "certc":
+ var zb0530 int
+ zb0530, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigCommit")
+ return
+ }
+ if zb0530 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0530), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit)
+ if err != nil {
+ err = msgp.WrapError(err, "SigCommit")
+ return
+ }
+ case "certcbm":
+ {
+ var zb0531 []byte
+ var zb0532 int
+ zb0532, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigCommit")
+ return
+ }
+ if zb0532 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0532), uint64(maxBitmaskSize))
+ return
+ }
+ zb0531, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigCommit")
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit = bitmask(zb0531)
+ }
+ case "certw":
+ var zb0533 int
+ var zb0534 bool
+ zb0533, zb0534, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SignedWeight")
+ return
+ }
+ if zb0533 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0533), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "SignedWeight")
+ return
+ }
+ if zb0534 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight) >= zb0533 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight = ((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight)[:zb0533]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight = make([]uint64, zb0533)
+ }
+ for zb0041 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight[zb0041], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SignedWeight", zb0041)
+ return
+ }
+ }
+ case "certwbm":
+ {
+ var zb0535 []byte
+ var zb0536 int
+ zb0536, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSignedWeight")
+ return
+ }
+ if zb0536 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0536), uint64(maxBitmaskSize))
+ return
+ }
+ zb0535, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSignedWeight")
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight = bitmask(zb0535)
+ }
+ case "certS":
+ var zb0537 int
+ var zb0538 bool
+ zb0537, zb0538, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs")
+ return
+ }
+ if zb0537 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0537), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "SigProofs")
+ return
+ }
+ if zb0538 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs) >= zb0537 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs = ((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs)[:zb0537]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs = make([]certProofs, zb0537)
+ }
+ for zb0042 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs {
+ var zb0539 int
+ var zb0540 bool
+ zb0539, zb0540, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs", zb0042)
+ return
+ }
+ if zb0539 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0539), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "SigProofs", zb0042)
+ return
+ }
+ if zb0540 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042]) >= zb0539 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] = ((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042])[:zb0539]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] = make(certProofs, zb0539)
+ }
+ for zb0043 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] {
+ bts, err = (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042][zb0043].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs", zb0042, zb0043)
+ return
+ }
+ }
+ }
+ case "certSbm":
+ {
+ var zb0541 []byte
+ var zb0542 int
+ zb0542, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigProofs")
+ return
+ }
+ if zb0542 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0542), uint64(maxBitmaskSize))
+ return
+ }
+ zb0541, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigProofs")
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs = bitmask(zb0541)
+ }
+ case "certP":
+ var zb0543 int
+ var zb0544 bool
+ zb0543, zb0544, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs")
+ return
+ }
+ if zb0543 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0543), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "PartProofs")
+ return
+ }
+ if zb0544 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs) >= zb0543 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs = ((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs)[:zb0543]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs = make([]certProofs, zb0543)
+ }
+ for zb0044 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs {
+ var zb0545 int
+ var zb0546 bool
+ zb0545, zb0546, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs", zb0044)
+ return
+ }
+ if zb0545 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0545), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "PartProofs", zb0044)
+ return
+ }
+ if zb0546 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044]) >= zb0545 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] = ((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044])[:zb0545]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] = make(certProofs, zb0545)
+ }
+ for zb0045 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] {
+ bts, err = (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044][zb0045].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs", zb0044, zb0045)
+ return
+ }
+ }
+ }
+ case "certPbm":
+ {
+ var zb0547 []byte
+ var zb0548 int
+ zb0548, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskPartProofs")
+ return
+ }
+ if zb0548 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0548), uint64(maxBitmaskSize))
+ return
+ }
+ zb0547, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskPartProofs")
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs = bitmask(zb0547)
+ }
+ case "certr":
+ var zb0549 int
+ var zb0550 bool
+ zb0549, zb0550, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals")
+ return
+ }
+ if zb0549 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0549), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Reveals")
+ return
+ }
+ if zb0550 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals != nil && cap((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals) >= zb0549 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals = ((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals)[:zb0549]
+ } else {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals = make([]revealMap, zb0549)
+ }
+ for zb0046 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals {
+ var zb0551 int
+ var zb0552 bool
+ zb0551, zb0552, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0046)
+ return
+ }
+ if zb0551 > compactcert.MaxReveals {
+ err = msgp.ErrOverflow(uint64(zb0551), uint64(compactcert.MaxReveals))
+ err = msgp.WrapError(err, "Reveals", zb0046)
+ return
+ }
+ if zb0552 {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] = nil
+ } else if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] == nil {
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] = make(revealMap, zb0551)
+ }
+ for zb0551 > 0 {
+ var zb0047 uint64
+ var zb0048 compactcert.Reveal
+ zb0551--
+ zb0047, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0046)
+ return
+ }
+ bts, err = zb0048.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0046, zb0047)
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046][zb0047] = zb0048
+ }
+ }
+ case "certrbm":
+ {
+ var zb0553 []byte
+ var zb0554 int
+ zb0554, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReveals")
+ return
+ }
+ if zb0554 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0554), uint64(maxBitmaskSize))
+ return
+ }
+ zb0553, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReveals")
+ return
+ }
+ (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals = bitmask(zb0553)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedSignedTxns) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedSignedTxns)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedSignedTxns) Msgsize() (s int) {
+ s = 3 + 4 + msgp.BytesPrefixSize + len((*z).Sig) + 6 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskSig)) + 6 + msgp.BytesPrefixSize + len((*z).encodedMsigs.Version) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedMsigs.BitmaskVersion)) + 8 + msgp.BytesPrefixSize + len((*z).encodedMsigs.Threshold) + 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedMsigs.BitmaskThreshold)) + 7 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).encodedMsigs.Subsigs {
+ s += msgp.ArrayHeaderSize
+ for zb0002 := range (*z).encodedMsigs.Subsigs[zb0001] {
+ s += (*z).encodedMsigs.Subsigs[zb0001][zb0002].Msgsize()
+ }
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedMsigs.BitmaskSubsigs)) + 6 + msgp.ArrayHeaderSize
+ for zb0003 := range (*z).encodedLsigs.Logic {
+ s += msgp.BytesPrefixSize + len((*z).encodedLsigs.Logic[zb0003])
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedLsigs.BitmaskLogic)) + 8 + msgp.ArrayHeaderSize
+ for zb0004 := range (*z).encodedLsigs.LogicArgs {
+ s += msgp.ArrayHeaderSize
+ for zb0005 := range (*z).encodedLsigs.LogicArgs[zb0004] {
+ s += msgp.BytesPrefixSize + len((*z).encodedLsigs.LogicArgs[zb0004][zb0005])
+ }
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedLsigs.BitmaskLogicArgs)) + 5 + msgp.BytesPrefixSize + len((*z).AuthAddr) + 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskAuthAddr)) + 5 + msgp.BytesPrefixSize + len((*z).encodedTxns.TxType) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.BitmaskTxType)) + 6 + msgp.ByteSize + 4 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedTxnHeaders.Sender) + 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedTxnHeaders.BitmaskSender)) + 4 + msgp.ArrayHeaderSize
+ for zb0006 := range (*z).encodedTxns.encodedTxnHeaders.Fee {
+ s += (*z).encodedTxns.encodedTxnHeaders.Fee[zb0006].Msgsize()
+ }
+ s += 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedTxnHeaders.BitmaskFee)) + 3 + msgp.ArrayHeaderSize
+ for zb0007 := range (*z).encodedTxns.encodedTxnHeaders.FirstValid {
+ s += (*z).encodedTxns.encodedTxnHeaders.FirstValid[zb0007].Msgsize()
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedTxnHeaders.BitmaskFirstValid)) + 3 + msgp.ArrayHeaderSize
+ for zb0008 := range (*z).encodedTxns.encodedTxnHeaders.LastValid {
+ s += (*z).encodedTxns.encodedTxnHeaders.LastValid[zb0008].Msgsize()
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedTxnHeaders.BitmaskLastValid)) + 5 + msgp.ArrayHeaderSize
+ for zb0009 := range (*z).encodedTxns.encodedTxnHeaders.Note {
+ s += msgp.BytesPrefixSize + len((*z).encodedTxns.encodedTxnHeaders.Note[zb0009])
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedTxnHeaders.BitmaskNote)) + 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedTxnHeaders.BitmaskGenesisID)) + 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedTxnHeaders.BitmaskGroup)) + 3 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedTxnHeaders.Lease) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedTxnHeaders.BitmaskLease)) + 6 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedTxnHeaders.RekeyTo) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedTxnHeaders.BitmaskRekeyTo)) + 8 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedKeyregTxnFields.VotePK) + 7 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedKeyregTxnFields.SelectionPK) + 8 + msgp.ArrayHeaderSize
+ for zb0010 := range (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst {
+ s += (*z).encodedTxns.encodedKeyregTxnFields.VoteFirst[zb0010].Msgsize()
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst)) + 8 + msgp.ArrayHeaderSize
+ for zb0011 := range (*z).encodedTxns.encodedKeyregTxnFields.VoteLast {
+ s += (*z).encodedTxns.encodedKeyregTxnFields.VoteLast[zb0011].Msgsize()
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast)) + 7 + msgp.ArrayHeaderSize + (len((*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution) * (msgp.Uint64Size)) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskKeys)) + 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation)) + 4 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedPaymentTxnFields.Receiver) + 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedPaymentTxnFields.BitmaskReceiver)) + 4 + msgp.ArrayHeaderSize
+ for zb0013 := range (*z).encodedTxns.encodedPaymentTxnFields.Amount {
+ s += (*z).encodedTxns.encodedPaymentTxnFields.Amount[zb0013].Msgsize()
+ }
+ s += 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedPaymentTxnFields.BitmaskAmount)) + 6 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedPaymentTxnFields.CloseRemainderTo) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo)) + 5 + msgp.ArrayHeaderSize
+ for zb0014 := range (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset {
+ s += (*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset[zb0014].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset)) + 2 + msgp.ArrayHeaderSize + (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total) * (msgp.Uint64Size)) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal)) + 3 + msgp.ArrayHeaderSize + (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals) * (msgp.Uint32Size)) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals)) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen)) + 3 + msgp.ArrayHeaderSize
+ for zb0017 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName {
+ s += msgp.StringPrefixSize + len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName[zb0017])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName)) + 3 + msgp.ArrayHeaderSize
+ for zb0018 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName {
+ s += msgp.StringPrefixSize + len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName[zb0018])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName)) + 3 + msgp.ArrayHeaderSize
+ for zb0019 := range (*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL {
+ s += msgp.StringPrefixSize + len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL[zb0019])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL)) + 3 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash)) + 2 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager)) + 2 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve)) + 2 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze)) + 2 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback)) + 5 + msgp.ArrayHeaderSize
+ for zb0020 := range (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset {
+ s += (*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset[zb0020].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount)) + 5 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedAssetTransferTxnFields.AssetSender) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender)) + 5 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedAssetTransferTxnFields.AssetReceiver) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver)) + 7 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo) + 9 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo)) + 5 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount)) + 5 + msgp.ArrayHeaderSize
+ for zb0022 := range (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset {
+ s += (*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset[zb0022].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen)) + 5 + msgp.ArrayHeaderSize
+ for zb0023 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID {
+ s += (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID[zb0023].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID)) + 5 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedApplicationCallTxnFields.OnCompletion) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion)) + 5 + msgp.ArrayHeaderSize
+ for zb0024 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs {
+ s += msgp.ArrayHeaderSize
+ for zb0025 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] {
+ s += msgp.BytesPrefixSize + len((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024][zb0025])
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs)) + 5 + msgp.ArrayHeaderSize
+ for zb0026 := range (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts {
+ s += msgp.ArrayHeaderSize
+ for zb0027 := range (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] {
+ s += (*z).encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026][zb0027].Msgsize()
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts)) + 5 + msgp.ArrayHeaderSize
+ for zb0028 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps {
+ s += msgp.ArrayHeaderSize
+ for zb0029 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] {
+ s += (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028][zb0029].Msgsize()
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps)) + 5 + msgp.ArrayHeaderSize
+ for zb0030 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets {
+ s += msgp.ArrayHeaderSize
+ for zb0031 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] {
+ s += (*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030][zb0031].Msgsize()
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice)) + 5 + msgp.ArrayHeaderSize
+ for zb0036 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram {
+ s += msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram[zb0036]))
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram)) + 5 + msgp.ArrayHeaderSize
+ for zb0037 := range (*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram {
+ s += msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram[zb0037]))
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages) * (msgp.Uint32Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages)) + 8 + msgp.ArrayHeaderSize
+ for zb0039 := range (*z).encodedTxns.encodedCompactCertTxnFields.CertRound {
+ s += (*z).encodedTxns.encodedCompactCertTxnFields.CertRound[zb0039].Msgsize()
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound)) + 9 + msgp.ArrayHeaderSize
+ for zb0040 := range (*z).encodedTxns.encodedCompactCertTxnFields.CertType {
+ s += (*z).encodedTxns.encodedCompactCertTxnFields.CertType[zb0040].Msgsize()
+ }
+ s += 11 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertType)) + 6 + msgp.BytesPrefixSize + len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit)) + 6 + msgp.ArrayHeaderSize + (len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight) * (msgp.Uint64Size)) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight)) + 6 + msgp.ArrayHeaderSize
+ for zb0042 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs {
+ s += msgp.ArrayHeaderSize
+ for zb0043 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] {
+ s += (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042][zb0043].Msgsize()
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs)) + 6 + msgp.ArrayHeaderSize
+ for zb0044 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs {
+ s += msgp.ArrayHeaderSize
+ for zb0045 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] {
+ s += (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044][zb0045].Msgsize()
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs)) + 6 + msgp.ArrayHeaderSize
+ for zb0046 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals {
+ s += msgp.MapHeaderSize
+ if (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] != nil {
+ for zb0047, zb0048 := range (*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] {
+ _ = zb0047
+ _ = zb0048
+ s += 0 + msgp.Uint64Size + zb0048.Msgsize()
+ }
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedSignedTxns) MsgIsZero() bool {
+ return (len((*z).Sig) == 0) && (len((*z).BitmaskSig) == 0) && (len((*z).encodedMsigs.Version) == 0) && (len((*z).encodedMsigs.BitmaskVersion) == 0) && (len((*z).encodedMsigs.Threshold) == 0) && (len((*z).encodedMsigs.BitmaskThreshold) == 0) && (len((*z).encodedMsigs.Subsigs) == 0) && (len((*z).encodedMsigs.BitmaskSubsigs) == 0) && (len((*z).encodedLsigs.Logic) == 0) && (len((*z).encodedLsigs.BitmaskLogic) == 0) && (len((*z).encodedLsigs.LogicArgs) == 0) && (len((*z).encodedLsigs.BitmaskLogicArgs) == 0) && (len((*z).AuthAddr) == 0) && (len((*z).BitmaskAuthAddr) == 0) && (len((*z).encodedTxns.TxType) == 0) && (len((*z).encodedTxns.BitmaskTxType) == 0) && ((*z).encodedTxns.TxTypeOffset == 0) && (len((*z).encodedTxns.encodedTxnHeaders.Sender) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.BitmaskSender) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.Fee) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.BitmaskFee) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.FirstValid) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.BitmaskFirstValid) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.LastValid) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.BitmaskLastValid) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.Note) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.BitmaskNote) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.BitmaskGenesisID) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.BitmaskGroup) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.Lease) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.BitmaskLease) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.RekeyTo) == 0) && (len((*z).encodedTxns.encodedTxnHeaders.BitmaskRekeyTo) == 0) && (len((*z).encodedTxns.encodedKeyregTxnFields.VotePK) == 0) && (len((*z).encodedTxns.encodedKeyregTxnFields.SelectionPK) == 0) && (len((*z).encodedTxns.encodedKeyregTxnFields.VoteFirst) == 0) && (len((*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst) == 0) && (len((*z).encodedTxns.encodedKeyregTxnFields.VoteLast) == 0) && (len((*z).encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast) == 0) && (len((*z).encodedTxns.encodedKeyregTxnFields.VoteKeyDilution) == 0) && (len((*z).encodedTxns.encodedKeyregTxnFields.BitmaskKeys) == 0) && (len((*z).encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation) == 0) && (len((*z).encodedTxns.encodedPaymentTxnFields.Receiver) == 0) && (len((*z).encodedTxns.encodedPaymentTxnFields.BitmaskReceiver) == 0) && (len((*z).encodedTxns.encodedPaymentTxnFields.Amount) == 0) && (len((*z).encodedTxns.encodedPaymentTxnFields.BitmaskAmount) == 0) && (len((*z).encodedTxns.encodedPaymentTxnFields.CloseRemainderTo) == 0) && (len((*z).encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.ConfigAsset) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback) == 0) && (len((*z).encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback) == 0) && (len((*z).encodedTxns.encodedAssetTransferTxnFields.XferAsset) == 0) && (len((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset) == 0) && (len((*z).encodedTxns.encodedAssetTransferTxnFields.AssetAmount) == 0) && (len((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount) == 0) && (len((*z).encodedTxns.encodedAssetTransferTxnFields.AssetSender) == 0) && (len((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender) == 0) && (len((*z).encodedTxns.encodedAssetTransferTxnFields.AssetReceiver) == 0) && (len((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver) == 0) && (len((*z).encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo) == 0) && (len((*z).encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo) == 0) && (len((*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount) == 0) && (len((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount) == 0) && (len((*z).encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset) == 0) && (len((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset) == 0) && (len((*z).encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationID) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.OnCompletion) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.Accounts) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignApps) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.ForeignAssets) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumUint) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages) == 0) && (len((*z).encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages) == 0) && (len((*z).encodedTxns.encodedCompactCertTxnFields.CertRound) == 0) && (len((*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound) == 0) && (len((*z).encodedTxns.encodedCompactCertTxnFields.CertType) == 0) && (len((*z).encodedTxns.encodedCompactCertTxnFields.BitmaskCertType) == 0) && (len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit) == 0) && (len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit) == 0) && (len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight) == 0) && (len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight) == 0) && (len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs) == 0) && (len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs) == 0) && (len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs) == 0) && (len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs) == 0) && (len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals) == 0) && (len((*z).encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedTxnHeaders) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0005Len := uint32(16)
+ var zb0005Mask uint32 /* 17 bits */
+ if len((*z).Fee) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x2
+ }
+ if len((*z).BitmaskFee) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x4
+ }
+ if len((*z).FirstValid) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x8
+ }
+ if len((*z).BitmaskFirstValid) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x10
+ }
+ if len((*z).BitmaskGenesisID) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x20
+ }
+ if len((*z).BitmaskGroup) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x40
+ }
+ if len((*z).LastValid) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x80
+ }
+ if len((*z).BitmaskLastValid) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x100
+ }
+ if len((*z).Lease) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x200
+ }
+ if len((*z).BitmaskLease) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x400
+ }
+ if len((*z).Note) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x800
+ }
+ if len((*z).BitmaskNote) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x1000
+ }
+ if len((*z).RekeyTo) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x2000
+ }
+ if len((*z).BitmaskRekeyTo) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x4000
+ }
+ if len((*z).Sender) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x8000
+ }
+ if len((*z).BitmaskSender) == 0 {
+ zb0005Len--
+ zb0005Mask |= 0x10000
+ }
+ // variable map header, size zb0005Len
+ o = msgp.AppendMapHeader(o, zb0005Len)
+ if zb0005Len != 0 {
+ if (zb0005Mask & 0x2) == 0 { // if not empty
+ // string "fee"
+ o = append(o, 0xa3, 0x66, 0x65, 0x65)
+ if (*z).Fee == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).Fee)))
+ }
+ for zb0001 := range (*z).Fee {
+ o = (*z).Fee[zb0001].MarshalMsg(o)
+ }
+ }
+ if (zb0005Mask & 0x4) == 0 { // if not empty
+ // string "feebm"
+ o = append(o, 0xa5, 0x66, 0x65, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskFee))
+ }
+ if (zb0005Mask & 0x8) == 0 { // if not empty
+ // string "fv"
+ o = append(o, 0xa2, 0x66, 0x76)
+ if (*z).FirstValid == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).FirstValid)))
+ }
+ for zb0002 := range (*z).FirstValid {
+ o = (*z).FirstValid[zb0002].MarshalMsg(o)
+ }
+ }
+ if (zb0005Mask & 0x10) == 0 { // if not empty
+ // string "fvbm"
+ o = append(o, 0xa4, 0x66, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskFirstValid))
+ }
+ if (zb0005Mask & 0x20) == 0 { // if not empty
+ // string "genbm"
+ o = append(o, 0xa5, 0x67, 0x65, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskGenesisID))
+ }
+ if (zb0005Mask & 0x40) == 0 { // if not empty
+ // string "grpbm"
+ o = append(o, 0xa5, 0x67, 0x72, 0x70, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskGroup))
+ }
+ if (zb0005Mask & 0x80) == 0 { // if not empty
+ // string "lv"
+ o = append(o, 0xa2, 0x6c, 0x76)
+ if (*z).LastValid == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).LastValid)))
+ }
+ for zb0003 := range (*z).LastValid {
+ o = (*z).LastValid[zb0003].MarshalMsg(o)
+ }
+ }
+ if (zb0005Mask & 0x100) == 0 { // if not empty
+ // string "lvbm"
+ o = append(o, 0xa4, 0x6c, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskLastValid))
+ }
+ if (zb0005Mask & 0x200) == 0 { // if not empty
+ // string "lx"
+ o = append(o, 0xa2, 0x6c, 0x78)
+ o = msgp.AppendBytes(o, (*z).Lease)
+ }
+ if (zb0005Mask & 0x400) == 0 { // if not empty
+ // string "lxbm"
+ o = append(o, 0xa4, 0x6c, 0x78, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskLease))
+ }
+ if (zb0005Mask & 0x800) == 0 { // if not empty
+ // string "note"
+ o = append(o, 0xa4, 0x6e, 0x6f, 0x74, 0x65)
+ if (*z).Note == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).Note)))
+ }
+ for zb0004 := range (*z).Note {
+ o = msgp.AppendBytes(o, (*z).Note[zb0004])
+ }
+ }
+ if (zb0005Mask & 0x1000) == 0 { // if not empty
+ // string "notebm"
+ o = append(o, 0xa6, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskNote))
+ }
+ if (zb0005Mask & 0x2000) == 0 { // if not empty
+ // string "rekey"
+ o = append(o, 0xa5, 0x72, 0x65, 0x6b, 0x65, 0x79)
+ o = msgp.AppendBytes(o, (*z).RekeyTo)
+ }
+ if (zb0005Mask & 0x4000) == 0 { // if not empty
+ // string "rekeybm"
+ o = append(o, 0xa7, 0x72, 0x65, 0x6b, 0x65, 0x79, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskRekeyTo))
+ }
+ if (zb0005Mask & 0x8000) == 0 { // if not empty
+ // string "snd"
+ o = append(o, 0xa3, 0x73, 0x6e, 0x64)
+ o = msgp.AppendBytes(o, (*z).Sender)
+ }
+ if (zb0005Mask & 0x10000) == 0 { // if not empty
+ // string "sndbm"
+ o = append(o, 0xa5, 0x73, 0x6e, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskSender))
+ }
+ }
+ return
+}
+
+func (_ *encodedTxnHeaders) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedTxnHeaders)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedTxnHeaders) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0005 int
+ var zb0006 bool
+ zb0005, zb0006, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0005, zb0006, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0005 > 0 {
+ zb0005--
+ var zb0007 int
+ zb0007, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Sender")
+ return
+ }
+ if zb0007 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0007), uint64(maxAddressBytes))
+ return
+ }
+ (*z).Sender, bts, err = msgp.ReadBytesBytes(bts, (*z).Sender)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Sender")
+ return
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ {
+ var zb0008 []byte
+ var zb0009 int
+ zb0009, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSender")
+ return
+ }
+ if zb0009 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0009), uint64(maxBitmaskSize))
+ return
+ }
+ zb0008, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskSender))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSender")
+ return
+ }
+ (*z).BitmaskSender = bitmask(zb0008)
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ var zb0010 int
+ var zb0011 bool
+ zb0010, zb0011, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Fee")
+ return
+ }
+ if zb0010 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0010), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Fee")
+ return
+ }
+ if zb0011 {
+ (*z).Fee = nil
+ } else if (*z).Fee != nil && cap((*z).Fee) >= zb0010 {
+ (*z).Fee = ((*z).Fee)[:zb0010]
+ } else {
+ (*z).Fee = make([]basics.MicroAlgos, zb0010)
+ }
+ for zb0001 := range (*z).Fee {
+ bts, err = (*z).Fee[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Fee", zb0001)
+ return
+ }
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ {
+ var zb0012 []byte
+ var zb0013 int
+ zb0013, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFee")
+ return
+ }
+ if zb0013 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0013), uint64(maxBitmaskSize))
+ return
+ }
+ zb0012, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskFee))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFee")
+ return
+ }
+ (*z).BitmaskFee = bitmask(zb0012)
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ var zb0014 int
+ var zb0015 bool
+ zb0014, zb0015, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FirstValid")
+ return
+ }
+ if zb0014 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0014), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "FirstValid")
+ return
+ }
+ if zb0015 {
+ (*z).FirstValid = nil
+ } else if (*z).FirstValid != nil && cap((*z).FirstValid) >= zb0014 {
+ (*z).FirstValid = ((*z).FirstValid)[:zb0014]
+ } else {
+ (*z).FirstValid = make([]basics.Round, zb0014)
+ }
+ for zb0002 := range (*z).FirstValid {
+ bts, err = (*z).FirstValid[zb0002].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FirstValid", zb0002)
+ return
+ }
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ {
+ var zb0016 []byte
+ var zb0017 int
+ zb0017, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFirstValid")
+ return
+ }
+ if zb0017 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0017), uint64(maxBitmaskSize))
+ return
+ }
+ zb0016, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskFirstValid))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFirstValid")
+ return
+ }
+ (*z).BitmaskFirstValid = bitmask(zb0016)
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ var zb0018 int
+ var zb0019 bool
+ zb0018, zb0019, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LastValid")
+ return
+ }
+ if zb0018 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0018), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LastValid")
+ return
+ }
+ if zb0019 {
+ (*z).LastValid = nil
+ } else if (*z).LastValid != nil && cap((*z).LastValid) >= zb0018 {
+ (*z).LastValid = ((*z).LastValid)[:zb0018]
+ } else {
+ (*z).LastValid = make([]basics.Round, zb0018)
+ }
+ for zb0003 := range (*z).LastValid {
+ bts, err = (*z).LastValid[zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LastValid", zb0003)
+ return
+ }
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ {
+ var zb0020 []byte
+ var zb0021 int
+ zb0021, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLastValid")
+ return
+ }
+ if zb0021 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0021), uint64(maxBitmaskSize))
+ return
+ }
+ zb0020, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskLastValid))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLastValid")
+ return
+ }
+ (*z).BitmaskLastValid = bitmask(zb0020)
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ var zb0022 int
+ var zb0023 bool
+ zb0022, zb0023, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Note")
+ return
+ }
+ if zb0022 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0022), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Note")
+ return
+ }
+ if zb0023 {
+ (*z).Note = nil
+ } else if (*z).Note != nil && cap((*z).Note) >= zb0022 {
+ (*z).Note = ((*z).Note)[:zb0022]
+ } else {
+ (*z).Note = make([][]byte, zb0022)
+ }
+ for zb0004 := range (*z).Note {
+ var zb0024 int
+ zb0024, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Note", zb0004)
+ return
+ }
+ if zb0024 > config.MaxTxnNoteBytes {
+ err = msgp.ErrOverflow(uint64(zb0024), uint64(config.MaxTxnNoteBytes))
+ return
+ }
+ (*z).Note[zb0004], bts, err = msgp.ReadBytesBytes(bts, (*z).Note[zb0004])
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Note", zb0004)
+ return
+ }
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ {
+ var zb0025 []byte
+ var zb0026 int
+ zb0026, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNote")
+ return
+ }
+ if zb0026 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0026), uint64(maxBitmaskSize))
+ return
+ }
+ zb0025, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskNote))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNote")
+ return
+ }
+ (*z).BitmaskNote = bitmask(zb0025)
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ {
+ var zb0027 []byte
+ var zb0028 int
+ zb0028, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGenesisID")
+ return
+ }
+ if zb0028 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0028), uint64(maxBitmaskSize))
+ return
+ }
+ zb0027, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskGenesisID))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGenesisID")
+ return
+ }
+ (*z).BitmaskGenesisID = bitmask(zb0027)
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ {
+ var zb0029 []byte
+ var zb0030 int
+ zb0030, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGroup")
+ return
+ }
+ if zb0030 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0030), uint64(maxBitmaskSize))
+ return
+ }
+ zb0029, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskGroup))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGroup")
+ return
+ }
+ (*z).BitmaskGroup = bitmask(zb0029)
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ var zb0031 int
+ zb0031, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Lease")
+ return
+ }
+ if zb0031 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0031), uint64(maxAddressBytes))
+ return
+ }
+ (*z).Lease, bts, err = msgp.ReadBytesBytes(bts, (*z).Lease)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Lease")
+ return
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ {
+ var zb0032 []byte
+ var zb0033 int
+ zb0033, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLease")
+ return
+ }
+ if zb0033 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0033), uint64(maxBitmaskSize))
+ return
+ }
+ zb0032, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskLease))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLease")
+ return
+ }
+ (*z).BitmaskLease = bitmask(zb0032)
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ var zb0034 int
+ zb0034, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "RekeyTo")
+ return
+ }
+ if zb0034 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0034), uint64(maxAddressBytes))
+ return
+ }
+ (*z).RekeyTo, bts, err = msgp.ReadBytesBytes(bts, (*z).RekeyTo)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "RekeyTo")
+ return
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ {
+ var zb0035 []byte
+ var zb0036 int
+ zb0036, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskRekeyTo")
+ return
+ }
+ if zb0036 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0036), uint64(maxBitmaskSize))
+ return
+ }
+ zb0035, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskRekeyTo))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskRekeyTo")
+ return
+ }
+ (*z).BitmaskRekeyTo = bitmask(zb0035)
+ }
+ }
+ if zb0005 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0005)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0006 {
+ (*z) = encodedTxnHeaders{}
+ }
+ for zb0005 > 0 {
+ zb0005--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "snd":
+ var zb0037 int
+ zb0037, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Sender")
+ return
+ }
+ if zb0037 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0037), uint64(maxAddressBytes))
+ return
+ }
+ (*z).Sender, bts, err = msgp.ReadBytesBytes(bts, (*z).Sender)
+ if err != nil {
+ err = msgp.WrapError(err, "Sender")
+ return
+ }
+ case "sndbm":
+ {
+ var zb0038 []byte
+ var zb0039 int
+ zb0039, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSender")
+ return
+ }
+ if zb0039 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0039), uint64(maxBitmaskSize))
+ return
+ }
+ zb0038, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskSender))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSender")
+ return
+ }
+ (*z).BitmaskSender = bitmask(zb0038)
+ }
+ case "fee":
+ var zb0040 int
+ var zb0041 bool
+ zb0040, zb0041, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Fee")
+ return
+ }
+ if zb0040 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0040), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Fee")
+ return
+ }
+ if zb0041 {
+ (*z).Fee = nil
+ } else if (*z).Fee != nil && cap((*z).Fee) >= zb0040 {
+ (*z).Fee = ((*z).Fee)[:zb0040]
+ } else {
+ (*z).Fee = make([]basics.MicroAlgos, zb0040)
+ }
+ for zb0001 := range (*z).Fee {
+ bts, err = (*z).Fee[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Fee", zb0001)
+ return
+ }
+ }
+ case "feebm":
+ {
+ var zb0042 []byte
+ var zb0043 int
+ zb0043, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFee")
+ return
+ }
+ if zb0043 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0043), uint64(maxBitmaskSize))
+ return
+ }
+ zb0042, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskFee))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFee")
+ return
+ }
+ (*z).BitmaskFee = bitmask(zb0042)
+ }
+ case "fv":
+ var zb0044 int
+ var zb0045 bool
+ zb0044, zb0045, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FirstValid")
+ return
+ }
+ if zb0044 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0044), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "FirstValid")
+ return
+ }
+ if zb0045 {
+ (*z).FirstValid = nil
+ } else if (*z).FirstValid != nil && cap((*z).FirstValid) >= zb0044 {
+ (*z).FirstValid = ((*z).FirstValid)[:zb0044]
+ } else {
+ (*z).FirstValid = make([]basics.Round, zb0044)
+ }
+ for zb0002 := range (*z).FirstValid {
+ bts, err = (*z).FirstValid[zb0002].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FirstValid", zb0002)
+ return
+ }
+ }
+ case "fvbm":
+ {
+ var zb0046 []byte
+ var zb0047 int
+ zb0047, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFirstValid")
+ return
+ }
+ if zb0047 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0047), uint64(maxBitmaskSize))
+ return
+ }
+ zb0046, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskFirstValid))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFirstValid")
+ return
+ }
+ (*z).BitmaskFirstValid = bitmask(zb0046)
+ }
+ case "lv":
+ var zb0048 int
+ var zb0049 bool
+ zb0048, zb0049, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LastValid")
+ return
+ }
+ if zb0048 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0048), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LastValid")
+ return
+ }
+ if zb0049 {
+ (*z).LastValid = nil
+ } else if (*z).LastValid != nil && cap((*z).LastValid) >= zb0048 {
+ (*z).LastValid = ((*z).LastValid)[:zb0048]
+ } else {
+ (*z).LastValid = make([]basics.Round, zb0048)
+ }
+ for zb0003 := range (*z).LastValid {
+ bts, err = (*z).LastValid[zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LastValid", zb0003)
+ return
+ }
+ }
+ case "lvbm":
+ {
+ var zb0050 []byte
+ var zb0051 int
+ zb0051, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLastValid")
+ return
+ }
+ if zb0051 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0051), uint64(maxBitmaskSize))
+ return
+ }
+ zb0050, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskLastValid))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLastValid")
+ return
+ }
+ (*z).BitmaskLastValid = bitmask(zb0050)
+ }
+ case "note":
+ var zb0052 int
+ var zb0053 bool
+ zb0052, zb0053, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Note")
+ return
+ }
+ if zb0052 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0052), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Note")
+ return
+ }
+ if zb0053 {
+ (*z).Note = nil
+ } else if (*z).Note != nil && cap((*z).Note) >= zb0052 {
+ (*z).Note = ((*z).Note)[:zb0052]
+ } else {
+ (*z).Note = make([][]byte, zb0052)
+ }
+ for zb0004 := range (*z).Note {
+ var zb0054 int
+ zb0054, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Note", zb0004)
+ return
+ }
+ if zb0054 > config.MaxTxnNoteBytes {
+ err = msgp.ErrOverflow(uint64(zb0054), uint64(config.MaxTxnNoteBytes))
+ return
+ }
+ (*z).Note[zb0004], bts, err = msgp.ReadBytesBytes(bts, (*z).Note[zb0004])
+ if err != nil {
+ err = msgp.WrapError(err, "Note", zb0004)
+ return
+ }
+ }
+ case "notebm":
+ {
+ var zb0055 []byte
+ var zb0056 int
+ zb0056, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNote")
+ return
+ }
+ if zb0056 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0056), uint64(maxBitmaskSize))
+ return
+ }
+ zb0055, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskNote))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNote")
+ return
+ }
+ (*z).BitmaskNote = bitmask(zb0055)
+ }
+ case "genbm":
+ {
+ var zb0057 []byte
+ var zb0058 int
+ zb0058, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGenesisID")
+ return
+ }
+ if zb0058 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0058), uint64(maxBitmaskSize))
+ return
+ }
+ zb0057, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskGenesisID))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGenesisID")
+ return
+ }
+ (*z).BitmaskGenesisID = bitmask(zb0057)
+ }
+ case "grpbm":
+ {
+ var zb0059 []byte
+ var zb0060 int
+ zb0060, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGroup")
+ return
+ }
+ if zb0060 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0060), uint64(maxBitmaskSize))
+ return
+ }
+ zb0059, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskGroup))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGroup")
+ return
+ }
+ (*z).BitmaskGroup = bitmask(zb0059)
+ }
+ case "lx":
+ var zb0061 int
+ zb0061, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Lease")
+ return
+ }
+ if zb0061 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0061), uint64(maxAddressBytes))
+ return
+ }
+ (*z).Lease, bts, err = msgp.ReadBytesBytes(bts, (*z).Lease)
+ if err != nil {
+ err = msgp.WrapError(err, "Lease")
+ return
+ }
+ case "lxbm":
+ {
+ var zb0062 []byte
+ var zb0063 int
+ zb0063, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLease")
+ return
+ }
+ if zb0063 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0063), uint64(maxBitmaskSize))
+ return
+ }
+ zb0062, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskLease))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLease")
+ return
+ }
+ (*z).BitmaskLease = bitmask(zb0062)
+ }
+ case "rekey":
+ var zb0064 int
+ zb0064, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "RekeyTo")
+ return
+ }
+ if zb0064 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0064), uint64(maxAddressBytes))
+ return
+ }
+ (*z).RekeyTo, bts, err = msgp.ReadBytesBytes(bts, (*z).RekeyTo)
+ if err != nil {
+ err = msgp.WrapError(err, "RekeyTo")
+ return
+ }
+ case "rekeybm":
+ {
+ var zb0065 []byte
+ var zb0066 int
+ zb0066, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskRekeyTo")
+ return
+ }
+ if zb0066 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0066), uint64(maxBitmaskSize))
+ return
+ }
+ zb0065, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskRekeyTo))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskRekeyTo")
+ return
+ }
+ (*z).BitmaskRekeyTo = bitmask(zb0065)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedTxnHeaders) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedTxnHeaders)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedTxnHeaders) Msgsize() (s int) {
+ s = 3 + 4 + msgp.BytesPrefixSize + len((*z).Sender) + 6 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskSender)) + 4 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).Fee {
+ s += (*z).Fee[zb0001].Msgsize()
+ }
+ s += 6 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskFee)) + 3 + msgp.ArrayHeaderSize
+ for zb0002 := range (*z).FirstValid {
+ s += (*z).FirstValid[zb0002].Msgsize()
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskFirstValid)) + 3 + msgp.ArrayHeaderSize
+ for zb0003 := range (*z).LastValid {
+ s += (*z).LastValid[zb0003].Msgsize()
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskLastValid)) + 5 + msgp.ArrayHeaderSize
+ for zb0004 := range (*z).Note {
+ s += msgp.BytesPrefixSize + len((*z).Note[zb0004])
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskNote)) + 6 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskGenesisID)) + 6 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskGroup)) + 3 + msgp.BytesPrefixSize + len((*z).Lease) + 5 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskLease)) + 6 + msgp.BytesPrefixSize + len((*z).RekeyTo) + 8 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskRekeyTo))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedTxnHeaders) MsgIsZero() bool {
+ return (len((*z).Sender) == 0) && (len((*z).BitmaskSender) == 0) && (len((*z).Fee) == 0) && (len((*z).BitmaskFee) == 0) && (len((*z).FirstValid) == 0) && (len((*z).BitmaskFirstValid) == 0) && (len((*z).LastValid) == 0) && (len((*z).BitmaskLastValid) == 0) && (len((*z).Note) == 0) && (len((*z).BitmaskNote) == 0) && (len((*z).BitmaskGenesisID) == 0) && (len((*z).BitmaskGroup) == 0) && (len((*z).Lease) == 0) && (len((*z).BitmaskLease) == 0) && (len((*z).RekeyTo) == 0) && (len((*z).BitmaskRekeyTo) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *encodedTxns) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0044Len := uint32(112)
+ var zb0044Mask [2]uint64 /* 123 bits */
+ if len((*z).encodedAssetTransferTxnFields.AssetAmount) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x800
+ }
+ if len((*z).encodedAssetTransferTxnFields.BitmaskAssetAmount) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x1000
+ }
+ if len((*z).encodedAssetTransferTxnFields.AssetCloseTo) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x2000
+ }
+ if len((*z).encodedAssetTransferTxnFields.BitmaskAssetCloseTo) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x4000
+ }
+ if len((*z).encodedAssetFreezeTxnFields.BitmaskAssetFrozen) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x8000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x10000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x20000
+ }
+ if len((*z).encodedPaymentTxnFields.Amount) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x40000
+ }
+ if len((*z).encodedPaymentTxnFields.BitmaskAmount) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x80000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x100000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x200000
+ }
+ if len((*z).encodedApplicationCallTxnFields.ApplicationArgs) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x400000
+ }
+ if len((*z).encodedApplicationCallTxnFields.BitmaskApplicationArgs) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x800000
+ }
+ if len((*z).encodedApplicationCallTxnFields.OnCompletion) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x1000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.BitmaskOnCompletion) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x2000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.ApprovalProgram) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x4000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.BitmaskApprovalProgram) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x8000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.ForeignAssets) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x10000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.BitmaskForeignAssets) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x20000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.Accounts) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x40000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.BitmaskAccounts) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x80000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.ExtraProgramPages) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x100000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.BitmaskExtraProgramPages) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x200000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.ForeignApps) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x400000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.BitmaskForeignApps) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x800000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.ApplicationID) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x1000000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.BitmaskApplicationID) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x2000000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.ClearStateProgram) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x4000000000
+ }
+ if len((*z).encodedApplicationCallTxnFields.BitmaskClearStateProgram) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x8000000000
+ }
+ if len((*z).encodedAssetTransferTxnFields.AssetReceiver) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x10000000000
+ }
+ if len((*z).encodedAssetTransferTxnFields.BitmaskAssetReceiver) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x20000000000
+ }
+ if len((*z).encodedAssetTransferTxnFields.AssetSender) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x40000000000
+ }
+ if len((*z).encodedAssetTransferTxnFields.BitmaskAssetSender) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x80000000000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.URL) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x100000000000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x200000000000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Clawback) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x400000000000
+ }
+ if len((*z).encodedAssetConfigTxnFields.ConfigAsset) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x800000000000
+ }
+ if len((*z).encodedAssetConfigTxnFields.BitmaskConfigAsset) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x1000000000000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x2000000000000
+ }
+ if len((*z).encodedCompactCertTxnFields.encodedCert.PartProofs) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x4000000000000
+ }
+ if len((*z).encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x8000000000000
+ }
+ if len((*z).encodedCompactCertTxnFields.encodedCert.SigProofs) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x10000000000000
+ }
+ if len((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x20000000000000
+ }
+ if len((*z).encodedCompactCertTxnFields.encodedCert.SigCommit) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x40000000000000
+ }
+ if len((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x80000000000000
+ }
+ if len((*z).encodedCompactCertTxnFields.encodedCert.Reveals) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x100000000000000
+ }
+ if len((*z).encodedCompactCertTxnFields.encodedCert.BitmaskReveals) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x200000000000000
+ }
+ if len((*z).encodedCompactCertTxnFields.CertRound) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x400000000000000
+ }
+ if len((*z).encodedCompactCertTxnFields.BitmaskCertRound) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x800000000000000
+ }
+ if len((*z).encodedCompactCertTxnFields.CertType) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x1000000000000000
+ }
+ if len((*z).encodedCompactCertTxnFields.BitmaskCertType) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x2000000000000000
+ }
+ if len((*z).encodedCompactCertTxnFields.encodedCert.SignedWeight) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x4000000000000000
+ }
+ if len((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight) == 0 {
+ zb0044Len--
+ zb0044Mask[0] |= 0x8000000000000000
+ }
+ if len((*z).encodedPaymentTxnFields.CloseRemainderTo) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x1
+ }
+ if len((*z).encodedPaymentTxnFields.BitmaskCloseRemainderTo) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x2
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x4
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x8
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x10
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Freeze) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x20
+ }
+ if len((*z).encodedAssetFreezeTxnFields.FreezeAccount) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x40
+ }
+ if len((*z).encodedAssetFreezeTxnFields.BitmaskFreezeAccount) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x80
+ }
+ if len((*z).encodedAssetFreezeTxnFields.FreezeAsset) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x100
+ }
+ if len((*z).encodedAssetFreezeTxnFields.BitmaskFreezeAsset) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x200
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x400
+ }
+ if len((*z).encodedTxnHeaders.Fee) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x800
+ }
+ if len((*z).encodedTxnHeaders.BitmaskFee) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x1000
+ }
+ if len((*z).encodedTxnHeaders.FirstValid) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x2000
+ }
+ if len((*z).encodedTxnHeaders.BitmaskFirstValid) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x4000
+ }
+ if len((*z).encodedTxnHeaders.BitmaskGenesisID) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x8000
+ }
+ if len((*z).encodedApplicationCallTxnFields.GlobalNumByteSlice) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x10000
+ }
+ if len((*z).encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x20000
+ }
+ if len((*z).encodedApplicationCallTxnFields.GlobalNumUint) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x40000
+ }
+ if len((*z).encodedApplicationCallTxnFields.BitmaskGlobalNumUint) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x80000
+ }
+ if len((*z).encodedTxnHeaders.BitmaskGroup) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x100000
+ }
+ if len((*z).encodedApplicationCallTxnFields.LocalNumByteSlice) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x200000
+ }
+ if len((*z).encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x400000
+ }
+ if len((*z).encodedApplicationCallTxnFields.LocalNumUint) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x800000
+ }
+ if len((*z).encodedApplicationCallTxnFields.BitmaskLocalNumUint) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x1000000
+ }
+ if len((*z).encodedTxnHeaders.LastValid) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x2000000
+ }
+ if len((*z).encodedTxnHeaders.BitmaskLastValid) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x4000000
+ }
+ if len((*z).encodedTxnHeaders.Lease) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x8000000
+ }
+ if len((*z).encodedTxnHeaders.BitmaskLease) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x10000000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Manager) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x20000000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x40000000
+ }
+ if len((*z).encodedKeyregTxnFields.BitmaskNonparticipation) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x80000000
+ }
+ if len((*z).encodedTxnHeaders.Note) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x100000000
+ }
+ if len((*z).encodedTxnHeaders.BitmaskNote) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x200000000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Reserve) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x400000000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x800000000
+ }
+ if len((*z).encodedPaymentTxnFields.Receiver) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x1000000000
+ }
+ if len((*z).encodedPaymentTxnFields.BitmaskReceiver) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x2000000000
+ }
+ if len((*z).encodedTxnHeaders.RekeyTo) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x4000000000
+ }
+ if len((*z).encodedTxnHeaders.BitmaskRekeyTo) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x8000000000
+ }
+ if len((*z).encodedKeyregTxnFields.SelectionPK) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x10000000000
+ }
+ if len((*z).encodedTxnHeaders.Sender) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x20000000000
+ }
+ if len((*z).encodedTxnHeaders.BitmaskSender) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x40000000000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Total) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x80000000000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x100000000000
+ }
+ if len((*z).TxType) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x200000000000
+ }
+ if len((*z).BitmaskTxType) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x400000000000
+ }
+ if (*z).TxTypeOffset == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x800000000000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x1000000000000
+ }
+ if len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x2000000000000
+ }
+ if len((*z).encodedKeyregTxnFields.VoteFirst) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x4000000000000
+ }
+ if len((*z).encodedKeyregTxnFields.BitmaskVoteFirst) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x8000000000000
+ }
+ if len((*z).encodedKeyregTxnFields.BitmaskKeys) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x10000000000000
+ }
+ if len((*z).encodedKeyregTxnFields.VoteKeyDilution) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x20000000000000
+ }
+ if len((*z).encodedKeyregTxnFields.VotePK) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x40000000000000
+ }
+ if len((*z).encodedKeyregTxnFields.VoteLast) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x80000000000000
+ }
+ if len((*z).encodedKeyregTxnFields.BitmaskVoteLast) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x100000000000000
+ }
+ if len((*z).encodedAssetTransferTxnFields.XferAsset) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x200000000000000
+ }
+ if len((*z).encodedAssetTransferTxnFields.BitmaskXferAsset) == 0 {
+ zb0044Len--
+ zb0044Mask[1] |= 0x400000000000000
+ }
+ // variable map header, size zb0044Len
+ o = msgp.AppendMapHeader(o, zb0044Len)
+ if zb0044Len != 0 {
+ if (zb0044Mask[0] & 0x800) == 0 { // if not empty
+ // string "aamt"
+ o = append(o, 0xa4, 0x61, 0x61, 0x6d, 0x74)
+ if (*z).encodedAssetTransferTxnFields.AssetAmount == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedAssetTransferTxnFields.AssetAmount)))
+ }
+ for zb0016 := range (*z).encodedAssetTransferTxnFields.AssetAmount {
+ o = msgp.AppendUint64(o, (*z).encodedAssetTransferTxnFields.AssetAmount[zb0016])
+ }
+ }
+ if (zb0044Mask[0] & 0x1000) == 0 { // if not empty
+ // string "aamtbm"
+ o = append(o, 0xa6, 0x61, 0x61, 0x6d, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetTransferTxnFields.BitmaskAssetAmount))
+ }
+ if (zb0044Mask[0] & 0x2000) == 0 { // if not empty
+ // string "aclose"
+ o = append(o, 0xa6, 0x61, 0x63, 0x6c, 0x6f, 0x73, 0x65)
+ o = msgp.AppendBytes(o, (*z).encodedAssetTransferTxnFields.AssetCloseTo)
+ }
+ if (zb0044Mask[0] & 0x4000) == 0 { // if not empty
+ // string "aclosebm"
+ o = append(o, 0xa8, 0x61, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetTransferTxnFields.BitmaskAssetCloseTo))
+ }
+ if (zb0044Mask[0] & 0x8000) == 0 { // if not empty
+ // string "afrzbm"
+ o = append(o, 0xa6, 0x61, 0x66, 0x72, 0x7a, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetFreezeTxnFields.BitmaskAssetFrozen))
+ }
+ if (zb0044Mask[0] & 0x10000) == 0 { // if not empty
+ // string "am"
+ o = append(o, 0xa2, 0x61, 0x6d)
+ o = msgp.AppendBytes(o, (*z).encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash)
+ }
+ if (zb0044Mask[0] & 0x20000) == 0 { // if not empty
+ // string "ambm"
+ o = append(o, 0xa4, 0x61, 0x6d, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash))
+ }
+ if (zb0044Mask[0] & 0x40000) == 0 { // if not empty
+ // string "amt"
+ o = append(o, 0xa3, 0x61, 0x6d, 0x74)
+ if (*z).encodedPaymentTxnFields.Amount == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedPaymentTxnFields.Amount)))
+ }
+ for zb0008 := range (*z).encodedPaymentTxnFields.Amount {
+ o = (*z).encodedPaymentTxnFields.Amount[zb0008].MarshalMsg(o)
+ }
+ }
+ if (zb0044Mask[0] & 0x80000) == 0 { // if not empty
+ // string "amtbm"
+ o = append(o, 0xa5, 0x61, 0x6d, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedPaymentTxnFields.BitmaskAmount))
+ }
+ if (zb0044Mask[0] & 0x100000) == 0 { // if not empty
+ // string "an"
+ o = append(o, 0xa2, 0x61, 0x6e)
+ if (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName)))
+ }
+ for zb0013 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName {
+ o = msgp.AppendString(o, (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName[zb0013])
+ }
+ }
+ if (zb0044Mask[0] & 0x200000) == 0 { // if not empty
+ // string "anbm"
+ o = append(o, 0xa4, 0x61, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName))
+ }
+ if (zb0044Mask[0] & 0x400000) == 0 { // if not empty
+ // string "apaa"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x61)
+ if (*z).encodedApplicationCallTxnFields.ApplicationArgs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.ApplicationArgs)))
+ }
+ for zb0019 := range (*z).encodedApplicationCallTxnFields.ApplicationArgs {
+ if (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019])))
+ }
+ for zb0020 := range (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019] {
+ o = msgp.AppendBytes(o, (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019][zb0020])
+ }
+ }
+ }
+ if (zb0044Mask[0] & 0x800000) == 0 { // if not empty
+ // string "apaabm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x61, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.BitmaskApplicationArgs))
+ }
+ if (zb0044Mask[0] & 0x1000000) == 0 { // if not empty
+ // string "apan"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x6e)
+ o = msgp.AppendBytes(o, (*z).encodedApplicationCallTxnFields.OnCompletion)
+ }
+ if (zb0044Mask[0] & 0x2000000) == 0 { // if not empty
+ // string "apanbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.BitmaskOnCompletion))
+ }
+ if (zb0044Mask[0] & 0x4000000) == 0 { // if not empty
+ // string "apap"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x70)
+ if (*z).encodedApplicationCallTxnFields.ApprovalProgram == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.ApprovalProgram)))
+ }
+ for zb0031 := range (*z).encodedApplicationCallTxnFields.ApprovalProgram {
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.ApprovalProgram[zb0031]))
+ }
+ }
+ if (zb0044Mask[0] & 0x8000000) == 0 { // if not empty
+ // string "apapbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x70, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.BitmaskApprovalProgram))
+ }
+ if (zb0044Mask[0] & 0x10000000) == 0 { // if not empty
+ // string "apas"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x73)
+ if (*z).encodedApplicationCallTxnFields.ForeignAssets == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.ForeignAssets)))
+ }
+ for zb0025 := range (*z).encodedApplicationCallTxnFields.ForeignAssets {
+ if (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025])))
+ }
+ for zb0026 := range (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025] {
+ o = (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025][zb0026].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0044Mask[0] & 0x20000000) == 0 { // if not empty
+ // string "apasbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.BitmaskForeignAssets))
+ }
+ if (zb0044Mask[0] & 0x40000000) == 0 { // if not empty
+ // string "apat"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x74)
+ if (*z).encodedApplicationCallTxnFields.Accounts == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.Accounts)))
+ }
+ for zb0021 := range (*z).encodedApplicationCallTxnFields.Accounts {
+ if (*z).encodedApplicationCallTxnFields.Accounts[zb0021] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.Accounts[zb0021])))
+ }
+ for zb0022 := range (*z).encodedApplicationCallTxnFields.Accounts[zb0021] {
+ o = (*z).encodedApplicationCallTxnFields.Accounts[zb0021][zb0022].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0044Mask[0] & 0x80000000) == 0 { // if not empty
+ // string "apatbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.BitmaskAccounts))
+ }
+ if (zb0044Mask[0] & 0x100000000) == 0 { // if not empty
+ // string "apep"
+ o = append(o, 0xa4, 0x61, 0x70, 0x65, 0x70)
+ if (*z).encodedApplicationCallTxnFields.ExtraProgramPages == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.ExtraProgramPages)))
+ }
+ for zb0033 := range (*z).encodedApplicationCallTxnFields.ExtraProgramPages {
+ o = msgp.AppendUint32(o, (*z).encodedApplicationCallTxnFields.ExtraProgramPages[zb0033])
+ }
+ }
+ if (zb0044Mask[0] & 0x200000000) == 0 { // if not empty
+ // string "apepbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x65, 0x70, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.BitmaskExtraProgramPages))
+ }
+ if (zb0044Mask[0] & 0x400000000) == 0 { // if not empty
+ // string "apfa"
+ o = append(o, 0xa4, 0x61, 0x70, 0x66, 0x61)
+ if (*z).encodedApplicationCallTxnFields.ForeignApps == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.ForeignApps)))
+ }
+ for zb0023 := range (*z).encodedApplicationCallTxnFields.ForeignApps {
+ if (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.ForeignApps[zb0023])))
+ }
+ for zb0024 := range (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023] {
+ o = (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023][zb0024].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0044Mask[0] & 0x800000000) == 0 { // if not empty
+ // string "apfabm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x66, 0x61, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.BitmaskForeignApps))
+ }
+ if (zb0044Mask[0] & 0x1000000000) == 0 { // if not empty
+ // string "apid"
+ o = append(o, 0xa4, 0x61, 0x70, 0x69, 0x64)
+ if (*z).encodedApplicationCallTxnFields.ApplicationID == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.ApplicationID)))
+ }
+ for zb0018 := range (*z).encodedApplicationCallTxnFields.ApplicationID {
+ o = (*z).encodedApplicationCallTxnFields.ApplicationID[zb0018].MarshalMsg(o)
+ }
+ }
+ if (zb0044Mask[0] & 0x2000000000) == 0 { // if not empty
+ // string "apidbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.BitmaskApplicationID))
+ }
+ if (zb0044Mask[0] & 0x4000000000) == 0 { // if not empty
+ // string "apsu"
+ o = append(o, 0xa4, 0x61, 0x70, 0x73, 0x75)
+ if (*z).encodedApplicationCallTxnFields.ClearStateProgram == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.ClearStateProgram)))
+ }
+ for zb0032 := range (*z).encodedApplicationCallTxnFields.ClearStateProgram {
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.ClearStateProgram[zb0032]))
+ }
+ }
+ if (zb0044Mask[0] & 0x8000000000) == 0 { // if not empty
+ // string "apsubm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x73, 0x75, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.BitmaskClearStateProgram))
+ }
+ if (zb0044Mask[0] & 0x10000000000) == 0 { // if not empty
+ // string "arcv"
+ o = append(o, 0xa4, 0x61, 0x72, 0x63, 0x76)
+ o = msgp.AppendBytes(o, (*z).encodedAssetTransferTxnFields.AssetReceiver)
+ }
+ if (zb0044Mask[0] & 0x20000000000) == 0 { // if not empty
+ // string "arcvbm"
+ o = append(o, 0xa6, 0x61, 0x72, 0x63, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetTransferTxnFields.BitmaskAssetReceiver))
+ }
+ if (zb0044Mask[0] & 0x40000000000) == 0 { // if not empty
+ // string "asnd"
+ o = append(o, 0xa4, 0x61, 0x73, 0x6e, 0x64)
+ o = msgp.AppendBytes(o, (*z).encodedAssetTransferTxnFields.AssetSender)
+ }
+ if (zb0044Mask[0] & 0x80000000000) == 0 { // if not empty
+ // string "asndbm"
+ o = append(o, 0xa6, 0x61, 0x73, 0x6e, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetTransferTxnFields.BitmaskAssetSender))
+ }
+ if (zb0044Mask[0] & 0x100000000000) == 0 { // if not empty
+ // string "au"
+ o = append(o, 0xa2, 0x61, 0x75)
+ if (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedAssetConfigTxnFields.encodedAssetParams.URL)))
+ }
+ for zb0014 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL {
+ o = msgp.AppendString(o, (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL[zb0014])
+ }
+ }
+ if (zb0044Mask[0] & 0x200000000000) == 0 { // if not empty
+ // string "aubm"
+ o = append(o, 0xa4, 0x61, 0x75, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL))
+ }
+ if (zb0044Mask[0] & 0x400000000000) == 0 { // if not empty
+ // string "c"
+ o = append(o, 0xa1, 0x63)
+ o = msgp.AppendBytes(o, (*z).encodedAssetConfigTxnFields.encodedAssetParams.Clawback)
+ }
+ if (zb0044Mask[0] & 0x800000000000) == 0 { // if not empty
+ // string "caid"
+ o = append(o, 0xa4, 0x63, 0x61, 0x69, 0x64)
+ if (*z).encodedAssetConfigTxnFields.ConfigAsset == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedAssetConfigTxnFields.ConfigAsset)))
+ }
+ for zb0009 := range (*z).encodedAssetConfigTxnFields.ConfigAsset {
+ o = (*z).encodedAssetConfigTxnFields.ConfigAsset[zb0009].MarshalMsg(o)
+ }
+ }
+ if (zb0044Mask[0] & 0x1000000000000) == 0 { // if not empty
+ // string "caidbm"
+ o = append(o, 0xa6, 0x63, 0x61, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetConfigTxnFields.BitmaskConfigAsset))
+ }
+ if (zb0044Mask[0] & 0x2000000000000) == 0 { // if not empty
+ // string "cbm"
+ o = append(o, 0xa3, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback))
+ }
+ if (zb0044Mask[0] & 0x4000000000000) == 0 { // if not empty
+ // string "certP"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x50)
+ if (*z).encodedCompactCertTxnFields.encodedCert.PartProofs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedCompactCertTxnFields.encodedCert.PartProofs)))
+ }
+ for zb0039 := range (*z).encodedCompactCertTxnFields.encodedCert.PartProofs {
+ if (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039])))
+ }
+ for zb0040 := range (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039] {
+ o = (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039][zb0040].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0044Mask[0] & 0x8000000000000) == 0 { // if not empty
+ // string "certPbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x50, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs))
+ }
+ if (zb0044Mask[0] & 0x10000000000000) == 0 { // if not empty
+ // string "certS"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x53)
+ if (*z).encodedCompactCertTxnFields.encodedCert.SigProofs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedCompactCertTxnFields.encodedCert.SigProofs)))
+ }
+ for zb0037 := range (*z).encodedCompactCertTxnFields.encodedCert.SigProofs {
+ if (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037])))
+ }
+ for zb0038 := range (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037] {
+ o = (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037][zb0038].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0044Mask[0] & 0x20000000000000) == 0 { // if not empty
+ // string "certSbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x53, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs))
+ }
+ if (zb0044Mask[0] & 0x40000000000000) == 0 { // if not empty
+ // string "certc"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x63)
+ o = msgp.AppendBytes(o, (*z).encodedCompactCertTxnFields.encodedCert.SigCommit)
+ }
+ if (zb0044Mask[0] & 0x80000000000000) == 0 { // if not empty
+ // string "certcbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit))
+ }
+ if (zb0044Mask[0] & 0x100000000000000) == 0 { // if not empty
+ // string "certr"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x72)
+ if (*z).encodedCompactCertTxnFields.encodedCert.Reveals == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedCompactCertTxnFields.encodedCert.Reveals)))
+ }
+ for zb0041 := range (*z).encodedCompactCertTxnFields.encodedCert.Reveals {
+ if (*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendMapHeader(o, uint32(len((*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041])))
+ }
+ zb0042_keys := make([]uint64, 0, len((*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041]))
+ for zb0042 := range (*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041] {
+ zb0042_keys = append(zb0042_keys, zb0042)
+ }
+ sort.Sort(SortUint64(zb0042_keys))
+ for _, zb0042 := range zb0042_keys {
+ zb0043 := (*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041][zb0042]
+ _ = zb0043
+ o = msgp.AppendUint64(o, zb0042)
+ o = zb0043.MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0044Mask[0] & 0x200000000000000) == 0 { // if not empty
+ // string "certrbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskReveals))
+ }
+ if (zb0044Mask[0] & 0x400000000000000) == 0 { // if not empty
+ // string "certrnd"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x72, 0x6e, 0x64)
+ if (*z).encodedCompactCertTxnFields.CertRound == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedCompactCertTxnFields.CertRound)))
+ }
+ for zb0034 := range (*z).encodedCompactCertTxnFields.CertRound {
+ o = (*z).encodedCompactCertTxnFields.CertRound[zb0034].MarshalMsg(o)
+ }
+ }
+ if (zb0044Mask[0] & 0x800000000000000) == 0 { // if not empty
+ // string "certrndbm"
+ o = append(o, 0xa9, 0x63, 0x65, 0x72, 0x74, 0x72, 0x6e, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedCompactCertTxnFields.BitmaskCertRound))
+ }
+ if (zb0044Mask[0] & 0x1000000000000000) == 0 { // if not empty
+ // string "certtype"
+ o = append(o, 0xa8, 0x63, 0x65, 0x72, 0x74, 0x74, 0x79, 0x70, 0x65)
+ if (*z).encodedCompactCertTxnFields.CertType == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedCompactCertTxnFields.CertType)))
+ }
+ for zb0035 := range (*z).encodedCompactCertTxnFields.CertType {
+ o = (*z).encodedCompactCertTxnFields.CertType[zb0035].MarshalMsg(o)
+ }
+ }
+ if (zb0044Mask[0] & 0x2000000000000000) == 0 { // if not empty
+ // string "certtypebm"
+ o = append(o, 0xaa, 0x63, 0x65, 0x72, 0x74, 0x74, 0x79, 0x70, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedCompactCertTxnFields.BitmaskCertType))
+ }
+ if (zb0044Mask[0] & 0x4000000000000000) == 0 { // if not empty
+ // string "certw"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x77)
+ if (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedCompactCertTxnFields.encodedCert.SignedWeight)))
+ }
+ for zb0036 := range (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight {
+ o = msgp.AppendUint64(o, (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight[zb0036])
+ }
+ }
+ if (zb0044Mask[0] & 0x8000000000000000) == 0 { // if not empty
+ // string "certwbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x77, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight))
+ }
+ if (zb0044Mask[1] & 0x1) == 0 { // if not empty
+ // string "close"
+ o = append(o, 0xa5, 0x63, 0x6c, 0x6f, 0x73, 0x65)
+ o = msgp.AppendBytes(o, (*z).encodedPaymentTxnFields.CloseRemainderTo)
+ }
+ if (zb0044Mask[1] & 0x2) == 0 { // if not empty
+ // string "closebm"
+ o = append(o, 0xa7, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedPaymentTxnFields.BitmaskCloseRemainderTo))
+ }
+ if (zb0044Mask[1] & 0x4) == 0 { // if not empty
+ // string "dc"
+ o = append(o, 0xa2, 0x64, 0x63)
+ if (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals)))
+ }
+ for zb0011 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals {
+ o = msgp.AppendUint32(o, (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals[zb0011])
+ }
+ }
+ if (zb0044Mask[1] & 0x8) == 0 { // if not empty
+ // string "dcbm"
+ o = append(o, 0xa4, 0x64, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals))
+ }
+ if (zb0044Mask[1] & 0x10) == 0 { // if not empty
+ // string "dfbm"
+ o = append(o, 0xa4, 0x64, 0x66, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen))
+ }
+ if (zb0044Mask[1] & 0x20) == 0 { // if not empty
+ // string "f"
+ o = append(o, 0xa1, 0x66)
+ o = msgp.AppendBytes(o, (*z).encodedAssetConfigTxnFields.encodedAssetParams.Freeze)
+ }
+ if (zb0044Mask[1] & 0x40) == 0 { // if not empty
+ // string "fadd"
+ o = append(o, 0xa4, 0x66, 0x61, 0x64, 0x64)
+ o = msgp.AppendBytes(o, (*z).encodedAssetFreezeTxnFields.FreezeAccount)
+ }
+ if (zb0044Mask[1] & 0x80) == 0 { // if not empty
+ // string "faddbm"
+ o = append(o, 0xa6, 0x66, 0x61, 0x64, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetFreezeTxnFields.BitmaskFreezeAccount))
+ }
+ if (zb0044Mask[1] & 0x100) == 0 { // if not empty
+ // string "faid"
+ o = append(o, 0xa4, 0x66, 0x61, 0x69, 0x64)
+ if (*z).encodedAssetFreezeTxnFields.FreezeAsset == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedAssetFreezeTxnFields.FreezeAsset)))
+ }
+ for zb0017 := range (*z).encodedAssetFreezeTxnFields.FreezeAsset {
+ o = (*z).encodedAssetFreezeTxnFields.FreezeAsset[zb0017].MarshalMsg(o)
+ }
+ }
+ if (zb0044Mask[1] & 0x200) == 0 { // if not empty
+ // string "faidbm"
+ o = append(o, 0xa6, 0x66, 0x61, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetFreezeTxnFields.BitmaskFreezeAsset))
+ }
+ if (zb0044Mask[1] & 0x400) == 0 { // if not empty
+ // string "fbm"
+ o = append(o, 0xa3, 0x66, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze))
+ }
+ if (zb0044Mask[1] & 0x800) == 0 { // if not empty
+ // string "fee"
+ o = append(o, 0xa3, 0x66, 0x65, 0x65)
+ if (*z).encodedTxnHeaders.Fee == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxnHeaders.Fee)))
+ }
+ for zb0001 := range (*z).encodedTxnHeaders.Fee {
+ o = (*z).encodedTxnHeaders.Fee[zb0001].MarshalMsg(o)
+ }
+ }
+ if (zb0044Mask[1] & 0x1000) == 0 { // if not empty
+ // string "feebm"
+ o = append(o, 0xa5, 0x66, 0x65, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxnHeaders.BitmaskFee))
+ }
+ if (zb0044Mask[1] & 0x2000) == 0 { // if not empty
+ // string "fv"
+ o = append(o, 0xa2, 0x66, 0x76)
+ if (*z).encodedTxnHeaders.FirstValid == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxnHeaders.FirstValid)))
+ }
+ for zb0002 := range (*z).encodedTxnHeaders.FirstValid {
+ o = (*z).encodedTxnHeaders.FirstValid[zb0002].MarshalMsg(o)
+ }
+ }
+ if (zb0044Mask[1] & 0x4000) == 0 { // if not empty
+ // string "fvbm"
+ o = append(o, 0xa4, 0x66, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxnHeaders.BitmaskFirstValid))
+ }
+ if (zb0044Mask[1] & 0x8000) == 0 { // if not empty
+ // string "genbm"
+ o = append(o, 0xa5, 0x67, 0x65, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxnHeaders.BitmaskGenesisID))
+ }
+ if (zb0044Mask[1] & 0x10000) == 0 { // if not empty
+ // string "gnbs"
+ o = append(o, 0xa4, 0x67, 0x6e, 0x62, 0x73)
+ if (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.GlobalNumByteSlice)))
+ }
+ for zb0030 := range (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice {
+ o = msgp.AppendUint64(o, (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice[zb0030])
+ }
+ }
+ if (zb0044Mask[1] & 0x20000) == 0 { // if not empty
+ // string "gnbsbm"
+ o = append(o, 0xa6, 0x67, 0x6e, 0x62, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice))
+ }
+ if (zb0044Mask[1] & 0x40000) == 0 { // if not empty
+ // string "gnui"
+ o = append(o, 0xa4, 0x67, 0x6e, 0x75, 0x69)
+ if (*z).encodedApplicationCallTxnFields.GlobalNumUint == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.GlobalNumUint)))
+ }
+ for zb0029 := range (*z).encodedApplicationCallTxnFields.GlobalNumUint {
+ o = msgp.AppendUint64(o, (*z).encodedApplicationCallTxnFields.GlobalNumUint[zb0029])
+ }
+ }
+ if (zb0044Mask[1] & 0x80000) == 0 { // if not empty
+ // string "gnuibm"
+ o = append(o, 0xa6, 0x67, 0x6e, 0x75, 0x69, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.BitmaskGlobalNumUint))
+ }
+ if (zb0044Mask[1] & 0x100000) == 0 { // if not empty
+ // string "grpbm"
+ o = append(o, 0xa5, 0x67, 0x72, 0x70, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxnHeaders.BitmaskGroup))
+ }
+ if (zb0044Mask[1] & 0x200000) == 0 { // if not empty
+ // string "lnbs"
+ o = append(o, 0xa4, 0x6c, 0x6e, 0x62, 0x73)
+ if (*z).encodedApplicationCallTxnFields.LocalNumByteSlice == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.LocalNumByteSlice)))
+ }
+ for zb0028 := range (*z).encodedApplicationCallTxnFields.LocalNumByteSlice {
+ o = msgp.AppendUint64(o, (*z).encodedApplicationCallTxnFields.LocalNumByteSlice[zb0028])
+ }
+ }
+ if (zb0044Mask[1] & 0x400000) == 0 { // if not empty
+ // string "lnbsbm"
+ o = append(o, 0xa6, 0x6c, 0x6e, 0x62, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice))
+ }
+ if (zb0044Mask[1] & 0x800000) == 0 { // if not empty
+ // string "lnui"
+ o = append(o, 0xa4, 0x6c, 0x6e, 0x75, 0x69)
+ if (*z).encodedApplicationCallTxnFields.LocalNumUint == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedApplicationCallTxnFields.LocalNumUint)))
+ }
+ for zb0027 := range (*z).encodedApplicationCallTxnFields.LocalNumUint {
+ o = msgp.AppendUint64(o, (*z).encodedApplicationCallTxnFields.LocalNumUint[zb0027])
+ }
+ }
+ if (zb0044Mask[1] & 0x1000000) == 0 { // if not empty
+ // string "lnuibm"
+ o = append(o, 0xa6, 0x6c, 0x6e, 0x75, 0x69, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedApplicationCallTxnFields.BitmaskLocalNumUint))
+ }
+ if (zb0044Mask[1] & 0x2000000) == 0 { // if not empty
+ // string "lv"
+ o = append(o, 0xa2, 0x6c, 0x76)
+ if (*z).encodedTxnHeaders.LastValid == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxnHeaders.LastValid)))
+ }
+ for zb0003 := range (*z).encodedTxnHeaders.LastValid {
+ o = (*z).encodedTxnHeaders.LastValid[zb0003].MarshalMsg(o)
+ }
+ }
+ if (zb0044Mask[1] & 0x4000000) == 0 { // if not empty
+ // string "lvbm"
+ o = append(o, 0xa4, 0x6c, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxnHeaders.BitmaskLastValid))
+ }
+ if (zb0044Mask[1] & 0x8000000) == 0 { // if not empty
+ // string "lx"
+ o = append(o, 0xa2, 0x6c, 0x78)
+ o = msgp.AppendBytes(o, (*z).encodedTxnHeaders.Lease)
+ }
+ if (zb0044Mask[1] & 0x10000000) == 0 { // if not empty
+ // string "lxbm"
+ o = append(o, 0xa4, 0x6c, 0x78, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxnHeaders.BitmaskLease))
+ }
+ if (zb0044Mask[1] & 0x20000000) == 0 { // if not empty
+ // string "m"
+ o = append(o, 0xa1, 0x6d)
+ o = msgp.AppendBytes(o, (*z).encodedAssetConfigTxnFields.encodedAssetParams.Manager)
+ }
+ if (zb0044Mask[1] & 0x40000000) == 0 { // if not empty
+ // string "mbm"
+ o = append(o, 0xa3, 0x6d, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager))
+ }
+ if (zb0044Mask[1] & 0x80000000) == 0 { // if not empty
+ // string "nonpartbm"
+ o = append(o, 0xa9, 0x6e, 0x6f, 0x6e, 0x70, 0x61, 0x72, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedKeyregTxnFields.BitmaskNonparticipation))
+ }
+ if (zb0044Mask[1] & 0x100000000) == 0 { // if not empty
+ // string "note"
+ o = append(o, 0xa4, 0x6e, 0x6f, 0x74, 0x65)
+ if (*z).encodedTxnHeaders.Note == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedTxnHeaders.Note)))
+ }
+ for zb0004 := range (*z).encodedTxnHeaders.Note {
+ o = msgp.AppendBytes(o, (*z).encodedTxnHeaders.Note[zb0004])
+ }
+ }
+ if (zb0044Mask[1] & 0x200000000) == 0 { // if not empty
+ // string "notebm"
+ o = append(o, 0xa6, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxnHeaders.BitmaskNote))
+ }
+ if (zb0044Mask[1] & 0x400000000) == 0 { // if not empty
+ // string "r"
+ o = append(o, 0xa1, 0x72)
+ o = msgp.AppendBytes(o, (*z).encodedAssetConfigTxnFields.encodedAssetParams.Reserve)
+ }
+ if (zb0044Mask[1] & 0x800000000) == 0 { // if not empty
+ // string "rbm"
+ o = append(o, 0xa3, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve))
+ }
+ if (zb0044Mask[1] & 0x1000000000) == 0 { // if not empty
+ // string "rcv"
+ o = append(o, 0xa3, 0x72, 0x63, 0x76)
+ o = msgp.AppendBytes(o, (*z).encodedPaymentTxnFields.Receiver)
+ }
+ if (zb0044Mask[1] & 0x2000000000) == 0 { // if not empty
+ // string "rcvbm"
+ o = append(o, 0xa5, 0x72, 0x63, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedPaymentTxnFields.BitmaskReceiver))
+ }
+ if (zb0044Mask[1] & 0x4000000000) == 0 { // if not empty
+ // string "rekey"
+ o = append(o, 0xa5, 0x72, 0x65, 0x6b, 0x65, 0x79)
+ o = msgp.AppendBytes(o, (*z).encodedTxnHeaders.RekeyTo)
+ }
+ if (zb0044Mask[1] & 0x8000000000) == 0 { // if not empty
+ // string "rekeybm"
+ o = append(o, 0xa7, 0x72, 0x65, 0x6b, 0x65, 0x79, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxnHeaders.BitmaskRekeyTo))
+ }
+ if (zb0044Mask[1] & 0x10000000000) == 0 { // if not empty
+ // string "selkey"
+ o = append(o, 0xa6, 0x73, 0x65, 0x6c, 0x6b, 0x65, 0x79)
+ o = msgp.AppendBytes(o, (*z).encodedKeyregTxnFields.SelectionPK)
+ }
+ if (zb0044Mask[1] & 0x20000000000) == 0 { // if not empty
+ // string "snd"
+ o = append(o, 0xa3, 0x73, 0x6e, 0x64)
+ o = msgp.AppendBytes(o, (*z).encodedTxnHeaders.Sender)
+ }
+ if (zb0044Mask[1] & 0x40000000000) == 0 { // if not empty
+ // string "sndbm"
+ o = append(o, 0xa5, 0x73, 0x6e, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedTxnHeaders.BitmaskSender))
+ }
+ if (zb0044Mask[1] & 0x80000000000) == 0 { // if not empty
+ // string "t"
+ o = append(o, 0xa1, 0x74)
+ if (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Total)))
+ }
+ for zb0010 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total {
+ o = msgp.AppendUint64(o, (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total[zb0010])
+ }
+ }
+ if (zb0044Mask[1] & 0x100000000000) == 0 { // if not empty
+ // string "tbm"
+ o = append(o, 0xa3, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal))
+ }
+ if (zb0044Mask[1] & 0x200000000000) == 0 { // if not empty
+ // string "type"
+ o = append(o, 0xa4, 0x74, 0x79, 0x70, 0x65)
+ o = msgp.AppendBytes(o, (*z).TxType)
+ }
+ if (zb0044Mask[1] & 0x400000000000) == 0 { // if not empty
+ // string "typebm"
+ o = append(o, 0xa6, 0x74, 0x79, 0x70, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).BitmaskTxType))
+ }
+ if (zb0044Mask[1] & 0x800000000000) == 0 { // if not empty
+ // string "typeo"
+ o = append(o, 0xa5, 0x74, 0x79, 0x70, 0x65, 0x6f)
+ o = msgp.AppendByte(o, (*z).TxTypeOffset)
+ }
+ if (zb0044Mask[1] & 0x1000000000000) == 0 { // if not empty
+ // string "un"
+ o = append(o, 0xa2, 0x75, 0x6e)
+ if (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName)))
+ }
+ for zb0012 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName {
+ o = msgp.AppendString(o, (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName[zb0012])
+ }
+ }
+ if (zb0044Mask[1] & 0x2000000000000) == 0 { // if not empty
+ // string "unbm"
+ o = append(o, 0xa4, 0x75, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName))
+ }
+ if (zb0044Mask[1] & 0x4000000000000) == 0 { // if not empty
+ // string "votefst"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x66, 0x73, 0x74)
+ if (*z).encodedKeyregTxnFields.VoteFirst == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedKeyregTxnFields.VoteFirst)))
+ }
+ for zb0005 := range (*z).encodedKeyregTxnFields.VoteFirst {
+ o = (*z).encodedKeyregTxnFields.VoteFirst[zb0005].MarshalMsg(o)
+ }
+ }
+ if (zb0044Mask[1] & 0x8000000000000) == 0 { // if not empty
+ // string "votefstbm"
+ o = append(o, 0xa9, 0x76, 0x6f, 0x74, 0x65, 0x66, 0x73, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedKeyregTxnFields.BitmaskVoteFirst))
+ }
+ if (zb0044Mask[1] & 0x10000000000000) == 0 { // if not empty
+ // string "votekbm"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x6b, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedKeyregTxnFields.BitmaskKeys))
+ }
+ if (zb0044Mask[1] & 0x20000000000000) == 0 { // if not empty
+ // string "votekd"
+ o = append(o, 0xa6, 0x76, 0x6f, 0x74, 0x65, 0x6b, 0x64)
+ if (*z).encodedKeyregTxnFields.VoteKeyDilution == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedKeyregTxnFields.VoteKeyDilution)))
+ }
+ for zb0007 := range (*z).encodedKeyregTxnFields.VoteKeyDilution {
+ o = msgp.AppendUint64(o, (*z).encodedKeyregTxnFields.VoteKeyDilution[zb0007])
+ }
+ }
+ if (zb0044Mask[1] & 0x40000000000000) == 0 { // if not empty
+ // string "votekey"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x6b, 0x65, 0x79)
+ o = msgp.AppendBytes(o, (*z).encodedKeyregTxnFields.VotePK)
+ }
+ if (zb0044Mask[1] & 0x80000000000000) == 0 { // if not empty
+ // string "votelst"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x6c, 0x73, 0x74)
+ if (*z).encodedKeyregTxnFields.VoteLast == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedKeyregTxnFields.VoteLast)))
+ }
+ for zb0006 := range (*z).encodedKeyregTxnFields.VoteLast {
+ o = (*z).encodedKeyregTxnFields.VoteLast[zb0006].MarshalMsg(o)
+ }
+ }
+ if (zb0044Mask[1] & 0x100000000000000) == 0 { // if not empty
+ // string "votelstbm"
+ o = append(o, 0xa9, 0x76, 0x6f, 0x74, 0x65, 0x6c, 0x73, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedKeyregTxnFields.BitmaskVoteLast))
+ }
+ if (zb0044Mask[1] & 0x200000000000000) == 0 { // if not empty
+ // string "xaid"
+ o = append(o, 0xa4, 0x78, 0x61, 0x69, 0x64)
+ if (*z).encodedAssetTransferTxnFields.XferAsset == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedAssetTransferTxnFields.XferAsset)))
+ }
+ for zb0015 := range (*z).encodedAssetTransferTxnFields.XferAsset {
+ o = (*z).encodedAssetTransferTxnFields.XferAsset[zb0015].MarshalMsg(o)
+ }
+ }
+ if (zb0044Mask[1] & 0x400000000000000) == 0 { // if not empty
+ // string "xaidbm"
+ o = append(o, 0xa6, 0x78, 0x61, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedAssetTransferTxnFields.BitmaskXferAsset))
+ }
+ }
+ return
+}
+
+func (_ *encodedTxns) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedTxns)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *encodedTxns) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0044 int
+ var zb0045 bool
+ zb0044, zb0045, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0044, zb0045, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0046 int
+ zb0046, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TxType")
+ return
+ }
+ if zb0046 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0046), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).TxType, bts, err = msgp.ReadBytesBytes(bts, (*z).TxType)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TxType")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0047 []byte
+ var zb0048 int
+ zb0048, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTxType")
+ return
+ }
+ if zb0048 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0048), uint64(maxBitmaskSize))
+ return
+ }
+ zb0047, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskTxType))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTxType")
+ return
+ }
+ (*z).BitmaskTxType = bitmask(zb0047)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ (*z).TxTypeOffset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TxTypeOffset")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0049 int
+ zb0049, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Sender")
+ return
+ }
+ if zb0049 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0049), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxnHeaders.Sender, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxnHeaders.Sender)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Sender")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0050 []byte
+ var zb0051 int
+ zb0051, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSender")
+ return
+ }
+ if zb0051 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0051), uint64(maxBitmaskSize))
+ return
+ }
+ zb0050, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskSender))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSender")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskSender = bitmask(zb0050)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0052 int
+ var zb0053 bool
+ zb0052, zb0053, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Fee")
+ return
+ }
+ if zb0052 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0052), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Fee")
+ return
+ }
+ if zb0053 {
+ (*z).encodedTxnHeaders.Fee = nil
+ } else if (*z).encodedTxnHeaders.Fee != nil && cap((*z).encodedTxnHeaders.Fee) >= zb0052 {
+ (*z).encodedTxnHeaders.Fee = ((*z).encodedTxnHeaders.Fee)[:zb0052]
+ } else {
+ (*z).encodedTxnHeaders.Fee = make([]basics.MicroAlgos, zb0052)
+ }
+ for zb0001 := range (*z).encodedTxnHeaders.Fee {
+ bts, err = (*z).encodedTxnHeaders.Fee[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Fee", zb0001)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0054 []byte
+ var zb0055 int
+ zb0055, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFee")
+ return
+ }
+ if zb0055 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0055), uint64(maxBitmaskSize))
+ return
+ }
+ zb0054, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskFee))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFee")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskFee = bitmask(zb0054)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0056 int
+ var zb0057 bool
+ zb0056, zb0057, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FirstValid")
+ return
+ }
+ if zb0056 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0056), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "FirstValid")
+ return
+ }
+ if zb0057 {
+ (*z).encodedTxnHeaders.FirstValid = nil
+ } else if (*z).encodedTxnHeaders.FirstValid != nil && cap((*z).encodedTxnHeaders.FirstValid) >= zb0056 {
+ (*z).encodedTxnHeaders.FirstValid = ((*z).encodedTxnHeaders.FirstValid)[:zb0056]
+ } else {
+ (*z).encodedTxnHeaders.FirstValid = make([]basics.Round, zb0056)
+ }
+ for zb0002 := range (*z).encodedTxnHeaders.FirstValid {
+ bts, err = (*z).encodedTxnHeaders.FirstValid[zb0002].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FirstValid", zb0002)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0058 []byte
+ var zb0059 int
+ zb0059, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFirstValid")
+ return
+ }
+ if zb0059 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0059), uint64(maxBitmaskSize))
+ return
+ }
+ zb0058, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskFirstValid))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFirstValid")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskFirstValid = bitmask(zb0058)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0060 int
+ var zb0061 bool
+ zb0060, zb0061, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LastValid")
+ return
+ }
+ if zb0060 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0060), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LastValid")
+ return
+ }
+ if zb0061 {
+ (*z).encodedTxnHeaders.LastValid = nil
+ } else if (*z).encodedTxnHeaders.LastValid != nil && cap((*z).encodedTxnHeaders.LastValid) >= zb0060 {
+ (*z).encodedTxnHeaders.LastValid = ((*z).encodedTxnHeaders.LastValid)[:zb0060]
+ } else {
+ (*z).encodedTxnHeaders.LastValid = make([]basics.Round, zb0060)
+ }
+ for zb0003 := range (*z).encodedTxnHeaders.LastValid {
+ bts, err = (*z).encodedTxnHeaders.LastValid[zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LastValid", zb0003)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0062 []byte
+ var zb0063 int
+ zb0063, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLastValid")
+ return
+ }
+ if zb0063 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0063), uint64(maxBitmaskSize))
+ return
+ }
+ zb0062, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskLastValid))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLastValid")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskLastValid = bitmask(zb0062)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0064 int
+ var zb0065 bool
+ zb0064, zb0065, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Note")
+ return
+ }
+ if zb0064 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0064), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Note")
+ return
+ }
+ if zb0065 {
+ (*z).encodedTxnHeaders.Note = nil
+ } else if (*z).encodedTxnHeaders.Note != nil && cap((*z).encodedTxnHeaders.Note) >= zb0064 {
+ (*z).encodedTxnHeaders.Note = ((*z).encodedTxnHeaders.Note)[:zb0064]
+ } else {
+ (*z).encodedTxnHeaders.Note = make([][]byte, zb0064)
+ }
+ for zb0004 := range (*z).encodedTxnHeaders.Note {
+ var zb0066 int
+ zb0066, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Note", zb0004)
+ return
+ }
+ if zb0066 > config.MaxTxnNoteBytes {
+ err = msgp.ErrOverflow(uint64(zb0066), uint64(config.MaxTxnNoteBytes))
+ return
+ }
+ (*z).encodedTxnHeaders.Note[zb0004], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxnHeaders.Note[zb0004])
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Note", zb0004)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0067 []byte
+ var zb0068 int
+ zb0068, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNote")
+ return
+ }
+ if zb0068 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0068), uint64(maxBitmaskSize))
+ return
+ }
+ zb0067, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskNote))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNote")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskNote = bitmask(zb0067)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0069 []byte
+ var zb0070 int
+ zb0070, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGenesisID")
+ return
+ }
+ if zb0070 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0070), uint64(maxBitmaskSize))
+ return
+ }
+ zb0069, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskGenesisID))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGenesisID")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskGenesisID = bitmask(zb0069)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0071 []byte
+ var zb0072 int
+ zb0072, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGroup")
+ return
+ }
+ if zb0072 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0072), uint64(maxBitmaskSize))
+ return
+ }
+ zb0071, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskGroup))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGroup")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskGroup = bitmask(zb0071)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0073 int
+ zb0073, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Lease")
+ return
+ }
+ if zb0073 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0073), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxnHeaders.Lease, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxnHeaders.Lease)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Lease")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0074 []byte
+ var zb0075 int
+ zb0075, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLease")
+ return
+ }
+ if zb0075 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0075), uint64(maxBitmaskSize))
+ return
+ }
+ zb0074, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskLease))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLease")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskLease = bitmask(zb0074)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0076 int
+ zb0076, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "RekeyTo")
+ return
+ }
+ if zb0076 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0076), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxnHeaders.RekeyTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxnHeaders.RekeyTo)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "RekeyTo")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0077 []byte
+ var zb0078 int
+ zb0078, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskRekeyTo")
+ return
+ }
+ if zb0078 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0078), uint64(maxBitmaskSize))
+ return
+ }
+ zb0077, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskRekeyTo))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskRekeyTo")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskRekeyTo = bitmask(zb0077)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0079 int
+ zb0079, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VotePK")
+ return
+ }
+ if zb0079 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0079), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedKeyregTxnFields.VotePK, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedKeyregTxnFields.VotePK)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VotePK")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0080 int
+ zb0080, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SelectionPK")
+ return
+ }
+ if zb0080 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0080), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedKeyregTxnFields.SelectionPK, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedKeyregTxnFields.SelectionPK)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SelectionPK")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0081 int
+ var zb0082 bool
+ zb0081, zb0082, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteFirst")
+ return
+ }
+ if zb0081 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0081), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "VoteFirst")
+ return
+ }
+ if zb0082 {
+ (*z).encodedKeyregTxnFields.VoteFirst = nil
+ } else if (*z).encodedKeyregTxnFields.VoteFirst != nil && cap((*z).encodedKeyregTxnFields.VoteFirst) >= zb0081 {
+ (*z).encodedKeyregTxnFields.VoteFirst = ((*z).encodedKeyregTxnFields.VoteFirst)[:zb0081]
+ } else {
+ (*z).encodedKeyregTxnFields.VoteFirst = make([]basics.Round, zb0081)
+ }
+ for zb0005 := range (*z).encodedKeyregTxnFields.VoteFirst {
+ bts, err = (*z).encodedKeyregTxnFields.VoteFirst[zb0005].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteFirst", zb0005)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0083 []byte
+ var zb0084 int
+ zb0084, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteFirst")
+ return
+ }
+ if zb0084 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0084), uint64(maxBitmaskSize))
+ return
+ }
+ zb0083, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedKeyregTxnFields.BitmaskVoteFirst))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteFirst")
+ return
+ }
+ (*z).encodedKeyregTxnFields.BitmaskVoteFirst = bitmask(zb0083)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0085 int
+ var zb0086 bool
+ zb0085, zb0086, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteLast")
+ return
+ }
+ if zb0085 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0085), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "VoteLast")
+ return
+ }
+ if zb0086 {
+ (*z).encodedKeyregTxnFields.VoteLast = nil
+ } else if (*z).encodedKeyregTxnFields.VoteLast != nil && cap((*z).encodedKeyregTxnFields.VoteLast) >= zb0085 {
+ (*z).encodedKeyregTxnFields.VoteLast = ((*z).encodedKeyregTxnFields.VoteLast)[:zb0085]
+ } else {
+ (*z).encodedKeyregTxnFields.VoteLast = make([]basics.Round, zb0085)
+ }
+ for zb0006 := range (*z).encodedKeyregTxnFields.VoteLast {
+ bts, err = (*z).encodedKeyregTxnFields.VoteLast[zb0006].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteLast", zb0006)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0087 []byte
+ var zb0088 int
+ zb0088, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteLast")
+ return
+ }
+ if zb0088 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0088), uint64(maxBitmaskSize))
+ return
+ }
+ zb0087, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedKeyregTxnFields.BitmaskVoteLast))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteLast")
+ return
+ }
+ (*z).encodedKeyregTxnFields.BitmaskVoteLast = bitmask(zb0087)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0089 int
+ var zb0090 bool
+ zb0089, zb0090, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteKeyDilution")
+ return
+ }
+ if zb0089 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0089), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "VoteKeyDilution")
+ return
+ }
+ if zb0090 {
+ (*z).encodedKeyregTxnFields.VoteKeyDilution = nil
+ } else if (*z).encodedKeyregTxnFields.VoteKeyDilution != nil && cap((*z).encodedKeyregTxnFields.VoteKeyDilution) >= zb0089 {
+ (*z).encodedKeyregTxnFields.VoteKeyDilution = ((*z).encodedKeyregTxnFields.VoteKeyDilution)[:zb0089]
+ } else {
+ (*z).encodedKeyregTxnFields.VoteKeyDilution = make([]uint64, zb0089)
+ }
+ for zb0007 := range (*z).encodedKeyregTxnFields.VoteKeyDilution {
+ (*z).encodedKeyregTxnFields.VoteKeyDilution[zb0007], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteKeyDilution", zb0007)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0091 []byte
+ var zb0092 int
+ zb0092, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskKeys")
+ return
+ }
+ if zb0092 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0092), uint64(maxBitmaskSize))
+ return
+ }
+ zb0091, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedKeyregTxnFields.BitmaskKeys))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskKeys")
+ return
+ }
+ (*z).encodedKeyregTxnFields.BitmaskKeys = bitmask(zb0091)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0093 []byte
+ var zb0094 int
+ zb0094, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNonparticipation")
+ return
+ }
+ if zb0094 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0094), uint64(maxBitmaskSize))
+ return
+ }
+ zb0093, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedKeyregTxnFields.BitmaskNonparticipation))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNonparticipation")
+ return
+ }
+ (*z).encodedKeyregTxnFields.BitmaskNonparticipation = bitmask(zb0093)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0095 int
+ zb0095, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Receiver")
+ return
+ }
+ if zb0095 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0095), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedPaymentTxnFields.Receiver, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedPaymentTxnFields.Receiver)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Receiver")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0096 []byte
+ var zb0097 int
+ zb0097, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReceiver")
+ return
+ }
+ if zb0097 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0097), uint64(maxBitmaskSize))
+ return
+ }
+ zb0096, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedPaymentTxnFields.BitmaskReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReceiver")
+ return
+ }
+ (*z).encodedPaymentTxnFields.BitmaskReceiver = bitmask(zb0096)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0098 int
+ var zb0099 bool
+ zb0098, zb0099, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Amount")
+ return
+ }
+ if zb0098 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0098), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Amount")
+ return
+ }
+ if zb0099 {
+ (*z).encodedPaymentTxnFields.Amount = nil
+ } else if (*z).encodedPaymentTxnFields.Amount != nil && cap((*z).encodedPaymentTxnFields.Amount) >= zb0098 {
+ (*z).encodedPaymentTxnFields.Amount = ((*z).encodedPaymentTxnFields.Amount)[:zb0098]
+ } else {
+ (*z).encodedPaymentTxnFields.Amount = make([]basics.MicroAlgos, zb0098)
+ }
+ for zb0008 := range (*z).encodedPaymentTxnFields.Amount {
+ bts, err = (*z).encodedPaymentTxnFields.Amount[zb0008].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Amount", zb0008)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0100 []byte
+ var zb0101 int
+ zb0101, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAmount")
+ return
+ }
+ if zb0101 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0101), uint64(maxBitmaskSize))
+ return
+ }
+ zb0100, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedPaymentTxnFields.BitmaskAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAmount")
+ return
+ }
+ (*z).encodedPaymentTxnFields.BitmaskAmount = bitmask(zb0100)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0102 int
+ zb0102, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CloseRemainderTo")
+ return
+ }
+ if zb0102 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0102), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedPaymentTxnFields.CloseRemainderTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedPaymentTxnFields.CloseRemainderTo)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CloseRemainderTo")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0103 []byte
+ var zb0104 int
+ zb0104, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCloseRemainderTo")
+ return
+ }
+ if zb0104 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0104), uint64(maxBitmaskSize))
+ return
+ }
+ zb0103, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedPaymentTxnFields.BitmaskCloseRemainderTo))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCloseRemainderTo")
+ return
+ }
+ (*z).encodedPaymentTxnFields.BitmaskCloseRemainderTo = bitmask(zb0103)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0105 int
+ var zb0106 bool
+ zb0105, zb0106, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ConfigAsset")
+ return
+ }
+ if zb0105 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0105), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ConfigAsset")
+ return
+ }
+ if zb0106 {
+ (*z).encodedAssetConfigTxnFields.ConfigAsset = nil
+ } else if (*z).encodedAssetConfigTxnFields.ConfigAsset != nil && cap((*z).encodedAssetConfigTxnFields.ConfigAsset) >= zb0105 {
+ (*z).encodedAssetConfigTxnFields.ConfigAsset = ((*z).encodedAssetConfigTxnFields.ConfigAsset)[:zb0105]
+ } else {
+ (*z).encodedAssetConfigTxnFields.ConfigAsset = make([]basics.AssetIndex, zb0105)
+ }
+ for zb0009 := range (*z).encodedAssetConfigTxnFields.ConfigAsset {
+ bts, err = (*z).encodedAssetConfigTxnFields.ConfigAsset[zb0009].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ConfigAsset", zb0009)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0107 []byte
+ var zb0108 int
+ zb0108, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskConfigAsset")
+ return
+ }
+ if zb0108 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0108), uint64(maxBitmaskSize))
+ return
+ }
+ zb0107, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.BitmaskConfigAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskConfigAsset")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.BitmaskConfigAsset = bitmask(zb0107)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0109 int
+ var zb0110 bool
+ zb0109, zb0110, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Total")
+ return
+ }
+ if zb0109 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0109), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Total")
+ return
+ }
+ if zb0110 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total = nil
+ } else if (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total != nil && cap((*z).encodedAssetConfigTxnFields.encodedAssetParams.Total) >= zb0109 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total = ((*z).encodedAssetConfigTxnFields.encodedAssetParams.Total)[:zb0109]
+ } else {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total = make([]uint64, zb0109)
+ }
+ for zb0010 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total[zb0010], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Total", zb0010)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0111 []byte
+ var zb0112 int
+ zb0112, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTotal")
+ return
+ }
+ if zb0112 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0112), uint64(maxBitmaskSize))
+ return
+ }
+ zb0111, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTotal")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal = bitmask(zb0111)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0113 int
+ var zb0114 bool
+ zb0113, zb0114, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Decimals")
+ return
+ }
+ if zb0113 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0113), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Decimals")
+ return
+ }
+ if zb0114 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals = nil
+ } else if (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals != nil && cap((*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals) >= zb0113 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals = ((*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals)[:zb0113]
+ } else {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals = make([]uint32, zb0113)
+ }
+ for zb0011 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals[zb0011], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Decimals", zb0011)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0115 []byte
+ var zb0116 int
+ zb0116, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDecimals")
+ return
+ }
+ if zb0116 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0116), uint64(maxBitmaskSize))
+ return
+ }
+ zb0115, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDecimals")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals = bitmask(zb0115)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0117 []byte
+ var zb0118 int
+ zb0118, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDefaultFrozen")
+ return
+ }
+ if zb0118 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0118), uint64(maxBitmaskSize))
+ return
+ }
+ zb0117, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDefaultFrozen")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen = bitmask(zb0117)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0119 int
+ var zb0120 bool
+ zb0119, zb0120, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UnitName")
+ return
+ }
+ if zb0119 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0119), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "UnitName")
+ return
+ }
+ if zb0120 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName = nil
+ } else if (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName != nil && cap((*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName) >= zb0119 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName = ((*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName)[:zb0119]
+ } else {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName = make([]string, zb0119)
+ }
+ for zb0012 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName[zb0012], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UnitName", zb0012)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0121 []byte
+ var zb0122 int
+ zb0122, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskUnitName")
+ return
+ }
+ if zb0122 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0122), uint64(maxBitmaskSize))
+ return
+ }
+ zb0121, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskUnitName")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName = bitmask(zb0121)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0123 int
+ var zb0124 bool
+ zb0123, zb0124, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetName")
+ return
+ }
+ if zb0123 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0123), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "AssetName")
+ return
+ }
+ if zb0124 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName = nil
+ } else if (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName != nil && cap((*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName) >= zb0123 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName = ((*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName)[:zb0123]
+ } else {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName = make([]string, zb0123)
+ }
+ for zb0013 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName[zb0013], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetName", zb0013)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0125 []byte
+ var zb0126 int
+ zb0126, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetName")
+ return
+ }
+ if zb0126 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0126), uint64(maxBitmaskSize))
+ return
+ }
+ zb0125, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetName")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName = bitmask(zb0125)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0127 int
+ var zb0128 bool
+ zb0127, zb0128, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "URL")
+ return
+ }
+ if zb0127 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0127), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "URL")
+ return
+ }
+ if zb0128 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL = nil
+ } else if (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL != nil && cap((*z).encodedAssetConfigTxnFields.encodedAssetParams.URL) >= zb0127 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL = ((*z).encodedAssetConfigTxnFields.encodedAssetParams.URL)[:zb0127]
+ } else {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL = make([]string, zb0127)
+ }
+ for zb0014 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL[zb0014], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "URL", zb0014)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0129 []byte
+ var zb0130 int
+ zb0130, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskURL")
+ return
+ }
+ if zb0130 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0130), uint64(maxBitmaskSize))
+ return
+ }
+ zb0129, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskURL")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL = bitmask(zb0129)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0131 int
+ zb0131, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "MetadataHash")
+ return
+ }
+ if zb0131 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0131), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "MetadataHash")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0132 []byte
+ var zb0133 int
+ zb0133, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskMetadataHash")
+ return
+ }
+ if zb0133 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0133), uint64(maxBitmaskSize))
+ return
+ }
+ zb0132, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskMetadataHash")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash = bitmask(zb0132)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0134 int
+ zb0134, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Manager")
+ return
+ }
+ if zb0134 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0134), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Manager, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetConfigTxnFields.encodedAssetParams.Manager)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Manager")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0135 []byte
+ var zb0136 int
+ zb0136, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskManager")
+ return
+ }
+ if zb0136 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0136), uint64(maxBitmaskSize))
+ return
+ }
+ zb0135, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskManager")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager = bitmask(zb0135)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0137 int
+ zb0137, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reserve")
+ return
+ }
+ if zb0137 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0137), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Reserve, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetConfigTxnFields.encodedAssetParams.Reserve)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reserve")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0138 []byte
+ var zb0139 int
+ zb0139, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReserve")
+ return
+ }
+ if zb0139 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0139), uint64(maxBitmaskSize))
+ return
+ }
+ zb0138, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReserve")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve = bitmask(zb0138)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0140 int
+ zb0140, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Freeze")
+ return
+ }
+ if zb0140 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0140), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Freeze, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetConfigTxnFields.encodedAssetParams.Freeze)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Freeze")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0141 []byte
+ var zb0142 int
+ zb0142, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreeze")
+ return
+ }
+ if zb0142 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0142), uint64(maxBitmaskSize))
+ return
+ }
+ zb0141, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreeze")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze = bitmask(zb0141)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0143 int
+ zb0143, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Clawback")
+ return
+ }
+ if zb0143 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0143), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Clawback, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetConfigTxnFields.encodedAssetParams.Clawback)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Clawback")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0144 []byte
+ var zb0145 int
+ zb0145, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClawback")
+ return
+ }
+ if zb0145 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0145), uint64(maxBitmaskSize))
+ return
+ }
+ zb0144, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClawback")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback = bitmask(zb0144)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0146 int
+ var zb0147 bool
+ zb0146, zb0147, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "XferAsset")
+ return
+ }
+ if zb0146 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0146), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "XferAsset")
+ return
+ }
+ if zb0147 {
+ (*z).encodedAssetTransferTxnFields.XferAsset = nil
+ } else if (*z).encodedAssetTransferTxnFields.XferAsset != nil && cap((*z).encodedAssetTransferTxnFields.XferAsset) >= zb0146 {
+ (*z).encodedAssetTransferTxnFields.XferAsset = ((*z).encodedAssetTransferTxnFields.XferAsset)[:zb0146]
+ } else {
+ (*z).encodedAssetTransferTxnFields.XferAsset = make([]basics.AssetIndex, zb0146)
+ }
+ for zb0015 := range (*z).encodedAssetTransferTxnFields.XferAsset {
+ bts, err = (*z).encodedAssetTransferTxnFields.XferAsset[zb0015].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "XferAsset", zb0015)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0148 []byte
+ var zb0149 int
+ zb0149, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskXferAsset")
+ return
+ }
+ if zb0149 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0149), uint64(maxBitmaskSize))
+ return
+ }
+ zb0148, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetTransferTxnFields.BitmaskXferAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskXferAsset")
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.BitmaskXferAsset = bitmask(zb0148)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0150 int
+ var zb0151 bool
+ zb0150, zb0151, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetAmount")
+ return
+ }
+ if zb0150 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0150), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "AssetAmount")
+ return
+ }
+ if zb0151 {
+ (*z).encodedAssetTransferTxnFields.AssetAmount = nil
+ } else if (*z).encodedAssetTransferTxnFields.AssetAmount != nil && cap((*z).encodedAssetTransferTxnFields.AssetAmount) >= zb0150 {
+ (*z).encodedAssetTransferTxnFields.AssetAmount = ((*z).encodedAssetTransferTxnFields.AssetAmount)[:zb0150]
+ } else {
+ (*z).encodedAssetTransferTxnFields.AssetAmount = make([]uint64, zb0150)
+ }
+ for zb0016 := range (*z).encodedAssetTransferTxnFields.AssetAmount {
+ (*z).encodedAssetTransferTxnFields.AssetAmount[zb0016], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetAmount", zb0016)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0152 []byte
+ var zb0153 int
+ zb0153, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetAmount")
+ return
+ }
+ if zb0153 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0153), uint64(maxBitmaskSize))
+ return
+ }
+ zb0152, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetTransferTxnFields.BitmaskAssetAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetAmount")
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.BitmaskAssetAmount = bitmask(zb0152)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0154 int
+ zb0154, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetSender")
+ return
+ }
+ if zb0154 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0154), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.AssetSender, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetTransferTxnFields.AssetSender)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetSender")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0155 []byte
+ var zb0156 int
+ zb0156, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetSender")
+ return
+ }
+ if zb0156 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0156), uint64(maxBitmaskSize))
+ return
+ }
+ zb0155, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetTransferTxnFields.BitmaskAssetSender))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetSender")
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.BitmaskAssetSender = bitmask(zb0155)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0157 int
+ zb0157, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetReceiver")
+ return
+ }
+ if zb0157 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0157), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.AssetReceiver, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetTransferTxnFields.AssetReceiver)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetReceiver")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0158 []byte
+ var zb0159 int
+ zb0159, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetReceiver")
+ return
+ }
+ if zb0159 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0159), uint64(maxBitmaskSize))
+ return
+ }
+ zb0158, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetTransferTxnFields.BitmaskAssetReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetReceiver")
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.BitmaskAssetReceiver = bitmask(zb0158)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0160 int
+ zb0160, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetCloseTo")
+ return
+ }
+ if zb0160 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0160), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.AssetCloseTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetTransferTxnFields.AssetCloseTo)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetCloseTo")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0161 []byte
+ var zb0162 int
+ zb0162, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetCloseTo")
+ return
+ }
+ if zb0162 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0162), uint64(maxBitmaskSize))
+ return
+ }
+ zb0161, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetTransferTxnFields.BitmaskAssetCloseTo))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetCloseTo")
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.BitmaskAssetCloseTo = bitmask(zb0161)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0163 int
+ zb0163, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAccount")
+ return
+ }
+ if zb0163 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0163), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetFreezeTxnFields.FreezeAccount, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetFreezeTxnFields.FreezeAccount)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAccount")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0164 []byte
+ var zb0165 int
+ zb0165, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAccount")
+ return
+ }
+ if zb0165 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0165), uint64(maxBitmaskSize))
+ return
+ }
+ zb0164, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetFreezeTxnFields.BitmaskFreezeAccount))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAccount")
+ return
+ }
+ (*z).encodedAssetFreezeTxnFields.BitmaskFreezeAccount = bitmask(zb0164)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0166 int
+ var zb0167 bool
+ zb0166, zb0167, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAsset")
+ return
+ }
+ if zb0166 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0166), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAsset")
+ return
+ }
+ if zb0167 {
+ (*z).encodedAssetFreezeTxnFields.FreezeAsset = nil
+ } else if (*z).encodedAssetFreezeTxnFields.FreezeAsset != nil && cap((*z).encodedAssetFreezeTxnFields.FreezeAsset) >= zb0166 {
+ (*z).encodedAssetFreezeTxnFields.FreezeAsset = ((*z).encodedAssetFreezeTxnFields.FreezeAsset)[:zb0166]
+ } else {
+ (*z).encodedAssetFreezeTxnFields.FreezeAsset = make([]basics.AssetIndex, zb0166)
+ }
+ for zb0017 := range (*z).encodedAssetFreezeTxnFields.FreezeAsset {
+ bts, err = (*z).encodedAssetFreezeTxnFields.FreezeAsset[zb0017].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAsset", zb0017)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0168 []byte
+ var zb0169 int
+ zb0169, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAsset")
+ return
+ }
+ if zb0169 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0169), uint64(maxBitmaskSize))
+ return
+ }
+ zb0168, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetFreezeTxnFields.BitmaskFreezeAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAsset")
+ return
+ }
+ (*z).encodedAssetFreezeTxnFields.BitmaskFreezeAsset = bitmask(zb0168)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0170 []byte
+ var zb0171 int
+ zb0171, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetFrozen")
+ return
+ }
+ if zb0171 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0171), uint64(maxBitmaskSize))
+ return
+ }
+ zb0170, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetFreezeTxnFields.BitmaskAssetFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetFrozen")
+ return
+ }
+ (*z).encodedAssetFreezeTxnFields.BitmaskAssetFrozen = bitmask(zb0170)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0172 int
+ var zb0173 bool
+ zb0172, zb0173, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationID")
+ return
+ }
+ if zb0172 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0172), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationID")
+ return
+ }
+ if zb0173 {
+ (*z).encodedApplicationCallTxnFields.ApplicationID = nil
+ } else if (*z).encodedApplicationCallTxnFields.ApplicationID != nil && cap((*z).encodedApplicationCallTxnFields.ApplicationID) >= zb0172 {
+ (*z).encodedApplicationCallTxnFields.ApplicationID = ((*z).encodedApplicationCallTxnFields.ApplicationID)[:zb0172]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ApplicationID = make([]basics.AppIndex, zb0172)
+ }
+ for zb0018 := range (*z).encodedApplicationCallTxnFields.ApplicationID {
+ bts, err = (*z).encodedApplicationCallTxnFields.ApplicationID[zb0018].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationID", zb0018)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0174 []byte
+ var zb0175 int
+ zb0175, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationID")
+ return
+ }
+ if zb0175 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0175), uint64(maxBitmaskSize))
+ return
+ }
+ zb0174, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskApplicationID))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationID")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskApplicationID = bitmask(zb0174)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0176 int
+ zb0176, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "OnCompletion")
+ return
+ }
+ if zb0176 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0176), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.OnCompletion, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedApplicationCallTxnFields.OnCompletion)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "OnCompletion")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0177 []byte
+ var zb0178 int
+ zb0178, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskOnCompletion")
+ return
+ }
+ if zb0178 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0178), uint64(maxBitmaskSize))
+ return
+ }
+ zb0177, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskOnCompletion))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskOnCompletion")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskOnCompletion = bitmask(zb0177)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0179 int
+ var zb0180 bool
+ zb0179, zb0180, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs")
+ return
+ }
+ if zb0179 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0179), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs")
+ return
+ }
+ if zb0180 {
+ (*z).encodedApplicationCallTxnFields.ApplicationArgs = nil
+ } else if (*z).encodedApplicationCallTxnFields.ApplicationArgs != nil && cap((*z).encodedApplicationCallTxnFields.ApplicationArgs) >= zb0179 {
+ (*z).encodedApplicationCallTxnFields.ApplicationArgs = ((*z).encodedApplicationCallTxnFields.ApplicationArgs)[:zb0179]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ApplicationArgs = make([]applicationArgs, zb0179)
+ }
+ for zb0019 := range (*z).encodedApplicationCallTxnFields.ApplicationArgs {
+ var zb0181 int
+ var zb0182 bool
+ zb0181, zb0182, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs", zb0019)
+ return
+ }
+ if zb0181 > transactions.EncodedMaxApplicationArgs {
+ err = msgp.ErrOverflow(uint64(zb0181), uint64(transactions.EncodedMaxApplicationArgs))
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs", zb0019)
+ return
+ }
+ if zb0182 {
+ (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019] = nil
+ } else if (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019] != nil && cap((*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019]) >= zb0181 {
+ (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019] = ((*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019])[:zb0181]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019] = make(applicationArgs, zb0181)
+ }
+ for zb0020 := range (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019] {
+ (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019][zb0020], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019][zb0020])
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs", zb0019, zb0020)
+ return
+ }
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0183 []byte
+ var zb0184 int
+ zb0184, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationArgs")
+ return
+ }
+ if zb0184 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0184), uint64(maxBitmaskSize))
+ return
+ }
+ zb0183, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskApplicationArgs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationArgs")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskApplicationArgs = bitmask(zb0183)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0185 int
+ var zb0186 bool
+ zb0185, zb0186, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Accounts")
+ return
+ }
+ if zb0185 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0185), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Accounts")
+ return
+ }
+ if zb0186 {
+ (*z).encodedApplicationCallTxnFields.Accounts = nil
+ } else if (*z).encodedApplicationCallTxnFields.Accounts != nil && cap((*z).encodedApplicationCallTxnFields.Accounts) >= zb0185 {
+ (*z).encodedApplicationCallTxnFields.Accounts = ((*z).encodedApplicationCallTxnFields.Accounts)[:zb0185]
+ } else {
+ (*z).encodedApplicationCallTxnFields.Accounts = make([]addresses, zb0185)
+ }
+ for zb0021 := range (*z).encodedApplicationCallTxnFields.Accounts {
+ var zb0187 int
+ var zb0188 bool
+ zb0187, zb0188, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Accounts", zb0021)
+ return
+ }
+ if zb0187 > transactions.EncodedMaxAccounts {
+ err = msgp.ErrOverflow(uint64(zb0187), uint64(transactions.EncodedMaxAccounts))
+ err = msgp.WrapError(err, "struct-from-array", "Accounts", zb0021)
+ return
+ }
+ if zb0188 {
+ (*z).encodedApplicationCallTxnFields.Accounts[zb0021] = nil
+ } else if (*z).encodedApplicationCallTxnFields.Accounts[zb0021] != nil && cap((*z).encodedApplicationCallTxnFields.Accounts[zb0021]) >= zb0187 {
+ (*z).encodedApplicationCallTxnFields.Accounts[zb0021] = ((*z).encodedApplicationCallTxnFields.Accounts[zb0021])[:zb0187]
+ } else {
+ (*z).encodedApplicationCallTxnFields.Accounts[zb0021] = make(addresses, zb0187)
+ }
+ for zb0022 := range (*z).encodedApplicationCallTxnFields.Accounts[zb0021] {
+ bts, err = (*z).encodedApplicationCallTxnFields.Accounts[zb0021][zb0022].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Accounts", zb0021, zb0022)
+ return
+ }
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0189 []byte
+ var zb0190 int
+ zb0190, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAccounts")
+ return
+ }
+ if zb0190 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0190), uint64(maxBitmaskSize))
+ return
+ }
+ zb0189, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskAccounts))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAccounts")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskAccounts = bitmask(zb0189)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0191 int
+ var zb0192 bool
+ zb0191, zb0192, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps")
+ return
+ }
+ if zb0191 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0191), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps")
+ return
+ }
+ if zb0192 {
+ (*z).encodedApplicationCallTxnFields.ForeignApps = nil
+ } else if (*z).encodedApplicationCallTxnFields.ForeignApps != nil && cap((*z).encodedApplicationCallTxnFields.ForeignApps) >= zb0191 {
+ (*z).encodedApplicationCallTxnFields.ForeignApps = ((*z).encodedApplicationCallTxnFields.ForeignApps)[:zb0191]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ForeignApps = make([]appIndices, zb0191)
+ }
+ for zb0023 := range (*z).encodedApplicationCallTxnFields.ForeignApps {
+ var zb0193 int
+ var zb0194 bool
+ zb0193, zb0194, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps", zb0023)
+ return
+ }
+ if zb0193 > transactions.EncodedMaxForeignApps {
+ err = msgp.ErrOverflow(uint64(zb0193), uint64(transactions.EncodedMaxForeignApps))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps", zb0023)
+ return
+ }
+ if zb0194 {
+ (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023] = nil
+ } else if (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023] != nil && cap((*z).encodedApplicationCallTxnFields.ForeignApps[zb0023]) >= zb0193 {
+ (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023] = ((*z).encodedApplicationCallTxnFields.ForeignApps[zb0023])[:zb0193]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023] = make(appIndices, zb0193)
+ }
+ for zb0024 := range (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023] {
+ bts, err = (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023][zb0024].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps", zb0023, zb0024)
+ return
+ }
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0195 []byte
+ var zb0196 int
+ zb0196, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignApps")
+ return
+ }
+ if zb0196 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0196), uint64(maxBitmaskSize))
+ return
+ }
+ zb0195, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskForeignApps))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignApps")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskForeignApps = bitmask(zb0195)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0197 int
+ var zb0198 bool
+ zb0197, zb0198, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets")
+ return
+ }
+ if zb0197 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0197), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets")
+ return
+ }
+ if zb0198 {
+ (*z).encodedApplicationCallTxnFields.ForeignAssets = nil
+ } else if (*z).encodedApplicationCallTxnFields.ForeignAssets != nil && cap((*z).encodedApplicationCallTxnFields.ForeignAssets) >= zb0197 {
+ (*z).encodedApplicationCallTxnFields.ForeignAssets = ((*z).encodedApplicationCallTxnFields.ForeignAssets)[:zb0197]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ForeignAssets = make([]assetIndices, zb0197)
+ }
+ for zb0025 := range (*z).encodedApplicationCallTxnFields.ForeignAssets {
+ var zb0199 int
+ var zb0200 bool
+ zb0199, zb0200, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets", zb0025)
+ return
+ }
+ if zb0199 > transactions.EncodedMaxForeignAssets {
+ err = msgp.ErrOverflow(uint64(zb0199), uint64(transactions.EncodedMaxForeignAssets))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets", zb0025)
+ return
+ }
+ if zb0200 {
+ (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025] = nil
+ } else if (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025] != nil && cap((*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025]) >= zb0199 {
+ (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025] = ((*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025])[:zb0199]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025] = make(assetIndices, zb0199)
+ }
+ for zb0026 := range (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025] {
+ bts, err = (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025][zb0026].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets", zb0025, zb0026)
+ return
+ }
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0201 []byte
+ var zb0202 int
+ zb0202, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignAssets")
+ return
+ }
+ if zb0202 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0202), uint64(maxBitmaskSize))
+ return
+ }
+ zb0201, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskForeignAssets))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignAssets")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskForeignAssets = bitmask(zb0201)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0203 int
+ var zb0204 bool
+ zb0203, zb0204, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumUint")
+ return
+ }
+ if zb0203 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0203), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumUint")
+ return
+ }
+ if zb0204 {
+ (*z).encodedApplicationCallTxnFields.LocalNumUint = nil
+ } else if (*z).encodedApplicationCallTxnFields.LocalNumUint != nil && cap((*z).encodedApplicationCallTxnFields.LocalNumUint) >= zb0203 {
+ (*z).encodedApplicationCallTxnFields.LocalNumUint = ((*z).encodedApplicationCallTxnFields.LocalNumUint)[:zb0203]
+ } else {
+ (*z).encodedApplicationCallTxnFields.LocalNumUint = make([]uint64, zb0203)
+ }
+ for zb0027 := range (*z).encodedApplicationCallTxnFields.LocalNumUint {
+ (*z).encodedApplicationCallTxnFields.LocalNumUint[zb0027], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumUint", zb0027)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0205 []byte
+ var zb0206 int
+ zb0206, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumUint")
+ return
+ }
+ if zb0206 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0206), uint64(maxBitmaskSize))
+ return
+ }
+ zb0205, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskLocalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumUint")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskLocalNumUint = bitmask(zb0205)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0207 int
+ var zb0208 bool
+ zb0207, zb0208, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumByteSlice")
+ return
+ }
+ if zb0207 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0207), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumByteSlice")
+ return
+ }
+ if zb0208 {
+ (*z).encodedApplicationCallTxnFields.LocalNumByteSlice = nil
+ } else if (*z).encodedApplicationCallTxnFields.LocalNumByteSlice != nil && cap((*z).encodedApplicationCallTxnFields.LocalNumByteSlice) >= zb0207 {
+ (*z).encodedApplicationCallTxnFields.LocalNumByteSlice = ((*z).encodedApplicationCallTxnFields.LocalNumByteSlice)[:zb0207]
+ } else {
+ (*z).encodedApplicationCallTxnFields.LocalNumByteSlice = make([]uint64, zb0207)
+ }
+ for zb0028 := range (*z).encodedApplicationCallTxnFields.LocalNumByteSlice {
+ (*z).encodedApplicationCallTxnFields.LocalNumByteSlice[zb0028], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumByteSlice", zb0028)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0209 []byte
+ var zb0210 int
+ zb0210, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumByteSlice")
+ return
+ }
+ if zb0210 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0210), uint64(maxBitmaskSize))
+ return
+ }
+ zb0209, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumByteSlice")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice = bitmask(zb0209)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0211 int
+ var zb0212 bool
+ zb0211, zb0212, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumUint")
+ return
+ }
+ if zb0211 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0211), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumUint")
+ return
+ }
+ if zb0212 {
+ (*z).encodedApplicationCallTxnFields.GlobalNumUint = nil
+ } else if (*z).encodedApplicationCallTxnFields.GlobalNumUint != nil && cap((*z).encodedApplicationCallTxnFields.GlobalNumUint) >= zb0211 {
+ (*z).encodedApplicationCallTxnFields.GlobalNumUint = ((*z).encodedApplicationCallTxnFields.GlobalNumUint)[:zb0211]
+ } else {
+ (*z).encodedApplicationCallTxnFields.GlobalNumUint = make([]uint64, zb0211)
+ }
+ for zb0029 := range (*z).encodedApplicationCallTxnFields.GlobalNumUint {
+ (*z).encodedApplicationCallTxnFields.GlobalNumUint[zb0029], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumUint", zb0029)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0213 []byte
+ var zb0214 int
+ zb0214, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumUint")
+ return
+ }
+ if zb0214 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0214), uint64(maxBitmaskSize))
+ return
+ }
+ zb0213, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskGlobalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumUint")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskGlobalNumUint = bitmask(zb0213)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0215 int
+ var zb0216 bool
+ zb0215, zb0216, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumByteSlice")
+ return
+ }
+ if zb0215 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0215), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumByteSlice")
+ return
+ }
+ if zb0216 {
+ (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice = nil
+ } else if (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice != nil && cap((*z).encodedApplicationCallTxnFields.GlobalNumByteSlice) >= zb0215 {
+ (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice = ((*z).encodedApplicationCallTxnFields.GlobalNumByteSlice)[:zb0215]
+ } else {
+ (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice = make([]uint64, zb0215)
+ }
+ for zb0030 := range (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice {
+ (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice[zb0030], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumByteSlice", zb0030)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0217 []byte
+ var zb0218 int
+ zb0218, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumByteSlice")
+ return
+ }
+ if zb0218 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0218), uint64(maxBitmaskSize))
+ return
+ }
+ zb0217, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumByteSlice")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice = bitmask(zb0217)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0219 int
+ var zb0220 bool
+ zb0219, zb0220, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram")
+ return
+ }
+ if zb0219 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0219), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram")
+ return
+ }
+ if zb0220 {
+ (*z).encodedApplicationCallTxnFields.ApprovalProgram = nil
+ } else if (*z).encodedApplicationCallTxnFields.ApprovalProgram != nil && cap((*z).encodedApplicationCallTxnFields.ApprovalProgram) >= zb0219 {
+ (*z).encodedApplicationCallTxnFields.ApprovalProgram = ((*z).encodedApplicationCallTxnFields.ApprovalProgram)[:zb0219]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ApprovalProgram = make([]program, zb0219)
+ }
+ for zb0031 := range (*z).encodedApplicationCallTxnFields.ApprovalProgram {
+ {
+ var zb0221 []byte
+ var zb0222 int
+ zb0222, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram", zb0031)
+ return
+ }
+ if zb0222 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0222), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0221, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.ApprovalProgram[zb0031]))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram", zb0031)
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.ApprovalProgram[zb0031] = program(zb0221)
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0223 []byte
+ var zb0224 int
+ zb0224, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApprovalProgram")
+ return
+ }
+ if zb0224 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0224), uint64(maxBitmaskSize))
+ return
+ }
+ zb0223, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskApprovalProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApprovalProgram")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskApprovalProgram = bitmask(zb0223)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0225 int
+ var zb0226 bool
+ zb0225, zb0226, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram")
+ return
+ }
+ if zb0225 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0225), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram")
+ return
+ }
+ if zb0226 {
+ (*z).encodedApplicationCallTxnFields.ClearStateProgram = nil
+ } else if (*z).encodedApplicationCallTxnFields.ClearStateProgram != nil && cap((*z).encodedApplicationCallTxnFields.ClearStateProgram) >= zb0225 {
+ (*z).encodedApplicationCallTxnFields.ClearStateProgram = ((*z).encodedApplicationCallTxnFields.ClearStateProgram)[:zb0225]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ClearStateProgram = make([]program, zb0225)
+ }
+ for zb0032 := range (*z).encodedApplicationCallTxnFields.ClearStateProgram {
+ {
+ var zb0227 []byte
+ var zb0228 int
+ zb0228, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram", zb0032)
+ return
+ }
+ if zb0228 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0228), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0227, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.ClearStateProgram[zb0032]))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram", zb0032)
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.ClearStateProgram[zb0032] = program(zb0227)
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0229 []byte
+ var zb0230 int
+ zb0230, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClearStateProgram")
+ return
+ }
+ if zb0230 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0230), uint64(maxBitmaskSize))
+ return
+ }
+ zb0229, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskClearStateProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClearStateProgram")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskClearStateProgram = bitmask(zb0229)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0231 int
+ var zb0232 bool
+ zb0231, zb0232, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExtraProgramPages")
+ return
+ }
+ if zb0231 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0231), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ExtraProgramPages")
+ return
+ }
+ if zb0232 {
+ (*z).encodedApplicationCallTxnFields.ExtraProgramPages = nil
+ } else if (*z).encodedApplicationCallTxnFields.ExtraProgramPages != nil && cap((*z).encodedApplicationCallTxnFields.ExtraProgramPages) >= zb0231 {
+ (*z).encodedApplicationCallTxnFields.ExtraProgramPages = ((*z).encodedApplicationCallTxnFields.ExtraProgramPages)[:zb0231]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ExtraProgramPages = make([]uint32, zb0231)
+ }
+ for zb0033 := range (*z).encodedApplicationCallTxnFields.ExtraProgramPages {
+ (*z).encodedApplicationCallTxnFields.ExtraProgramPages[zb0033], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExtraProgramPages", zb0033)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0233 []byte
+ var zb0234 int
+ zb0234, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskExtraProgramPages")
+ return
+ }
+ if zb0234 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0234), uint64(maxBitmaskSize))
+ return
+ }
+ zb0233, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskExtraProgramPages))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskExtraProgramPages")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskExtraProgramPages = bitmask(zb0233)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0235 int
+ var zb0236 bool
+ zb0235, zb0236, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertRound")
+ return
+ }
+ if zb0235 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0235), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "CertRound")
+ return
+ }
+ if zb0236 {
+ (*z).encodedCompactCertTxnFields.CertRound = nil
+ } else if (*z).encodedCompactCertTxnFields.CertRound != nil && cap((*z).encodedCompactCertTxnFields.CertRound) >= zb0235 {
+ (*z).encodedCompactCertTxnFields.CertRound = ((*z).encodedCompactCertTxnFields.CertRound)[:zb0235]
+ } else {
+ (*z).encodedCompactCertTxnFields.CertRound = make([]basics.Round, zb0235)
+ }
+ for zb0034 := range (*z).encodedCompactCertTxnFields.CertRound {
+ bts, err = (*z).encodedCompactCertTxnFields.CertRound[zb0034].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertRound", zb0034)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0237 []byte
+ var zb0238 int
+ zb0238, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertRound")
+ return
+ }
+ if zb0238 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0238), uint64(maxBitmaskSize))
+ return
+ }
+ zb0237, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCompactCertTxnFields.BitmaskCertRound))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertRound")
+ return
+ }
+ (*z).encodedCompactCertTxnFields.BitmaskCertRound = bitmask(zb0237)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0239 int
+ var zb0240 bool
+ zb0239, zb0240, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertType")
+ return
+ }
+ if zb0239 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0239), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "CertType")
+ return
+ }
+ if zb0240 {
+ (*z).encodedCompactCertTxnFields.CertType = nil
+ } else if (*z).encodedCompactCertTxnFields.CertType != nil && cap((*z).encodedCompactCertTxnFields.CertType) >= zb0239 {
+ (*z).encodedCompactCertTxnFields.CertType = ((*z).encodedCompactCertTxnFields.CertType)[:zb0239]
+ } else {
+ (*z).encodedCompactCertTxnFields.CertType = make([]protocol.CompactCertType, zb0239)
+ }
+ for zb0035 := range (*z).encodedCompactCertTxnFields.CertType {
+ bts, err = (*z).encodedCompactCertTxnFields.CertType[zb0035].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertType", zb0035)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0241 []byte
+ var zb0242 int
+ zb0242, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertType")
+ return
+ }
+ if zb0242 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0242), uint64(maxBitmaskSize))
+ return
+ }
+ zb0241, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCompactCertTxnFields.BitmaskCertType))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertType")
+ return
+ }
+ (*z).encodedCompactCertTxnFields.BitmaskCertType = bitmask(zb0241)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0243 int
+ zb0243, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigCommit")
+ return
+ }
+ if zb0243 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0243), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedCompactCertTxnFields.encodedCert.SigCommit, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedCompactCertTxnFields.encodedCert.SigCommit)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigCommit")
+ return
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0244 []byte
+ var zb0245 int
+ zb0245, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigCommit")
+ return
+ }
+ if zb0245 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0245), uint64(maxBitmaskSize))
+ return
+ }
+ zb0244, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigCommit")
+ return
+ }
+ (*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit = bitmask(zb0244)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0246 int
+ var zb0247 bool
+ zb0246, zb0247, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight")
+ return
+ }
+ if zb0246 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0246), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight")
+ return
+ }
+ if zb0247 {
+ (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight = nil
+ } else if (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight != nil && cap((*z).encodedCompactCertTxnFields.encodedCert.SignedWeight) >= zb0246 {
+ (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight = ((*z).encodedCompactCertTxnFields.encodedCert.SignedWeight)[:zb0246]
+ } else {
+ (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight = make([]uint64, zb0246)
+ }
+ for zb0036 := range (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight {
+ (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight[zb0036], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight", zb0036)
+ return
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0248 []byte
+ var zb0249 int
+ zb0249, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSignedWeight")
+ return
+ }
+ if zb0249 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0249), uint64(maxBitmaskSize))
+ return
+ }
+ zb0248, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSignedWeight")
+ return
+ }
+ (*z).encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight = bitmask(zb0248)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0250 int
+ var zb0251 bool
+ zb0250, zb0251, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs")
+ return
+ }
+ if zb0250 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0250), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs")
+ return
+ }
+ if zb0251 {
+ (*z).encodedCompactCertTxnFields.encodedCert.SigProofs = nil
+ } else if (*z).encodedCompactCertTxnFields.encodedCert.SigProofs != nil && cap((*z).encodedCompactCertTxnFields.encodedCert.SigProofs) >= zb0250 {
+ (*z).encodedCompactCertTxnFields.encodedCert.SigProofs = ((*z).encodedCompactCertTxnFields.encodedCert.SigProofs)[:zb0250]
+ } else {
+ (*z).encodedCompactCertTxnFields.encodedCert.SigProofs = make([]certProofs, zb0250)
+ }
+ for zb0037 := range (*z).encodedCompactCertTxnFields.encodedCert.SigProofs {
+ var zb0252 int
+ var zb0253 bool
+ zb0252, zb0253, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0037)
+ return
+ }
+ if zb0252 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0252), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0037)
+ return
+ }
+ if zb0253 {
+ (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037] = nil
+ } else if (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037] != nil && cap((*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037]) >= zb0252 {
+ (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037] = ((*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037])[:zb0252]
+ } else {
+ (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037] = make(certProofs, zb0252)
+ }
+ for zb0038 := range (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037] {
+ bts, err = (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037][zb0038].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0037, zb0038)
+ return
+ }
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0254 []byte
+ var zb0255 int
+ zb0255, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigProofs")
+ return
+ }
+ if zb0255 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0255), uint64(maxBitmaskSize))
+ return
+ }
+ zb0254, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigProofs")
+ return
+ }
+ (*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs = bitmask(zb0254)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0256 int
+ var zb0257 bool
+ zb0256, zb0257, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs")
+ return
+ }
+ if zb0256 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0256), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs")
+ return
+ }
+ if zb0257 {
+ (*z).encodedCompactCertTxnFields.encodedCert.PartProofs = nil
+ } else if (*z).encodedCompactCertTxnFields.encodedCert.PartProofs != nil && cap((*z).encodedCompactCertTxnFields.encodedCert.PartProofs) >= zb0256 {
+ (*z).encodedCompactCertTxnFields.encodedCert.PartProofs = ((*z).encodedCompactCertTxnFields.encodedCert.PartProofs)[:zb0256]
+ } else {
+ (*z).encodedCompactCertTxnFields.encodedCert.PartProofs = make([]certProofs, zb0256)
+ }
+ for zb0039 := range (*z).encodedCompactCertTxnFields.encodedCert.PartProofs {
+ var zb0258 int
+ var zb0259 bool
+ zb0258, zb0259, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0039)
+ return
+ }
+ if zb0258 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0258), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0039)
+ return
+ }
+ if zb0259 {
+ (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039] = nil
+ } else if (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039] != nil && cap((*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039]) >= zb0258 {
+ (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039] = ((*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039])[:zb0258]
+ } else {
+ (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039] = make(certProofs, zb0258)
+ }
+ for zb0040 := range (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039] {
+ bts, err = (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039][zb0040].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0039, zb0040)
+ return
+ }
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0260 []byte
+ var zb0261 int
+ zb0261, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskPartProofs")
+ return
+ }
+ if zb0261 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0261), uint64(maxBitmaskSize))
+ return
+ }
+ zb0260, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskPartProofs")
+ return
+ }
+ (*z).encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs = bitmask(zb0260)
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ var zb0262 int
+ var zb0263 bool
+ zb0262, zb0263, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals")
+ return
+ }
+ if zb0262 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0262), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Reveals")
+ return
+ }
+ if zb0263 {
+ (*z).encodedCompactCertTxnFields.encodedCert.Reveals = nil
+ } else if (*z).encodedCompactCertTxnFields.encodedCert.Reveals != nil && cap((*z).encodedCompactCertTxnFields.encodedCert.Reveals) >= zb0262 {
+ (*z).encodedCompactCertTxnFields.encodedCert.Reveals = ((*z).encodedCompactCertTxnFields.encodedCert.Reveals)[:zb0262]
+ } else {
+ (*z).encodedCompactCertTxnFields.encodedCert.Reveals = make([]revealMap, zb0262)
+ }
+ for zb0041 := range (*z).encodedCompactCertTxnFields.encodedCert.Reveals {
+ var zb0264 int
+ var zb0265 bool
+ zb0264, zb0265, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0041)
+ return
+ }
+ if zb0264 > compactcert.MaxReveals {
+ err = msgp.ErrOverflow(uint64(zb0264), uint64(compactcert.MaxReveals))
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0041)
+ return
+ }
+ if zb0265 {
+ (*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041] = nil
+ } else if (*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041] == nil {
+ (*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041] = make(revealMap, zb0264)
+ }
+ for zb0264 > 0 {
+ var zb0042 uint64
+ var zb0043 compactcert.Reveal
+ zb0264--
+ zb0042, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0041)
+ return
+ }
+ bts, err = zb0043.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0041, zb0042)
+ return
+ }
+ (*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041][zb0042] = zb0043
+ }
+ }
+ }
+ if zb0044 > 0 {
+ zb0044--
+ {
+ var zb0266 []byte
+ var zb0267 int
+ zb0267, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReveals")
+ return
+ }
+ if zb0267 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0267), uint64(maxBitmaskSize))
+ return
+ }
+ zb0266, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskReveals))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReveals")
+ return
+ }
+ (*z).encodedCompactCertTxnFields.encodedCert.BitmaskReveals = bitmask(zb0266)
+ }
+ }
+ if zb0044 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0044)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0045 {
+ (*z) = encodedTxns{}
+ }
+ for zb0044 > 0 {
+ zb0044--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "type":
+ var zb0268 int
+ zb0268, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "TxType")
+ return
+ }
+ if zb0268 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0268), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).TxType, bts, err = msgp.ReadBytesBytes(bts, (*z).TxType)
+ if err != nil {
+ err = msgp.WrapError(err, "TxType")
+ return
+ }
+ case "typebm":
+ {
+ var zb0269 []byte
+ var zb0270 int
+ zb0270, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTxType")
+ return
+ }
+ if zb0270 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0270), uint64(maxBitmaskSize))
+ return
+ }
+ zb0269, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).BitmaskTxType))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTxType")
+ return
+ }
+ (*z).BitmaskTxType = bitmask(zb0269)
+ }
+ case "typeo":
+ (*z).TxTypeOffset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "TxTypeOffset")
+ return
+ }
+ case "snd":
+ var zb0271 int
+ zb0271, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Sender")
+ return
+ }
+ if zb0271 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0271), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxnHeaders.Sender, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxnHeaders.Sender)
+ if err != nil {
+ err = msgp.WrapError(err, "Sender")
+ return
+ }
+ case "sndbm":
+ {
+ var zb0272 []byte
+ var zb0273 int
+ zb0273, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSender")
+ return
+ }
+ if zb0273 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0273), uint64(maxBitmaskSize))
+ return
+ }
+ zb0272, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskSender))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSender")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskSender = bitmask(zb0272)
+ }
+ case "fee":
+ var zb0274 int
+ var zb0275 bool
+ zb0274, zb0275, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Fee")
+ return
+ }
+ if zb0274 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0274), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Fee")
+ return
+ }
+ if zb0275 {
+ (*z).encodedTxnHeaders.Fee = nil
+ } else if (*z).encodedTxnHeaders.Fee != nil && cap((*z).encodedTxnHeaders.Fee) >= zb0274 {
+ (*z).encodedTxnHeaders.Fee = ((*z).encodedTxnHeaders.Fee)[:zb0274]
+ } else {
+ (*z).encodedTxnHeaders.Fee = make([]basics.MicroAlgos, zb0274)
+ }
+ for zb0001 := range (*z).encodedTxnHeaders.Fee {
+ bts, err = (*z).encodedTxnHeaders.Fee[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Fee", zb0001)
+ return
+ }
+ }
+ case "feebm":
+ {
+ var zb0276 []byte
+ var zb0277 int
+ zb0277, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFee")
+ return
+ }
+ if zb0277 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0277), uint64(maxBitmaskSize))
+ return
+ }
+ zb0276, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskFee))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFee")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskFee = bitmask(zb0276)
+ }
+ case "fv":
+ var zb0278 int
+ var zb0279 bool
+ zb0278, zb0279, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FirstValid")
+ return
+ }
+ if zb0278 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0278), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "FirstValid")
+ return
+ }
+ if zb0279 {
+ (*z).encodedTxnHeaders.FirstValid = nil
+ } else if (*z).encodedTxnHeaders.FirstValid != nil && cap((*z).encodedTxnHeaders.FirstValid) >= zb0278 {
+ (*z).encodedTxnHeaders.FirstValid = ((*z).encodedTxnHeaders.FirstValid)[:zb0278]
+ } else {
+ (*z).encodedTxnHeaders.FirstValid = make([]basics.Round, zb0278)
+ }
+ for zb0002 := range (*z).encodedTxnHeaders.FirstValid {
+ bts, err = (*z).encodedTxnHeaders.FirstValid[zb0002].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FirstValid", zb0002)
+ return
+ }
+ }
+ case "fvbm":
+ {
+ var zb0280 []byte
+ var zb0281 int
+ zb0281, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFirstValid")
+ return
+ }
+ if zb0281 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0281), uint64(maxBitmaskSize))
+ return
+ }
+ zb0280, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskFirstValid))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFirstValid")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskFirstValid = bitmask(zb0280)
+ }
+ case "lv":
+ var zb0282 int
+ var zb0283 bool
+ zb0282, zb0283, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LastValid")
+ return
+ }
+ if zb0282 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0282), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LastValid")
+ return
+ }
+ if zb0283 {
+ (*z).encodedTxnHeaders.LastValid = nil
+ } else if (*z).encodedTxnHeaders.LastValid != nil && cap((*z).encodedTxnHeaders.LastValid) >= zb0282 {
+ (*z).encodedTxnHeaders.LastValid = ((*z).encodedTxnHeaders.LastValid)[:zb0282]
+ } else {
+ (*z).encodedTxnHeaders.LastValid = make([]basics.Round, zb0282)
+ }
+ for zb0003 := range (*z).encodedTxnHeaders.LastValid {
+ bts, err = (*z).encodedTxnHeaders.LastValid[zb0003].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LastValid", zb0003)
+ return
+ }
+ }
+ case "lvbm":
+ {
+ var zb0284 []byte
+ var zb0285 int
+ zb0285, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLastValid")
+ return
+ }
+ if zb0285 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0285), uint64(maxBitmaskSize))
+ return
+ }
+ zb0284, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskLastValid))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLastValid")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskLastValid = bitmask(zb0284)
+ }
+ case "note":
+ var zb0286 int
+ var zb0287 bool
+ zb0286, zb0287, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Note")
+ return
+ }
+ if zb0286 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0286), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Note")
+ return
+ }
+ if zb0287 {
+ (*z).encodedTxnHeaders.Note = nil
+ } else if (*z).encodedTxnHeaders.Note != nil && cap((*z).encodedTxnHeaders.Note) >= zb0286 {
+ (*z).encodedTxnHeaders.Note = ((*z).encodedTxnHeaders.Note)[:zb0286]
+ } else {
+ (*z).encodedTxnHeaders.Note = make([][]byte, zb0286)
+ }
+ for zb0004 := range (*z).encodedTxnHeaders.Note {
+ var zb0288 int
+ zb0288, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Note", zb0004)
+ return
+ }
+ if zb0288 > config.MaxTxnNoteBytes {
+ err = msgp.ErrOverflow(uint64(zb0288), uint64(config.MaxTxnNoteBytes))
+ return
+ }
+ (*z).encodedTxnHeaders.Note[zb0004], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxnHeaders.Note[zb0004])
+ if err != nil {
+ err = msgp.WrapError(err, "Note", zb0004)
+ return
+ }
+ }
+ case "notebm":
+ {
+ var zb0289 []byte
+ var zb0290 int
+ zb0290, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNote")
+ return
+ }
+ if zb0290 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0290), uint64(maxBitmaskSize))
+ return
+ }
+ zb0289, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskNote))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNote")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskNote = bitmask(zb0289)
+ }
+ case "genbm":
+ {
+ var zb0291 []byte
+ var zb0292 int
+ zb0292, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGenesisID")
+ return
+ }
+ if zb0292 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0292), uint64(maxBitmaskSize))
+ return
+ }
+ zb0291, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskGenesisID))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGenesisID")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskGenesisID = bitmask(zb0291)
+ }
+ case "grpbm":
+ {
+ var zb0293 []byte
+ var zb0294 int
+ zb0294, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGroup")
+ return
+ }
+ if zb0294 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0294), uint64(maxBitmaskSize))
+ return
+ }
+ zb0293, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskGroup))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGroup")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskGroup = bitmask(zb0293)
+ }
+ case "lx":
+ var zb0295 int
+ zb0295, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Lease")
+ return
+ }
+ if zb0295 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0295), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxnHeaders.Lease, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxnHeaders.Lease)
+ if err != nil {
+ err = msgp.WrapError(err, "Lease")
+ return
+ }
+ case "lxbm":
+ {
+ var zb0296 []byte
+ var zb0297 int
+ zb0297, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLease")
+ return
+ }
+ if zb0297 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0297), uint64(maxBitmaskSize))
+ return
+ }
+ zb0296, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskLease))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLease")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskLease = bitmask(zb0296)
+ }
+ case "rekey":
+ var zb0298 int
+ zb0298, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "RekeyTo")
+ return
+ }
+ if zb0298 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0298), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedTxnHeaders.RekeyTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedTxnHeaders.RekeyTo)
+ if err != nil {
+ err = msgp.WrapError(err, "RekeyTo")
+ return
+ }
+ case "rekeybm":
+ {
+ var zb0299 []byte
+ var zb0300 int
+ zb0300, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskRekeyTo")
+ return
+ }
+ if zb0300 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0300), uint64(maxBitmaskSize))
+ return
+ }
+ zb0299, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedTxnHeaders.BitmaskRekeyTo))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskRekeyTo")
+ return
+ }
+ (*z).encodedTxnHeaders.BitmaskRekeyTo = bitmask(zb0299)
+ }
+ case "votekey":
+ var zb0301 int
+ zb0301, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VotePK")
+ return
+ }
+ if zb0301 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0301), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedKeyregTxnFields.VotePK, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedKeyregTxnFields.VotePK)
+ if err != nil {
+ err = msgp.WrapError(err, "VotePK")
+ return
+ }
+ case "selkey":
+ var zb0302 int
+ zb0302, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SelectionPK")
+ return
+ }
+ if zb0302 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0302), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedKeyregTxnFields.SelectionPK, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedKeyregTxnFields.SelectionPK)
+ if err != nil {
+ err = msgp.WrapError(err, "SelectionPK")
+ return
+ }
+ case "votefst":
+ var zb0303 int
+ var zb0304 bool
+ zb0303, zb0304, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteFirst")
+ return
+ }
+ if zb0303 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0303), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "VoteFirst")
+ return
+ }
+ if zb0304 {
+ (*z).encodedKeyregTxnFields.VoteFirst = nil
+ } else if (*z).encodedKeyregTxnFields.VoteFirst != nil && cap((*z).encodedKeyregTxnFields.VoteFirst) >= zb0303 {
+ (*z).encodedKeyregTxnFields.VoteFirst = ((*z).encodedKeyregTxnFields.VoteFirst)[:zb0303]
+ } else {
+ (*z).encodedKeyregTxnFields.VoteFirst = make([]basics.Round, zb0303)
+ }
+ for zb0005 := range (*z).encodedKeyregTxnFields.VoteFirst {
+ bts, err = (*z).encodedKeyregTxnFields.VoteFirst[zb0005].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteFirst", zb0005)
+ return
+ }
+ }
+ case "votefstbm":
+ {
+ var zb0305 []byte
+ var zb0306 int
+ zb0306, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteFirst")
+ return
+ }
+ if zb0306 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0306), uint64(maxBitmaskSize))
+ return
+ }
+ zb0305, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedKeyregTxnFields.BitmaskVoteFirst))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteFirst")
+ return
+ }
+ (*z).encodedKeyregTxnFields.BitmaskVoteFirst = bitmask(zb0305)
+ }
+ case "votelst":
+ var zb0307 int
+ var zb0308 bool
+ zb0307, zb0308, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteLast")
+ return
+ }
+ if zb0307 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0307), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "VoteLast")
+ return
+ }
+ if zb0308 {
+ (*z).encodedKeyregTxnFields.VoteLast = nil
+ } else if (*z).encodedKeyregTxnFields.VoteLast != nil && cap((*z).encodedKeyregTxnFields.VoteLast) >= zb0307 {
+ (*z).encodedKeyregTxnFields.VoteLast = ((*z).encodedKeyregTxnFields.VoteLast)[:zb0307]
+ } else {
+ (*z).encodedKeyregTxnFields.VoteLast = make([]basics.Round, zb0307)
+ }
+ for zb0006 := range (*z).encodedKeyregTxnFields.VoteLast {
+ bts, err = (*z).encodedKeyregTxnFields.VoteLast[zb0006].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteLast", zb0006)
+ return
+ }
+ }
+ case "votelstbm":
+ {
+ var zb0309 []byte
+ var zb0310 int
+ zb0310, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteLast")
+ return
+ }
+ if zb0310 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0310), uint64(maxBitmaskSize))
+ return
+ }
+ zb0309, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedKeyregTxnFields.BitmaskVoteLast))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteLast")
+ return
+ }
+ (*z).encodedKeyregTxnFields.BitmaskVoteLast = bitmask(zb0309)
+ }
+ case "votekd":
+ var zb0311 int
+ var zb0312 bool
+ zb0311, zb0312, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteKeyDilution")
+ return
+ }
+ if zb0311 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0311), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "VoteKeyDilution")
+ return
+ }
+ if zb0312 {
+ (*z).encodedKeyregTxnFields.VoteKeyDilution = nil
+ } else if (*z).encodedKeyregTxnFields.VoteKeyDilution != nil && cap((*z).encodedKeyregTxnFields.VoteKeyDilution) >= zb0311 {
+ (*z).encodedKeyregTxnFields.VoteKeyDilution = ((*z).encodedKeyregTxnFields.VoteKeyDilution)[:zb0311]
+ } else {
+ (*z).encodedKeyregTxnFields.VoteKeyDilution = make([]uint64, zb0311)
+ }
+ for zb0007 := range (*z).encodedKeyregTxnFields.VoteKeyDilution {
+ (*z).encodedKeyregTxnFields.VoteKeyDilution[zb0007], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteKeyDilution", zb0007)
+ return
+ }
+ }
+ case "votekbm":
+ {
+ var zb0313 []byte
+ var zb0314 int
+ zb0314, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskKeys")
+ return
+ }
+ if zb0314 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0314), uint64(maxBitmaskSize))
+ return
+ }
+ zb0313, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedKeyregTxnFields.BitmaskKeys))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskKeys")
+ return
+ }
+ (*z).encodedKeyregTxnFields.BitmaskKeys = bitmask(zb0313)
+ }
+ case "nonpartbm":
+ {
+ var zb0315 []byte
+ var zb0316 int
+ zb0316, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNonparticipation")
+ return
+ }
+ if zb0316 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0316), uint64(maxBitmaskSize))
+ return
+ }
+ zb0315, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedKeyregTxnFields.BitmaskNonparticipation))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNonparticipation")
+ return
+ }
+ (*z).encodedKeyregTxnFields.BitmaskNonparticipation = bitmask(zb0315)
+ }
+ case "rcv":
+ var zb0317 int
+ zb0317, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Receiver")
+ return
+ }
+ if zb0317 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0317), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedPaymentTxnFields.Receiver, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedPaymentTxnFields.Receiver)
+ if err != nil {
+ err = msgp.WrapError(err, "Receiver")
+ return
+ }
+ case "rcvbm":
+ {
+ var zb0318 []byte
+ var zb0319 int
+ zb0319, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReceiver")
+ return
+ }
+ if zb0319 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0319), uint64(maxBitmaskSize))
+ return
+ }
+ zb0318, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedPaymentTxnFields.BitmaskReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReceiver")
+ return
+ }
+ (*z).encodedPaymentTxnFields.BitmaskReceiver = bitmask(zb0318)
+ }
+ case "amt":
+ var zb0320 int
+ var zb0321 bool
+ zb0320, zb0321, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Amount")
+ return
+ }
+ if zb0320 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0320), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Amount")
+ return
+ }
+ if zb0321 {
+ (*z).encodedPaymentTxnFields.Amount = nil
+ } else if (*z).encodedPaymentTxnFields.Amount != nil && cap((*z).encodedPaymentTxnFields.Amount) >= zb0320 {
+ (*z).encodedPaymentTxnFields.Amount = ((*z).encodedPaymentTxnFields.Amount)[:zb0320]
+ } else {
+ (*z).encodedPaymentTxnFields.Amount = make([]basics.MicroAlgos, zb0320)
+ }
+ for zb0008 := range (*z).encodedPaymentTxnFields.Amount {
+ bts, err = (*z).encodedPaymentTxnFields.Amount[zb0008].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Amount", zb0008)
+ return
+ }
+ }
+ case "amtbm":
+ {
+ var zb0322 []byte
+ var zb0323 int
+ zb0323, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAmount")
+ return
+ }
+ if zb0323 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0323), uint64(maxBitmaskSize))
+ return
+ }
+ zb0322, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedPaymentTxnFields.BitmaskAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAmount")
+ return
+ }
+ (*z).encodedPaymentTxnFields.BitmaskAmount = bitmask(zb0322)
+ }
+ case "close":
+ var zb0324 int
+ zb0324, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CloseRemainderTo")
+ return
+ }
+ if zb0324 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0324), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedPaymentTxnFields.CloseRemainderTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedPaymentTxnFields.CloseRemainderTo)
+ if err != nil {
+ err = msgp.WrapError(err, "CloseRemainderTo")
+ return
+ }
+ case "closebm":
+ {
+ var zb0325 []byte
+ var zb0326 int
+ zb0326, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCloseRemainderTo")
+ return
+ }
+ if zb0326 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0326), uint64(maxBitmaskSize))
+ return
+ }
+ zb0325, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedPaymentTxnFields.BitmaskCloseRemainderTo))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCloseRemainderTo")
+ return
+ }
+ (*z).encodedPaymentTxnFields.BitmaskCloseRemainderTo = bitmask(zb0325)
+ }
+ case "caid":
+ var zb0327 int
+ var zb0328 bool
+ zb0327, zb0328, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ConfigAsset")
+ return
+ }
+ if zb0327 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0327), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ConfigAsset")
+ return
+ }
+ if zb0328 {
+ (*z).encodedAssetConfigTxnFields.ConfigAsset = nil
+ } else if (*z).encodedAssetConfigTxnFields.ConfigAsset != nil && cap((*z).encodedAssetConfigTxnFields.ConfigAsset) >= zb0327 {
+ (*z).encodedAssetConfigTxnFields.ConfigAsset = ((*z).encodedAssetConfigTxnFields.ConfigAsset)[:zb0327]
+ } else {
+ (*z).encodedAssetConfigTxnFields.ConfigAsset = make([]basics.AssetIndex, zb0327)
+ }
+ for zb0009 := range (*z).encodedAssetConfigTxnFields.ConfigAsset {
+ bts, err = (*z).encodedAssetConfigTxnFields.ConfigAsset[zb0009].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ConfigAsset", zb0009)
+ return
+ }
+ }
+ case "caidbm":
+ {
+ var zb0329 []byte
+ var zb0330 int
+ zb0330, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskConfigAsset")
+ return
+ }
+ if zb0330 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0330), uint64(maxBitmaskSize))
+ return
+ }
+ zb0329, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.BitmaskConfigAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskConfigAsset")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.BitmaskConfigAsset = bitmask(zb0329)
+ }
+ case "t":
+ var zb0331 int
+ var zb0332 bool
+ zb0331, zb0332, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Total")
+ return
+ }
+ if zb0331 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0331), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Total")
+ return
+ }
+ if zb0332 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total = nil
+ } else if (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total != nil && cap((*z).encodedAssetConfigTxnFields.encodedAssetParams.Total) >= zb0331 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total = ((*z).encodedAssetConfigTxnFields.encodedAssetParams.Total)[:zb0331]
+ } else {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total = make([]uint64, zb0331)
+ }
+ for zb0010 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Total[zb0010], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Total", zb0010)
+ return
+ }
+ }
+ case "tbm":
+ {
+ var zb0333 []byte
+ var zb0334 int
+ zb0334, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTotal")
+ return
+ }
+ if zb0334 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0334), uint64(maxBitmaskSize))
+ return
+ }
+ zb0333, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTotal")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal = bitmask(zb0333)
+ }
+ case "dc":
+ var zb0335 int
+ var zb0336 bool
+ zb0335, zb0336, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Decimals")
+ return
+ }
+ if zb0335 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0335), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Decimals")
+ return
+ }
+ if zb0336 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals = nil
+ } else if (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals != nil && cap((*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals) >= zb0335 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals = ((*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals)[:zb0335]
+ } else {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals = make([]uint32, zb0335)
+ }
+ for zb0011 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals[zb0011], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Decimals", zb0011)
+ return
+ }
+ }
+ case "dcbm":
+ {
+ var zb0337 []byte
+ var zb0338 int
+ zb0338, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDecimals")
+ return
+ }
+ if zb0338 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0338), uint64(maxBitmaskSize))
+ return
+ }
+ zb0337, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDecimals")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals = bitmask(zb0337)
+ }
+ case "dfbm":
+ {
+ var zb0339 []byte
+ var zb0340 int
+ zb0340, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDefaultFrozen")
+ return
+ }
+ if zb0340 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0340), uint64(maxBitmaskSize))
+ return
+ }
+ zb0339, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDefaultFrozen")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen = bitmask(zb0339)
+ }
+ case "un":
+ var zb0341 int
+ var zb0342 bool
+ zb0341, zb0342, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UnitName")
+ return
+ }
+ if zb0341 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0341), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "UnitName")
+ return
+ }
+ if zb0342 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName = nil
+ } else if (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName != nil && cap((*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName) >= zb0341 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName = ((*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName)[:zb0341]
+ } else {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName = make([]string, zb0341)
+ }
+ for zb0012 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName[zb0012], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UnitName", zb0012)
+ return
+ }
+ }
+ case "unbm":
+ {
+ var zb0343 []byte
+ var zb0344 int
+ zb0344, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskUnitName")
+ return
+ }
+ if zb0344 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0344), uint64(maxBitmaskSize))
+ return
+ }
+ zb0343, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskUnitName")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName = bitmask(zb0343)
+ }
+ case "an":
+ var zb0345 int
+ var zb0346 bool
+ zb0345, zb0346, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetName")
+ return
+ }
+ if zb0345 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0345), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "AssetName")
+ return
+ }
+ if zb0346 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName = nil
+ } else if (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName != nil && cap((*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName) >= zb0345 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName = ((*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName)[:zb0345]
+ } else {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName = make([]string, zb0345)
+ }
+ for zb0013 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName[zb0013], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetName", zb0013)
+ return
+ }
+ }
+ case "anbm":
+ {
+ var zb0347 []byte
+ var zb0348 int
+ zb0348, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetName")
+ return
+ }
+ if zb0348 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0348), uint64(maxBitmaskSize))
+ return
+ }
+ zb0347, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetName")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName = bitmask(zb0347)
+ }
+ case "au":
+ var zb0349 int
+ var zb0350 bool
+ zb0349, zb0350, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "URL")
+ return
+ }
+ if zb0349 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0349), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "URL")
+ return
+ }
+ if zb0350 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL = nil
+ } else if (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL != nil && cap((*z).encodedAssetConfigTxnFields.encodedAssetParams.URL) >= zb0349 {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL = ((*z).encodedAssetConfigTxnFields.encodedAssetParams.URL)[:zb0349]
+ } else {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL = make([]string, zb0349)
+ }
+ for zb0014 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL {
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL[zb0014], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "URL", zb0014)
+ return
+ }
+ }
+ case "aubm":
+ {
+ var zb0351 []byte
+ var zb0352 int
+ zb0352, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskURL")
+ return
+ }
+ if zb0352 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0352), uint64(maxBitmaskSize))
+ return
+ }
+ zb0351, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskURL")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL = bitmask(zb0351)
+ }
+ case "am":
+ var zb0353 int
+ zb0353, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "MetadataHash")
+ return
+ }
+ if zb0353 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0353), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash)
+ if err != nil {
+ err = msgp.WrapError(err, "MetadataHash")
+ return
+ }
+ case "ambm":
+ {
+ var zb0354 []byte
+ var zb0355 int
+ zb0355, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskMetadataHash")
+ return
+ }
+ if zb0355 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0355), uint64(maxBitmaskSize))
+ return
+ }
+ zb0354, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskMetadataHash")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash = bitmask(zb0354)
+ }
+ case "m":
+ var zb0356 int
+ zb0356, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Manager")
+ return
+ }
+ if zb0356 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0356), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Manager, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetConfigTxnFields.encodedAssetParams.Manager)
+ if err != nil {
+ err = msgp.WrapError(err, "Manager")
+ return
+ }
+ case "mbm":
+ {
+ var zb0357 []byte
+ var zb0358 int
+ zb0358, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskManager")
+ return
+ }
+ if zb0358 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0358), uint64(maxBitmaskSize))
+ return
+ }
+ zb0357, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskManager")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager = bitmask(zb0357)
+ }
+ case "r":
+ var zb0359 int
+ zb0359, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reserve")
+ return
+ }
+ if zb0359 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0359), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Reserve, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetConfigTxnFields.encodedAssetParams.Reserve)
+ if err != nil {
+ err = msgp.WrapError(err, "Reserve")
+ return
+ }
+ case "rbm":
+ {
+ var zb0360 []byte
+ var zb0361 int
+ zb0361, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReserve")
+ return
+ }
+ if zb0361 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0361), uint64(maxBitmaskSize))
+ return
+ }
+ zb0360, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReserve")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve = bitmask(zb0360)
+ }
+ case "f":
+ var zb0362 int
+ zb0362, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Freeze")
+ return
+ }
+ if zb0362 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0362), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Freeze, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetConfigTxnFields.encodedAssetParams.Freeze)
+ if err != nil {
+ err = msgp.WrapError(err, "Freeze")
+ return
+ }
+ case "fbm":
+ {
+ var zb0363 []byte
+ var zb0364 int
+ zb0364, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreeze")
+ return
+ }
+ if zb0364 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0364), uint64(maxBitmaskSize))
+ return
+ }
+ zb0363, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreeze")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze = bitmask(zb0363)
+ }
+ case "c":
+ var zb0365 int
+ zb0365, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Clawback")
+ return
+ }
+ if zb0365 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0365), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.Clawback, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetConfigTxnFields.encodedAssetParams.Clawback)
+ if err != nil {
+ err = msgp.WrapError(err, "Clawback")
+ return
+ }
+ case "cbm":
+ {
+ var zb0366 []byte
+ var zb0367 int
+ zb0367, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClawback")
+ return
+ }
+ if zb0367 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0367), uint64(maxBitmaskSize))
+ return
+ }
+ zb0366, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClawback")
+ return
+ }
+ (*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback = bitmask(zb0366)
+ }
+ case "xaid":
+ var zb0368 int
+ var zb0369 bool
+ zb0368, zb0369, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "XferAsset")
+ return
+ }
+ if zb0368 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0368), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "XferAsset")
+ return
+ }
+ if zb0369 {
+ (*z).encodedAssetTransferTxnFields.XferAsset = nil
+ } else if (*z).encodedAssetTransferTxnFields.XferAsset != nil && cap((*z).encodedAssetTransferTxnFields.XferAsset) >= zb0368 {
+ (*z).encodedAssetTransferTxnFields.XferAsset = ((*z).encodedAssetTransferTxnFields.XferAsset)[:zb0368]
+ } else {
+ (*z).encodedAssetTransferTxnFields.XferAsset = make([]basics.AssetIndex, zb0368)
+ }
+ for zb0015 := range (*z).encodedAssetTransferTxnFields.XferAsset {
+ bts, err = (*z).encodedAssetTransferTxnFields.XferAsset[zb0015].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "XferAsset", zb0015)
+ return
+ }
+ }
+ case "xaidbm":
+ {
+ var zb0370 []byte
+ var zb0371 int
+ zb0371, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskXferAsset")
+ return
+ }
+ if zb0371 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0371), uint64(maxBitmaskSize))
+ return
+ }
+ zb0370, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetTransferTxnFields.BitmaskXferAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskXferAsset")
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.BitmaskXferAsset = bitmask(zb0370)
+ }
+ case "aamt":
+ var zb0372 int
+ var zb0373 bool
+ zb0372, zb0373, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetAmount")
+ return
+ }
+ if zb0372 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0372), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "AssetAmount")
+ return
+ }
+ if zb0373 {
+ (*z).encodedAssetTransferTxnFields.AssetAmount = nil
+ } else if (*z).encodedAssetTransferTxnFields.AssetAmount != nil && cap((*z).encodedAssetTransferTxnFields.AssetAmount) >= zb0372 {
+ (*z).encodedAssetTransferTxnFields.AssetAmount = ((*z).encodedAssetTransferTxnFields.AssetAmount)[:zb0372]
+ } else {
+ (*z).encodedAssetTransferTxnFields.AssetAmount = make([]uint64, zb0372)
+ }
+ for zb0016 := range (*z).encodedAssetTransferTxnFields.AssetAmount {
+ (*z).encodedAssetTransferTxnFields.AssetAmount[zb0016], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetAmount", zb0016)
+ return
+ }
+ }
+ case "aamtbm":
+ {
+ var zb0374 []byte
+ var zb0375 int
+ zb0375, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetAmount")
+ return
+ }
+ if zb0375 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0375), uint64(maxBitmaskSize))
+ return
+ }
+ zb0374, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetTransferTxnFields.BitmaskAssetAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetAmount")
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.BitmaskAssetAmount = bitmask(zb0374)
+ }
+ case "asnd":
+ var zb0376 int
+ zb0376, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetSender")
+ return
+ }
+ if zb0376 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0376), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.AssetSender, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetTransferTxnFields.AssetSender)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetSender")
+ return
+ }
+ case "asndbm":
+ {
+ var zb0377 []byte
+ var zb0378 int
+ zb0378, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetSender")
+ return
+ }
+ if zb0378 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0378), uint64(maxBitmaskSize))
+ return
+ }
+ zb0377, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetTransferTxnFields.BitmaskAssetSender))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetSender")
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.BitmaskAssetSender = bitmask(zb0377)
+ }
+ case "arcv":
+ var zb0379 int
+ zb0379, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetReceiver")
+ return
+ }
+ if zb0379 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0379), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.AssetReceiver, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetTransferTxnFields.AssetReceiver)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetReceiver")
+ return
+ }
+ case "arcvbm":
+ {
+ var zb0380 []byte
+ var zb0381 int
+ zb0381, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetReceiver")
+ return
+ }
+ if zb0381 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0381), uint64(maxBitmaskSize))
+ return
+ }
+ zb0380, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetTransferTxnFields.BitmaskAssetReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetReceiver")
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.BitmaskAssetReceiver = bitmask(zb0380)
+ }
+ case "aclose":
+ var zb0382 int
+ zb0382, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetCloseTo")
+ return
+ }
+ if zb0382 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0382), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.AssetCloseTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetTransferTxnFields.AssetCloseTo)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetCloseTo")
+ return
+ }
+ case "aclosebm":
+ {
+ var zb0383 []byte
+ var zb0384 int
+ zb0384, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetCloseTo")
+ return
+ }
+ if zb0384 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0384), uint64(maxBitmaskSize))
+ return
+ }
+ zb0383, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetTransferTxnFields.BitmaskAssetCloseTo))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetCloseTo")
+ return
+ }
+ (*z).encodedAssetTransferTxnFields.BitmaskAssetCloseTo = bitmask(zb0383)
+ }
+ case "fadd":
+ var zb0385 int
+ zb0385, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAccount")
+ return
+ }
+ if zb0385 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0385), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedAssetFreezeTxnFields.FreezeAccount, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedAssetFreezeTxnFields.FreezeAccount)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAccount")
+ return
+ }
+ case "faddbm":
+ {
+ var zb0386 []byte
+ var zb0387 int
+ zb0387, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAccount")
+ return
+ }
+ if zb0387 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0387), uint64(maxBitmaskSize))
+ return
+ }
+ zb0386, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetFreezeTxnFields.BitmaskFreezeAccount))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAccount")
+ return
+ }
+ (*z).encodedAssetFreezeTxnFields.BitmaskFreezeAccount = bitmask(zb0386)
+ }
+ case "faid":
+ var zb0388 int
+ var zb0389 bool
+ zb0388, zb0389, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAsset")
+ return
+ }
+ if zb0388 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0388), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "FreezeAsset")
+ return
+ }
+ if zb0389 {
+ (*z).encodedAssetFreezeTxnFields.FreezeAsset = nil
+ } else if (*z).encodedAssetFreezeTxnFields.FreezeAsset != nil && cap((*z).encodedAssetFreezeTxnFields.FreezeAsset) >= zb0388 {
+ (*z).encodedAssetFreezeTxnFields.FreezeAsset = ((*z).encodedAssetFreezeTxnFields.FreezeAsset)[:zb0388]
+ } else {
+ (*z).encodedAssetFreezeTxnFields.FreezeAsset = make([]basics.AssetIndex, zb0388)
+ }
+ for zb0017 := range (*z).encodedAssetFreezeTxnFields.FreezeAsset {
+ bts, err = (*z).encodedAssetFreezeTxnFields.FreezeAsset[zb0017].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAsset", zb0017)
+ return
+ }
+ }
+ case "faidbm":
+ {
+ var zb0390 []byte
+ var zb0391 int
+ zb0391, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAsset")
+ return
+ }
+ if zb0391 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0391), uint64(maxBitmaskSize))
+ return
+ }
+ zb0390, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetFreezeTxnFields.BitmaskFreezeAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAsset")
+ return
+ }
+ (*z).encodedAssetFreezeTxnFields.BitmaskFreezeAsset = bitmask(zb0390)
+ }
+ case "afrzbm":
+ {
+ var zb0392 []byte
+ var zb0393 int
+ zb0393, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetFrozen")
+ return
+ }
+ if zb0393 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0393), uint64(maxBitmaskSize))
+ return
+ }
+ zb0392, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedAssetFreezeTxnFields.BitmaskAssetFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetFrozen")
+ return
+ }
+ (*z).encodedAssetFreezeTxnFields.BitmaskAssetFrozen = bitmask(zb0392)
+ }
+ case "apid":
+ var zb0394 int
+ var zb0395 bool
+ zb0394, zb0395, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationID")
+ return
+ }
+ if zb0394 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0394), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ApplicationID")
+ return
+ }
+ if zb0395 {
+ (*z).encodedApplicationCallTxnFields.ApplicationID = nil
+ } else if (*z).encodedApplicationCallTxnFields.ApplicationID != nil && cap((*z).encodedApplicationCallTxnFields.ApplicationID) >= zb0394 {
+ (*z).encodedApplicationCallTxnFields.ApplicationID = ((*z).encodedApplicationCallTxnFields.ApplicationID)[:zb0394]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ApplicationID = make([]basics.AppIndex, zb0394)
+ }
+ for zb0018 := range (*z).encodedApplicationCallTxnFields.ApplicationID {
+ bts, err = (*z).encodedApplicationCallTxnFields.ApplicationID[zb0018].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationID", zb0018)
+ return
+ }
+ }
+ case "apidbm":
+ {
+ var zb0396 []byte
+ var zb0397 int
+ zb0397, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationID")
+ return
+ }
+ if zb0397 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0397), uint64(maxBitmaskSize))
+ return
+ }
+ zb0396, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskApplicationID))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationID")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskApplicationID = bitmask(zb0396)
+ }
+ case "apan":
+ var zb0398 int
+ zb0398, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "OnCompletion")
+ return
+ }
+ if zb0398 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0398), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.OnCompletion, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedApplicationCallTxnFields.OnCompletion)
+ if err != nil {
+ err = msgp.WrapError(err, "OnCompletion")
+ return
+ }
+ case "apanbm":
+ {
+ var zb0399 []byte
+ var zb0400 int
+ zb0400, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskOnCompletion")
+ return
+ }
+ if zb0400 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0400), uint64(maxBitmaskSize))
+ return
+ }
+ zb0399, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskOnCompletion))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskOnCompletion")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskOnCompletion = bitmask(zb0399)
+ }
+ case "apaa":
+ var zb0401 int
+ var zb0402 bool
+ zb0401, zb0402, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationArgs")
+ return
+ }
+ if zb0401 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0401), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ApplicationArgs")
+ return
+ }
+ if zb0402 {
+ (*z).encodedApplicationCallTxnFields.ApplicationArgs = nil
+ } else if (*z).encodedApplicationCallTxnFields.ApplicationArgs != nil && cap((*z).encodedApplicationCallTxnFields.ApplicationArgs) >= zb0401 {
+ (*z).encodedApplicationCallTxnFields.ApplicationArgs = ((*z).encodedApplicationCallTxnFields.ApplicationArgs)[:zb0401]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ApplicationArgs = make([]applicationArgs, zb0401)
+ }
+ for zb0019 := range (*z).encodedApplicationCallTxnFields.ApplicationArgs {
+ var zb0403 int
+ var zb0404 bool
+ zb0403, zb0404, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationArgs", zb0019)
+ return
+ }
+ if zb0403 > transactions.EncodedMaxApplicationArgs {
+ err = msgp.ErrOverflow(uint64(zb0403), uint64(transactions.EncodedMaxApplicationArgs))
+ err = msgp.WrapError(err, "ApplicationArgs", zb0019)
+ return
+ }
+ if zb0404 {
+ (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019] = nil
+ } else if (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019] != nil && cap((*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019]) >= zb0403 {
+ (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019] = ((*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019])[:zb0403]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019] = make(applicationArgs, zb0403)
+ }
+ for zb0020 := range (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019] {
+ (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019][zb0020], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019][zb0020])
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationArgs", zb0019, zb0020)
+ return
+ }
+ }
+ }
+ case "apaabm":
+ {
+ var zb0405 []byte
+ var zb0406 int
+ zb0406, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationArgs")
+ return
+ }
+ if zb0406 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0406), uint64(maxBitmaskSize))
+ return
+ }
+ zb0405, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskApplicationArgs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationArgs")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskApplicationArgs = bitmask(zb0405)
+ }
+ case "apat":
+ var zb0407 int
+ var zb0408 bool
+ zb0407, zb0408, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Accounts")
+ return
+ }
+ if zb0407 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0407), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Accounts")
+ return
+ }
+ if zb0408 {
+ (*z).encodedApplicationCallTxnFields.Accounts = nil
+ } else if (*z).encodedApplicationCallTxnFields.Accounts != nil && cap((*z).encodedApplicationCallTxnFields.Accounts) >= zb0407 {
+ (*z).encodedApplicationCallTxnFields.Accounts = ((*z).encodedApplicationCallTxnFields.Accounts)[:zb0407]
+ } else {
+ (*z).encodedApplicationCallTxnFields.Accounts = make([]addresses, zb0407)
+ }
+ for zb0021 := range (*z).encodedApplicationCallTxnFields.Accounts {
+ var zb0409 int
+ var zb0410 bool
+ zb0409, zb0410, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Accounts", zb0021)
+ return
+ }
+ if zb0409 > transactions.EncodedMaxAccounts {
+ err = msgp.ErrOverflow(uint64(zb0409), uint64(transactions.EncodedMaxAccounts))
+ err = msgp.WrapError(err, "Accounts", zb0021)
+ return
+ }
+ if zb0410 {
+ (*z).encodedApplicationCallTxnFields.Accounts[zb0021] = nil
+ } else if (*z).encodedApplicationCallTxnFields.Accounts[zb0021] != nil && cap((*z).encodedApplicationCallTxnFields.Accounts[zb0021]) >= zb0409 {
+ (*z).encodedApplicationCallTxnFields.Accounts[zb0021] = ((*z).encodedApplicationCallTxnFields.Accounts[zb0021])[:zb0409]
+ } else {
+ (*z).encodedApplicationCallTxnFields.Accounts[zb0021] = make(addresses, zb0409)
+ }
+ for zb0022 := range (*z).encodedApplicationCallTxnFields.Accounts[zb0021] {
+ bts, err = (*z).encodedApplicationCallTxnFields.Accounts[zb0021][zb0022].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Accounts", zb0021, zb0022)
+ return
+ }
+ }
+ }
+ case "apatbm":
+ {
+ var zb0411 []byte
+ var zb0412 int
+ zb0412, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAccounts")
+ return
+ }
+ if zb0412 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0412), uint64(maxBitmaskSize))
+ return
+ }
+ zb0411, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskAccounts))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAccounts")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskAccounts = bitmask(zb0411)
+ }
+ case "apfa":
+ var zb0413 int
+ var zb0414 bool
+ zb0413, zb0414, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignApps")
+ return
+ }
+ if zb0413 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0413), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ForeignApps")
+ return
+ }
+ if zb0414 {
+ (*z).encodedApplicationCallTxnFields.ForeignApps = nil
+ } else if (*z).encodedApplicationCallTxnFields.ForeignApps != nil && cap((*z).encodedApplicationCallTxnFields.ForeignApps) >= zb0413 {
+ (*z).encodedApplicationCallTxnFields.ForeignApps = ((*z).encodedApplicationCallTxnFields.ForeignApps)[:zb0413]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ForeignApps = make([]appIndices, zb0413)
+ }
+ for zb0023 := range (*z).encodedApplicationCallTxnFields.ForeignApps {
+ var zb0415 int
+ var zb0416 bool
+ zb0415, zb0416, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignApps", zb0023)
+ return
+ }
+ if zb0415 > transactions.EncodedMaxForeignApps {
+ err = msgp.ErrOverflow(uint64(zb0415), uint64(transactions.EncodedMaxForeignApps))
+ err = msgp.WrapError(err, "ForeignApps", zb0023)
+ return
+ }
+ if zb0416 {
+ (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023] = nil
+ } else if (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023] != nil && cap((*z).encodedApplicationCallTxnFields.ForeignApps[zb0023]) >= zb0415 {
+ (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023] = ((*z).encodedApplicationCallTxnFields.ForeignApps[zb0023])[:zb0415]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023] = make(appIndices, zb0415)
+ }
+ for zb0024 := range (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023] {
+ bts, err = (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023][zb0024].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignApps", zb0023, zb0024)
+ return
+ }
+ }
+ }
+ case "apfabm":
+ {
+ var zb0417 []byte
+ var zb0418 int
+ zb0418, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignApps")
+ return
+ }
+ if zb0418 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0418), uint64(maxBitmaskSize))
+ return
+ }
+ zb0417, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskForeignApps))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignApps")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskForeignApps = bitmask(zb0417)
+ }
+ case "apas":
+ var zb0419 int
+ var zb0420 bool
+ zb0419, zb0420, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignAssets")
+ return
+ }
+ if zb0419 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0419), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ForeignAssets")
+ return
+ }
+ if zb0420 {
+ (*z).encodedApplicationCallTxnFields.ForeignAssets = nil
+ } else if (*z).encodedApplicationCallTxnFields.ForeignAssets != nil && cap((*z).encodedApplicationCallTxnFields.ForeignAssets) >= zb0419 {
+ (*z).encodedApplicationCallTxnFields.ForeignAssets = ((*z).encodedApplicationCallTxnFields.ForeignAssets)[:zb0419]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ForeignAssets = make([]assetIndices, zb0419)
+ }
+ for zb0025 := range (*z).encodedApplicationCallTxnFields.ForeignAssets {
+ var zb0421 int
+ var zb0422 bool
+ zb0421, zb0422, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignAssets", zb0025)
+ return
+ }
+ if zb0421 > transactions.EncodedMaxForeignAssets {
+ err = msgp.ErrOverflow(uint64(zb0421), uint64(transactions.EncodedMaxForeignAssets))
+ err = msgp.WrapError(err, "ForeignAssets", zb0025)
+ return
+ }
+ if zb0422 {
+ (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025] = nil
+ } else if (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025] != nil && cap((*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025]) >= zb0421 {
+ (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025] = ((*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025])[:zb0421]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025] = make(assetIndices, zb0421)
+ }
+ for zb0026 := range (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025] {
+ bts, err = (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025][zb0026].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignAssets", zb0025, zb0026)
+ return
+ }
+ }
+ }
+ case "apasbm":
+ {
+ var zb0423 []byte
+ var zb0424 int
+ zb0424, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignAssets")
+ return
+ }
+ if zb0424 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0424), uint64(maxBitmaskSize))
+ return
+ }
+ zb0423, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskForeignAssets))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignAssets")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskForeignAssets = bitmask(zb0423)
+ }
+ case "lnui":
+ var zb0425 int
+ var zb0426 bool
+ zb0425, zb0426, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumUint")
+ return
+ }
+ if zb0425 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0425), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LocalNumUint")
+ return
+ }
+ if zb0426 {
+ (*z).encodedApplicationCallTxnFields.LocalNumUint = nil
+ } else if (*z).encodedApplicationCallTxnFields.LocalNumUint != nil && cap((*z).encodedApplicationCallTxnFields.LocalNumUint) >= zb0425 {
+ (*z).encodedApplicationCallTxnFields.LocalNumUint = ((*z).encodedApplicationCallTxnFields.LocalNumUint)[:zb0425]
+ } else {
+ (*z).encodedApplicationCallTxnFields.LocalNumUint = make([]uint64, zb0425)
+ }
+ for zb0027 := range (*z).encodedApplicationCallTxnFields.LocalNumUint {
+ (*z).encodedApplicationCallTxnFields.LocalNumUint[zb0027], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumUint", zb0027)
+ return
+ }
+ }
+ case "lnuibm":
+ {
+ var zb0427 []byte
+ var zb0428 int
+ zb0428, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumUint")
+ return
+ }
+ if zb0428 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0428), uint64(maxBitmaskSize))
+ return
+ }
+ zb0427, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskLocalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumUint")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskLocalNumUint = bitmask(zb0427)
+ }
+ case "lnbs":
+ var zb0429 int
+ var zb0430 bool
+ zb0429, zb0430, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumByteSlice")
+ return
+ }
+ if zb0429 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0429), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LocalNumByteSlice")
+ return
+ }
+ if zb0430 {
+ (*z).encodedApplicationCallTxnFields.LocalNumByteSlice = nil
+ } else if (*z).encodedApplicationCallTxnFields.LocalNumByteSlice != nil && cap((*z).encodedApplicationCallTxnFields.LocalNumByteSlice) >= zb0429 {
+ (*z).encodedApplicationCallTxnFields.LocalNumByteSlice = ((*z).encodedApplicationCallTxnFields.LocalNumByteSlice)[:zb0429]
+ } else {
+ (*z).encodedApplicationCallTxnFields.LocalNumByteSlice = make([]uint64, zb0429)
+ }
+ for zb0028 := range (*z).encodedApplicationCallTxnFields.LocalNumByteSlice {
+ (*z).encodedApplicationCallTxnFields.LocalNumByteSlice[zb0028], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumByteSlice", zb0028)
+ return
+ }
+ }
+ case "lnbsbm":
+ {
+ var zb0431 []byte
+ var zb0432 int
+ zb0432, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumByteSlice")
+ return
+ }
+ if zb0432 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0432), uint64(maxBitmaskSize))
+ return
+ }
+ zb0431, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumByteSlice")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice = bitmask(zb0431)
+ }
+ case "gnui":
+ var zb0433 int
+ var zb0434 bool
+ zb0433, zb0434, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumUint")
+ return
+ }
+ if zb0433 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0433), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "GlobalNumUint")
+ return
+ }
+ if zb0434 {
+ (*z).encodedApplicationCallTxnFields.GlobalNumUint = nil
+ } else if (*z).encodedApplicationCallTxnFields.GlobalNumUint != nil && cap((*z).encodedApplicationCallTxnFields.GlobalNumUint) >= zb0433 {
+ (*z).encodedApplicationCallTxnFields.GlobalNumUint = ((*z).encodedApplicationCallTxnFields.GlobalNumUint)[:zb0433]
+ } else {
+ (*z).encodedApplicationCallTxnFields.GlobalNumUint = make([]uint64, zb0433)
+ }
+ for zb0029 := range (*z).encodedApplicationCallTxnFields.GlobalNumUint {
+ (*z).encodedApplicationCallTxnFields.GlobalNumUint[zb0029], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumUint", zb0029)
+ return
+ }
+ }
+ case "gnuibm":
+ {
+ var zb0435 []byte
+ var zb0436 int
+ zb0436, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumUint")
+ return
+ }
+ if zb0436 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0436), uint64(maxBitmaskSize))
+ return
+ }
+ zb0435, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskGlobalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumUint")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskGlobalNumUint = bitmask(zb0435)
+ }
+ case "gnbs":
+ var zb0437 int
+ var zb0438 bool
+ zb0437, zb0438, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumByteSlice")
+ return
+ }
+ if zb0437 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0437), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "GlobalNumByteSlice")
+ return
+ }
+ if zb0438 {
+ (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice = nil
+ } else if (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice != nil && cap((*z).encodedApplicationCallTxnFields.GlobalNumByteSlice) >= zb0437 {
+ (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice = ((*z).encodedApplicationCallTxnFields.GlobalNumByteSlice)[:zb0437]
+ } else {
+ (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice = make([]uint64, zb0437)
+ }
+ for zb0030 := range (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice {
+ (*z).encodedApplicationCallTxnFields.GlobalNumByteSlice[zb0030], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumByteSlice", zb0030)
+ return
+ }
+ }
+ case "gnbsbm":
+ {
+ var zb0439 []byte
+ var zb0440 int
+ zb0440, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumByteSlice")
+ return
+ }
+ if zb0440 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0440), uint64(maxBitmaskSize))
+ return
+ }
+ zb0439, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumByteSlice")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice = bitmask(zb0439)
+ }
+ case "apap":
+ var zb0441 int
+ var zb0442 bool
+ zb0441, zb0442, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApprovalProgram")
+ return
+ }
+ if zb0441 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0441), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ApprovalProgram")
+ return
+ }
+ if zb0442 {
+ (*z).encodedApplicationCallTxnFields.ApprovalProgram = nil
+ } else if (*z).encodedApplicationCallTxnFields.ApprovalProgram != nil && cap((*z).encodedApplicationCallTxnFields.ApprovalProgram) >= zb0441 {
+ (*z).encodedApplicationCallTxnFields.ApprovalProgram = ((*z).encodedApplicationCallTxnFields.ApprovalProgram)[:zb0441]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ApprovalProgram = make([]program, zb0441)
+ }
+ for zb0031 := range (*z).encodedApplicationCallTxnFields.ApprovalProgram {
+ {
+ var zb0443 []byte
+ var zb0444 int
+ zb0444, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApprovalProgram", zb0031)
+ return
+ }
+ if zb0444 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0444), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0443, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.ApprovalProgram[zb0031]))
+ if err != nil {
+ err = msgp.WrapError(err, "ApprovalProgram", zb0031)
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.ApprovalProgram[zb0031] = program(zb0443)
+ }
+ }
+ case "apapbm":
+ {
+ var zb0445 []byte
+ var zb0446 int
+ zb0446, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApprovalProgram")
+ return
+ }
+ if zb0446 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0446), uint64(maxBitmaskSize))
+ return
+ }
+ zb0445, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskApprovalProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApprovalProgram")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskApprovalProgram = bitmask(zb0445)
+ }
+ case "apsu":
+ var zb0447 int
+ var zb0448 bool
+ zb0447, zb0448, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ClearStateProgram")
+ return
+ }
+ if zb0447 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0447), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ClearStateProgram")
+ return
+ }
+ if zb0448 {
+ (*z).encodedApplicationCallTxnFields.ClearStateProgram = nil
+ } else if (*z).encodedApplicationCallTxnFields.ClearStateProgram != nil && cap((*z).encodedApplicationCallTxnFields.ClearStateProgram) >= zb0447 {
+ (*z).encodedApplicationCallTxnFields.ClearStateProgram = ((*z).encodedApplicationCallTxnFields.ClearStateProgram)[:zb0447]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ClearStateProgram = make([]program, zb0447)
+ }
+ for zb0032 := range (*z).encodedApplicationCallTxnFields.ClearStateProgram {
+ {
+ var zb0449 []byte
+ var zb0450 int
+ zb0450, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ClearStateProgram", zb0032)
+ return
+ }
+ if zb0450 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0450), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0449, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.ClearStateProgram[zb0032]))
+ if err != nil {
+ err = msgp.WrapError(err, "ClearStateProgram", zb0032)
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.ClearStateProgram[zb0032] = program(zb0449)
+ }
+ }
+ case "apsubm":
+ {
+ var zb0451 []byte
+ var zb0452 int
+ zb0452, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClearStateProgram")
+ return
+ }
+ if zb0452 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0452), uint64(maxBitmaskSize))
+ return
+ }
+ zb0451, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskClearStateProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClearStateProgram")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskClearStateProgram = bitmask(zb0451)
+ }
+ case "apep":
+ var zb0453 int
+ var zb0454 bool
+ zb0453, zb0454, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExtraProgramPages")
+ return
+ }
+ if zb0453 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0453), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ExtraProgramPages")
+ return
+ }
+ if zb0454 {
+ (*z).encodedApplicationCallTxnFields.ExtraProgramPages = nil
+ } else if (*z).encodedApplicationCallTxnFields.ExtraProgramPages != nil && cap((*z).encodedApplicationCallTxnFields.ExtraProgramPages) >= zb0453 {
+ (*z).encodedApplicationCallTxnFields.ExtraProgramPages = ((*z).encodedApplicationCallTxnFields.ExtraProgramPages)[:zb0453]
+ } else {
+ (*z).encodedApplicationCallTxnFields.ExtraProgramPages = make([]uint32, zb0453)
+ }
+ for zb0033 := range (*z).encodedApplicationCallTxnFields.ExtraProgramPages {
+ (*z).encodedApplicationCallTxnFields.ExtraProgramPages[zb0033], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExtraProgramPages", zb0033)
+ return
+ }
+ }
+ case "apepbm":
+ {
+ var zb0455 []byte
+ var zb0456 int
+ zb0456, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskExtraProgramPages")
+ return
+ }
+ if zb0456 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0456), uint64(maxBitmaskSize))
+ return
+ }
+ zb0455, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedApplicationCallTxnFields.BitmaskExtraProgramPages))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskExtraProgramPages")
+ return
+ }
+ (*z).encodedApplicationCallTxnFields.BitmaskExtraProgramPages = bitmask(zb0455)
+ }
+ case "certrnd":
+ var zb0457 int
+ var zb0458 bool
+ zb0457, zb0458, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertRound")
+ return
+ }
+ if zb0457 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0457), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "CertRound")
+ return
+ }
+ if zb0458 {
+ (*z).encodedCompactCertTxnFields.CertRound = nil
+ } else if (*z).encodedCompactCertTxnFields.CertRound != nil && cap((*z).encodedCompactCertTxnFields.CertRound) >= zb0457 {
+ (*z).encodedCompactCertTxnFields.CertRound = ((*z).encodedCompactCertTxnFields.CertRound)[:zb0457]
+ } else {
+ (*z).encodedCompactCertTxnFields.CertRound = make([]basics.Round, zb0457)
+ }
+ for zb0034 := range (*z).encodedCompactCertTxnFields.CertRound {
+ bts, err = (*z).encodedCompactCertTxnFields.CertRound[zb0034].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertRound", zb0034)
+ return
+ }
+ }
+ case "certrndbm":
+ {
+ var zb0459 []byte
+ var zb0460 int
+ zb0460, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertRound")
+ return
+ }
+ if zb0460 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0460), uint64(maxBitmaskSize))
+ return
+ }
+ zb0459, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCompactCertTxnFields.BitmaskCertRound))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertRound")
+ return
+ }
+ (*z).encodedCompactCertTxnFields.BitmaskCertRound = bitmask(zb0459)
+ }
+ case "certtype":
+ var zb0461 int
+ var zb0462 bool
+ zb0461, zb0462, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertType")
+ return
+ }
+ if zb0461 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0461), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "CertType")
+ return
+ }
+ if zb0462 {
+ (*z).encodedCompactCertTxnFields.CertType = nil
+ } else if (*z).encodedCompactCertTxnFields.CertType != nil && cap((*z).encodedCompactCertTxnFields.CertType) >= zb0461 {
+ (*z).encodedCompactCertTxnFields.CertType = ((*z).encodedCompactCertTxnFields.CertType)[:zb0461]
+ } else {
+ (*z).encodedCompactCertTxnFields.CertType = make([]protocol.CompactCertType, zb0461)
+ }
+ for zb0035 := range (*z).encodedCompactCertTxnFields.CertType {
+ bts, err = (*z).encodedCompactCertTxnFields.CertType[zb0035].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertType", zb0035)
+ return
+ }
+ }
+ case "certtypebm":
+ {
+ var zb0463 []byte
+ var zb0464 int
+ zb0464, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertType")
+ return
+ }
+ if zb0464 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0464), uint64(maxBitmaskSize))
+ return
+ }
+ zb0463, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCompactCertTxnFields.BitmaskCertType))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertType")
+ return
+ }
+ (*z).encodedCompactCertTxnFields.BitmaskCertType = bitmask(zb0463)
+ }
+ case "certc":
+ var zb0465 int
+ zb0465, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigCommit")
+ return
+ }
+ if zb0465 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0465), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedCompactCertTxnFields.encodedCert.SigCommit, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedCompactCertTxnFields.encodedCert.SigCommit)
+ if err != nil {
+ err = msgp.WrapError(err, "SigCommit")
+ return
+ }
+ case "certcbm":
+ {
+ var zb0466 []byte
+ var zb0467 int
+ zb0467, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigCommit")
+ return
+ }
+ if zb0467 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0467), uint64(maxBitmaskSize))
+ return
+ }
+ zb0466, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigCommit")
+ return
+ }
+ (*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit = bitmask(zb0466)
+ }
+ case "certw":
+ var zb0468 int
+ var zb0469 bool
+ zb0468, zb0469, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SignedWeight")
+ return
+ }
+ if zb0468 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0468), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "SignedWeight")
+ return
+ }
+ if zb0469 {
+ (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight = nil
+ } else if (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight != nil && cap((*z).encodedCompactCertTxnFields.encodedCert.SignedWeight) >= zb0468 {
+ (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight = ((*z).encodedCompactCertTxnFields.encodedCert.SignedWeight)[:zb0468]
+ } else {
+ (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight = make([]uint64, zb0468)
+ }
+ for zb0036 := range (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight {
+ (*z).encodedCompactCertTxnFields.encodedCert.SignedWeight[zb0036], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SignedWeight", zb0036)
+ return
+ }
+ }
+ case "certwbm":
+ {
+ var zb0470 []byte
+ var zb0471 int
+ zb0471, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSignedWeight")
+ return
+ }
+ if zb0471 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0471), uint64(maxBitmaskSize))
+ return
+ }
+ zb0470, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSignedWeight")
+ return
+ }
+ (*z).encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight = bitmask(zb0470)
+ }
+ case "certS":
+ var zb0472 int
+ var zb0473 bool
+ zb0472, zb0473, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs")
+ return
+ }
+ if zb0472 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0472), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "SigProofs")
+ return
+ }
+ if zb0473 {
+ (*z).encodedCompactCertTxnFields.encodedCert.SigProofs = nil
+ } else if (*z).encodedCompactCertTxnFields.encodedCert.SigProofs != nil && cap((*z).encodedCompactCertTxnFields.encodedCert.SigProofs) >= zb0472 {
+ (*z).encodedCompactCertTxnFields.encodedCert.SigProofs = ((*z).encodedCompactCertTxnFields.encodedCert.SigProofs)[:zb0472]
+ } else {
+ (*z).encodedCompactCertTxnFields.encodedCert.SigProofs = make([]certProofs, zb0472)
+ }
+ for zb0037 := range (*z).encodedCompactCertTxnFields.encodedCert.SigProofs {
+ var zb0474 int
+ var zb0475 bool
+ zb0474, zb0475, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs", zb0037)
+ return
+ }
+ if zb0474 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0474), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "SigProofs", zb0037)
+ return
+ }
+ if zb0475 {
+ (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037] = nil
+ } else if (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037] != nil && cap((*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037]) >= zb0474 {
+ (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037] = ((*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037])[:zb0474]
+ } else {
+ (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037] = make(certProofs, zb0474)
+ }
+ for zb0038 := range (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037] {
+ bts, err = (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037][zb0038].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs", zb0037, zb0038)
+ return
+ }
+ }
+ }
+ case "certSbm":
+ {
+ var zb0476 []byte
+ var zb0477 int
+ zb0477, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigProofs")
+ return
+ }
+ if zb0477 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0477), uint64(maxBitmaskSize))
+ return
+ }
+ zb0476, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigProofs")
+ return
+ }
+ (*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs = bitmask(zb0476)
+ }
+ case "certP":
+ var zb0478 int
+ var zb0479 bool
+ zb0478, zb0479, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs")
+ return
+ }
+ if zb0478 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0478), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "PartProofs")
+ return
+ }
+ if zb0479 {
+ (*z).encodedCompactCertTxnFields.encodedCert.PartProofs = nil
+ } else if (*z).encodedCompactCertTxnFields.encodedCert.PartProofs != nil && cap((*z).encodedCompactCertTxnFields.encodedCert.PartProofs) >= zb0478 {
+ (*z).encodedCompactCertTxnFields.encodedCert.PartProofs = ((*z).encodedCompactCertTxnFields.encodedCert.PartProofs)[:zb0478]
+ } else {
+ (*z).encodedCompactCertTxnFields.encodedCert.PartProofs = make([]certProofs, zb0478)
+ }
+ for zb0039 := range (*z).encodedCompactCertTxnFields.encodedCert.PartProofs {
+ var zb0480 int
+ var zb0481 bool
+ zb0480, zb0481, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs", zb0039)
+ return
+ }
+ if zb0480 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0480), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "PartProofs", zb0039)
+ return
+ }
+ if zb0481 {
+ (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039] = nil
+ } else if (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039] != nil && cap((*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039]) >= zb0480 {
+ (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039] = ((*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039])[:zb0480]
+ } else {
+ (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039] = make(certProofs, zb0480)
+ }
+ for zb0040 := range (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039] {
+ bts, err = (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039][zb0040].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs", zb0039, zb0040)
+ return
+ }
+ }
+ }
+ case "certPbm":
+ {
+ var zb0482 []byte
+ var zb0483 int
+ zb0483, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskPartProofs")
+ return
+ }
+ if zb0483 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0483), uint64(maxBitmaskSize))
+ return
+ }
+ zb0482, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskPartProofs")
+ return
+ }
+ (*z).encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs = bitmask(zb0482)
+ }
+ case "certr":
+ var zb0484 int
+ var zb0485 bool
+ zb0484, zb0485, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals")
+ return
+ }
+ if zb0484 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0484), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Reveals")
+ return
+ }
+ if zb0485 {
+ (*z).encodedCompactCertTxnFields.encodedCert.Reveals = nil
+ } else if (*z).encodedCompactCertTxnFields.encodedCert.Reveals != nil && cap((*z).encodedCompactCertTxnFields.encodedCert.Reveals) >= zb0484 {
+ (*z).encodedCompactCertTxnFields.encodedCert.Reveals = ((*z).encodedCompactCertTxnFields.encodedCert.Reveals)[:zb0484]
+ } else {
+ (*z).encodedCompactCertTxnFields.encodedCert.Reveals = make([]revealMap, zb0484)
+ }
+ for zb0041 := range (*z).encodedCompactCertTxnFields.encodedCert.Reveals {
+ var zb0486 int
+ var zb0487 bool
+ zb0486, zb0487, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0041)
+ return
+ }
+ if zb0486 > compactcert.MaxReveals {
+ err = msgp.ErrOverflow(uint64(zb0486), uint64(compactcert.MaxReveals))
+ err = msgp.WrapError(err, "Reveals", zb0041)
+ return
+ }
+ if zb0487 {
+ (*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041] = nil
+ } else if (*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041] == nil {
+ (*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041] = make(revealMap, zb0486)
+ }
+ for zb0486 > 0 {
+ var zb0042 uint64
+ var zb0043 compactcert.Reveal
+ zb0486--
+ zb0042, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0041)
+ return
+ }
+ bts, err = zb0043.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0041, zb0042)
+ return
+ }
+ (*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041][zb0042] = zb0043
+ }
+ }
+ case "certrbm":
+ {
+ var zb0488 []byte
+ var zb0489 int
+ zb0489, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReveals")
+ return
+ }
+ if zb0489 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0489), uint64(maxBitmaskSize))
+ return
+ }
+ zb0488, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskReveals))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReveals")
+ return
+ }
+ (*z).encodedCompactCertTxnFields.encodedCert.BitmaskReveals = bitmask(zb0488)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *encodedTxns) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*encodedTxns)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *encodedTxns) Msgsize() (s int) {
+ s = 3 + 5 + msgp.BytesPrefixSize + len((*z).TxType) + 7 + msgp.BytesPrefixSize + len([]byte((*z).BitmaskTxType)) + 6 + msgp.ByteSize + 4 + msgp.BytesPrefixSize + len((*z).encodedTxnHeaders.Sender) + 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxnHeaders.BitmaskSender)) + 4 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).encodedTxnHeaders.Fee {
+ s += (*z).encodedTxnHeaders.Fee[zb0001].Msgsize()
+ }
+ s += 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxnHeaders.BitmaskFee)) + 3 + msgp.ArrayHeaderSize
+ for zb0002 := range (*z).encodedTxnHeaders.FirstValid {
+ s += (*z).encodedTxnHeaders.FirstValid[zb0002].Msgsize()
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxnHeaders.BitmaskFirstValid)) + 3 + msgp.ArrayHeaderSize
+ for zb0003 := range (*z).encodedTxnHeaders.LastValid {
+ s += (*z).encodedTxnHeaders.LastValid[zb0003].Msgsize()
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxnHeaders.BitmaskLastValid)) + 5 + msgp.ArrayHeaderSize
+ for zb0004 := range (*z).encodedTxnHeaders.Note {
+ s += msgp.BytesPrefixSize + len((*z).encodedTxnHeaders.Note[zb0004])
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxnHeaders.BitmaskNote)) + 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxnHeaders.BitmaskGenesisID)) + 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxnHeaders.BitmaskGroup)) + 3 + msgp.BytesPrefixSize + len((*z).encodedTxnHeaders.Lease) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxnHeaders.BitmaskLease)) + 6 + msgp.BytesPrefixSize + len((*z).encodedTxnHeaders.RekeyTo) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedTxnHeaders.BitmaskRekeyTo)) + 8 + msgp.BytesPrefixSize + len((*z).encodedKeyregTxnFields.VotePK) + 7 + msgp.BytesPrefixSize + len((*z).encodedKeyregTxnFields.SelectionPK) + 8 + msgp.ArrayHeaderSize
+ for zb0005 := range (*z).encodedKeyregTxnFields.VoteFirst {
+ s += (*z).encodedKeyregTxnFields.VoteFirst[zb0005].Msgsize()
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedKeyregTxnFields.BitmaskVoteFirst)) + 8 + msgp.ArrayHeaderSize
+ for zb0006 := range (*z).encodedKeyregTxnFields.VoteLast {
+ s += (*z).encodedKeyregTxnFields.VoteLast[zb0006].Msgsize()
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedKeyregTxnFields.BitmaskVoteLast)) + 7 + msgp.ArrayHeaderSize + (len((*z).encodedKeyregTxnFields.VoteKeyDilution) * (msgp.Uint64Size)) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedKeyregTxnFields.BitmaskKeys)) + 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedKeyregTxnFields.BitmaskNonparticipation)) + 4 + msgp.BytesPrefixSize + len((*z).encodedPaymentTxnFields.Receiver) + 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedPaymentTxnFields.BitmaskReceiver)) + 4 + msgp.ArrayHeaderSize
+ for zb0008 := range (*z).encodedPaymentTxnFields.Amount {
+ s += (*z).encodedPaymentTxnFields.Amount[zb0008].Msgsize()
+ }
+ s += 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedPaymentTxnFields.BitmaskAmount)) + 6 + msgp.BytesPrefixSize + len((*z).encodedPaymentTxnFields.CloseRemainderTo) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedPaymentTxnFields.BitmaskCloseRemainderTo)) + 5 + msgp.ArrayHeaderSize
+ for zb0009 := range (*z).encodedAssetConfigTxnFields.ConfigAsset {
+ s += (*z).encodedAssetConfigTxnFields.ConfigAsset[zb0009].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetConfigTxnFields.BitmaskConfigAsset)) + 2 + msgp.ArrayHeaderSize + (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Total) * (msgp.Uint64Size)) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal)) + 3 + msgp.ArrayHeaderSize + (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals) * (msgp.Uint32Size)) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals)) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen)) + 3 + msgp.ArrayHeaderSize
+ for zb0012 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName {
+ s += msgp.StringPrefixSize + len((*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName[zb0012])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName)) + 3 + msgp.ArrayHeaderSize
+ for zb0013 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName {
+ s += msgp.StringPrefixSize + len((*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName[zb0013])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName)) + 3 + msgp.ArrayHeaderSize
+ for zb0014 := range (*z).encodedAssetConfigTxnFields.encodedAssetParams.URL {
+ s += msgp.StringPrefixSize + len((*z).encodedAssetConfigTxnFields.encodedAssetParams.URL[zb0014])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL)) + 3 + msgp.BytesPrefixSize + len((*z).encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash)) + 2 + msgp.BytesPrefixSize + len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Manager) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager)) + 2 + msgp.BytesPrefixSize + len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Reserve) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve)) + 2 + msgp.BytesPrefixSize + len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Freeze) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze)) + 2 + msgp.BytesPrefixSize + len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Clawback) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback)) + 5 + msgp.ArrayHeaderSize
+ for zb0015 := range (*z).encodedAssetTransferTxnFields.XferAsset {
+ s += (*z).encodedAssetTransferTxnFields.XferAsset[zb0015].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetTransferTxnFields.BitmaskXferAsset)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedAssetTransferTxnFields.AssetAmount) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetTransferTxnFields.BitmaskAssetAmount)) + 5 + msgp.BytesPrefixSize + len((*z).encodedAssetTransferTxnFields.AssetSender) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetTransferTxnFields.BitmaskAssetSender)) + 5 + msgp.BytesPrefixSize + len((*z).encodedAssetTransferTxnFields.AssetReceiver) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetTransferTxnFields.BitmaskAssetReceiver)) + 7 + msgp.BytesPrefixSize + len((*z).encodedAssetTransferTxnFields.AssetCloseTo) + 9 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetTransferTxnFields.BitmaskAssetCloseTo)) + 5 + msgp.BytesPrefixSize + len((*z).encodedAssetFreezeTxnFields.FreezeAccount) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetFreezeTxnFields.BitmaskFreezeAccount)) + 5 + msgp.ArrayHeaderSize
+ for zb0017 := range (*z).encodedAssetFreezeTxnFields.FreezeAsset {
+ s += (*z).encodedAssetFreezeTxnFields.FreezeAsset[zb0017].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetFreezeTxnFields.BitmaskFreezeAsset)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedAssetFreezeTxnFields.BitmaskAssetFrozen)) + 5 + msgp.ArrayHeaderSize
+ for zb0018 := range (*z).encodedApplicationCallTxnFields.ApplicationID {
+ s += (*z).encodedApplicationCallTxnFields.ApplicationID[zb0018].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.BitmaskApplicationID)) + 5 + msgp.BytesPrefixSize + len((*z).encodedApplicationCallTxnFields.OnCompletion) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.BitmaskOnCompletion)) + 5 + msgp.ArrayHeaderSize
+ for zb0019 := range (*z).encodedApplicationCallTxnFields.ApplicationArgs {
+ s += msgp.ArrayHeaderSize
+ for zb0020 := range (*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019] {
+ s += msgp.BytesPrefixSize + len((*z).encodedApplicationCallTxnFields.ApplicationArgs[zb0019][zb0020])
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.BitmaskApplicationArgs)) + 5 + msgp.ArrayHeaderSize
+ for zb0021 := range (*z).encodedApplicationCallTxnFields.Accounts {
+ s += msgp.ArrayHeaderSize
+ for zb0022 := range (*z).encodedApplicationCallTxnFields.Accounts[zb0021] {
+ s += (*z).encodedApplicationCallTxnFields.Accounts[zb0021][zb0022].Msgsize()
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.BitmaskAccounts)) + 5 + msgp.ArrayHeaderSize
+ for zb0023 := range (*z).encodedApplicationCallTxnFields.ForeignApps {
+ s += msgp.ArrayHeaderSize
+ for zb0024 := range (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023] {
+ s += (*z).encodedApplicationCallTxnFields.ForeignApps[zb0023][zb0024].Msgsize()
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.BitmaskForeignApps)) + 5 + msgp.ArrayHeaderSize
+ for zb0025 := range (*z).encodedApplicationCallTxnFields.ForeignAssets {
+ s += msgp.ArrayHeaderSize
+ for zb0026 := range (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025] {
+ s += (*z).encodedApplicationCallTxnFields.ForeignAssets[zb0025][zb0026].Msgsize()
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.BitmaskForeignAssets)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedApplicationCallTxnFields.LocalNumUint) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.BitmaskLocalNumUint)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedApplicationCallTxnFields.LocalNumByteSlice) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedApplicationCallTxnFields.GlobalNumUint) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.BitmaskGlobalNumUint)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedApplicationCallTxnFields.GlobalNumByteSlice) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice)) + 5 + msgp.ArrayHeaderSize
+ for zb0031 := range (*z).encodedApplicationCallTxnFields.ApprovalProgram {
+ s += msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.ApprovalProgram[zb0031]))
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.BitmaskApprovalProgram)) + 5 + msgp.ArrayHeaderSize
+ for zb0032 := range (*z).encodedApplicationCallTxnFields.ClearStateProgram {
+ s += msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.ClearStateProgram[zb0032]))
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.BitmaskClearStateProgram)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedApplicationCallTxnFields.ExtraProgramPages) * (msgp.Uint32Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedApplicationCallTxnFields.BitmaskExtraProgramPages)) + 8 + msgp.ArrayHeaderSize
+ for zb0034 := range (*z).encodedCompactCertTxnFields.CertRound {
+ s += (*z).encodedCompactCertTxnFields.CertRound[zb0034].Msgsize()
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedCompactCertTxnFields.BitmaskCertRound)) + 9 + msgp.ArrayHeaderSize
+ for zb0035 := range (*z).encodedCompactCertTxnFields.CertType {
+ s += (*z).encodedCompactCertTxnFields.CertType[zb0035].Msgsize()
+ }
+ s += 11 + msgp.BytesPrefixSize + len([]byte((*z).encodedCompactCertTxnFields.BitmaskCertType)) + 6 + msgp.BytesPrefixSize + len((*z).encodedCompactCertTxnFields.encodedCert.SigCommit) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit)) + 6 + msgp.ArrayHeaderSize + (len((*z).encodedCompactCertTxnFields.encodedCert.SignedWeight) * (msgp.Uint64Size)) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight)) + 6 + msgp.ArrayHeaderSize
+ for zb0037 := range (*z).encodedCompactCertTxnFields.encodedCert.SigProofs {
+ s += msgp.ArrayHeaderSize
+ for zb0038 := range (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037] {
+ s += (*z).encodedCompactCertTxnFields.encodedCert.SigProofs[zb0037][zb0038].Msgsize()
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs)) + 6 + msgp.ArrayHeaderSize
+ for zb0039 := range (*z).encodedCompactCertTxnFields.encodedCert.PartProofs {
+ s += msgp.ArrayHeaderSize
+ for zb0040 := range (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039] {
+ s += (*z).encodedCompactCertTxnFields.encodedCert.PartProofs[zb0039][zb0040].Msgsize()
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs)) + 6 + msgp.ArrayHeaderSize
+ for zb0041 := range (*z).encodedCompactCertTxnFields.encodedCert.Reveals {
+ s += msgp.MapHeaderSize
+ if (*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041] != nil {
+ for zb0042, zb0043 := range (*z).encodedCompactCertTxnFields.encodedCert.Reveals[zb0041] {
+ _ = zb0042
+ _ = zb0043
+ s += 0 + msgp.Uint64Size + zb0043.Msgsize()
+ }
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedCompactCertTxnFields.encodedCert.BitmaskReveals))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *encodedTxns) MsgIsZero() bool {
+ return (len((*z).TxType) == 0) && (len((*z).BitmaskTxType) == 0) && ((*z).TxTypeOffset == 0) && (len((*z).encodedTxnHeaders.Sender) == 0) && (len((*z).encodedTxnHeaders.BitmaskSender) == 0) && (len((*z).encodedTxnHeaders.Fee) == 0) && (len((*z).encodedTxnHeaders.BitmaskFee) == 0) && (len((*z).encodedTxnHeaders.FirstValid) == 0) && (len((*z).encodedTxnHeaders.BitmaskFirstValid) == 0) && (len((*z).encodedTxnHeaders.LastValid) == 0) && (len((*z).encodedTxnHeaders.BitmaskLastValid) == 0) && (len((*z).encodedTxnHeaders.Note) == 0) && (len((*z).encodedTxnHeaders.BitmaskNote) == 0) && (len((*z).encodedTxnHeaders.BitmaskGenesisID) == 0) && (len((*z).encodedTxnHeaders.BitmaskGroup) == 0) && (len((*z).encodedTxnHeaders.Lease) == 0) && (len((*z).encodedTxnHeaders.BitmaskLease) == 0) && (len((*z).encodedTxnHeaders.RekeyTo) == 0) && (len((*z).encodedTxnHeaders.BitmaskRekeyTo) == 0) && (len((*z).encodedKeyregTxnFields.VotePK) == 0) && (len((*z).encodedKeyregTxnFields.SelectionPK) == 0) && (len((*z).encodedKeyregTxnFields.VoteFirst) == 0) && (len((*z).encodedKeyregTxnFields.BitmaskVoteFirst) == 0) && (len((*z).encodedKeyregTxnFields.VoteLast) == 0) && (len((*z).encodedKeyregTxnFields.BitmaskVoteLast) == 0) && (len((*z).encodedKeyregTxnFields.VoteKeyDilution) == 0) && (len((*z).encodedKeyregTxnFields.BitmaskKeys) == 0) && (len((*z).encodedKeyregTxnFields.BitmaskNonparticipation) == 0) && (len((*z).encodedPaymentTxnFields.Receiver) == 0) && (len((*z).encodedPaymentTxnFields.BitmaskReceiver) == 0) && (len((*z).encodedPaymentTxnFields.Amount) == 0) && (len((*z).encodedPaymentTxnFields.BitmaskAmount) == 0) && (len((*z).encodedPaymentTxnFields.CloseRemainderTo) == 0) && (len((*z).encodedPaymentTxnFields.BitmaskCloseRemainderTo) == 0) && (len((*z).encodedAssetConfigTxnFields.ConfigAsset) == 0) && (len((*z).encodedAssetConfigTxnFields.BitmaskConfigAsset) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Total) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Decimals) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.UnitName) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.AssetName) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.URL) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Manager) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Reserve) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Freeze) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.Clawback) == 0) && (len((*z).encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback) == 0) && (len((*z).encodedAssetTransferTxnFields.XferAsset) == 0) && (len((*z).encodedAssetTransferTxnFields.BitmaskXferAsset) == 0) && (len((*z).encodedAssetTransferTxnFields.AssetAmount) == 0) && (len((*z).encodedAssetTransferTxnFields.BitmaskAssetAmount) == 0) && (len((*z).encodedAssetTransferTxnFields.AssetSender) == 0) && (len((*z).encodedAssetTransferTxnFields.BitmaskAssetSender) == 0) && (len((*z).encodedAssetTransferTxnFields.AssetReceiver) == 0) && (len((*z).encodedAssetTransferTxnFields.BitmaskAssetReceiver) == 0) && (len((*z).encodedAssetTransferTxnFields.AssetCloseTo) == 0) && (len((*z).encodedAssetTransferTxnFields.BitmaskAssetCloseTo) == 0) && (len((*z).encodedAssetFreezeTxnFields.FreezeAccount) == 0) && (len((*z).encodedAssetFreezeTxnFields.BitmaskFreezeAccount) == 0) && (len((*z).encodedAssetFreezeTxnFields.FreezeAsset) == 0) && (len((*z).encodedAssetFreezeTxnFields.BitmaskFreezeAsset) == 0) && (len((*z).encodedAssetFreezeTxnFields.BitmaskAssetFrozen) == 0) && (len((*z).encodedApplicationCallTxnFields.ApplicationID) == 0) && (len((*z).encodedApplicationCallTxnFields.BitmaskApplicationID) == 0) && (len((*z).encodedApplicationCallTxnFields.OnCompletion) == 0) && (len((*z).encodedApplicationCallTxnFields.BitmaskOnCompletion) == 0) && (len((*z).encodedApplicationCallTxnFields.ApplicationArgs) == 0) && (len((*z).encodedApplicationCallTxnFields.BitmaskApplicationArgs) == 0) && (len((*z).encodedApplicationCallTxnFields.Accounts) == 0) && (len((*z).encodedApplicationCallTxnFields.BitmaskAccounts) == 0) && (len((*z).encodedApplicationCallTxnFields.ForeignApps) == 0) && (len((*z).encodedApplicationCallTxnFields.BitmaskForeignApps) == 0) && (len((*z).encodedApplicationCallTxnFields.ForeignAssets) == 0) && (len((*z).encodedApplicationCallTxnFields.BitmaskForeignAssets) == 0) && (len((*z).encodedApplicationCallTxnFields.LocalNumUint) == 0) && (len((*z).encodedApplicationCallTxnFields.BitmaskLocalNumUint) == 0) && (len((*z).encodedApplicationCallTxnFields.LocalNumByteSlice) == 0) && (len((*z).encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice) == 0) && (len((*z).encodedApplicationCallTxnFields.GlobalNumUint) == 0) && (len((*z).encodedApplicationCallTxnFields.BitmaskGlobalNumUint) == 0) && (len((*z).encodedApplicationCallTxnFields.GlobalNumByteSlice) == 0) && (len((*z).encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice) == 0) && (len((*z).encodedApplicationCallTxnFields.ApprovalProgram) == 0) && (len((*z).encodedApplicationCallTxnFields.BitmaskApprovalProgram) == 0) && (len((*z).encodedApplicationCallTxnFields.ClearStateProgram) == 0) && (len((*z).encodedApplicationCallTxnFields.BitmaskClearStateProgram) == 0) && (len((*z).encodedApplicationCallTxnFields.ExtraProgramPages) == 0) && (len((*z).encodedApplicationCallTxnFields.BitmaskExtraProgramPages) == 0) && (len((*z).encodedCompactCertTxnFields.CertRound) == 0) && (len((*z).encodedCompactCertTxnFields.BitmaskCertRound) == 0) && (len((*z).encodedCompactCertTxnFields.CertType) == 0) && (len((*z).encodedCompactCertTxnFields.BitmaskCertType) == 0) && (len((*z).encodedCompactCertTxnFields.encodedCert.SigCommit) == 0) && (len((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit) == 0) && (len((*z).encodedCompactCertTxnFields.encodedCert.SignedWeight) == 0) && (len((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight) == 0) && (len((*z).encodedCompactCertTxnFields.encodedCert.SigProofs) == 0) && (len((*z).encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs) == 0) && (len((*z).encodedCompactCertTxnFields.encodedCert.PartProofs) == 0) && (len((*z).encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs) == 0) && (len((*z).encodedCompactCertTxnFields.encodedCert.Reveals) == 0) && (len((*z).encodedCompactCertTxnFields.encodedCert.BitmaskReveals) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *packedTransactionGroups) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0001Len := uint32(3)
+ var zb0001Mask uint8 /* 4 bits */
+ if (*z).CompressionFormat == 0 {
+ zb0001Len--
+ zb0001Mask |= 0x2
+ }
+ if len((*z).Bytes) == 0 {
+ zb0001Len--
+ zb0001Mask |= 0x4
+ }
+ if (*z).LenDecompressedBytes == 0 {
+ zb0001Len--
+ zb0001Mask |= 0x8
+ }
+ // variable map header, size zb0001Len
+ o = append(o, 0x80|uint8(zb0001Len))
+ if zb0001Len != 0 {
+ if (zb0001Mask & 0x2) == 0 { // if not empty
+ // string "c"
+ o = append(o, 0xa1, 0x63)
+ o = msgp.AppendByte(o, (*z).CompressionFormat)
+ }
+ if (zb0001Mask & 0x4) == 0 { // if not empty
+ // string "g"
+ o = append(o, 0xa1, 0x67)
+ o = msgp.AppendBytes(o, (*z).Bytes)
+ }
+ if (zb0001Mask & 0x8) == 0 { // if not empty
+ // string "l"
+ o = append(o, 0xa1, 0x6c)
+ o = msgp.AppendUint64(o, (*z).LenDecompressedBytes)
+ }
+ }
+ return
+}
+
+func (_ *packedTransactionGroups) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*packedTransactionGroups)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *packedTransactionGroups) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0001 int
+ var zb0002 bool
+ zb0001, zb0002, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0001, zb0002, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0001 > 0 {
+ zb0001--
+ var zb0003 int
+ zb0003, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Bytes")
+ return
+ }
+ if zb0003 > maxEncodedTransactionGroupBytes {
+ err = msgp.ErrOverflow(uint64(zb0003), uint64(maxEncodedTransactionGroupBytes))
+ return
+ }
+ (*z).Bytes, bts, err = msgp.ReadBytesBytes(bts, (*z).Bytes)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Bytes")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ zb0001--
+ (*z).CompressionFormat, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CompressionFormat")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ zb0001--
+ (*z).LenDecompressedBytes, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LenDecompressedBytes")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0001)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 {
+ (*z) = packedTransactionGroups{}
+ }
+ for zb0001 > 0 {
+ zb0001--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "g":
+ var zb0004 int
+ zb0004, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Bytes")
+ return
+ }
+ if zb0004 > maxEncodedTransactionGroupBytes {
+ err = msgp.ErrOverflow(uint64(zb0004), uint64(maxEncodedTransactionGroupBytes))
+ return
+ }
+ (*z).Bytes, bts, err = msgp.ReadBytesBytes(bts, (*z).Bytes)
+ if err != nil {
+ err = msgp.WrapError(err, "Bytes")
+ return
+ }
+ case "c":
+ (*z).CompressionFormat, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CompressionFormat")
+ return
+ }
+ case "l":
+ (*z).LenDecompressedBytes, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LenDecompressedBytes")
+ return
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *packedTransactionGroups) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*packedTransactionGroups)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *packedTransactionGroups) Msgsize() (s int) {
+ s = 1 + 2 + msgp.BytesPrefixSize + len((*z).Bytes) + 2 + msgp.ByteSize + 2 + msgp.Uint64Size
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *packedTransactionGroups) MsgIsZero() bool {
+ return (len((*z).Bytes) == 0) && ((*z).CompressionFormat == 0) && ((*z).LenDecompressedBytes == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z program) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ o = msgp.AppendBytes(o, []byte(z))
+ return
+}
+
+func (_ program) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(program)
+ if !ok {
+ _, ok = (z).(*program)
+ }
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *program) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ {
+ var zb0001 []byte
+ var zb0002 int
+ zb0002, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0002), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0001, bts, err = msgp.ReadBytesBytes(bts, []byte((*z)))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ (*z) = program(zb0001)
+ }
+ o = bts
+ return
+}
+
+func (_ *program) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*program)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z program) Msgsize() (s int) {
+ s = msgp.BytesPrefixSize + len([]byte(z))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z program) MsgIsZero() bool {
+ return len(z) == 0
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *relayedProposal) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0001Len := uint32(3)
+ var zb0001Mask uint8 /* 4 bits */
+ if len((*z).RawBytes) == 0 {
+ zb0001Len--
+ zb0001Mask |= 0x2
+ }
+ if (*z).Content == 0 {
+ zb0001Len--
+ zb0001Mask |= 0x4
+ }
+ if (*z).ExcludeProposal.MsgIsZero() {
+ zb0001Len--
+ zb0001Mask |= 0x8
+ }
+ // variable map header, size zb0001Len
+ o = append(o, 0x80|uint8(zb0001Len))
+ if zb0001Len != 0 {
+ if (zb0001Mask & 0x2) == 0 { // if not empty
+ // string "b"
+ o = append(o, 0xa1, 0x62)
+ o = msgp.AppendBytes(o, (*z).RawBytes)
+ }
+ if (zb0001Mask & 0x4) == 0 { // if not empty
+ // string "c"
+ o = append(o, 0xa1, 0x63)
+ o = msgp.AppendByte(o, (*z).Content)
+ }
+ if (zb0001Mask & 0x8) == 0 { // if not empty
+ // string "e"
+ o = append(o, 0xa1, 0x65)
+ o = (*z).ExcludeProposal.MarshalMsg(o)
+ }
+ }
+ return
+}
+
+func (_ *relayedProposal) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*relayedProposal)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *relayedProposal) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0001 int
+ var zb0002 bool
+ zb0001, zb0002, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0001, zb0002, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0001 > 0 {
+ zb0001--
+ var zb0003 int
+ zb0003, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "RawBytes")
+ return
+ }
+ if zb0003 > maxProposalSize {
+ err = msgp.ErrOverflow(uint64(zb0003), uint64(maxProposalSize))
+ return
+ }
+ (*z).RawBytes, bts, err = msgp.ReadBytesBytes(bts, (*z).RawBytes)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "RawBytes")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ zb0001--
+ bts, err = (*z).ExcludeProposal.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExcludeProposal")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ zb0001--
+ (*z).Content, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Content")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0001)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 {
+ (*z) = relayedProposal{}
+ }
+ for zb0001 > 0 {
+ zb0001--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "b":
+ var zb0004 int
+ zb0004, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "RawBytes")
+ return
+ }
+ if zb0004 > maxProposalSize {
+ err = msgp.ErrOverflow(uint64(zb0004), uint64(maxProposalSize))
+ return
+ }
+ (*z).RawBytes, bts, err = msgp.ReadBytesBytes(bts, (*z).RawBytes)
+ if err != nil {
+ err = msgp.WrapError(err, "RawBytes")
+ return
+ }
+ case "e":
+ bts, err = (*z).ExcludeProposal.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExcludeProposal")
+ return
+ }
+ case "c":
+ (*z).Content, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Content")
+ return
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *relayedProposal) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*relayedProposal)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *relayedProposal) Msgsize() (s int) {
+ s = 1 + 2 + msgp.BytesPrefixSize + len((*z).RawBytes) + 2 + (*z).ExcludeProposal.Msgsize() + 2 + msgp.ByteSize
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *relayedProposal) MsgIsZero() bool {
+ return (len((*z).RawBytes) == 0) && ((*z).ExcludeProposal.MsgIsZero()) && ((*z).Content == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *requestParams) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0001Len := uint32(2)
+ var zb0001Mask uint8 /* 3 bits */
+ if (*z).Modulator == 0 {
+ zb0001Len--
+ zb0001Mask |= 0x2
+ }
+ if (*z).Offset == 0 {
+ zb0001Len--
+ zb0001Mask |= 0x4
+ }
+ // variable map header, size zb0001Len
+ o = append(o, 0x80|uint8(zb0001Len))
+ if zb0001Len != 0 {
+ if (zb0001Mask & 0x2) == 0 { // if not empty
+ // string "m"
+ o = append(o, 0xa1, 0x6d)
+ o = msgp.AppendByte(o, (*z).Modulator)
+ }
+ if (zb0001Mask & 0x4) == 0 { // if not empty
+ // string "o"
+ o = append(o, 0xa1, 0x6f)
+ o = msgp.AppendByte(o, (*z).Offset)
+ }
+ }
+ return
+}
+
+func (_ *requestParams) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*requestParams)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *requestParams) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0001 int
+ var zb0002 bool
+ zb0001, zb0002, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0001, zb0002, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0001 > 0 {
+ zb0001--
+ (*z).Offset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Offset")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ zb0001--
+ (*z).Modulator, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Modulator")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0001)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 {
+ (*z) = requestParams{}
+ }
+ for zb0001 > 0 {
+ zb0001--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "o":
+ (*z).Offset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Offset")
+ return
+ }
+ case "m":
+ (*z).Modulator, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Modulator")
+ return
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *requestParams) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*requestParams)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *requestParams) Msgsize() (s int) {
+ s = 1 + 2 + msgp.ByteSize + 2 + msgp.ByteSize
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *requestParams) MsgIsZero() bool {
+ return ((*z).Offset == 0) && ((*z).Modulator == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z revealMap) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ if z == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendMapHeader(o, uint32(len(z)))
+ }
+ za0002_keys := make([]uint64, 0, len(z))
+ for za0002 := range z {
+ za0002_keys = append(za0002_keys, za0002)
+ }
+ sort.Sort(SortUint64(za0002_keys))
+ for _, za0002 := range za0002_keys {
+ za0003 := z[za0002]
+ _ = za0003
+ o = msgp.AppendUint64(o, za0002)
+ o = za0003.MarshalMsg(o)
+ }
+ return
+}
+
+func (_ revealMap) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(revealMap)
+ if !ok {
+ _, ok = (z).(*revealMap)
+ }
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *revealMap) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var zb0003 int
+ var zb0004 bool
+ zb0003, zb0004, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0003 > compactcert.MaxReveals {
+ err = msgp.ErrOverflow(uint64(zb0003), uint64(compactcert.MaxReveals))
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0004 {
+ (*z) = nil
+ } else if (*z) == nil {
+ (*z) = make(revealMap, zb0003)
+ }
+ for zb0003 > 0 {
+ var zb0001 uint64
+ var zb0002 compactcert.Reveal
+ zb0003--
+ zb0001, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ bts, err = zb0002.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, zb0001)
+ return
+ }
+ (*z)[zb0001] = zb0002
+ }
+ o = bts
+ return
+}
+
+func (_ *revealMap) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*revealMap)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z revealMap) Msgsize() (s int) {
+ s = msgp.MapHeaderSize
+ if z != nil {
+ for za0002, za0003 := range z {
+ _ = za0002
+ _ = za0003
+ s += 0 + msgp.Uint64Size + za0003.Msgsize()
+ }
+ }
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z revealMap) MsgIsZero() bool {
+ return len(z) == 0
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *timingParams) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0002Len := uint32(4)
+ var zb0002Mask uint8 /* 5 bits */
+ if len((*z).AcceptedMsgSeq) == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x2
+ }
+ if (*z).NextMsgMinDelay == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x4
+ }
+ if (*z).ResponseElapsedTime == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x8
+ }
+ if (*z).RefTxnBlockMsgSeq == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x10
+ }
+ // variable map header, size zb0002Len
+ o = append(o, 0x80|uint8(zb0002Len))
+ if zb0002Len != 0 {
+ if (zb0002Mask & 0x2) == 0 { // if not empty
+ // string "a"
+ o = append(o, 0xa1, 0x61)
+ if (*z).AcceptedMsgSeq == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).AcceptedMsgSeq)))
+ }
+ for zb0001 := range (*z).AcceptedMsgSeq {
+ o = msgp.AppendUint64(o, (*z).AcceptedMsgSeq[zb0001])
+ }
+ }
+ if (zb0002Mask & 0x4) == 0 { // if not empty
+ // string "m"
+ o = append(o, 0xa1, 0x6d)
+ o = msgp.AppendUint64(o, (*z).NextMsgMinDelay)
+ }
+ if (zb0002Mask & 0x8) == 0 { // if not empty
+ // string "r"
+ o = append(o, 0xa1, 0x72)
+ o = msgp.AppendUint64(o, (*z).ResponseElapsedTime)
+ }
+ if (zb0002Mask & 0x10) == 0 { // if not empty
+ // string "s"
+ o = append(o, 0xa1, 0x73)
+ o = msgp.AppendUint64(o, (*z).RefTxnBlockMsgSeq)
+ }
+ }
+ return
+}
+
+func (_ *timingParams) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*timingParams)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *timingParams) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0002 int
+ var zb0003 bool
+ zb0002, zb0003, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0002, zb0003, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 > 0 {
+ zb0002--
+ (*z).RefTxnBlockMsgSeq, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "RefTxnBlockMsgSeq")
+ return
+ }
+ }
+ if zb0002 > 0 {
+ zb0002--
+ (*z).ResponseElapsedTime, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ResponseElapsedTime")
+ return
+ }
+ }
+ if zb0002 > 0 {
+ zb0002--
+ var zb0004 int
+ var zb0005 bool
+ zb0004, zb0005, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AcceptedMsgSeq")
+ return
+ }
+ if zb0004 > maxAcceptedMsgSeq {
+ err = msgp.ErrOverflow(uint64(zb0004), uint64(maxAcceptedMsgSeq))
+ err = msgp.WrapError(err, "struct-from-array", "AcceptedMsgSeq")
+ return
+ }
+ if zb0005 {
+ (*z).AcceptedMsgSeq = nil
+ } else if (*z).AcceptedMsgSeq != nil && cap((*z).AcceptedMsgSeq) >= zb0004 {
+ (*z).AcceptedMsgSeq = ((*z).AcceptedMsgSeq)[:zb0004]
+ } else {
+ (*z).AcceptedMsgSeq = make([]uint64, zb0004)
+ }
+ for zb0001 := range (*z).AcceptedMsgSeq {
+ (*z).AcceptedMsgSeq[zb0001], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AcceptedMsgSeq", zb0001)
+ return
+ }
+ }
+ }
+ if zb0002 > 0 {
+ zb0002--
+ (*z).NextMsgMinDelay, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "NextMsgMinDelay")
+ return
+ }
+ }
+ if zb0002 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0002)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0003 {
+ (*z) = timingParams{}
+ }
+ for zb0002 > 0 {
+ zb0002--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "s":
+ (*z).RefTxnBlockMsgSeq, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "RefTxnBlockMsgSeq")
+ return
+ }
+ case "r":
+ (*z).ResponseElapsedTime, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ResponseElapsedTime")
+ return
+ }
+ case "a":
+ var zb0006 int
+ var zb0007 bool
+ zb0006, zb0007, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AcceptedMsgSeq")
+ return
+ }
+ if zb0006 > maxAcceptedMsgSeq {
+ err = msgp.ErrOverflow(uint64(zb0006), uint64(maxAcceptedMsgSeq))
+ err = msgp.WrapError(err, "AcceptedMsgSeq")
+ return
+ }
+ if zb0007 {
+ (*z).AcceptedMsgSeq = nil
+ } else if (*z).AcceptedMsgSeq != nil && cap((*z).AcceptedMsgSeq) >= zb0006 {
+ (*z).AcceptedMsgSeq = ((*z).AcceptedMsgSeq)[:zb0006]
+ } else {
+ (*z).AcceptedMsgSeq = make([]uint64, zb0006)
+ }
+ for zb0001 := range (*z).AcceptedMsgSeq {
+ (*z).AcceptedMsgSeq[zb0001], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AcceptedMsgSeq", zb0001)
+ return
+ }
+ }
+ case "m":
+ (*z).NextMsgMinDelay, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "NextMsgMinDelay")
+ return
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *timingParams) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*timingParams)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *timingParams) Msgsize() (s int) {
+ s = 1 + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + msgp.ArrayHeaderSize + (len((*z).AcceptedMsgSeq) * (msgp.Uint64Size)) + 2 + msgp.Uint64Size
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *timingParams) MsgIsZero() bool {
+ return ((*z).RefTxnBlockMsgSeq == 0) && ((*z).ResponseElapsedTime == 0) && (len((*z).AcceptedMsgSeq) == 0) && ((*z).NextMsgMinDelay == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *transactionBlockMessage) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0001Len := uint32(7)
+ var zb0001Mask uint8 /* 8 bits */
+ if (*z).TxnBloomFilter.MsgIsZero() {
+ zb0001Len--
+ zb0001Mask |= 0x2
+ }
+ if (*z).TransactionGroups.MsgIsZero() {
+ zb0001Len--
+ zb0001Mask |= 0x4
+ }
+ if ((*z).UpdatedRequestParams.Offset == 0) && ((*z).UpdatedRequestParams.Modulator == 0) {
+ zb0001Len--
+ zb0001Mask |= 0x8
+ }
+ if (*z).Round.MsgIsZero() {
+ zb0001Len--
+ zb0001Mask |= 0x10
+ }
+ if (*z).RelayedProposal.MsgIsZero() {
+ zb0001Len--
+ zb0001Mask |= 0x20
+ }
+ if (*z).MsgSync.MsgIsZero() {
+ zb0001Len--
+ zb0001Mask |= 0x40
+ }
+ if (*z).Version == 0 {
+ zb0001Len--
+ zb0001Mask |= 0x80
+ }
+ // variable map header, size zb0001Len
+ o = append(o, 0x80|uint8(zb0001Len))
+ if zb0001Len != 0 {
+ if (zb0001Mask & 0x2) == 0 { // if not empty
+ // string "b"
+ o = append(o, 0xa1, 0x62)
+ o = (*z).TxnBloomFilter.MarshalMsg(o)
+ }
+ if (zb0001Mask & 0x4) == 0 { // if not empty
+ // string "g"
+ o = append(o, 0xa1, 0x67)
+ o = (*z).TransactionGroups.MarshalMsg(o)
+ }
+ if (zb0001Mask & 0x8) == 0 { // if not empty
+ // string "p"
+ o = append(o, 0xa1, 0x70)
+ // omitempty: check for empty values
+ zb0002Len := uint32(2)
+ var zb0002Mask uint8 /* 3 bits */
+ if (*z).UpdatedRequestParams.Modulator == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x2
+ }
+ if (*z).UpdatedRequestParams.Offset == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x4
+ }
+ // variable map header, size zb0002Len
+ o = append(o, 0x80|uint8(zb0002Len))
+ if (zb0002Mask & 0x2) == 0 { // if not empty
+ // string "m"
+ o = append(o, 0xa1, 0x6d)
+ o = msgp.AppendByte(o, (*z).UpdatedRequestParams.Modulator)
+ }
+ if (zb0002Mask & 0x4) == 0 { // if not empty
+ // string "o"
+ o = append(o, 0xa1, 0x6f)
+ o = msgp.AppendByte(o, (*z).UpdatedRequestParams.Offset)
+ }
+ }
+ if (zb0001Mask & 0x10) == 0 { // if not empty
+ // string "r"
+ o = append(o, 0xa1, 0x72)
+ o = (*z).Round.MarshalMsg(o)
+ }
+ if (zb0001Mask & 0x20) == 0 { // if not empty
+ // string "rp"
+ o = append(o, 0xa2, 0x72, 0x70)
+ o = (*z).RelayedProposal.MarshalMsg(o)
+ }
+ if (zb0001Mask & 0x40) == 0 { // if not empty
+ // string "t"
+ o = append(o, 0xa1, 0x74)
+ o = (*z).MsgSync.MarshalMsg(o)
+ }
+ if (zb0001Mask & 0x80) == 0 { // if not empty
+ // string "v"
+ o = append(o, 0xa1, 0x76)
+ o = msgp.AppendInt32(o, (*z).Version)
+ }
+ }
+ return
+}
+
+func (_ *transactionBlockMessage) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*transactionBlockMessage)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *transactionBlockMessage) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0001 int
+ var zb0002 bool
+ zb0001, zb0002, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0001, zb0002, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0001 > 0 {
+ zb0001--
+ (*z).Version, bts, err = msgp.ReadInt32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Version")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ zb0001--
+ bts, err = (*z).Round.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Round")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ zb0001--
+ bts, err = (*z).TxnBloomFilter.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TxnBloomFilter")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ zb0001--
+ var zb0003 int
+ var zb0004 bool
+ zb0003, zb0004, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0003, zb0004, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UpdatedRequestParams")
+ return
+ }
+ if zb0003 > 0 {
+ zb0003--
+ (*z).UpdatedRequestParams.Offset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UpdatedRequestParams", "struct-from-array", "Offset")
+ return
+ }
+ }
+ if zb0003 > 0 {
+ zb0003--
+ (*z).UpdatedRequestParams.Modulator, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UpdatedRequestParams", "struct-from-array", "Modulator")
+ return
+ }
+ }
+ if zb0003 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0003)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UpdatedRequestParams", "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UpdatedRequestParams")
+ return
+ }
+ if zb0004 {
+ (*z).UpdatedRequestParams = requestParams{}
+ }
+ for zb0003 > 0 {
+ zb0003--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UpdatedRequestParams")
+ return
+ }
+ switch string(field) {
+ case "o":
+ (*z).UpdatedRequestParams.Offset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UpdatedRequestParams", "Offset")
+ return
+ }
+ case "m":
+ (*z).UpdatedRequestParams.Modulator, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UpdatedRequestParams", "Modulator")
+ return
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UpdatedRequestParams")
+ return
+ }
+ }
+ }
+ }
+ }
+ if zb0001 > 0 {
+ zb0001--
+ bts, err = (*z).TransactionGroups.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TransactionGroups")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ zb0001--
+ bts, err = (*z).MsgSync.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "MsgSync")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ zb0001--
+ bts, err = (*z).RelayedProposal.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "RelayedProposal")
+ return
+ }
+ }
+ if zb0001 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0001)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 {
+ (*z) = transactionBlockMessage{}
+ }
+ for zb0001 > 0 {
+ zb0001--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "v":
+ (*z).Version, bts, err = msgp.ReadInt32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Version")
+ return
+ }
+ case "r":
+ bts, err = (*z).Round.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Round")
+ return
+ }
+ case "b":
+ bts, err = (*z).TxnBloomFilter.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "TxnBloomFilter")
+ return
+ }
+ case "p":
+ var zb0005 int
+ var zb0006 bool
+ zb0005, zb0006, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0005, zb0006, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UpdatedRequestParams")
+ return
+ }
+ if zb0005 > 0 {
+ zb0005--
+ (*z).UpdatedRequestParams.Offset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UpdatedRequestParams", "struct-from-array", "Offset")
+ return
+ }
+ }
+ if zb0005 > 0 {
+ zb0005--
+ (*z).UpdatedRequestParams.Modulator, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UpdatedRequestParams", "struct-from-array", "Modulator")
+ return
+ }
+ }
+ if zb0005 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0005)
+ if err != nil {
+ err = msgp.WrapError(err, "UpdatedRequestParams", "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err, "UpdatedRequestParams")
+ return
+ }
+ if zb0006 {
+ (*z).UpdatedRequestParams = requestParams{}
+ }
+ for zb0005 > 0 {
+ zb0005--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UpdatedRequestParams")
+ return
+ }
+ switch string(field) {
+ case "o":
+ (*z).UpdatedRequestParams.Offset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UpdatedRequestParams", "Offset")
+ return
+ }
+ case "m":
+ (*z).UpdatedRequestParams.Modulator, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UpdatedRequestParams", "Modulator")
+ return
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err, "UpdatedRequestParams")
+ return
+ }
+ }
+ }
+ }
+ case "g":
+ bts, err = (*z).TransactionGroups.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "TransactionGroups")
+ return
+ }
+ case "t":
+ bts, err = (*z).MsgSync.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "MsgSync")
+ return
+ }
+ case "rp":
+ bts, err = (*z).RelayedProposal.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "RelayedProposal")
+ return
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *transactionBlockMessage) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*transactionBlockMessage)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *transactionBlockMessage) Msgsize() (s int) {
+ s = 1 + 2 + msgp.Int32Size + 2 + (*z).Round.Msgsize() + 2 + (*z).TxnBloomFilter.Msgsize() + 2 + 1 + 2 + msgp.ByteSize + 2 + msgp.ByteSize + 2 + (*z).TransactionGroups.Msgsize() + 2 + (*z).MsgSync.Msgsize() + 3 + (*z).RelayedProposal.Msgsize()
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *transactionBlockMessage) MsgIsZero() bool {
+ return ((*z).Version == 0) && ((*z).Round.MsgIsZero()) && ((*z).TxnBloomFilter.MsgIsZero()) && (((*z).UpdatedRequestParams.Offset == 0) && ((*z).UpdatedRequestParams.Modulator == 0)) && ((*z).TransactionGroups.MsgIsZero()) && ((*z).MsgSync.MsgIsZero()) && ((*z).RelayedProposal.MsgIsZero())
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *txGroupsEncodingStub) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0049Len := uint32(129)
+ var zb0049Mask [3]uint64 /* 144 bits */
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x8000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x10000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x20000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x40000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x80000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x100000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x200000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x400000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskAmount) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x800000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x1000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x2000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x4000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x8000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.OnCompletion) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x10000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x20000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x40000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x80000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x100000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x200000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x400000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x800000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x1000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x2000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x4000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x8000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x10000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x20000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x40000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x80000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetReceiver) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x100000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x200000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetSender) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x400000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x800000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x1000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x2000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x4000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x8000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x10000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x20000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x40000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x80000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x100000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x200000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x400000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x800000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x1000000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x2000000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x4000000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound) == 0 {
+ zb0049Len--
+ zb0049Mask[0] |= 0x8000000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x1
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertType) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x2
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x4
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x8
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.CloseRemainderTo) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x10
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x20
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x40
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x80
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x100
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x200
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x400
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x800
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x1000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x2000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x4000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x8000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFee) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x10000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x20000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFirstValid) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x40000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGenesisID) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x80000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x100000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x200000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x400000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x800000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGroup) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x1000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x2000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x4000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x8000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x10000000
+ }
+ if len((*z).encodedSignedTxns.encodedLsigs.LogicArgs) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x20000000
+ }
+ if len((*z).encodedSignedTxns.encodedLsigs.BitmaskLogicArgs) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x40000000
+ }
+ if len((*z).encodedSignedTxns.encodedLsigs.Logic) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x80000000
+ }
+ if len((*z).encodedSignedTxns.encodedLsigs.BitmaskLogic) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x100000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x200000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLastValid) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x400000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Lease) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x800000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLease) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x1000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x2000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x4000000000
+ }
+ if len((*z).encodedSignedTxns.encodedMsigs.Threshold) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x8000000000
+ }
+ if len((*z).encodedSignedTxns.encodedMsigs.BitmaskThreshold) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x10000000000
+ }
+ if len((*z).encodedSignedTxns.encodedMsigs.Version) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x20000000000
+ }
+ if len((*z).encodedSignedTxns.encodedMsigs.BitmaskVersion) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x40000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x80000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x100000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskNote) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x200000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x400000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x800000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Receiver) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x1000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskReceiver) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x2000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.RekeyTo) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x4000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskRekeyTo) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x8000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.SelectionPK) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x10000000000000
+ }
+ if len((*z).encodedSignedTxns.AuthAddr) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x20000000000000
+ }
+ if len((*z).encodedSignedTxns.BitmaskAuthAddr) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x40000000000000
+ }
+ if len((*z).encodedSignedTxns.Sig) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x80000000000000
+ }
+ if len((*z).encodedSignedTxns.BitmaskSig) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x100000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Sender) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x200000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskSender) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x400000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedMsigs.Subsigs) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x800000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedMsigs.BitmaskSubsigs) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x1000000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x2000000000000000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal) == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x4000000000000000
+ }
+ if (*z).TransactionGroupCount == 0 {
+ zb0049Len--
+ zb0049Mask[1] |= 0x8000000000000000
+ }
+ if len((*z).TransactionGroupSizes) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x1
+ }
+ if (*z).TotalTransactionsCount == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x2
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.TxType) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x4
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.BitmaskTxType) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x8
+ }
+ if (*z).encodedSignedTxns.encodedTxns.TxTypeOffset == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x10
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x20
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x40
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x80
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x100
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskKeys) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x200
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x400
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VotePK) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x800
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x1000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x2000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x4000
+ }
+ if len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset) == 0 {
+ zb0049Len--
+ zb0049Mask[2] |= 0x8000
+ }
+ // variable map header, size zb0049Len
+ o = msgp.AppendMapHeader(o, zb0049Len)
+ if zb0049Len != 0 {
+ if (zb0049Mask[0] & 0x8000) == 0 { // if not empty
+ // string "aamt"
+ o = append(o, 0xa4, 0x61, 0x61, 0x6d, 0x74)
+ if (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount)))
+ }
+ for zb0021 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount {
+ o = msgp.AppendUint64(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount[zb0021])
+ }
+ }
+ if (zb0049Mask[0] & 0x10000) == 0 { // if not empty
+ // string "aamtbm"
+ o = append(o, 0xa6, 0x61, 0x61, 0x6d, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount))
+ }
+ if (zb0049Mask[0] & 0x20000) == 0 { // if not empty
+ // string "aclose"
+ o = append(o, 0xa6, 0x61, 0x63, 0x6c, 0x6f, 0x73, 0x65)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo)
+ }
+ if (zb0049Mask[0] & 0x40000) == 0 { // if not empty
+ // string "aclosebm"
+ o = append(o, 0xa8, 0x61, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo))
+ }
+ if (zb0049Mask[0] & 0x80000) == 0 { // if not empty
+ // string "afrzbm"
+ o = append(o, 0xa6, 0x61, 0x66, 0x72, 0x7a, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen))
+ }
+ if (zb0049Mask[0] & 0x100000) == 0 { // if not empty
+ // string "am"
+ o = append(o, 0xa2, 0x61, 0x6d)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash)
+ }
+ if (zb0049Mask[0] & 0x200000) == 0 { // if not empty
+ // string "ambm"
+ o = append(o, 0xa4, 0x61, 0x6d, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash))
+ }
+ if (zb0049Mask[0] & 0x400000) == 0 { // if not empty
+ // string "amt"
+ o = append(o, 0xa3, 0x61, 0x6d, 0x74)
+ if (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount)))
+ }
+ for zb0013 := range (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount[zb0013].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[0] & 0x800000) == 0 { // if not empty
+ // string "amtbm"
+ o = append(o, 0xa5, 0x61, 0x6d, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskAmount))
+ }
+ if (zb0049Mask[0] & 0x1000000) == 0 { // if not empty
+ // string "an"
+ o = append(o, 0xa2, 0x61, 0x6e)
+ if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName)))
+ }
+ for zb0018 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName {
+ o = msgp.AppendString(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName[zb0018])
+ }
+ }
+ if (zb0049Mask[0] & 0x2000000) == 0 { // if not empty
+ // string "anbm"
+ o = append(o, 0xa4, 0x61, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName))
+ }
+ if (zb0049Mask[0] & 0x4000000) == 0 { // if not empty
+ // string "apaa"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x61)
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs)))
+ }
+ for zb0024 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs {
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024])))
+ }
+ for zb0025 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] {
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024][zb0025])
+ }
+ }
+ }
+ if (zb0049Mask[0] & 0x8000000) == 0 { // if not empty
+ // string "apaabm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x61, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs))
+ }
+ if (zb0049Mask[0] & 0x10000000) == 0 { // if not empty
+ // string "apan"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x6e)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.OnCompletion)
+ }
+ if (zb0049Mask[0] & 0x20000000) == 0 { // if not empty
+ // string "apanbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion))
+ }
+ if (zb0049Mask[0] & 0x40000000) == 0 { // if not empty
+ // string "apap"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x70)
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram)))
+ }
+ for zb0036 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram {
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram[zb0036]))
+ }
+ }
+ if (zb0049Mask[0] & 0x80000000) == 0 { // if not empty
+ // string "apapbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x70, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram))
+ }
+ if (zb0049Mask[0] & 0x100000000) == 0 { // if not empty
+ // string "apas"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x73)
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets)))
+ }
+ for zb0030 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets {
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030])))
+ }
+ for zb0031 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030][zb0031].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0049Mask[0] & 0x200000000) == 0 { // if not empty
+ // string "apasbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets))
+ }
+ if (zb0049Mask[0] & 0x400000000) == 0 { // if not empty
+ // string "apat"
+ o = append(o, 0xa4, 0x61, 0x70, 0x61, 0x74)
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts)))
+ }
+ for zb0026 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts {
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026])))
+ }
+ for zb0027 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026][zb0027].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0049Mask[0] & 0x800000000) == 0 { // if not empty
+ // string "apatbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x61, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts))
+ }
+ if (zb0049Mask[0] & 0x1000000000) == 0 { // if not empty
+ // string "apep"
+ o = append(o, 0xa4, 0x61, 0x70, 0x65, 0x70)
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages)))
+ }
+ for zb0038 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages {
+ o = msgp.AppendUint32(o, (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages[zb0038])
+ }
+ }
+ if (zb0049Mask[0] & 0x2000000000) == 0 { // if not empty
+ // string "apepbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x65, 0x70, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages))
+ }
+ if (zb0049Mask[0] & 0x4000000000) == 0 { // if not empty
+ // string "apfa"
+ o = append(o, 0xa4, 0x61, 0x70, 0x66, 0x61)
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps)))
+ }
+ for zb0028 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps {
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028])))
+ }
+ for zb0029 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028][zb0029].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0049Mask[0] & 0x8000000000) == 0 { // if not empty
+ // string "apfabm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x66, 0x61, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps))
+ }
+ if (zb0049Mask[0] & 0x10000000000) == 0 { // if not empty
+ // string "apid"
+ o = append(o, 0xa4, 0x61, 0x70, 0x69, 0x64)
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID)))
+ }
+ for zb0023 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID[zb0023].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[0] & 0x20000000000) == 0 { // if not empty
+ // string "apidbm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID))
+ }
+ if (zb0049Mask[0] & 0x40000000000) == 0 { // if not empty
+ // string "apsu"
+ o = append(o, 0xa4, 0x61, 0x70, 0x73, 0x75)
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram)))
+ }
+ for zb0037 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram {
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram[zb0037]))
+ }
+ }
+ if (zb0049Mask[0] & 0x80000000000) == 0 { // if not empty
+ // string "apsubm"
+ o = append(o, 0xa6, 0x61, 0x70, 0x73, 0x75, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram))
+ }
+ if (zb0049Mask[0] & 0x100000000000) == 0 { // if not empty
+ // string "arcv"
+ o = append(o, 0xa4, 0x61, 0x72, 0x63, 0x76)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetReceiver)
+ }
+ if (zb0049Mask[0] & 0x200000000000) == 0 { // if not empty
+ // string "arcvbm"
+ o = append(o, 0xa6, 0x61, 0x72, 0x63, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver))
+ }
+ if (zb0049Mask[0] & 0x400000000000) == 0 { // if not empty
+ // string "asnd"
+ o = append(o, 0xa4, 0x61, 0x73, 0x6e, 0x64)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetSender)
+ }
+ if (zb0049Mask[0] & 0x800000000000) == 0 { // if not empty
+ // string "asndbm"
+ o = append(o, 0xa6, 0x61, 0x73, 0x6e, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender))
+ }
+ if (zb0049Mask[0] & 0x1000000000000) == 0 { // if not empty
+ // string "au"
+ o = append(o, 0xa2, 0x61, 0x75)
+ if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL)))
+ }
+ for zb0019 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL {
+ o = msgp.AppendString(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL[zb0019])
+ }
+ }
+ if (zb0049Mask[0] & 0x2000000000000) == 0 { // if not empty
+ // string "aubm"
+ o = append(o, 0xa4, 0x61, 0x75, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL))
+ }
+ if (zb0049Mask[0] & 0x4000000000000) == 0 { // if not empty
+ // string "c"
+ o = append(o, 0xa1, 0x63)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback)
+ }
+ if (zb0049Mask[0] & 0x8000000000000) == 0 { // if not empty
+ // string "caid"
+ o = append(o, 0xa4, 0x63, 0x61, 0x69, 0x64)
+ if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset)))
+ }
+ for zb0014 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset[zb0014].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[0] & 0x10000000000000) == 0 { // if not empty
+ // string "caidbm"
+ o = append(o, 0xa6, 0x63, 0x61, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset))
+ }
+ if (zb0049Mask[0] & 0x20000000000000) == 0 { // if not empty
+ // string "cbm"
+ o = append(o, 0xa3, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback))
+ }
+ if (zb0049Mask[0] & 0x40000000000000) == 0 { // if not empty
+ // string "certP"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x50)
+ if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs)))
+ }
+ for zb0044 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs {
+ if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044])))
+ }
+ for zb0045 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044][zb0045].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0049Mask[0] & 0x80000000000000) == 0 { // if not empty
+ // string "certPbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x50, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs))
+ }
+ if (zb0049Mask[0] & 0x100000000000000) == 0 { // if not empty
+ // string "certS"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x53)
+ if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs)))
+ }
+ for zb0042 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs {
+ if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042])))
+ }
+ for zb0043 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042][zb0043].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0049Mask[0] & 0x200000000000000) == 0 { // if not empty
+ // string "certSbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x53, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs))
+ }
+ if (zb0049Mask[0] & 0x400000000000000) == 0 { // if not empty
+ // string "certc"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x63)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit)
+ }
+ if (zb0049Mask[0] & 0x800000000000000) == 0 { // if not empty
+ // string "certcbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit))
+ }
+ if (zb0049Mask[0] & 0x1000000000000000) == 0 { // if not empty
+ // string "certr"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x72)
+ if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals)))
+ }
+ for zb0046 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals {
+ if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendMapHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046])))
+ }
+ zb0047_keys := make([]uint64, 0, len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046]))
+ for zb0047 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] {
+ zb0047_keys = append(zb0047_keys, zb0047)
+ }
+ sort.Sort(SortUint64(zb0047_keys))
+ for _, zb0047 := range zb0047_keys {
+ zb0048 := (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046][zb0047]
+ _ = zb0048
+ o = msgp.AppendUint64(o, zb0047)
+ o = zb0048.MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0049Mask[0] & 0x2000000000000000) == 0 { // if not empty
+ // string "certrbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals))
+ }
+ if (zb0049Mask[0] & 0x4000000000000000) == 0 { // if not empty
+ // string "certrnd"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x72, 0x6e, 0x64)
+ if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound)))
+ }
+ for zb0039 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound[zb0039].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[0] & 0x8000000000000000) == 0 { // if not empty
+ // string "certrndbm"
+ o = append(o, 0xa9, 0x63, 0x65, 0x72, 0x74, 0x72, 0x6e, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound))
+ }
+ if (zb0049Mask[1] & 0x1) == 0 { // if not empty
+ // string "certtype"
+ o = append(o, 0xa8, 0x63, 0x65, 0x72, 0x74, 0x74, 0x79, 0x70, 0x65)
+ if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType)))
+ }
+ for zb0040 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType[zb0040].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[1] & 0x2) == 0 { // if not empty
+ // string "certtypebm"
+ o = append(o, 0xaa, 0x63, 0x65, 0x72, 0x74, 0x74, 0x79, 0x70, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertType))
+ }
+ if (zb0049Mask[1] & 0x4) == 0 { // if not empty
+ // string "certw"
+ o = append(o, 0xa5, 0x63, 0x65, 0x72, 0x74, 0x77)
+ if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight)))
+ }
+ for zb0041 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight {
+ o = msgp.AppendUint64(o, (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight[zb0041])
+ }
+ }
+ if (zb0049Mask[1] & 0x8) == 0 { // if not empty
+ // string "certwbm"
+ o = append(o, 0xa7, 0x63, 0x65, 0x72, 0x74, 0x77, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight))
+ }
+ if (zb0049Mask[1] & 0x10) == 0 { // if not empty
+ // string "close"
+ o = append(o, 0xa5, 0x63, 0x6c, 0x6f, 0x73, 0x65)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.CloseRemainderTo)
+ }
+ if (zb0049Mask[1] & 0x20) == 0 { // if not empty
+ // string "closebm"
+ o = append(o, 0xa7, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo))
+ }
+ if (zb0049Mask[1] & 0x40) == 0 { // if not empty
+ // string "dc"
+ o = append(o, 0xa2, 0x64, 0x63)
+ if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals)))
+ }
+ for zb0016 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals {
+ o = msgp.AppendUint32(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals[zb0016])
+ }
+ }
+ if (zb0049Mask[1] & 0x80) == 0 { // if not empty
+ // string "dcbm"
+ o = append(o, 0xa4, 0x64, 0x63, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals))
+ }
+ if (zb0049Mask[1] & 0x100) == 0 { // if not empty
+ // string "dfbm"
+ o = append(o, 0xa4, 0x64, 0x66, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen))
+ }
+ if (zb0049Mask[1] & 0x200) == 0 { // if not empty
+ // string "f"
+ o = append(o, 0xa1, 0x66)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze)
+ }
+ if (zb0049Mask[1] & 0x400) == 0 { // if not empty
+ // string "fadd"
+ o = append(o, 0xa4, 0x66, 0x61, 0x64, 0x64)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount)
+ }
+ if (zb0049Mask[1] & 0x800) == 0 { // if not empty
+ // string "faddbm"
+ o = append(o, 0xa6, 0x66, 0x61, 0x64, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount))
+ }
+ if (zb0049Mask[1] & 0x1000) == 0 { // if not empty
+ // string "faid"
+ o = append(o, 0xa4, 0x66, 0x61, 0x69, 0x64)
+ if (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset)))
+ }
+ for zb0022 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset[zb0022].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[1] & 0x2000) == 0 { // if not empty
+ // string "faidbm"
+ o = append(o, 0xa6, 0x66, 0x61, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset))
+ }
+ if (zb0049Mask[1] & 0x4000) == 0 { // if not empty
+ // string "fbm"
+ o = append(o, 0xa3, 0x66, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze))
+ }
+ if (zb0049Mask[1] & 0x8000) == 0 { // if not empty
+ // string "fee"
+ o = append(o, 0xa3, 0x66, 0x65, 0x65)
+ if (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee)))
+ }
+ for zb0006 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee[zb0006].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[1] & 0x10000) == 0 { // if not empty
+ // string "feebm"
+ o = append(o, 0xa5, 0x66, 0x65, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFee))
+ }
+ if (zb0049Mask[1] & 0x20000) == 0 { // if not empty
+ // string "fv"
+ o = append(o, 0xa2, 0x66, 0x76)
+ if (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid)))
+ }
+ for zb0007 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid[zb0007].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[1] & 0x40000) == 0 { // if not empty
+ // string "fvbm"
+ o = append(o, 0xa4, 0x66, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFirstValid))
+ }
+ if (zb0049Mask[1] & 0x80000) == 0 { // if not empty
+ // string "genbm"
+ o = append(o, 0xa5, 0x67, 0x65, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGenesisID))
+ }
+ if (zb0049Mask[1] & 0x100000) == 0 { // if not empty
+ // string "gnbs"
+ o = append(o, 0xa4, 0x67, 0x6e, 0x62, 0x73)
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice)))
+ }
+ for zb0035 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice {
+ o = msgp.AppendUint64(o, (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice[zb0035])
+ }
+ }
+ if (zb0049Mask[1] & 0x200000) == 0 { // if not empty
+ // string "gnbsbm"
+ o = append(o, 0xa6, 0x67, 0x6e, 0x62, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice))
+ }
+ if (zb0049Mask[1] & 0x400000) == 0 { // if not empty
+ // string "gnui"
+ o = append(o, 0xa4, 0x67, 0x6e, 0x75, 0x69)
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint)))
+ }
+ for zb0034 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint {
+ o = msgp.AppendUint64(o, (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint[zb0034])
+ }
+ }
+ if (zb0049Mask[1] & 0x800000) == 0 { // if not empty
+ // string "gnuibm"
+ o = append(o, 0xa6, 0x67, 0x6e, 0x75, 0x69, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint))
+ }
+ if (zb0049Mask[1] & 0x1000000) == 0 { // if not empty
+ // string "grpbm"
+ o = append(o, 0xa5, 0x67, 0x72, 0x70, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGroup))
+ }
+ if (zb0049Mask[1] & 0x2000000) == 0 { // if not empty
+ // string "lnbs"
+ o = append(o, 0xa4, 0x6c, 0x6e, 0x62, 0x73)
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice)))
+ }
+ for zb0033 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice {
+ o = msgp.AppendUint64(o, (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice[zb0033])
+ }
+ }
+ if (zb0049Mask[1] & 0x4000000) == 0 { // if not empty
+ // string "lnbsbm"
+ o = append(o, 0xa6, 0x6c, 0x6e, 0x62, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice))
+ }
+ if (zb0049Mask[1] & 0x8000000) == 0 { // if not empty
+ // string "lnui"
+ o = append(o, 0xa4, 0x6c, 0x6e, 0x75, 0x69)
+ if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint)))
+ }
+ for zb0032 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint {
+ o = msgp.AppendUint64(o, (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint[zb0032])
+ }
+ }
+ if (zb0049Mask[1] & 0x10000000) == 0 { // if not empty
+ // string "lnuibm"
+ o = append(o, 0xa6, 0x6c, 0x6e, 0x75, 0x69, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint))
+ }
+ if (zb0049Mask[1] & 0x20000000) == 0 { // if not empty
+ // string "lsigarg"
+ o = append(o, 0xa7, 0x6c, 0x73, 0x69, 0x67, 0x61, 0x72, 0x67)
+ if (*z).encodedSignedTxns.encodedLsigs.LogicArgs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedLsigs.LogicArgs)))
+ }
+ for zb0004 := range (*z).encodedSignedTxns.encodedLsigs.LogicArgs {
+ if (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004])))
+ }
+ for zb0005 := range (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004] {
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004][zb0005])
+ }
+ }
+ }
+ if (zb0049Mask[1] & 0x40000000) == 0 { // if not empty
+ // string "lsigargbm"
+ o = append(o, 0xa9, 0x6c, 0x73, 0x69, 0x67, 0x61, 0x72, 0x67, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedLsigs.BitmaskLogicArgs))
+ }
+ if (zb0049Mask[1] & 0x80000000) == 0 { // if not empty
+ // string "lsigl"
+ o = append(o, 0xa5, 0x6c, 0x73, 0x69, 0x67, 0x6c)
+ if (*z).encodedSignedTxns.encodedLsigs.Logic == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedLsigs.Logic)))
+ }
+ for zb0003 := range (*z).encodedSignedTxns.encodedLsigs.Logic {
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedLsigs.Logic[zb0003])
+ }
+ }
+ if (zb0049Mask[1] & 0x100000000) == 0 { // if not empty
+ // string "lsiglbm"
+ o = append(o, 0xa7, 0x6c, 0x73, 0x69, 0x67, 0x6c, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedLsigs.BitmaskLogic))
+ }
+ if (zb0049Mask[1] & 0x200000000) == 0 { // if not empty
+ // string "lv"
+ o = append(o, 0xa2, 0x6c, 0x76)
+ if (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid)))
+ }
+ for zb0008 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid[zb0008].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[1] & 0x400000000) == 0 { // if not empty
+ // string "lvbm"
+ o = append(o, 0xa4, 0x6c, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLastValid))
+ }
+ if (zb0049Mask[1] & 0x800000000) == 0 { // if not empty
+ // string "lx"
+ o = append(o, 0xa2, 0x6c, 0x78)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Lease)
+ }
+ if (zb0049Mask[1] & 0x1000000000) == 0 { // if not empty
+ // string "lxbm"
+ o = append(o, 0xa4, 0x6c, 0x78, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLease))
+ }
+ if (zb0049Mask[1] & 0x2000000000) == 0 { // if not empty
+ // string "m"
+ o = append(o, 0xa1, 0x6d)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager)
+ }
+ if (zb0049Mask[1] & 0x4000000000) == 0 { // if not empty
+ // string "mbm"
+ o = append(o, 0xa3, 0x6d, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager))
+ }
+ if (zb0049Mask[1] & 0x8000000000) == 0 { // if not empty
+ // string "msigthr"
+ o = append(o, 0xa7, 0x6d, 0x73, 0x69, 0x67, 0x74, 0x68, 0x72)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedMsigs.Threshold)
+ }
+ if (zb0049Mask[1] & 0x10000000000) == 0 { // if not empty
+ // string "msigthrbm"
+ o = append(o, 0xa9, 0x6d, 0x73, 0x69, 0x67, 0x74, 0x68, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedMsigs.BitmaskThreshold))
+ }
+ if (zb0049Mask[1] & 0x20000000000) == 0 { // if not empty
+ // string "msigv"
+ o = append(o, 0xa5, 0x6d, 0x73, 0x69, 0x67, 0x76)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedMsigs.Version)
+ }
+ if (zb0049Mask[1] & 0x40000000000) == 0 { // if not empty
+ // string "msigvbm"
+ o = append(o, 0xa7, 0x6d, 0x73, 0x69, 0x67, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedMsigs.BitmaskVersion))
+ }
+ if (zb0049Mask[1] & 0x80000000000) == 0 { // if not empty
+ // string "nonpartbm"
+ o = append(o, 0xa9, 0x6e, 0x6f, 0x6e, 0x70, 0x61, 0x72, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation))
+ }
+ if (zb0049Mask[1] & 0x100000000000) == 0 { // if not empty
+ // string "note"
+ o = append(o, 0xa4, 0x6e, 0x6f, 0x74, 0x65)
+ if (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note)))
+ }
+ for zb0009 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note {
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note[zb0009])
+ }
+ }
+ if (zb0049Mask[1] & 0x200000000000) == 0 { // if not empty
+ // string "notebm"
+ o = append(o, 0xa6, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskNote))
+ }
+ if (zb0049Mask[1] & 0x400000000000) == 0 { // if not empty
+ // string "r"
+ o = append(o, 0xa1, 0x72)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve)
+ }
+ if (zb0049Mask[1] & 0x800000000000) == 0 { // if not empty
+ // string "rbm"
+ o = append(o, 0xa3, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve))
+ }
+ if (zb0049Mask[1] & 0x1000000000000) == 0 { // if not empty
+ // string "rcv"
+ o = append(o, 0xa3, 0x72, 0x63, 0x76)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Receiver)
+ }
+ if (zb0049Mask[1] & 0x2000000000000) == 0 { // if not empty
+ // string "rcvbm"
+ o = append(o, 0xa5, 0x72, 0x63, 0x76, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskReceiver))
+ }
+ if (zb0049Mask[1] & 0x4000000000000) == 0 { // if not empty
+ // string "rekey"
+ o = append(o, 0xa5, 0x72, 0x65, 0x6b, 0x65, 0x79)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.RekeyTo)
+ }
+ if (zb0049Mask[1] & 0x8000000000000) == 0 { // if not empty
+ // string "rekeybm"
+ o = append(o, 0xa7, 0x72, 0x65, 0x6b, 0x65, 0x79, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskRekeyTo))
+ }
+ if (zb0049Mask[1] & 0x10000000000000) == 0 { // if not empty
+ // string "selkey"
+ o = append(o, 0xa6, 0x73, 0x65, 0x6c, 0x6b, 0x65, 0x79)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.SelectionPK)
+ }
+ if (zb0049Mask[1] & 0x20000000000000) == 0 { // if not empty
+ // string "sgnr"
+ o = append(o, 0xa4, 0x73, 0x67, 0x6e, 0x72)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.AuthAddr)
+ }
+ if (zb0049Mask[1] & 0x40000000000000) == 0 { // if not empty
+ // string "sgnrbm"
+ o = append(o, 0xa6, 0x73, 0x67, 0x6e, 0x72, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.BitmaskAuthAddr))
+ }
+ if (zb0049Mask[1] & 0x80000000000000) == 0 { // if not empty
+ // string "sig"
+ o = append(o, 0xa3, 0x73, 0x69, 0x67)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.Sig)
+ }
+ if (zb0049Mask[1] & 0x100000000000000) == 0 { // if not empty
+ // string "sigbm"
+ o = append(o, 0xa5, 0x73, 0x69, 0x67, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.BitmaskSig))
+ }
+ if (zb0049Mask[1] & 0x200000000000000) == 0 { // if not empty
+ // string "snd"
+ o = append(o, 0xa3, 0x73, 0x6e, 0x64)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Sender)
+ }
+ if (zb0049Mask[1] & 0x400000000000000) == 0 { // if not empty
+ // string "sndbm"
+ o = append(o, 0xa5, 0x73, 0x6e, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskSender))
+ }
+ if (zb0049Mask[1] & 0x800000000000000) == 0 { // if not empty
+ // string "subsig"
+ o = append(o, 0xa6, 0x73, 0x75, 0x62, 0x73, 0x69, 0x67)
+ if (*z).encodedSignedTxns.encodedMsigs.Subsigs == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedMsigs.Subsigs)))
+ }
+ for zb0001 := range (*z).encodedSignedTxns.encodedMsigs.Subsigs {
+ if (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001] == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001])))
+ }
+ for zb0002 := range (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001] {
+ o = (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001][zb0002].MarshalMsg(o)
+ }
+ }
+ }
+ if (zb0049Mask[1] & 0x1000000000000000) == 0 { // if not empty
+ // string "subsigsbm"
+ o = append(o, 0xa9, 0x73, 0x75, 0x62, 0x73, 0x69, 0x67, 0x73, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedMsigs.BitmaskSubsigs))
+ }
+ if (zb0049Mask[1] & 0x2000000000000000) == 0 { // if not empty
+ // string "t"
+ o = append(o, 0xa1, 0x74)
+ if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total)))
+ }
+ for zb0015 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total {
+ o = msgp.AppendUint64(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total[zb0015])
+ }
+ }
+ if (zb0049Mask[1] & 0x4000000000000000) == 0 { // if not empty
+ // string "tbm"
+ o = append(o, 0xa3, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal))
+ }
+ if (zb0049Mask[1] & 0x8000000000000000) == 0 { // if not empty
+ // string "tgc"
+ o = append(o, 0xa3, 0x74, 0x67, 0x63)
+ o = msgp.AppendUint64(o, (*z).TransactionGroupCount)
+ }
+ if (zb0049Mask[2] & 0x1) == 0 { // if not empty
+ // string "tgs"
+ o = append(o, 0xa3, 0x74, 0x67, 0x73)
+ o = msgp.AppendBytes(o, (*z).TransactionGroupSizes)
+ }
+ if (zb0049Mask[2] & 0x2) == 0 { // if not empty
+ // string "ttc"
+ o = append(o, 0xa3, 0x74, 0x74, 0x63)
+ o = msgp.AppendUint64(o, (*z).TotalTransactionsCount)
+ }
+ if (zb0049Mask[2] & 0x4) == 0 { // if not empty
+ // string "type"
+ o = append(o, 0xa4, 0x74, 0x79, 0x70, 0x65)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.TxType)
+ }
+ if (zb0049Mask[2] & 0x8) == 0 { // if not empty
+ // string "typebm"
+ o = append(o, 0xa6, 0x74, 0x79, 0x70, 0x65, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.BitmaskTxType))
+ }
+ if (zb0049Mask[2] & 0x10) == 0 { // if not empty
+ // string "typeo"
+ o = append(o, 0xa5, 0x74, 0x79, 0x70, 0x65, 0x6f)
+ o = msgp.AppendByte(o, (*z).encodedSignedTxns.encodedTxns.TxTypeOffset)
+ }
+ if (zb0049Mask[2] & 0x20) == 0 { // if not empty
+ // string "un"
+ o = append(o, 0xa2, 0x75, 0x6e)
+ if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName)))
+ }
+ for zb0017 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName {
+ o = msgp.AppendString(o, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName[zb0017])
+ }
+ }
+ if (zb0049Mask[2] & 0x40) == 0 { // if not empty
+ // string "unbm"
+ o = append(o, 0xa4, 0x75, 0x6e, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName))
+ }
+ if (zb0049Mask[2] & 0x80) == 0 { // if not empty
+ // string "votefst"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x66, 0x73, 0x74)
+ if (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst)))
+ }
+ for zb0010 := range (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst[zb0010].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[2] & 0x100) == 0 { // if not empty
+ // string "votefstbm"
+ o = append(o, 0xa9, 0x76, 0x6f, 0x74, 0x65, 0x66, 0x73, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst))
+ }
+ if (zb0049Mask[2] & 0x200) == 0 { // if not empty
+ // string "votekbm"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x6b, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskKeys))
+ }
+ if (zb0049Mask[2] & 0x400) == 0 { // if not empty
+ // string "votekd"
+ o = append(o, 0xa6, 0x76, 0x6f, 0x74, 0x65, 0x6b, 0x64)
+ if (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution)))
+ }
+ for zb0012 := range (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution {
+ o = msgp.AppendUint64(o, (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution[zb0012])
+ }
+ }
+ if (zb0049Mask[2] & 0x800) == 0 { // if not empty
+ // string "votekey"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x6b, 0x65, 0x79)
+ o = msgp.AppendBytes(o, (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VotePK)
+ }
+ if (zb0049Mask[2] & 0x1000) == 0 { // if not empty
+ // string "votelst"
+ o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x6c, 0x73, 0x74)
+ if (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast)))
+ }
+ for zb0011 := range (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast[zb0011].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[2] & 0x2000) == 0 { // if not empty
+ // string "votelstbm"
+ o = append(o, 0xa9, 0x76, 0x6f, 0x74, 0x65, 0x6c, 0x73, 0x74, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast))
+ }
+ if (zb0049Mask[2] & 0x4000) == 0 { // if not empty
+ // string "xaid"
+ o = append(o, 0xa4, 0x78, 0x61, 0x69, 0x64)
+ if (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset)))
+ }
+ for zb0020 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset {
+ o = (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset[zb0020].MarshalMsg(o)
+ }
+ }
+ if (zb0049Mask[2] & 0x8000) == 0 { // if not empty
+ // string "xaidbm"
+ o = append(o, 0xa6, 0x78, 0x61, 0x69, 0x64, 0x62, 0x6d)
+ o = msgp.AppendBytes(o, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset))
+ }
+ }
+ return
+}
+
+func (_ *txGroupsEncodingStub) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*txGroupsEncodingStub)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *txGroupsEncodingStub) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0049 int
+ var zb0050 bool
+ zb0049, zb0050, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0049, zb0050, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0049 > 0 {
+ zb0049--
+ (*z).TotalTransactionsCount, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TotalTransactionsCount")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ (*z).TransactionGroupCount, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TransactionGroupCount")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0051 int
+ zb0051, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TransactionGroupSizes")
+ return
+ }
+ if zb0051 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0051), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).TransactionGroupSizes, bts, err = msgp.ReadBytesBytes(bts, (*z).TransactionGroupSizes)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TransactionGroupSizes")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0052 int
+ zb0052, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Sig")
+ return
+ }
+ if zb0052 > maxSignatureBytes {
+ err = msgp.ErrOverflow(uint64(zb0052), uint64(maxSignatureBytes))
+ return
+ }
+ (*z).encodedSignedTxns.Sig, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.Sig)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Sig")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0053 []byte
+ var zb0054 int
+ zb0054, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSig")
+ return
+ }
+ if zb0054 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0054), uint64(maxBitmaskSize))
+ return
+ }
+ zb0053, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.BitmaskSig))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSig")
+ return
+ }
+ (*z).encodedSignedTxns.BitmaskSig = bitmask(zb0053)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0055 int
+ zb0055, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Version")
+ return
+ }
+ if zb0055 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0055), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedSignedTxns.encodedMsigs.Version, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedMsigs.Version)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Version")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0056 []byte
+ var zb0057 int
+ zb0057, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVersion")
+ return
+ }
+ if zb0057 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0057), uint64(maxBitmaskSize))
+ return
+ }
+ zb0056, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedMsigs.BitmaskVersion))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVersion")
+ return
+ }
+ (*z).encodedSignedTxns.encodedMsigs.BitmaskVersion = bitmask(zb0056)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0058 int
+ zb0058, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Threshold")
+ return
+ }
+ if zb0058 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0058), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedSignedTxns.encodedMsigs.Threshold, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedMsigs.Threshold)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Threshold")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0059 []byte
+ var zb0060 int
+ zb0060, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskThreshold")
+ return
+ }
+ if zb0060 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0060), uint64(maxBitmaskSize))
+ return
+ }
+ zb0059, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedMsigs.BitmaskThreshold))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskThreshold")
+ return
+ }
+ (*z).encodedSignedTxns.encodedMsigs.BitmaskThreshold = bitmask(zb0059)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0061 int
+ var zb0062 bool
+ zb0061, zb0062, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs")
+ return
+ }
+ if zb0061 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0061), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs")
+ return
+ }
+ if zb0062 {
+ (*z).encodedSignedTxns.encodedMsigs.Subsigs = nil
+ } else if (*z).encodedSignedTxns.encodedMsigs.Subsigs != nil && cap((*z).encodedSignedTxns.encodedMsigs.Subsigs) >= zb0061 {
+ (*z).encodedSignedTxns.encodedMsigs.Subsigs = ((*z).encodedSignedTxns.encodedMsigs.Subsigs)[:zb0061]
+ } else {
+ (*z).encodedSignedTxns.encodedMsigs.Subsigs = make([][]crypto.MultisigSubsig, zb0061)
+ }
+ for zb0001 := range (*z).encodedSignedTxns.encodedMsigs.Subsigs {
+ var zb0063 int
+ var zb0064 bool
+ zb0063, zb0064, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs", zb0001)
+ return
+ }
+ if zb0063 > crypto.MaxMultisig {
+ err = msgp.ErrOverflow(uint64(zb0063), uint64(crypto.MaxMultisig))
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs", zb0001)
+ return
+ }
+ if zb0064 {
+ (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001] = nil
+ } else if (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001] != nil && cap((*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001]) >= zb0063 {
+ (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001] = ((*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001])[:zb0063]
+ } else {
+ (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001] = make([]crypto.MultisigSubsig, zb0063)
+ }
+ for zb0002 := range (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001] {
+ bts, err = (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001][zb0002].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Subsigs", zb0001, zb0002)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0065 []byte
+ var zb0066 int
+ zb0066, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSubsigs")
+ return
+ }
+ if zb0066 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0066), uint64(maxBitmaskSize))
+ return
+ }
+ zb0065, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedMsigs.BitmaskSubsigs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSubsigs")
+ return
+ }
+ (*z).encodedSignedTxns.encodedMsigs.BitmaskSubsigs = bitmask(zb0065)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0067 int
+ var zb0068 bool
+ zb0067, zb0068, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Logic")
+ return
+ }
+ if zb0067 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0067), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Logic")
+ return
+ }
+ if zb0068 {
+ (*z).encodedSignedTxns.encodedLsigs.Logic = nil
+ } else if (*z).encodedSignedTxns.encodedLsigs.Logic != nil && cap((*z).encodedSignedTxns.encodedLsigs.Logic) >= zb0067 {
+ (*z).encodedSignedTxns.encodedLsigs.Logic = ((*z).encodedSignedTxns.encodedLsigs.Logic)[:zb0067]
+ } else {
+ (*z).encodedSignedTxns.encodedLsigs.Logic = make([][]byte, zb0067)
+ }
+ for zb0003 := range (*z).encodedSignedTxns.encodedLsigs.Logic {
+ var zb0069 int
+ zb0069, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Logic", zb0003)
+ return
+ }
+ if zb0069 > config.MaxLogicSigMaxSize {
+ err = msgp.ErrOverflow(uint64(zb0069), uint64(config.MaxLogicSigMaxSize))
+ return
+ }
+ (*z).encodedSignedTxns.encodedLsigs.Logic[zb0003], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedLsigs.Logic[zb0003])
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Logic", zb0003)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0070 []byte
+ var zb0071 int
+ zb0071, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLogic")
+ return
+ }
+ if zb0071 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0071), uint64(maxBitmaskSize))
+ return
+ }
+ zb0070, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedLsigs.BitmaskLogic))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLogic")
+ return
+ }
+ (*z).encodedSignedTxns.encodedLsigs.BitmaskLogic = bitmask(zb0070)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0072 int
+ var zb0073 bool
+ zb0072, zb0073, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs")
+ return
+ }
+ if zb0072 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0072), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs")
+ return
+ }
+ if zb0073 {
+ (*z).encodedSignedTxns.encodedLsigs.LogicArgs = nil
+ } else if (*z).encodedSignedTxns.encodedLsigs.LogicArgs != nil && cap((*z).encodedSignedTxns.encodedLsigs.LogicArgs) >= zb0072 {
+ (*z).encodedSignedTxns.encodedLsigs.LogicArgs = ((*z).encodedSignedTxns.encodedLsigs.LogicArgs)[:zb0072]
+ } else {
+ (*z).encodedSignedTxns.encodedLsigs.LogicArgs = make([][][]byte, zb0072)
+ }
+ for zb0004 := range (*z).encodedSignedTxns.encodedLsigs.LogicArgs {
+ var zb0074 int
+ var zb0075 bool
+ zb0074, zb0075, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs", zb0004)
+ return
+ }
+ if zb0074 > transactions.EvalMaxArgs {
+ err = msgp.ErrOverflow(uint64(zb0074), uint64(transactions.EvalMaxArgs))
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs", zb0004)
+ return
+ }
+ if zb0075 {
+ (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004] = nil
+ } else if (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004] != nil && cap((*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004]) >= zb0074 {
+ (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004] = ((*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004])[:zb0074]
+ } else {
+ (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004] = make([][]byte, zb0074)
+ }
+ for zb0005 := range (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004] {
+ var zb0076 int
+ zb0076, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs", zb0004, zb0005)
+ return
+ }
+ if zb0076 > config.MaxLogicSigMaxSize {
+ err = msgp.ErrOverflow(uint64(zb0076), uint64(config.MaxLogicSigMaxSize))
+ return
+ }
+ (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004][zb0005], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004][zb0005])
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LogicArgs", zb0004, zb0005)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0077 []byte
+ var zb0078 int
+ zb0078, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLogicArgs")
+ return
+ }
+ if zb0078 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0078), uint64(maxBitmaskSize))
+ return
+ }
+ zb0077, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedLsigs.BitmaskLogicArgs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLogicArgs")
+ return
+ }
+ (*z).encodedSignedTxns.encodedLsigs.BitmaskLogicArgs = bitmask(zb0077)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0079 int
+ zb0079, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AuthAddr")
+ return
+ }
+ if zb0079 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0079), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.AuthAddr, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.AuthAddr)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AuthAddr")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0080 []byte
+ var zb0081 int
+ zb0081, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAuthAddr")
+ return
+ }
+ if zb0081 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0081), uint64(maxBitmaskSize))
+ return
+ }
+ zb0080, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.BitmaskAuthAddr))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAuthAddr")
+ return
+ }
+ (*z).encodedSignedTxns.BitmaskAuthAddr = bitmask(zb0080)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0082 int
+ zb0082, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TxType")
+ return
+ }
+ if zb0082 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0082), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.TxType, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.TxType)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TxType")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0083 []byte
+ var zb0084 int
+ zb0084, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTxType")
+ return
+ }
+ if zb0084 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0084), uint64(maxBitmaskSize))
+ return
+ }
+ zb0083, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.BitmaskTxType))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTxType")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.BitmaskTxType = bitmask(zb0083)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ (*z).encodedSignedTxns.encodedTxns.TxTypeOffset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TxTypeOffset")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0085 int
+ zb0085, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Sender")
+ return
+ }
+ if zb0085 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0085), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Sender, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Sender)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Sender")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0086 []byte
+ var zb0087 int
+ zb0087, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSender")
+ return
+ }
+ if zb0087 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0087), uint64(maxBitmaskSize))
+ return
+ }
+ zb0086, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskSender))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSender")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskSender = bitmask(zb0086)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0088 int
+ var zb0089 bool
+ zb0088, zb0089, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Fee")
+ return
+ }
+ if zb0088 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0088), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Fee")
+ return
+ }
+ if zb0089 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee) >= zb0088 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee = ((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee)[:zb0088]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee = make([]basics.MicroAlgos, zb0088)
+ }
+ for zb0006 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee[zb0006].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Fee", zb0006)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0090 []byte
+ var zb0091 int
+ zb0091, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFee")
+ return
+ }
+ if zb0091 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0091), uint64(maxBitmaskSize))
+ return
+ }
+ zb0090, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFee))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFee")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFee = bitmask(zb0090)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0092 int
+ var zb0093 bool
+ zb0092, zb0093, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FirstValid")
+ return
+ }
+ if zb0092 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0092), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "FirstValid")
+ return
+ }
+ if zb0093 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid) >= zb0092 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid = ((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid)[:zb0092]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid = make([]basics.Round, zb0092)
+ }
+ for zb0007 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid[zb0007].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FirstValid", zb0007)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0094 []byte
+ var zb0095 int
+ zb0095, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFirstValid")
+ return
+ }
+ if zb0095 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0095), uint64(maxBitmaskSize))
+ return
+ }
+ zb0094, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFirstValid))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFirstValid")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFirstValid = bitmask(zb0094)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0096 int
+ var zb0097 bool
+ zb0096, zb0097, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LastValid")
+ return
+ }
+ if zb0096 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0096), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LastValid")
+ return
+ }
+ if zb0097 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid) >= zb0096 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid = ((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid)[:zb0096]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid = make([]basics.Round, zb0096)
+ }
+ for zb0008 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid[zb0008].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LastValid", zb0008)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0098 []byte
+ var zb0099 int
+ zb0099, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLastValid")
+ return
+ }
+ if zb0099 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0099), uint64(maxBitmaskSize))
+ return
+ }
+ zb0098, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLastValid))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLastValid")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLastValid = bitmask(zb0098)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0100 int
+ var zb0101 bool
+ zb0100, zb0101, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Note")
+ return
+ }
+ if zb0100 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0100), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Note")
+ return
+ }
+ if zb0101 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note) >= zb0100 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note = ((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note)[:zb0100]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note = make([][]byte, zb0100)
+ }
+ for zb0009 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note {
+ var zb0102 int
+ zb0102, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Note", zb0009)
+ return
+ }
+ if zb0102 > config.MaxTxnNoteBytes {
+ err = msgp.ErrOverflow(uint64(zb0102), uint64(config.MaxTxnNoteBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note[zb0009], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note[zb0009])
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Note", zb0009)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0103 []byte
+ var zb0104 int
+ zb0104, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNote")
+ return
+ }
+ if zb0104 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0104), uint64(maxBitmaskSize))
+ return
+ }
+ zb0103, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskNote))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNote")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskNote = bitmask(zb0103)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0105 []byte
+ var zb0106 int
+ zb0106, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGenesisID")
+ return
+ }
+ if zb0106 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0106), uint64(maxBitmaskSize))
+ return
+ }
+ zb0105, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGenesisID))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGenesisID")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGenesisID = bitmask(zb0105)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0107 []byte
+ var zb0108 int
+ zb0108, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGroup")
+ return
+ }
+ if zb0108 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0108), uint64(maxBitmaskSize))
+ return
+ }
+ zb0107, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGroup))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGroup")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGroup = bitmask(zb0107)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0109 int
+ zb0109, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Lease")
+ return
+ }
+ if zb0109 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0109), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Lease, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Lease)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Lease")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0110 []byte
+ var zb0111 int
+ zb0111, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLease")
+ return
+ }
+ if zb0111 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0111), uint64(maxBitmaskSize))
+ return
+ }
+ zb0110, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLease))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLease")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLease = bitmask(zb0110)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0112 int
+ zb0112, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "RekeyTo")
+ return
+ }
+ if zb0112 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0112), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.RekeyTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.RekeyTo)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "RekeyTo")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0113 []byte
+ var zb0114 int
+ zb0114, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskRekeyTo")
+ return
+ }
+ if zb0114 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0114), uint64(maxBitmaskSize))
+ return
+ }
+ zb0113, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskRekeyTo))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskRekeyTo")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskRekeyTo = bitmask(zb0113)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0115 int
+ zb0115, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VotePK")
+ return
+ }
+ if zb0115 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0115), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VotePK, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VotePK)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VotePK")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0116 int
+ zb0116, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SelectionPK")
+ return
+ }
+ if zb0116 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0116), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.SelectionPK, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.SelectionPK)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SelectionPK")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0117 int
+ var zb0118 bool
+ zb0117, zb0118, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteFirst")
+ return
+ }
+ if zb0117 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0117), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "VoteFirst")
+ return
+ }
+ if zb0118 {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst) >= zb0117 {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst = ((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst)[:zb0117]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst = make([]basics.Round, zb0117)
+ }
+ for zb0010 := range (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst[zb0010].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteFirst", zb0010)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0119 []byte
+ var zb0120 int
+ zb0120, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteFirst")
+ return
+ }
+ if zb0120 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0120), uint64(maxBitmaskSize))
+ return
+ }
+ zb0119, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteFirst")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst = bitmask(zb0119)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0121 int
+ var zb0122 bool
+ zb0121, zb0122, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteLast")
+ return
+ }
+ if zb0121 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0121), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "VoteLast")
+ return
+ }
+ if zb0122 {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast) >= zb0121 {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast = ((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast)[:zb0121]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast = make([]basics.Round, zb0121)
+ }
+ for zb0011 := range (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast[zb0011].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteLast", zb0011)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0123 []byte
+ var zb0124 int
+ zb0124, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteLast")
+ return
+ }
+ if zb0124 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0124), uint64(maxBitmaskSize))
+ return
+ }
+ zb0123, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskVoteLast")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast = bitmask(zb0123)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0125 int
+ var zb0126 bool
+ zb0125, zb0126, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteKeyDilution")
+ return
+ }
+ if zb0125 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0125), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "VoteKeyDilution")
+ return
+ }
+ if zb0126 {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution) >= zb0125 {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution = ((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution)[:zb0125]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution = make([]uint64, zb0125)
+ }
+ for zb0012 := range (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution[zb0012], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "VoteKeyDilution", zb0012)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0127 []byte
+ var zb0128 int
+ zb0128, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskKeys")
+ return
+ }
+ if zb0128 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0128), uint64(maxBitmaskSize))
+ return
+ }
+ zb0127, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskKeys))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskKeys")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskKeys = bitmask(zb0127)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0129 []byte
+ var zb0130 int
+ zb0130, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNonparticipation")
+ return
+ }
+ if zb0130 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0130), uint64(maxBitmaskSize))
+ return
+ }
+ zb0129, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskNonparticipation")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation = bitmask(zb0129)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0131 int
+ zb0131, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Receiver")
+ return
+ }
+ if zb0131 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0131), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Receiver, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Receiver)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Receiver")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0132 []byte
+ var zb0133 int
+ zb0133, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReceiver")
+ return
+ }
+ if zb0133 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0133), uint64(maxBitmaskSize))
+ return
+ }
+ zb0132, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReceiver")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskReceiver = bitmask(zb0132)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0134 int
+ var zb0135 bool
+ zb0134, zb0135, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Amount")
+ return
+ }
+ if zb0134 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0134), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Amount")
+ return
+ }
+ if zb0135 {
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount) >= zb0134 {
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount = ((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount)[:zb0134]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount = make([]basics.MicroAlgos, zb0134)
+ }
+ for zb0013 := range (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount[zb0013].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Amount", zb0013)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0136 []byte
+ var zb0137 int
+ zb0137, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAmount")
+ return
+ }
+ if zb0137 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0137), uint64(maxBitmaskSize))
+ return
+ }
+ zb0136, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAmount")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskAmount = bitmask(zb0136)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0138 int
+ zb0138, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CloseRemainderTo")
+ return
+ }
+ if zb0138 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0138), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.CloseRemainderTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.CloseRemainderTo)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CloseRemainderTo")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0139 []byte
+ var zb0140 int
+ zb0140, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCloseRemainderTo")
+ return
+ }
+ if zb0140 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0140), uint64(maxBitmaskSize))
+ return
+ }
+ zb0139, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCloseRemainderTo")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo = bitmask(zb0139)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0141 int
+ var zb0142 bool
+ zb0141, zb0142, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ConfigAsset")
+ return
+ }
+ if zb0141 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0141), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ConfigAsset")
+ return
+ }
+ if zb0142 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset) >= zb0141 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset = ((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset)[:zb0141]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset = make([]basics.AssetIndex, zb0141)
+ }
+ for zb0014 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset[zb0014].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ConfigAsset", zb0014)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0143 []byte
+ var zb0144 int
+ zb0144, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskConfigAsset")
+ return
+ }
+ if zb0144 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0144), uint64(maxBitmaskSize))
+ return
+ }
+ zb0143, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskConfigAsset")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset = bitmask(zb0143)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0145 int
+ var zb0146 bool
+ zb0145, zb0146, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Total")
+ return
+ }
+ if zb0145 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0145), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Total")
+ return
+ }
+ if zb0146 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total) >= zb0145 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total = ((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total)[:zb0145]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total = make([]uint64, zb0145)
+ }
+ for zb0015 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total[zb0015], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Total", zb0015)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0147 []byte
+ var zb0148 int
+ zb0148, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTotal")
+ return
+ }
+ if zb0148 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0148), uint64(maxBitmaskSize))
+ return
+ }
+ zb0147, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskTotal")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal = bitmask(zb0147)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0149 int
+ var zb0150 bool
+ zb0149, zb0150, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Decimals")
+ return
+ }
+ if zb0149 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0149), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Decimals")
+ return
+ }
+ if zb0150 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals) >= zb0149 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals = ((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals)[:zb0149]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals = make([]uint32, zb0149)
+ }
+ for zb0016 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals[zb0016], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Decimals", zb0016)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0151 []byte
+ var zb0152 int
+ zb0152, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDecimals")
+ return
+ }
+ if zb0152 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0152), uint64(maxBitmaskSize))
+ return
+ }
+ zb0151, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDecimals")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals = bitmask(zb0151)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0153 []byte
+ var zb0154 int
+ zb0154, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDefaultFrozen")
+ return
+ }
+ if zb0154 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0154), uint64(maxBitmaskSize))
+ return
+ }
+ zb0153, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskDefaultFrozen")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen = bitmask(zb0153)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0155 int
+ var zb0156 bool
+ zb0155, zb0156, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UnitName")
+ return
+ }
+ if zb0155 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0155), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "UnitName")
+ return
+ }
+ if zb0156 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName) >= zb0155 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName = ((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName)[:zb0155]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName = make([]string, zb0155)
+ }
+ for zb0017 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName[zb0017], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "UnitName", zb0017)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0157 []byte
+ var zb0158 int
+ zb0158, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskUnitName")
+ return
+ }
+ if zb0158 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0158), uint64(maxBitmaskSize))
+ return
+ }
+ zb0157, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskUnitName")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName = bitmask(zb0157)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0159 int
+ var zb0160 bool
+ zb0159, zb0160, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetName")
+ return
+ }
+ if zb0159 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0159), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "AssetName")
+ return
+ }
+ if zb0160 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName) >= zb0159 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName = ((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName)[:zb0159]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName = make([]string, zb0159)
+ }
+ for zb0018 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName[zb0018], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetName", zb0018)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0161 []byte
+ var zb0162 int
+ zb0162, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetName")
+ return
+ }
+ if zb0162 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0162), uint64(maxBitmaskSize))
+ return
+ }
+ zb0161, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetName")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName = bitmask(zb0161)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0163 int
+ var zb0164 bool
+ zb0163, zb0164, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "URL")
+ return
+ }
+ if zb0163 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0163), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "URL")
+ return
+ }
+ if zb0164 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL) >= zb0163 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL = ((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL)[:zb0163]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL = make([]string, zb0163)
+ }
+ for zb0019 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL[zb0019], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "URL", zb0019)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0165 []byte
+ var zb0166 int
+ zb0166, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskURL")
+ return
+ }
+ if zb0166 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0166), uint64(maxBitmaskSize))
+ return
+ }
+ zb0165, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskURL")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL = bitmask(zb0165)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0167 int
+ zb0167, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "MetadataHash")
+ return
+ }
+ if zb0167 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0167), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "MetadataHash")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0168 []byte
+ var zb0169 int
+ zb0169, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskMetadataHash")
+ return
+ }
+ if zb0169 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0169), uint64(maxBitmaskSize))
+ return
+ }
+ zb0168, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskMetadataHash")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash = bitmask(zb0168)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0170 int
+ zb0170, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Manager")
+ return
+ }
+ if zb0170 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0170), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Manager")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0171 []byte
+ var zb0172 int
+ zb0172, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskManager")
+ return
+ }
+ if zb0172 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0172), uint64(maxBitmaskSize))
+ return
+ }
+ zb0171, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskManager")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager = bitmask(zb0171)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0173 int
+ zb0173, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reserve")
+ return
+ }
+ if zb0173 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0173), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reserve")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0174 []byte
+ var zb0175 int
+ zb0175, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReserve")
+ return
+ }
+ if zb0175 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0175), uint64(maxBitmaskSize))
+ return
+ }
+ zb0174, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReserve")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve = bitmask(zb0174)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0176 int
+ zb0176, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Freeze")
+ return
+ }
+ if zb0176 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0176), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Freeze")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0177 []byte
+ var zb0178 int
+ zb0178, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreeze")
+ return
+ }
+ if zb0178 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0178), uint64(maxBitmaskSize))
+ return
+ }
+ zb0177, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreeze")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze = bitmask(zb0177)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0179 int
+ zb0179, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Clawback")
+ return
+ }
+ if zb0179 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0179), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Clawback")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0180 []byte
+ var zb0181 int
+ zb0181, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClawback")
+ return
+ }
+ if zb0181 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0181), uint64(maxBitmaskSize))
+ return
+ }
+ zb0180, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClawback")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback = bitmask(zb0180)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0182 int
+ var zb0183 bool
+ zb0182, zb0183, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "XferAsset")
+ return
+ }
+ if zb0182 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0182), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "XferAsset")
+ return
+ }
+ if zb0183 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset) >= zb0182 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset = ((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset)[:zb0182]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset = make([]basics.AssetIndex, zb0182)
+ }
+ for zb0020 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset[zb0020].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "XferAsset", zb0020)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0184 []byte
+ var zb0185 int
+ zb0185, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskXferAsset")
+ return
+ }
+ if zb0185 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0185), uint64(maxBitmaskSize))
+ return
+ }
+ zb0184, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskXferAsset")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset = bitmask(zb0184)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0186 int
+ var zb0187 bool
+ zb0186, zb0187, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetAmount")
+ return
+ }
+ if zb0186 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0186), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "AssetAmount")
+ return
+ }
+ if zb0187 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount) >= zb0186 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount = ((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount)[:zb0186]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount = make([]uint64, zb0186)
+ }
+ for zb0021 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount[zb0021], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetAmount", zb0021)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0188 []byte
+ var zb0189 int
+ zb0189, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetAmount")
+ return
+ }
+ if zb0189 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0189), uint64(maxBitmaskSize))
+ return
+ }
+ zb0188, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetAmount")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount = bitmask(zb0188)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0190 int
+ zb0190, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetSender")
+ return
+ }
+ if zb0190 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0190), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetSender, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetSender)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetSender")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0191 []byte
+ var zb0192 int
+ zb0192, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetSender")
+ return
+ }
+ if zb0192 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0192), uint64(maxBitmaskSize))
+ return
+ }
+ zb0191, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetSender")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender = bitmask(zb0191)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0193 int
+ zb0193, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetReceiver")
+ return
+ }
+ if zb0193 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0193), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetReceiver, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetReceiver)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetReceiver")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0194 []byte
+ var zb0195 int
+ zb0195, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetReceiver")
+ return
+ }
+ if zb0195 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0195), uint64(maxBitmaskSize))
+ return
+ }
+ zb0194, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetReceiver")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver = bitmask(zb0194)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0196 int
+ zb0196, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetCloseTo")
+ return
+ }
+ if zb0196 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0196), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "AssetCloseTo")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0197 []byte
+ var zb0198 int
+ zb0198, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetCloseTo")
+ return
+ }
+ if zb0198 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0198), uint64(maxBitmaskSize))
+ return
+ }
+ zb0197, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetCloseTo")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo = bitmask(zb0197)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0199 int
+ zb0199, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAccount")
+ return
+ }
+ if zb0199 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0199), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAccount")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0200 []byte
+ var zb0201 int
+ zb0201, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAccount")
+ return
+ }
+ if zb0201 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0201), uint64(maxBitmaskSize))
+ return
+ }
+ zb0200, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAccount")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount = bitmask(zb0200)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0202 int
+ var zb0203 bool
+ zb0202, zb0203, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAsset")
+ return
+ }
+ if zb0202 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0202), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAsset")
+ return
+ }
+ if zb0203 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset) >= zb0202 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset = ((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset)[:zb0202]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset = make([]basics.AssetIndex, zb0202)
+ }
+ for zb0022 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset[zb0022].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "FreezeAsset", zb0022)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0204 []byte
+ var zb0205 int
+ zb0205, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAsset")
+ return
+ }
+ if zb0205 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0205), uint64(maxBitmaskSize))
+ return
+ }
+ zb0204, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskFreezeAsset")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset = bitmask(zb0204)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0206 []byte
+ var zb0207 int
+ zb0207, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetFrozen")
+ return
+ }
+ if zb0207 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0207), uint64(maxBitmaskSize))
+ return
+ }
+ zb0206, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAssetFrozen")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen = bitmask(zb0206)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0208 int
+ var zb0209 bool
+ zb0208, zb0209, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationID")
+ return
+ }
+ if zb0208 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0208), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationID")
+ return
+ }
+ if zb0209 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID) >= zb0208 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID)[:zb0208]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID = make([]basics.AppIndex, zb0208)
+ }
+ for zb0023 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID[zb0023].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationID", zb0023)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0210 []byte
+ var zb0211 int
+ zb0211, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationID")
+ return
+ }
+ if zb0211 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0211), uint64(maxBitmaskSize))
+ return
+ }
+ zb0210, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationID")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID = bitmask(zb0210)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0212 int
+ zb0212, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "OnCompletion")
+ return
+ }
+ if zb0212 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0212), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.OnCompletion, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.OnCompletion)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "OnCompletion")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0213 []byte
+ var zb0214 int
+ zb0214, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskOnCompletion")
+ return
+ }
+ if zb0214 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0214), uint64(maxBitmaskSize))
+ return
+ }
+ zb0213, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskOnCompletion")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion = bitmask(zb0213)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0215 int
+ var zb0216 bool
+ zb0215, zb0216, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs")
+ return
+ }
+ if zb0215 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0215), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs")
+ return
+ }
+ if zb0216 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs) >= zb0215 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs)[:zb0215]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs = make([]applicationArgs, zb0215)
+ }
+ for zb0024 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs {
+ var zb0217 int
+ var zb0218 bool
+ zb0217, zb0218, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs", zb0024)
+ return
+ }
+ if zb0217 > transactions.EncodedMaxApplicationArgs {
+ err = msgp.ErrOverflow(uint64(zb0217), uint64(transactions.EncodedMaxApplicationArgs))
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs", zb0024)
+ return
+ }
+ if zb0218 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024]) >= zb0217 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024])[:zb0217]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] = make(applicationArgs, zb0217)
+ }
+ for zb0025 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024][zb0025], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024][zb0025])
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs", zb0024, zb0025)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0219 []byte
+ var zb0220 int
+ zb0220, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationArgs")
+ return
+ }
+ if zb0220 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0220), uint64(maxBitmaskSize))
+ return
+ }
+ zb0219, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApplicationArgs")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs = bitmask(zb0219)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0221 int
+ var zb0222 bool
+ zb0221, zb0222, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Accounts")
+ return
+ }
+ if zb0221 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0221), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Accounts")
+ return
+ }
+ if zb0222 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts) >= zb0221 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts)[:zb0221]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts = make([]addresses, zb0221)
+ }
+ for zb0026 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts {
+ var zb0223 int
+ var zb0224 bool
+ zb0223, zb0224, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Accounts", zb0026)
+ return
+ }
+ if zb0223 > transactions.EncodedMaxAccounts {
+ err = msgp.ErrOverflow(uint64(zb0223), uint64(transactions.EncodedMaxAccounts))
+ err = msgp.WrapError(err, "struct-from-array", "Accounts", zb0026)
+ return
+ }
+ if zb0224 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026]) >= zb0223 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026])[:zb0223]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] = make(addresses, zb0223)
+ }
+ for zb0027 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026][zb0027].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Accounts", zb0026, zb0027)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0225 []byte
+ var zb0226 int
+ zb0226, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAccounts")
+ return
+ }
+ if zb0226 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0226), uint64(maxBitmaskSize))
+ return
+ }
+ zb0225, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskAccounts")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts = bitmask(zb0225)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0227 int
+ var zb0228 bool
+ zb0227, zb0228, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps")
+ return
+ }
+ if zb0227 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0227), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps")
+ return
+ }
+ if zb0228 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps) >= zb0227 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps)[:zb0227]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps = make([]appIndices, zb0227)
+ }
+ for zb0028 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps {
+ var zb0229 int
+ var zb0230 bool
+ zb0229, zb0230, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps", zb0028)
+ return
+ }
+ if zb0229 > transactions.EncodedMaxForeignApps {
+ err = msgp.ErrOverflow(uint64(zb0229), uint64(transactions.EncodedMaxForeignApps))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps", zb0028)
+ return
+ }
+ if zb0230 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028]) >= zb0229 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028])[:zb0229]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] = make(appIndices, zb0229)
+ }
+ for zb0029 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028][zb0029].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignApps", zb0028, zb0029)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0231 []byte
+ var zb0232 int
+ zb0232, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignApps")
+ return
+ }
+ if zb0232 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0232), uint64(maxBitmaskSize))
+ return
+ }
+ zb0231, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignApps")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps = bitmask(zb0231)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0233 int
+ var zb0234 bool
+ zb0233, zb0234, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets")
+ return
+ }
+ if zb0233 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0233), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets")
+ return
+ }
+ if zb0234 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets) >= zb0233 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets)[:zb0233]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets = make([]assetIndices, zb0233)
+ }
+ for zb0030 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets {
+ var zb0235 int
+ var zb0236 bool
+ zb0235, zb0236, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets", zb0030)
+ return
+ }
+ if zb0235 > transactions.EncodedMaxForeignAssets {
+ err = msgp.ErrOverflow(uint64(zb0235), uint64(transactions.EncodedMaxForeignAssets))
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets", zb0030)
+ return
+ }
+ if zb0236 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030]) >= zb0235 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030])[:zb0235]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] = make(assetIndices, zb0235)
+ }
+ for zb0031 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030][zb0031].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ForeignAssets", zb0030, zb0031)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0237 []byte
+ var zb0238 int
+ zb0238, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignAssets")
+ return
+ }
+ if zb0238 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0238), uint64(maxBitmaskSize))
+ return
+ }
+ zb0237, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskForeignAssets")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets = bitmask(zb0237)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0239 int
+ var zb0240 bool
+ zb0239, zb0240, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumUint")
+ return
+ }
+ if zb0239 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0239), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumUint")
+ return
+ }
+ if zb0240 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint) >= zb0239 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint)[:zb0239]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint = make([]uint64, zb0239)
+ }
+ for zb0032 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint[zb0032], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumUint", zb0032)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0241 []byte
+ var zb0242 int
+ zb0242, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumUint")
+ return
+ }
+ if zb0242 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0242), uint64(maxBitmaskSize))
+ return
+ }
+ zb0241, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumUint")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint = bitmask(zb0241)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0243 int
+ var zb0244 bool
+ zb0243, zb0244, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumByteSlice")
+ return
+ }
+ if zb0243 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0243), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumByteSlice")
+ return
+ }
+ if zb0244 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice) >= zb0243 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice)[:zb0243]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice = make([]uint64, zb0243)
+ }
+ for zb0033 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice[zb0033], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "LocalNumByteSlice", zb0033)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0245 []byte
+ var zb0246 int
+ zb0246, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumByteSlice")
+ return
+ }
+ if zb0246 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0246), uint64(maxBitmaskSize))
+ return
+ }
+ zb0245, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskLocalNumByteSlice")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice = bitmask(zb0245)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0247 int
+ var zb0248 bool
+ zb0247, zb0248, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumUint")
+ return
+ }
+ if zb0247 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0247), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumUint")
+ return
+ }
+ if zb0248 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint) >= zb0247 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint)[:zb0247]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint = make([]uint64, zb0247)
+ }
+ for zb0034 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint[zb0034], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumUint", zb0034)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0249 []byte
+ var zb0250 int
+ zb0250, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumUint")
+ return
+ }
+ if zb0250 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0250), uint64(maxBitmaskSize))
+ return
+ }
+ zb0249, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumUint")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint = bitmask(zb0249)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0251 int
+ var zb0252 bool
+ zb0251, zb0252, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumByteSlice")
+ return
+ }
+ if zb0251 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0251), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumByteSlice")
+ return
+ }
+ if zb0252 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice) >= zb0251 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice)[:zb0251]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice = make([]uint64, zb0251)
+ }
+ for zb0035 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice[zb0035], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "GlobalNumByteSlice", zb0035)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0253 []byte
+ var zb0254 int
+ zb0254, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumByteSlice")
+ return
+ }
+ if zb0254 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0254), uint64(maxBitmaskSize))
+ return
+ }
+ zb0253, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskGlobalNumByteSlice")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice = bitmask(zb0253)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0255 int
+ var zb0256 bool
+ zb0255, zb0256, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram")
+ return
+ }
+ if zb0255 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0255), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram")
+ return
+ }
+ if zb0256 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram) >= zb0255 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram)[:zb0255]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram = make([]program, zb0255)
+ }
+ for zb0036 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram {
+ {
+ var zb0257 []byte
+ var zb0258 int
+ zb0258, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram", zb0036)
+ return
+ }
+ if zb0258 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0258), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0257, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram[zb0036]))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram", zb0036)
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram[zb0036] = program(zb0257)
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0259 []byte
+ var zb0260 int
+ zb0260, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApprovalProgram")
+ return
+ }
+ if zb0260 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0260), uint64(maxBitmaskSize))
+ return
+ }
+ zb0259, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskApprovalProgram")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram = bitmask(zb0259)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0261 int
+ var zb0262 bool
+ zb0261, zb0262, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram")
+ return
+ }
+ if zb0261 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0261), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram")
+ return
+ }
+ if zb0262 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram) >= zb0261 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram)[:zb0261]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram = make([]program, zb0261)
+ }
+ for zb0037 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram {
+ {
+ var zb0263 []byte
+ var zb0264 int
+ zb0264, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram", zb0037)
+ return
+ }
+ if zb0264 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0264), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0263, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram[zb0037]))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram", zb0037)
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram[zb0037] = program(zb0263)
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0265 []byte
+ var zb0266 int
+ zb0266, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClearStateProgram")
+ return
+ }
+ if zb0266 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0266), uint64(maxBitmaskSize))
+ return
+ }
+ zb0265, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskClearStateProgram")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram = bitmask(zb0265)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0267 int
+ var zb0268 bool
+ zb0267, zb0268, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExtraProgramPages")
+ return
+ }
+ if zb0267 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0267), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "ExtraProgramPages")
+ return
+ }
+ if zb0268 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages) >= zb0267 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages)[:zb0267]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages = make([]uint32, zb0267)
+ }
+ for zb0038 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages[zb0038], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "ExtraProgramPages", zb0038)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0269 []byte
+ var zb0270 int
+ zb0270, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskExtraProgramPages")
+ return
+ }
+ if zb0270 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0270), uint64(maxBitmaskSize))
+ return
+ }
+ zb0269, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskExtraProgramPages")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages = bitmask(zb0269)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0271 int
+ var zb0272 bool
+ zb0271, zb0272, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertRound")
+ return
+ }
+ if zb0271 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0271), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "CertRound")
+ return
+ }
+ if zb0272 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound) >= zb0271 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound)[:zb0271]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound = make([]basics.Round, zb0271)
+ }
+ for zb0039 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound[zb0039].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertRound", zb0039)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0273 []byte
+ var zb0274 int
+ zb0274, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertRound")
+ return
+ }
+ if zb0274 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0274), uint64(maxBitmaskSize))
+ return
+ }
+ zb0273, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertRound")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound = bitmask(zb0273)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0275 int
+ var zb0276 bool
+ zb0275, zb0276, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertType")
+ return
+ }
+ if zb0275 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0275), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "CertType")
+ return
+ }
+ if zb0276 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType) >= zb0275 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType)[:zb0275]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType = make([]protocol.CompactCertType, zb0275)
+ }
+ for zb0040 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType[zb0040].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "CertType", zb0040)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0277 []byte
+ var zb0278 int
+ zb0278, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertType")
+ return
+ }
+ if zb0278 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0278), uint64(maxBitmaskSize))
+ return
+ }
+ zb0277, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertType))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskCertType")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertType = bitmask(zb0277)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0279 int
+ zb0279, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigCommit")
+ return
+ }
+ if zb0279 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0279), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigCommit")
+ return
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0280 []byte
+ var zb0281 int
+ zb0281, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigCommit")
+ return
+ }
+ if zb0281 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0281), uint64(maxBitmaskSize))
+ return
+ }
+ zb0280, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigCommit")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit = bitmask(zb0280)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0282 int
+ var zb0283 bool
+ zb0282, zb0283, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight")
+ return
+ }
+ if zb0282 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0282), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight")
+ return
+ }
+ if zb0283 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight) >= zb0282 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight)[:zb0282]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight = make([]uint64, zb0282)
+ }
+ for zb0041 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight[zb0041], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SignedWeight", zb0041)
+ return
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0284 []byte
+ var zb0285 int
+ zb0285, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSignedWeight")
+ return
+ }
+ if zb0285 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0285), uint64(maxBitmaskSize))
+ return
+ }
+ zb0284, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSignedWeight")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight = bitmask(zb0284)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0286 int
+ var zb0287 bool
+ zb0286, zb0287, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs")
+ return
+ }
+ if zb0286 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0286), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs")
+ return
+ }
+ if zb0287 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs) >= zb0286 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs)[:zb0286]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs = make([]certProofs, zb0286)
+ }
+ for zb0042 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs {
+ var zb0288 int
+ var zb0289 bool
+ zb0288, zb0289, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0042)
+ return
+ }
+ if zb0288 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0288), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0042)
+ return
+ }
+ if zb0289 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042]) >= zb0288 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042])[:zb0288]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] = make(certProofs, zb0288)
+ }
+ for zb0043 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042][zb0043].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SigProofs", zb0042, zb0043)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0290 []byte
+ var zb0291 int
+ zb0291, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigProofs")
+ return
+ }
+ if zb0291 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0291), uint64(maxBitmaskSize))
+ return
+ }
+ zb0290, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskSigProofs")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs = bitmask(zb0290)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0292 int
+ var zb0293 bool
+ zb0292, zb0293, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs")
+ return
+ }
+ if zb0292 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0292), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs")
+ return
+ }
+ if zb0293 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs) >= zb0292 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs)[:zb0292]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs = make([]certProofs, zb0292)
+ }
+ for zb0044 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs {
+ var zb0294 int
+ var zb0295 bool
+ zb0294, zb0295, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0044)
+ return
+ }
+ if zb0294 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0294), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0044)
+ return
+ }
+ if zb0295 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044]) >= zb0294 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044])[:zb0294]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] = make(certProofs, zb0294)
+ }
+ for zb0045 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044][zb0045].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "PartProofs", zb0044, zb0045)
+ return
+ }
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0296 []byte
+ var zb0297 int
+ zb0297, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskPartProofs")
+ return
+ }
+ if zb0297 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0297), uint64(maxBitmaskSize))
+ return
+ }
+ zb0296, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskPartProofs")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs = bitmask(zb0296)
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ var zb0298 int
+ var zb0299 bool
+ zb0298, zb0299, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals")
+ return
+ }
+ if zb0298 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0298), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "Reveals")
+ return
+ }
+ if zb0299 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals) >= zb0298 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals)[:zb0298]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals = make([]revealMap, zb0298)
+ }
+ for zb0046 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals {
+ var zb0300 int
+ var zb0301 bool
+ zb0300, zb0301, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0046)
+ return
+ }
+ if zb0300 > compactcert.MaxReveals {
+ err = msgp.ErrOverflow(uint64(zb0300), uint64(compactcert.MaxReveals))
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0046)
+ return
+ }
+ if zb0301 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] == nil {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] = make(revealMap, zb0300)
+ }
+ for zb0300 > 0 {
+ var zb0047 uint64
+ var zb0048 compactcert.Reveal
+ zb0300--
+ zb0047, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0046)
+ return
+ }
+ bts, err = zb0048.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "Reveals", zb0046, zb0047)
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046][zb0047] = zb0048
+ }
+ }
+ }
+ if zb0049 > 0 {
+ zb0049--
+ {
+ var zb0302 []byte
+ var zb0303 int
+ zb0303, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReveals")
+ return
+ }
+ if zb0303 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0303), uint64(maxBitmaskSize))
+ return
+ }
+ zb0302, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals))
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "BitmaskReveals")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals = bitmask(zb0302)
+ }
+ }
+ if zb0049 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0049)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0050 {
+ (*z) = txGroupsEncodingStub{}
+ }
+ for zb0049 > 0 {
+ zb0049--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "ttc":
+ (*z).TotalTransactionsCount, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "TotalTransactionsCount")
+ return
+ }
+ case "tgc":
+ (*z).TransactionGroupCount, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "TransactionGroupCount")
+ return
+ }
+ case "tgs":
+ var zb0304 int
+ zb0304, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "TransactionGroupSizes")
+ return
+ }
+ if zb0304 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0304), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).TransactionGroupSizes, bts, err = msgp.ReadBytesBytes(bts, (*z).TransactionGroupSizes)
+ if err != nil {
+ err = msgp.WrapError(err, "TransactionGroupSizes")
+ return
+ }
+ case "sig":
+ var zb0305 int
+ zb0305, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Sig")
+ return
+ }
+ if zb0305 > maxSignatureBytes {
+ err = msgp.ErrOverflow(uint64(zb0305), uint64(maxSignatureBytes))
+ return
+ }
+ (*z).encodedSignedTxns.Sig, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.Sig)
+ if err != nil {
+ err = msgp.WrapError(err, "Sig")
+ return
+ }
+ case "sigbm":
+ {
+ var zb0306 []byte
+ var zb0307 int
+ zb0307, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSig")
+ return
+ }
+ if zb0307 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0307), uint64(maxBitmaskSize))
+ return
+ }
+ zb0306, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.BitmaskSig))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSig")
+ return
+ }
+ (*z).encodedSignedTxns.BitmaskSig = bitmask(zb0306)
+ }
+ case "msigv":
+ var zb0308 int
+ zb0308, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Version")
+ return
+ }
+ if zb0308 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0308), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedSignedTxns.encodedMsigs.Version, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedMsigs.Version)
+ if err != nil {
+ err = msgp.WrapError(err, "Version")
+ return
+ }
+ case "msigvbm":
+ {
+ var zb0309 []byte
+ var zb0310 int
+ zb0310, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVersion")
+ return
+ }
+ if zb0310 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0310), uint64(maxBitmaskSize))
+ return
+ }
+ zb0309, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedMsigs.BitmaskVersion))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVersion")
+ return
+ }
+ (*z).encodedSignedTxns.encodedMsigs.BitmaskVersion = bitmask(zb0309)
+ }
+ case "msigthr":
+ var zb0311 int
+ zb0311, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Threshold")
+ return
+ }
+ if zb0311 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0311), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedSignedTxns.encodedMsigs.Threshold, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedMsigs.Threshold)
+ if err != nil {
+ err = msgp.WrapError(err, "Threshold")
+ return
+ }
+ case "msigthrbm":
+ {
+ var zb0312 []byte
+ var zb0313 int
+ zb0313, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskThreshold")
+ return
+ }
+ if zb0313 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0313), uint64(maxBitmaskSize))
+ return
+ }
+ zb0312, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedMsigs.BitmaskThreshold))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskThreshold")
+ return
+ }
+ (*z).encodedSignedTxns.encodedMsigs.BitmaskThreshold = bitmask(zb0312)
+ }
+ case "subsig":
+ var zb0314 int
+ var zb0315 bool
+ zb0314, zb0315, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Subsigs")
+ return
+ }
+ if zb0314 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0314), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Subsigs")
+ return
+ }
+ if zb0315 {
+ (*z).encodedSignedTxns.encodedMsigs.Subsigs = nil
+ } else if (*z).encodedSignedTxns.encodedMsigs.Subsigs != nil && cap((*z).encodedSignedTxns.encodedMsigs.Subsigs) >= zb0314 {
+ (*z).encodedSignedTxns.encodedMsigs.Subsigs = ((*z).encodedSignedTxns.encodedMsigs.Subsigs)[:zb0314]
+ } else {
+ (*z).encodedSignedTxns.encodedMsigs.Subsigs = make([][]crypto.MultisigSubsig, zb0314)
+ }
+ for zb0001 := range (*z).encodedSignedTxns.encodedMsigs.Subsigs {
+ var zb0316 int
+ var zb0317 bool
+ zb0316, zb0317, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Subsigs", zb0001)
+ return
+ }
+ if zb0316 > crypto.MaxMultisig {
+ err = msgp.ErrOverflow(uint64(zb0316), uint64(crypto.MaxMultisig))
+ err = msgp.WrapError(err, "Subsigs", zb0001)
+ return
+ }
+ if zb0317 {
+ (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001] = nil
+ } else if (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001] != nil && cap((*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001]) >= zb0316 {
+ (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001] = ((*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001])[:zb0316]
+ } else {
+ (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001] = make([]crypto.MultisigSubsig, zb0316)
+ }
+ for zb0002 := range (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001] {
+ bts, err = (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001][zb0002].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Subsigs", zb0001, zb0002)
+ return
+ }
+ }
+ }
+ case "subsigsbm":
+ {
+ var zb0318 []byte
+ var zb0319 int
+ zb0319, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSubsigs")
+ return
+ }
+ if zb0319 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0319), uint64(maxBitmaskSize))
+ return
+ }
+ zb0318, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedMsigs.BitmaskSubsigs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSubsigs")
+ return
+ }
+ (*z).encodedSignedTxns.encodedMsigs.BitmaskSubsigs = bitmask(zb0318)
+ }
+ case "lsigl":
+ var zb0320 int
+ var zb0321 bool
+ zb0320, zb0321, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Logic")
+ return
+ }
+ if zb0320 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0320), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Logic")
+ return
+ }
+ if zb0321 {
+ (*z).encodedSignedTxns.encodedLsigs.Logic = nil
+ } else if (*z).encodedSignedTxns.encodedLsigs.Logic != nil && cap((*z).encodedSignedTxns.encodedLsigs.Logic) >= zb0320 {
+ (*z).encodedSignedTxns.encodedLsigs.Logic = ((*z).encodedSignedTxns.encodedLsigs.Logic)[:zb0320]
+ } else {
+ (*z).encodedSignedTxns.encodedLsigs.Logic = make([][]byte, zb0320)
+ }
+ for zb0003 := range (*z).encodedSignedTxns.encodedLsigs.Logic {
+ var zb0322 int
+ zb0322, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Logic", zb0003)
+ return
+ }
+ if zb0322 > config.MaxLogicSigMaxSize {
+ err = msgp.ErrOverflow(uint64(zb0322), uint64(config.MaxLogicSigMaxSize))
+ return
+ }
+ (*z).encodedSignedTxns.encodedLsigs.Logic[zb0003], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedLsigs.Logic[zb0003])
+ if err != nil {
+ err = msgp.WrapError(err, "Logic", zb0003)
+ return
+ }
+ }
+ case "lsiglbm":
+ {
+ var zb0323 []byte
+ var zb0324 int
+ zb0324, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLogic")
+ return
+ }
+ if zb0324 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0324), uint64(maxBitmaskSize))
+ return
+ }
+ zb0323, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedLsigs.BitmaskLogic))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLogic")
+ return
+ }
+ (*z).encodedSignedTxns.encodedLsigs.BitmaskLogic = bitmask(zb0323)
+ }
+ case "lsigarg":
+ var zb0325 int
+ var zb0326 bool
+ zb0325, zb0326, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LogicArgs")
+ return
+ }
+ if zb0325 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0325), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LogicArgs")
+ return
+ }
+ if zb0326 {
+ (*z).encodedSignedTxns.encodedLsigs.LogicArgs = nil
+ } else if (*z).encodedSignedTxns.encodedLsigs.LogicArgs != nil && cap((*z).encodedSignedTxns.encodedLsigs.LogicArgs) >= zb0325 {
+ (*z).encodedSignedTxns.encodedLsigs.LogicArgs = ((*z).encodedSignedTxns.encodedLsigs.LogicArgs)[:zb0325]
+ } else {
+ (*z).encodedSignedTxns.encodedLsigs.LogicArgs = make([][][]byte, zb0325)
+ }
+ for zb0004 := range (*z).encodedSignedTxns.encodedLsigs.LogicArgs {
+ var zb0327 int
+ var zb0328 bool
+ zb0327, zb0328, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LogicArgs", zb0004)
+ return
+ }
+ if zb0327 > transactions.EvalMaxArgs {
+ err = msgp.ErrOverflow(uint64(zb0327), uint64(transactions.EvalMaxArgs))
+ err = msgp.WrapError(err, "LogicArgs", zb0004)
+ return
+ }
+ if zb0328 {
+ (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004] = nil
+ } else if (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004] != nil && cap((*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004]) >= zb0327 {
+ (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004] = ((*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004])[:zb0327]
+ } else {
+ (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004] = make([][]byte, zb0327)
+ }
+ for zb0005 := range (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004] {
+ var zb0329 int
+ zb0329, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LogicArgs", zb0004, zb0005)
+ return
+ }
+ if zb0329 > config.MaxLogicSigMaxSize {
+ err = msgp.ErrOverflow(uint64(zb0329), uint64(config.MaxLogicSigMaxSize))
+ return
+ }
+ (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004][zb0005], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004][zb0005])
+ if err != nil {
+ err = msgp.WrapError(err, "LogicArgs", zb0004, zb0005)
+ return
+ }
+ }
+ }
+ case "lsigargbm":
+ {
+ var zb0330 []byte
+ var zb0331 int
+ zb0331, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLogicArgs")
+ return
+ }
+ if zb0331 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0331), uint64(maxBitmaskSize))
+ return
+ }
+ zb0330, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedLsigs.BitmaskLogicArgs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLogicArgs")
+ return
+ }
+ (*z).encodedSignedTxns.encodedLsigs.BitmaskLogicArgs = bitmask(zb0330)
+ }
+ case "sgnr":
+ var zb0332 int
+ zb0332, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AuthAddr")
+ return
+ }
+ if zb0332 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0332), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.AuthAddr, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.AuthAddr)
+ if err != nil {
+ err = msgp.WrapError(err, "AuthAddr")
+ return
+ }
+ case "sgnrbm":
+ {
+ var zb0333 []byte
+ var zb0334 int
+ zb0334, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAuthAddr")
+ return
+ }
+ if zb0334 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0334), uint64(maxBitmaskSize))
+ return
+ }
+ zb0333, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.BitmaskAuthAddr))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAuthAddr")
+ return
+ }
+ (*z).encodedSignedTxns.BitmaskAuthAddr = bitmask(zb0333)
+ }
+ case "type":
+ var zb0335 int
+ zb0335, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "TxType")
+ return
+ }
+ if zb0335 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0335), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.TxType, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.TxType)
+ if err != nil {
+ err = msgp.WrapError(err, "TxType")
+ return
+ }
+ case "typebm":
+ {
+ var zb0336 []byte
+ var zb0337 int
+ zb0337, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTxType")
+ return
+ }
+ if zb0337 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0337), uint64(maxBitmaskSize))
+ return
+ }
+ zb0336, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.BitmaskTxType))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTxType")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.BitmaskTxType = bitmask(zb0336)
+ }
+ case "typeo":
+ (*z).encodedSignedTxns.encodedTxns.TxTypeOffset, bts, err = msgp.ReadByteBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "TxTypeOffset")
+ return
+ }
+ case "snd":
+ var zb0338 int
+ zb0338, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Sender")
+ return
+ }
+ if zb0338 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0338), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Sender, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Sender)
+ if err != nil {
+ err = msgp.WrapError(err, "Sender")
+ return
+ }
+ case "sndbm":
+ {
+ var zb0339 []byte
+ var zb0340 int
+ zb0340, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSender")
+ return
+ }
+ if zb0340 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0340), uint64(maxBitmaskSize))
+ return
+ }
+ zb0339, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskSender))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSender")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskSender = bitmask(zb0339)
+ }
+ case "fee":
+ var zb0341 int
+ var zb0342 bool
+ zb0341, zb0342, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Fee")
+ return
+ }
+ if zb0341 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0341), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Fee")
+ return
+ }
+ if zb0342 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee) >= zb0341 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee = ((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee)[:zb0341]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee = make([]basics.MicroAlgos, zb0341)
+ }
+ for zb0006 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee[zb0006].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Fee", zb0006)
+ return
+ }
+ }
+ case "feebm":
+ {
+ var zb0343 []byte
+ var zb0344 int
+ zb0344, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFee")
+ return
+ }
+ if zb0344 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0344), uint64(maxBitmaskSize))
+ return
+ }
+ zb0343, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFee))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFee")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFee = bitmask(zb0343)
+ }
+ case "fv":
+ var zb0345 int
+ var zb0346 bool
+ zb0345, zb0346, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FirstValid")
+ return
+ }
+ if zb0345 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0345), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "FirstValid")
+ return
+ }
+ if zb0346 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid) >= zb0345 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid = ((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid)[:zb0345]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid = make([]basics.Round, zb0345)
+ }
+ for zb0007 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid[zb0007].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FirstValid", zb0007)
+ return
+ }
+ }
+ case "fvbm":
+ {
+ var zb0347 []byte
+ var zb0348 int
+ zb0348, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFirstValid")
+ return
+ }
+ if zb0348 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0348), uint64(maxBitmaskSize))
+ return
+ }
+ zb0347, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFirstValid))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFirstValid")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFirstValid = bitmask(zb0347)
+ }
+ case "lv":
+ var zb0349 int
+ var zb0350 bool
+ zb0349, zb0350, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LastValid")
+ return
+ }
+ if zb0349 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0349), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LastValid")
+ return
+ }
+ if zb0350 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid) >= zb0349 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid = ((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid)[:zb0349]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid = make([]basics.Round, zb0349)
+ }
+ for zb0008 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid[zb0008].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LastValid", zb0008)
+ return
+ }
+ }
+ case "lvbm":
+ {
+ var zb0351 []byte
+ var zb0352 int
+ zb0352, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLastValid")
+ return
+ }
+ if zb0352 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0352), uint64(maxBitmaskSize))
+ return
+ }
+ zb0351, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLastValid))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLastValid")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLastValid = bitmask(zb0351)
+ }
+ case "note":
+ var zb0353 int
+ var zb0354 bool
+ zb0353, zb0354, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Note")
+ return
+ }
+ if zb0353 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0353), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Note")
+ return
+ }
+ if zb0354 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note) >= zb0353 {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note = ((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note)[:zb0353]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note = make([][]byte, zb0353)
+ }
+ for zb0009 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note {
+ var zb0355 int
+ zb0355, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Note", zb0009)
+ return
+ }
+ if zb0355 > config.MaxTxnNoteBytes {
+ err = msgp.ErrOverflow(uint64(zb0355), uint64(config.MaxTxnNoteBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note[zb0009], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note[zb0009])
+ if err != nil {
+ err = msgp.WrapError(err, "Note", zb0009)
+ return
+ }
+ }
+ case "notebm":
+ {
+ var zb0356 []byte
+ var zb0357 int
+ zb0357, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNote")
+ return
+ }
+ if zb0357 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0357), uint64(maxBitmaskSize))
+ return
+ }
+ zb0356, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskNote))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNote")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskNote = bitmask(zb0356)
+ }
+ case "genbm":
+ {
+ var zb0358 []byte
+ var zb0359 int
+ zb0359, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGenesisID")
+ return
+ }
+ if zb0359 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0359), uint64(maxBitmaskSize))
+ return
+ }
+ zb0358, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGenesisID))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGenesisID")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGenesisID = bitmask(zb0358)
+ }
+ case "grpbm":
+ {
+ var zb0360 []byte
+ var zb0361 int
+ zb0361, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGroup")
+ return
+ }
+ if zb0361 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0361), uint64(maxBitmaskSize))
+ return
+ }
+ zb0360, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGroup))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGroup")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGroup = bitmask(zb0360)
+ }
+ case "lx":
+ var zb0362 int
+ zb0362, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Lease")
+ return
+ }
+ if zb0362 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0362), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Lease, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Lease)
+ if err != nil {
+ err = msgp.WrapError(err, "Lease")
+ return
+ }
+ case "lxbm":
+ {
+ var zb0363 []byte
+ var zb0364 int
+ zb0364, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLease")
+ return
+ }
+ if zb0364 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0364), uint64(maxBitmaskSize))
+ return
+ }
+ zb0363, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLease))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLease")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLease = bitmask(zb0363)
+ }
+ case "rekey":
+ var zb0365 int
+ zb0365, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "RekeyTo")
+ return
+ }
+ if zb0365 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0365), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.RekeyTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.RekeyTo)
+ if err != nil {
+ err = msgp.WrapError(err, "RekeyTo")
+ return
+ }
+ case "rekeybm":
+ {
+ var zb0366 []byte
+ var zb0367 int
+ zb0367, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskRekeyTo")
+ return
+ }
+ if zb0367 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0367), uint64(maxBitmaskSize))
+ return
+ }
+ zb0366, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskRekeyTo))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskRekeyTo")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskRekeyTo = bitmask(zb0366)
+ }
+ case "votekey":
+ var zb0368 int
+ zb0368, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VotePK")
+ return
+ }
+ if zb0368 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0368), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VotePK, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VotePK)
+ if err != nil {
+ err = msgp.WrapError(err, "VotePK")
+ return
+ }
+ case "selkey":
+ var zb0369 int
+ zb0369, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SelectionPK")
+ return
+ }
+ if zb0369 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0369), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.SelectionPK, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.SelectionPK)
+ if err != nil {
+ err = msgp.WrapError(err, "SelectionPK")
+ return
+ }
+ case "votefst":
+ var zb0370 int
+ var zb0371 bool
+ zb0370, zb0371, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteFirst")
+ return
+ }
+ if zb0370 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0370), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "VoteFirst")
+ return
+ }
+ if zb0371 {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst) >= zb0370 {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst = ((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst)[:zb0370]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst = make([]basics.Round, zb0370)
+ }
+ for zb0010 := range (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst[zb0010].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteFirst", zb0010)
+ return
+ }
+ }
+ case "votefstbm":
+ {
+ var zb0372 []byte
+ var zb0373 int
+ zb0373, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteFirst")
+ return
+ }
+ if zb0373 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0373), uint64(maxBitmaskSize))
+ return
+ }
+ zb0372, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteFirst")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst = bitmask(zb0372)
+ }
+ case "votelst":
+ var zb0374 int
+ var zb0375 bool
+ zb0374, zb0375, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteLast")
+ return
+ }
+ if zb0374 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0374), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "VoteLast")
+ return
+ }
+ if zb0375 {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast) >= zb0374 {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast = ((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast)[:zb0374]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast = make([]basics.Round, zb0374)
+ }
+ for zb0011 := range (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast[zb0011].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteLast", zb0011)
+ return
+ }
+ }
+ case "votelstbm":
+ {
+ var zb0376 []byte
+ var zb0377 int
+ zb0377, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteLast")
+ return
+ }
+ if zb0377 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0377), uint64(maxBitmaskSize))
+ return
+ }
+ zb0376, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskVoteLast")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast = bitmask(zb0376)
+ }
+ case "votekd":
+ var zb0378 int
+ var zb0379 bool
+ zb0378, zb0379, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteKeyDilution")
+ return
+ }
+ if zb0378 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0378), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "VoteKeyDilution")
+ return
+ }
+ if zb0379 {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution) >= zb0378 {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution = ((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution)[:zb0378]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution = make([]uint64, zb0378)
+ }
+ for zb0012 := range (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution {
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution[zb0012], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "VoteKeyDilution", zb0012)
+ return
+ }
+ }
+ case "votekbm":
+ {
+ var zb0380 []byte
+ var zb0381 int
+ zb0381, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskKeys")
+ return
+ }
+ if zb0381 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0381), uint64(maxBitmaskSize))
+ return
+ }
+ zb0380, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskKeys))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskKeys")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskKeys = bitmask(zb0380)
+ }
+ case "nonpartbm":
+ {
+ var zb0382 []byte
+ var zb0383 int
+ zb0383, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNonparticipation")
+ return
+ }
+ if zb0383 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0383), uint64(maxBitmaskSize))
+ return
+ }
+ zb0382, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskNonparticipation")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation = bitmask(zb0382)
+ }
+ case "rcv":
+ var zb0384 int
+ zb0384, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Receiver")
+ return
+ }
+ if zb0384 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0384), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Receiver, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Receiver)
+ if err != nil {
+ err = msgp.WrapError(err, "Receiver")
+ return
+ }
+ case "rcvbm":
+ {
+ var zb0385 []byte
+ var zb0386 int
+ zb0386, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReceiver")
+ return
+ }
+ if zb0386 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0386), uint64(maxBitmaskSize))
+ return
+ }
+ zb0385, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReceiver")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskReceiver = bitmask(zb0385)
+ }
+ case "amt":
+ var zb0387 int
+ var zb0388 bool
+ zb0387, zb0388, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Amount")
+ return
+ }
+ if zb0387 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0387), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Amount")
+ return
+ }
+ if zb0388 {
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount) >= zb0387 {
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount = ((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount)[:zb0387]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount = make([]basics.MicroAlgos, zb0387)
+ }
+ for zb0013 := range (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount[zb0013].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Amount", zb0013)
+ return
+ }
+ }
+ case "amtbm":
+ {
+ var zb0389 []byte
+ var zb0390 int
+ zb0390, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAmount")
+ return
+ }
+ if zb0390 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0390), uint64(maxBitmaskSize))
+ return
+ }
+ zb0389, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAmount")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskAmount = bitmask(zb0389)
+ }
+ case "close":
+ var zb0391 int
+ zb0391, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CloseRemainderTo")
+ return
+ }
+ if zb0391 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0391), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.CloseRemainderTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.CloseRemainderTo)
+ if err != nil {
+ err = msgp.WrapError(err, "CloseRemainderTo")
+ return
+ }
+ case "closebm":
+ {
+ var zb0392 []byte
+ var zb0393 int
+ zb0393, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCloseRemainderTo")
+ return
+ }
+ if zb0393 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0393), uint64(maxBitmaskSize))
+ return
+ }
+ zb0392, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCloseRemainderTo")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo = bitmask(zb0392)
+ }
+ case "caid":
+ var zb0394 int
+ var zb0395 bool
+ zb0394, zb0395, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ConfigAsset")
+ return
+ }
+ if zb0394 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0394), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ConfigAsset")
+ return
+ }
+ if zb0395 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset) >= zb0394 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset = ((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset)[:zb0394]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset = make([]basics.AssetIndex, zb0394)
+ }
+ for zb0014 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset[zb0014].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ConfigAsset", zb0014)
+ return
+ }
+ }
+ case "caidbm":
+ {
+ var zb0396 []byte
+ var zb0397 int
+ zb0397, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskConfigAsset")
+ return
+ }
+ if zb0397 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0397), uint64(maxBitmaskSize))
+ return
+ }
+ zb0396, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskConfigAsset")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset = bitmask(zb0396)
+ }
+ case "t":
+ var zb0398 int
+ var zb0399 bool
+ zb0398, zb0399, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Total")
+ return
+ }
+ if zb0398 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0398), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Total")
+ return
+ }
+ if zb0399 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total) >= zb0398 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total = ((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total)[:zb0398]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total = make([]uint64, zb0398)
+ }
+ for zb0015 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total[zb0015], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Total", zb0015)
+ return
+ }
+ }
+ case "tbm":
+ {
+ var zb0400 []byte
+ var zb0401 int
+ zb0401, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTotal")
+ return
+ }
+ if zb0401 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0401), uint64(maxBitmaskSize))
+ return
+ }
+ zb0400, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskTotal")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal = bitmask(zb0400)
+ }
+ case "dc":
+ var zb0402 int
+ var zb0403 bool
+ zb0402, zb0403, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Decimals")
+ return
+ }
+ if zb0402 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0402), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Decimals")
+ return
+ }
+ if zb0403 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals) >= zb0402 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals = ((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals)[:zb0402]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals = make([]uint32, zb0402)
+ }
+ for zb0016 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals[zb0016], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Decimals", zb0016)
+ return
+ }
+ }
+ case "dcbm":
+ {
+ var zb0404 []byte
+ var zb0405 int
+ zb0405, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDecimals")
+ return
+ }
+ if zb0405 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0405), uint64(maxBitmaskSize))
+ return
+ }
+ zb0404, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDecimals")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals = bitmask(zb0404)
+ }
+ case "dfbm":
+ {
+ var zb0406 []byte
+ var zb0407 int
+ zb0407, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDefaultFrozen")
+ return
+ }
+ if zb0407 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0407), uint64(maxBitmaskSize))
+ return
+ }
+ zb0406, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskDefaultFrozen")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen = bitmask(zb0406)
+ }
+ case "un":
+ var zb0408 int
+ var zb0409 bool
+ zb0408, zb0409, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UnitName")
+ return
+ }
+ if zb0408 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0408), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "UnitName")
+ return
+ }
+ if zb0409 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName) >= zb0408 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName = ((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName)[:zb0408]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName = make([]string, zb0408)
+ }
+ for zb0017 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName[zb0017], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "UnitName", zb0017)
+ return
+ }
+ }
+ case "unbm":
+ {
+ var zb0410 []byte
+ var zb0411 int
+ zb0411, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskUnitName")
+ return
+ }
+ if zb0411 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0411), uint64(maxBitmaskSize))
+ return
+ }
+ zb0410, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskUnitName")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName = bitmask(zb0410)
+ }
+ case "an":
+ var zb0412 int
+ var zb0413 bool
+ zb0412, zb0413, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetName")
+ return
+ }
+ if zb0412 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0412), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "AssetName")
+ return
+ }
+ if zb0413 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName) >= zb0412 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName = ((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName)[:zb0412]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName = make([]string, zb0412)
+ }
+ for zb0018 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName[zb0018], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetName", zb0018)
+ return
+ }
+ }
+ case "anbm":
+ {
+ var zb0414 []byte
+ var zb0415 int
+ zb0415, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetName")
+ return
+ }
+ if zb0415 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0415), uint64(maxBitmaskSize))
+ return
+ }
+ zb0414, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetName")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName = bitmask(zb0414)
+ }
+ case "au":
+ var zb0416 int
+ var zb0417 bool
+ zb0416, zb0417, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "URL")
+ return
+ }
+ if zb0416 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0416), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "URL")
+ return
+ }
+ if zb0417 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL) >= zb0416 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL = ((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL)[:zb0416]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL = make([]string, zb0416)
+ }
+ for zb0019 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL[zb0019], bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "URL", zb0019)
+ return
+ }
+ }
+ case "aubm":
+ {
+ var zb0418 []byte
+ var zb0419 int
+ zb0419, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskURL")
+ return
+ }
+ if zb0419 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0419), uint64(maxBitmaskSize))
+ return
+ }
+ zb0418, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskURL")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL = bitmask(zb0418)
+ }
+ case "am":
+ var zb0420 int
+ zb0420, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "MetadataHash")
+ return
+ }
+ if zb0420 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0420), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash)
+ if err != nil {
+ err = msgp.WrapError(err, "MetadataHash")
+ return
+ }
+ case "ambm":
+ {
+ var zb0421 []byte
+ var zb0422 int
+ zb0422, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskMetadataHash")
+ return
+ }
+ if zb0422 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0422), uint64(maxBitmaskSize))
+ return
+ }
+ zb0421, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskMetadataHash")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash = bitmask(zb0421)
+ }
+ case "m":
+ var zb0423 int
+ zb0423, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Manager")
+ return
+ }
+ if zb0423 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0423), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager)
+ if err != nil {
+ err = msgp.WrapError(err, "Manager")
+ return
+ }
+ case "mbm":
+ {
+ var zb0424 []byte
+ var zb0425 int
+ zb0425, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskManager")
+ return
+ }
+ if zb0425 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0425), uint64(maxBitmaskSize))
+ return
+ }
+ zb0424, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskManager")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager = bitmask(zb0424)
+ }
+ case "r":
+ var zb0426 int
+ zb0426, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reserve")
+ return
+ }
+ if zb0426 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0426), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve)
+ if err != nil {
+ err = msgp.WrapError(err, "Reserve")
+ return
+ }
+ case "rbm":
+ {
+ var zb0427 []byte
+ var zb0428 int
+ zb0428, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReserve")
+ return
+ }
+ if zb0428 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0428), uint64(maxBitmaskSize))
+ return
+ }
+ zb0427, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReserve")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve = bitmask(zb0427)
+ }
+ case "f":
+ var zb0429 int
+ zb0429, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Freeze")
+ return
+ }
+ if zb0429 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0429), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze)
+ if err != nil {
+ err = msgp.WrapError(err, "Freeze")
+ return
+ }
+ case "fbm":
+ {
+ var zb0430 []byte
+ var zb0431 int
+ zb0431, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreeze")
+ return
+ }
+ if zb0431 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0431), uint64(maxBitmaskSize))
+ return
+ }
+ zb0430, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreeze")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze = bitmask(zb0430)
+ }
+ case "c":
+ var zb0432 int
+ zb0432, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Clawback")
+ return
+ }
+ if zb0432 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0432), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback)
+ if err != nil {
+ err = msgp.WrapError(err, "Clawback")
+ return
+ }
+ case "cbm":
+ {
+ var zb0433 []byte
+ var zb0434 int
+ zb0434, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClawback")
+ return
+ }
+ if zb0434 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0434), uint64(maxBitmaskSize))
+ return
+ }
+ zb0433, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClawback")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback = bitmask(zb0433)
+ }
+ case "xaid":
+ var zb0435 int
+ var zb0436 bool
+ zb0435, zb0436, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "XferAsset")
+ return
+ }
+ if zb0435 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0435), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "XferAsset")
+ return
+ }
+ if zb0436 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset) >= zb0435 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset = ((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset)[:zb0435]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset = make([]basics.AssetIndex, zb0435)
+ }
+ for zb0020 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset[zb0020].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "XferAsset", zb0020)
+ return
+ }
+ }
+ case "xaidbm":
+ {
+ var zb0437 []byte
+ var zb0438 int
+ zb0438, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskXferAsset")
+ return
+ }
+ if zb0438 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0438), uint64(maxBitmaskSize))
+ return
+ }
+ zb0437, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskXferAsset")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset = bitmask(zb0437)
+ }
+ case "aamt":
+ var zb0439 int
+ var zb0440 bool
+ zb0439, zb0440, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetAmount")
+ return
+ }
+ if zb0439 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0439), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "AssetAmount")
+ return
+ }
+ if zb0440 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount) >= zb0439 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount = ((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount)[:zb0439]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount = make([]uint64, zb0439)
+ }
+ for zb0021 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount[zb0021], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetAmount", zb0021)
+ return
+ }
+ }
+ case "aamtbm":
+ {
+ var zb0441 []byte
+ var zb0442 int
+ zb0442, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetAmount")
+ return
+ }
+ if zb0442 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0442), uint64(maxBitmaskSize))
+ return
+ }
+ zb0441, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetAmount")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount = bitmask(zb0441)
+ }
+ case "asnd":
+ var zb0443 int
+ zb0443, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetSender")
+ return
+ }
+ if zb0443 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0443), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetSender, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetSender)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetSender")
+ return
+ }
+ case "asndbm":
+ {
+ var zb0444 []byte
+ var zb0445 int
+ zb0445, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetSender")
+ return
+ }
+ if zb0445 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0445), uint64(maxBitmaskSize))
+ return
+ }
+ zb0444, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetSender")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender = bitmask(zb0444)
+ }
+ case "arcv":
+ var zb0446 int
+ zb0446, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetReceiver")
+ return
+ }
+ if zb0446 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0446), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetReceiver, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetReceiver)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetReceiver")
+ return
+ }
+ case "arcvbm":
+ {
+ var zb0447 []byte
+ var zb0448 int
+ zb0448, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetReceiver")
+ return
+ }
+ if zb0448 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0448), uint64(maxBitmaskSize))
+ return
+ }
+ zb0447, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetReceiver")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver = bitmask(zb0447)
+ }
+ case "aclose":
+ var zb0449 int
+ zb0449, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetCloseTo")
+ return
+ }
+ if zb0449 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0449), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo)
+ if err != nil {
+ err = msgp.WrapError(err, "AssetCloseTo")
+ return
+ }
+ case "aclosebm":
+ {
+ var zb0450 []byte
+ var zb0451 int
+ zb0451, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetCloseTo")
+ return
+ }
+ if zb0451 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0451), uint64(maxBitmaskSize))
+ return
+ }
+ zb0450, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetCloseTo")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo = bitmask(zb0450)
+ }
+ case "fadd":
+ var zb0452 int
+ zb0452, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAccount")
+ return
+ }
+ if zb0452 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0452), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAccount")
+ return
+ }
+ case "faddbm":
+ {
+ var zb0453 []byte
+ var zb0454 int
+ zb0454, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAccount")
+ return
+ }
+ if zb0454 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0454), uint64(maxBitmaskSize))
+ return
+ }
+ zb0453, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAccount")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount = bitmask(zb0453)
+ }
+ case "faid":
+ var zb0455 int
+ var zb0456 bool
+ zb0455, zb0456, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAsset")
+ return
+ }
+ if zb0455 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0455), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "FreezeAsset")
+ return
+ }
+ if zb0456 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset) >= zb0455 {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset = ((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset)[:zb0455]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset = make([]basics.AssetIndex, zb0455)
+ }
+ for zb0022 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset[zb0022].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "FreezeAsset", zb0022)
+ return
+ }
+ }
+ case "faidbm":
+ {
+ var zb0457 []byte
+ var zb0458 int
+ zb0458, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAsset")
+ return
+ }
+ if zb0458 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0458), uint64(maxBitmaskSize))
+ return
+ }
+ zb0457, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskFreezeAsset")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset = bitmask(zb0457)
+ }
+ case "afrzbm":
+ {
+ var zb0459 []byte
+ var zb0460 int
+ zb0460, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetFrozen")
+ return
+ }
+ if zb0460 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0460), uint64(maxBitmaskSize))
+ return
+ }
+ zb0459, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAssetFrozen")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen = bitmask(zb0459)
+ }
+ case "apid":
+ var zb0461 int
+ var zb0462 bool
+ zb0461, zb0462, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationID")
+ return
+ }
+ if zb0461 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0461), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ApplicationID")
+ return
+ }
+ if zb0462 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID) >= zb0461 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID)[:zb0461]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID = make([]basics.AppIndex, zb0461)
+ }
+ for zb0023 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID[zb0023].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationID", zb0023)
+ return
+ }
+ }
+ case "apidbm":
+ {
+ var zb0463 []byte
+ var zb0464 int
+ zb0464, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationID")
+ return
+ }
+ if zb0464 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0464), uint64(maxBitmaskSize))
+ return
+ }
+ zb0463, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationID")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID = bitmask(zb0463)
+ }
+ case "apan":
+ var zb0465 int
+ zb0465, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "OnCompletion")
+ return
+ }
+ if zb0465 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0465), uint64(maxEncodedTransactionGroups))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.OnCompletion, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.OnCompletion)
+ if err != nil {
+ err = msgp.WrapError(err, "OnCompletion")
+ return
+ }
+ case "apanbm":
+ {
+ var zb0466 []byte
+ var zb0467 int
+ zb0467, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskOnCompletion")
+ return
+ }
+ if zb0467 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0467), uint64(maxBitmaskSize))
+ return
+ }
+ zb0466, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskOnCompletion")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion = bitmask(zb0466)
+ }
+ case "apaa":
+ var zb0468 int
+ var zb0469 bool
+ zb0468, zb0469, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationArgs")
+ return
+ }
+ if zb0468 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0468), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ApplicationArgs")
+ return
+ }
+ if zb0469 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs) >= zb0468 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs)[:zb0468]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs = make([]applicationArgs, zb0468)
+ }
+ for zb0024 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs {
+ var zb0470 int
+ var zb0471 bool
+ zb0470, zb0471, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationArgs", zb0024)
+ return
+ }
+ if zb0470 > transactions.EncodedMaxApplicationArgs {
+ err = msgp.ErrOverflow(uint64(zb0470), uint64(transactions.EncodedMaxApplicationArgs))
+ err = msgp.WrapError(err, "ApplicationArgs", zb0024)
+ return
+ }
+ if zb0471 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024]) >= zb0470 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024])[:zb0470]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] = make(applicationArgs, zb0470)
+ }
+ for zb0025 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024][zb0025], bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024][zb0025])
+ if err != nil {
+ err = msgp.WrapError(err, "ApplicationArgs", zb0024, zb0025)
+ return
+ }
+ }
+ }
+ case "apaabm":
+ {
+ var zb0472 []byte
+ var zb0473 int
+ zb0473, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationArgs")
+ return
+ }
+ if zb0473 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0473), uint64(maxBitmaskSize))
+ return
+ }
+ zb0472, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApplicationArgs")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs = bitmask(zb0472)
+ }
+ case "apat":
+ var zb0474 int
+ var zb0475 bool
+ zb0474, zb0475, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Accounts")
+ return
+ }
+ if zb0474 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0474), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Accounts")
+ return
+ }
+ if zb0475 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts) >= zb0474 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts)[:zb0474]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts = make([]addresses, zb0474)
+ }
+ for zb0026 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts {
+ var zb0476 int
+ var zb0477 bool
+ zb0476, zb0477, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Accounts", zb0026)
+ return
+ }
+ if zb0476 > transactions.EncodedMaxAccounts {
+ err = msgp.ErrOverflow(uint64(zb0476), uint64(transactions.EncodedMaxAccounts))
+ err = msgp.WrapError(err, "Accounts", zb0026)
+ return
+ }
+ if zb0477 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026]) >= zb0476 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026])[:zb0476]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] = make(addresses, zb0476)
+ }
+ for zb0027 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026][zb0027].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Accounts", zb0026, zb0027)
+ return
+ }
+ }
+ }
+ case "apatbm":
+ {
+ var zb0478 []byte
+ var zb0479 int
+ zb0479, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAccounts")
+ return
+ }
+ if zb0479 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0479), uint64(maxBitmaskSize))
+ return
+ }
+ zb0478, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskAccounts")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts = bitmask(zb0478)
+ }
+ case "apfa":
+ var zb0480 int
+ var zb0481 bool
+ zb0480, zb0481, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignApps")
+ return
+ }
+ if zb0480 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0480), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ForeignApps")
+ return
+ }
+ if zb0481 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps) >= zb0480 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps)[:zb0480]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps = make([]appIndices, zb0480)
+ }
+ for zb0028 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps {
+ var zb0482 int
+ var zb0483 bool
+ zb0482, zb0483, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignApps", zb0028)
+ return
+ }
+ if zb0482 > transactions.EncodedMaxForeignApps {
+ err = msgp.ErrOverflow(uint64(zb0482), uint64(transactions.EncodedMaxForeignApps))
+ err = msgp.WrapError(err, "ForeignApps", zb0028)
+ return
+ }
+ if zb0483 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028]) >= zb0482 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028])[:zb0482]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] = make(appIndices, zb0482)
+ }
+ for zb0029 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028][zb0029].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignApps", zb0028, zb0029)
+ return
+ }
+ }
+ }
+ case "apfabm":
+ {
+ var zb0484 []byte
+ var zb0485 int
+ zb0485, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignApps")
+ return
+ }
+ if zb0485 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0485), uint64(maxBitmaskSize))
+ return
+ }
+ zb0484, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignApps")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps = bitmask(zb0484)
+ }
+ case "apas":
+ var zb0486 int
+ var zb0487 bool
+ zb0486, zb0487, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignAssets")
+ return
+ }
+ if zb0486 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0486), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ForeignAssets")
+ return
+ }
+ if zb0487 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets) >= zb0486 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets)[:zb0486]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets = make([]assetIndices, zb0486)
+ }
+ for zb0030 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets {
+ var zb0488 int
+ var zb0489 bool
+ zb0488, zb0489, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignAssets", zb0030)
+ return
+ }
+ if zb0488 > transactions.EncodedMaxForeignAssets {
+ err = msgp.ErrOverflow(uint64(zb0488), uint64(transactions.EncodedMaxForeignAssets))
+ err = msgp.WrapError(err, "ForeignAssets", zb0030)
+ return
+ }
+ if zb0489 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030]) >= zb0488 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030])[:zb0488]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] = make(assetIndices, zb0488)
+ }
+ for zb0031 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030][zb0031].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ForeignAssets", zb0030, zb0031)
+ return
+ }
+ }
+ }
+ case "apasbm":
+ {
+ var zb0490 []byte
+ var zb0491 int
+ zb0491, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignAssets")
+ return
+ }
+ if zb0491 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0491), uint64(maxBitmaskSize))
+ return
+ }
+ zb0490, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskForeignAssets")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets = bitmask(zb0490)
+ }
+ case "lnui":
+ var zb0492 int
+ var zb0493 bool
+ zb0492, zb0493, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumUint")
+ return
+ }
+ if zb0492 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0492), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LocalNumUint")
+ return
+ }
+ if zb0493 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint) >= zb0492 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint)[:zb0492]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint = make([]uint64, zb0492)
+ }
+ for zb0032 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint[zb0032], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumUint", zb0032)
+ return
+ }
+ }
+ case "lnuibm":
+ {
+ var zb0494 []byte
+ var zb0495 int
+ zb0495, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumUint")
+ return
+ }
+ if zb0495 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0495), uint64(maxBitmaskSize))
+ return
+ }
+ zb0494, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumUint")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint = bitmask(zb0494)
+ }
+ case "lnbs":
+ var zb0496 int
+ var zb0497 bool
+ zb0496, zb0497, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumByteSlice")
+ return
+ }
+ if zb0496 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0496), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "LocalNumByteSlice")
+ return
+ }
+ if zb0497 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice) >= zb0496 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice)[:zb0496]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice = make([]uint64, zb0496)
+ }
+ for zb0033 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice[zb0033], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "LocalNumByteSlice", zb0033)
+ return
+ }
+ }
+ case "lnbsbm":
+ {
+ var zb0498 []byte
+ var zb0499 int
+ zb0499, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumByteSlice")
+ return
+ }
+ if zb0499 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0499), uint64(maxBitmaskSize))
+ return
+ }
+ zb0498, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskLocalNumByteSlice")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice = bitmask(zb0498)
+ }
+ case "gnui":
+ var zb0500 int
+ var zb0501 bool
+ zb0500, zb0501, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumUint")
+ return
+ }
+ if zb0500 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0500), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "GlobalNumUint")
+ return
+ }
+ if zb0501 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint) >= zb0500 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint)[:zb0500]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint = make([]uint64, zb0500)
+ }
+ for zb0034 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint[zb0034], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumUint", zb0034)
+ return
+ }
+ }
+ case "gnuibm":
+ {
+ var zb0502 []byte
+ var zb0503 int
+ zb0503, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumUint")
+ return
+ }
+ if zb0503 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0503), uint64(maxBitmaskSize))
+ return
+ }
+ zb0502, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumUint")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint = bitmask(zb0502)
+ }
+ case "gnbs":
+ var zb0504 int
+ var zb0505 bool
+ zb0504, zb0505, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumByteSlice")
+ return
+ }
+ if zb0504 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0504), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "GlobalNumByteSlice")
+ return
+ }
+ if zb0505 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice) >= zb0504 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice)[:zb0504]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice = make([]uint64, zb0504)
+ }
+ for zb0035 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice[zb0035], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "GlobalNumByteSlice", zb0035)
+ return
+ }
+ }
+ case "gnbsbm":
+ {
+ var zb0506 []byte
+ var zb0507 int
+ zb0507, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumByteSlice")
+ return
+ }
+ if zb0507 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0507), uint64(maxBitmaskSize))
+ return
+ }
+ zb0506, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskGlobalNumByteSlice")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice = bitmask(zb0506)
+ }
+ case "apap":
+ var zb0508 int
+ var zb0509 bool
+ zb0508, zb0509, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApprovalProgram")
+ return
+ }
+ if zb0508 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0508), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ApprovalProgram")
+ return
+ }
+ if zb0509 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram) >= zb0508 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram)[:zb0508]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram = make([]program, zb0508)
+ }
+ for zb0036 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram {
+ {
+ var zb0510 []byte
+ var zb0511 int
+ zb0511, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ApprovalProgram", zb0036)
+ return
+ }
+ if zb0511 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0511), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0510, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram[zb0036]))
+ if err != nil {
+ err = msgp.WrapError(err, "ApprovalProgram", zb0036)
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram[zb0036] = program(zb0510)
+ }
+ }
+ case "apapbm":
+ {
+ var zb0512 []byte
+ var zb0513 int
+ zb0513, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApprovalProgram")
+ return
+ }
+ if zb0513 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0513), uint64(maxBitmaskSize))
+ return
+ }
+ zb0512, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskApprovalProgram")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram = bitmask(zb0512)
+ }
+ case "apsu":
+ var zb0514 int
+ var zb0515 bool
+ zb0514, zb0515, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ClearStateProgram")
+ return
+ }
+ if zb0514 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0514), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ClearStateProgram")
+ return
+ }
+ if zb0515 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram) >= zb0514 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram)[:zb0514]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram = make([]program, zb0514)
+ }
+ for zb0037 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram {
+ {
+ var zb0516 []byte
+ var zb0517 int
+ zb0517, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ClearStateProgram", zb0037)
+ return
+ }
+ if zb0517 > config.MaxAvailableAppProgramLen {
+ err = msgp.ErrOverflow(uint64(zb0517), uint64(config.MaxAvailableAppProgramLen))
+ return
+ }
+ zb0516, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram[zb0037]))
+ if err != nil {
+ err = msgp.WrapError(err, "ClearStateProgram", zb0037)
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram[zb0037] = program(zb0516)
+ }
+ }
+ case "apsubm":
+ {
+ var zb0518 []byte
+ var zb0519 int
+ zb0519, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClearStateProgram")
+ return
+ }
+ if zb0519 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0519), uint64(maxBitmaskSize))
+ return
+ }
+ zb0518, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskClearStateProgram")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram = bitmask(zb0518)
+ }
+ case "apep":
+ var zb0520 int
+ var zb0521 bool
+ zb0520, zb0521, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExtraProgramPages")
+ return
+ }
+ if zb0520 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0520), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "ExtraProgramPages")
+ return
+ }
+ if zb0521 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages) >= zb0520 {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages = ((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages)[:zb0520]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages = make([]uint32, zb0520)
+ }
+ for zb0038 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages {
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages[zb0038], bts, err = msgp.ReadUint32Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "ExtraProgramPages", zb0038)
+ return
+ }
+ }
+ case "apepbm":
+ {
+ var zb0522 []byte
+ var zb0523 int
+ zb0523, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskExtraProgramPages")
+ return
+ }
+ if zb0523 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0523), uint64(maxBitmaskSize))
+ return
+ }
+ zb0522, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskExtraProgramPages")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages = bitmask(zb0522)
+ }
+ case "certrnd":
+ var zb0524 int
+ var zb0525 bool
+ zb0524, zb0525, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertRound")
+ return
+ }
+ if zb0524 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0524), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "CertRound")
+ return
+ }
+ if zb0525 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound) >= zb0524 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound)[:zb0524]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound = make([]basics.Round, zb0524)
+ }
+ for zb0039 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound[zb0039].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertRound", zb0039)
+ return
+ }
+ }
+ case "certrndbm":
+ {
+ var zb0526 []byte
+ var zb0527 int
+ zb0527, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertRound")
+ return
+ }
+ if zb0527 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0527), uint64(maxBitmaskSize))
+ return
+ }
+ zb0526, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertRound")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound = bitmask(zb0526)
+ }
+ case "certtype":
+ var zb0528 int
+ var zb0529 bool
+ zb0528, zb0529, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertType")
+ return
+ }
+ if zb0528 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0528), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "CertType")
+ return
+ }
+ if zb0529 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType) >= zb0528 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType)[:zb0528]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType = make([]protocol.CompactCertType, zb0528)
+ }
+ for zb0040 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType[zb0040].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "CertType", zb0040)
+ return
+ }
+ }
+ case "certtypebm":
+ {
+ var zb0530 []byte
+ var zb0531 int
+ zb0531, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertType")
+ return
+ }
+ if zb0531 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0531), uint64(maxBitmaskSize))
+ return
+ }
+ zb0530, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertType))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskCertType")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertType = bitmask(zb0530)
+ }
+ case "certc":
+ var zb0532 int
+ zb0532, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigCommit")
+ return
+ }
+ if zb0532 > maxAddressBytes {
+ err = msgp.ErrOverflow(uint64(zb0532), uint64(maxAddressBytes))
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit, bts, err = msgp.ReadBytesBytes(bts, (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit)
+ if err != nil {
+ err = msgp.WrapError(err, "SigCommit")
+ return
+ }
+ case "certcbm":
+ {
+ var zb0533 []byte
+ var zb0534 int
+ zb0534, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigCommit")
+ return
+ }
+ if zb0534 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0534), uint64(maxBitmaskSize))
+ return
+ }
+ zb0533, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigCommit")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit = bitmask(zb0533)
+ }
+ case "certw":
+ var zb0535 int
+ var zb0536 bool
+ zb0535, zb0536, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SignedWeight")
+ return
+ }
+ if zb0535 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0535), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "SignedWeight")
+ return
+ }
+ if zb0536 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight) >= zb0535 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight)[:zb0535]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight = make([]uint64, zb0535)
+ }
+ for zb0041 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight[zb0041], bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SignedWeight", zb0041)
+ return
+ }
+ }
+ case "certwbm":
+ {
+ var zb0537 []byte
+ var zb0538 int
+ zb0538, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSignedWeight")
+ return
+ }
+ if zb0538 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0538), uint64(maxBitmaskSize))
+ return
+ }
+ zb0537, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSignedWeight")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight = bitmask(zb0537)
+ }
+ case "certS":
+ var zb0539 int
+ var zb0540 bool
+ zb0539, zb0540, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs")
+ return
+ }
+ if zb0539 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0539), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "SigProofs")
+ return
+ }
+ if zb0540 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs) >= zb0539 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs)[:zb0539]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs = make([]certProofs, zb0539)
+ }
+ for zb0042 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs {
+ var zb0541 int
+ var zb0542 bool
+ zb0541, zb0542, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs", zb0042)
+ return
+ }
+ if zb0541 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0541), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "SigProofs", zb0042)
+ return
+ }
+ if zb0542 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042]) >= zb0541 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042])[:zb0541]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] = make(certProofs, zb0541)
+ }
+ for zb0043 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042][zb0043].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "SigProofs", zb0042, zb0043)
+ return
+ }
+ }
+ }
+ case "certSbm":
+ {
+ var zb0543 []byte
+ var zb0544 int
+ zb0544, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigProofs")
+ return
+ }
+ if zb0544 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0544), uint64(maxBitmaskSize))
+ return
+ }
+ zb0543, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskSigProofs")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs = bitmask(zb0543)
+ }
+ case "certP":
+ var zb0545 int
+ var zb0546 bool
+ zb0545, zb0546, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs")
+ return
+ }
+ if zb0545 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0545), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "PartProofs")
+ return
+ }
+ if zb0546 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs) >= zb0545 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs)[:zb0545]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs = make([]certProofs, zb0545)
+ }
+ for zb0044 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs {
+ var zb0547 int
+ var zb0548 bool
+ zb0547, zb0548, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs", zb0044)
+ return
+ }
+ if zb0547 > compactcert.MaxProofDigests {
+ err = msgp.ErrOverflow(uint64(zb0547), uint64(compactcert.MaxProofDigests))
+ err = msgp.WrapError(err, "PartProofs", zb0044)
+ return
+ }
+ if zb0548 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044]) >= zb0547 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044])[:zb0547]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] = make(certProofs, zb0547)
+ }
+ for zb0045 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] {
+ bts, err = (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044][zb0045].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "PartProofs", zb0044, zb0045)
+ return
+ }
+ }
+ }
+ case "certPbm":
+ {
+ var zb0549 []byte
+ var zb0550 int
+ zb0550, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskPartProofs")
+ return
+ }
+ if zb0550 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0550), uint64(maxBitmaskSize))
+ return
+ }
+ zb0549, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskPartProofs")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs = bitmask(zb0549)
+ }
+ case "certr":
+ var zb0551 int
+ var zb0552 bool
+ zb0551, zb0552, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals")
+ return
+ }
+ if zb0551 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0551), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "Reveals")
+ return
+ }
+ if zb0552 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals != nil && cap((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals) >= zb0551 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals = ((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals)[:zb0551]
+ } else {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals = make([]revealMap, zb0551)
+ }
+ for zb0046 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals {
+ var zb0553 int
+ var zb0554 bool
+ zb0553, zb0554, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0046)
+ return
+ }
+ if zb0553 > compactcert.MaxReveals {
+ err = msgp.ErrOverflow(uint64(zb0553), uint64(compactcert.MaxReveals))
+ err = msgp.WrapError(err, "Reveals", zb0046)
+ return
+ }
+ if zb0554 {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] = nil
+ } else if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] == nil {
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] = make(revealMap, zb0553)
+ }
+ for zb0553 > 0 {
+ var zb0047 uint64
+ var zb0048 compactcert.Reveal
+ zb0553--
+ zb0047, bts, err = msgp.ReadUint64Bytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0046)
+ return
+ }
+ bts, err = zb0048.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "Reveals", zb0046, zb0047)
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046][zb0047] = zb0048
+ }
+ }
+ case "certrbm":
+ {
+ var zb0555 []byte
+ var zb0556 int
+ zb0556, err = msgp.ReadBytesBytesHeader(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReveals")
+ return
+ }
+ if zb0556 > maxBitmaskSize {
+ err = msgp.ErrOverflow(uint64(zb0556), uint64(maxBitmaskSize))
+ return
+ }
+ zb0555, bts, err = msgp.ReadBytesBytes(bts, []byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals))
+ if err != nil {
+ err = msgp.WrapError(err, "BitmaskReveals")
+ return
+ }
+ (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals = bitmask(zb0555)
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *txGroupsEncodingStub) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*txGroupsEncodingStub)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *txGroupsEncodingStub) Msgsize() (s int) {
+ s = 3 + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size + 4 + msgp.BytesPrefixSize + len((*z).TransactionGroupSizes) + 4 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.Sig) + 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.BitmaskSig)) + 6 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedMsigs.Version) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedMsigs.BitmaskVersion)) + 8 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedMsigs.Threshold) + 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedMsigs.BitmaskThreshold)) + 7 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).encodedSignedTxns.encodedMsigs.Subsigs {
+ s += msgp.ArrayHeaderSize
+ for zb0002 := range (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001] {
+ s += (*z).encodedSignedTxns.encodedMsigs.Subsigs[zb0001][zb0002].Msgsize()
+ }
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedMsigs.BitmaskSubsigs)) + 6 + msgp.ArrayHeaderSize
+ for zb0003 := range (*z).encodedSignedTxns.encodedLsigs.Logic {
+ s += msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedLsigs.Logic[zb0003])
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedLsigs.BitmaskLogic)) + 8 + msgp.ArrayHeaderSize
+ for zb0004 := range (*z).encodedSignedTxns.encodedLsigs.LogicArgs {
+ s += msgp.ArrayHeaderSize
+ for zb0005 := range (*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004] {
+ s += msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedLsigs.LogicArgs[zb0004][zb0005])
+ }
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedLsigs.BitmaskLogicArgs)) + 5 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.AuthAddr) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.BitmaskAuthAddr)) + 5 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.TxType) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.BitmaskTxType)) + 6 + msgp.ByteSize + 4 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Sender) + 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskSender)) + 4 + msgp.ArrayHeaderSize
+ for zb0006 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee[zb0006].Msgsize()
+ }
+ s += 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFee)) + 3 + msgp.ArrayHeaderSize
+ for zb0007 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid[zb0007].Msgsize()
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFirstValid)) + 3 + msgp.ArrayHeaderSize
+ for zb0008 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid[zb0008].Msgsize()
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLastValid)) + 5 + msgp.ArrayHeaderSize
+ for zb0009 := range (*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note {
+ s += msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note[zb0009])
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskNote)) + 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGenesisID)) + 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGroup)) + 3 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Lease) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLease)) + 6 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.RekeyTo) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskRekeyTo)) + 8 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VotePK) + 7 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.SelectionPK) + 8 + msgp.ArrayHeaderSize
+ for zb0010 := range (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst[zb0010].Msgsize()
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst)) + 8 + msgp.ArrayHeaderSize
+ for zb0011 := range (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast[zb0011].Msgsize()
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast)) + 7 + msgp.ArrayHeaderSize + (len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution) * (msgp.Uint64Size)) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskKeys)) + 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation)) + 4 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Receiver) + 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskReceiver)) + 4 + msgp.ArrayHeaderSize
+ for zb0013 := range (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount[zb0013].Msgsize()
+ }
+ s += 6 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskAmount)) + 6 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.CloseRemainderTo) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo)) + 5 + msgp.ArrayHeaderSize
+ for zb0014 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset[zb0014].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset)) + 2 + msgp.ArrayHeaderSize + (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total) * (msgp.Uint64Size)) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal)) + 3 + msgp.ArrayHeaderSize + (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals) * (msgp.Uint32Size)) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals)) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen)) + 3 + msgp.ArrayHeaderSize
+ for zb0017 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName {
+ s += msgp.StringPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName[zb0017])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName)) + 3 + msgp.ArrayHeaderSize
+ for zb0018 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName {
+ s += msgp.StringPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName[zb0018])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName)) + 3 + msgp.ArrayHeaderSize
+ for zb0019 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL {
+ s += msgp.StringPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL[zb0019])
+ }
+ s += 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL)) + 3 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash) + 5 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash)) + 2 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager)) + 2 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve)) + 2 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze)) + 2 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback) + 4 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback)) + 5 + msgp.ArrayHeaderSize
+ for zb0020 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset[zb0020].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount)) + 5 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetSender) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender)) + 5 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetReceiver) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver)) + 7 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo) + 9 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo)) + 5 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount)) + 5 + msgp.ArrayHeaderSize
+ for zb0022 := range (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset[zb0022].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen)) + 5 + msgp.ArrayHeaderSize
+ for zb0023 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID[zb0023].Msgsize()
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID)) + 5 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.OnCompletion) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion)) + 5 + msgp.ArrayHeaderSize
+ for zb0024 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs {
+ s += msgp.ArrayHeaderSize
+ for zb0025 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024] {
+ s += msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs[zb0024][zb0025])
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs)) + 5 + msgp.ArrayHeaderSize
+ for zb0026 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts {
+ s += msgp.ArrayHeaderSize
+ for zb0027 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026] {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts[zb0026][zb0027].Msgsize()
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts)) + 5 + msgp.ArrayHeaderSize
+ for zb0028 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps {
+ s += msgp.ArrayHeaderSize
+ for zb0029 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028] {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps[zb0028][zb0029].Msgsize()
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps)) + 5 + msgp.ArrayHeaderSize
+ for zb0030 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets {
+ s += msgp.ArrayHeaderSize
+ for zb0031 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030] {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets[zb0030][zb0031].Msgsize()
+ }
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice) * (msgp.Uint64Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice)) + 5 + msgp.ArrayHeaderSize
+ for zb0036 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram {
+ s += msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram[zb0036]))
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram)) + 5 + msgp.ArrayHeaderSize
+ for zb0037 := range (*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram {
+ s += msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram[zb0037]))
+ }
+ s += 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram)) + 5 + msgp.ArrayHeaderSize + (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages) * (msgp.Uint32Size)) + 7 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages)) + 8 + msgp.ArrayHeaderSize
+ for zb0039 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound[zb0039].Msgsize()
+ }
+ s += 10 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound)) + 9 + msgp.ArrayHeaderSize
+ for zb0040 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType[zb0040].Msgsize()
+ }
+ s += 11 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertType)) + 6 + msgp.BytesPrefixSize + len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit)) + 6 + msgp.ArrayHeaderSize + (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight) * (msgp.Uint64Size)) + 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight)) + 6 + msgp.ArrayHeaderSize
+ for zb0042 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs {
+ s += msgp.ArrayHeaderSize
+ for zb0043 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042] {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs[zb0042][zb0043].Msgsize()
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs)) + 6 + msgp.ArrayHeaderSize
+ for zb0044 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs {
+ s += msgp.ArrayHeaderSize
+ for zb0045 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044] {
+ s += (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs[zb0044][zb0045].Msgsize()
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs)) + 6 + msgp.ArrayHeaderSize
+ for zb0046 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals {
+ s += msgp.MapHeaderSize
+ if (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] != nil {
+ for zb0047, zb0048 := range (*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals[zb0046] {
+ _ = zb0047
+ _ = zb0048
+ s += 0 + msgp.Uint64Size + zb0048.Msgsize()
+ }
+ }
+ }
+ s += 8 + msgp.BytesPrefixSize + len([]byte((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals))
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *txGroupsEncodingStub) MsgIsZero() bool {
+ return ((*z).TotalTransactionsCount == 0) && ((*z).TransactionGroupCount == 0) && (len((*z).TransactionGroupSizes) == 0) && (len((*z).encodedSignedTxns.Sig) == 0) && (len((*z).encodedSignedTxns.BitmaskSig) == 0) && (len((*z).encodedSignedTxns.encodedMsigs.Version) == 0) && (len((*z).encodedSignedTxns.encodedMsigs.BitmaskVersion) == 0) && (len((*z).encodedSignedTxns.encodedMsigs.Threshold) == 0) && (len((*z).encodedSignedTxns.encodedMsigs.BitmaskThreshold) == 0) && (len((*z).encodedSignedTxns.encodedMsigs.Subsigs) == 0) && (len((*z).encodedSignedTxns.encodedMsigs.BitmaskSubsigs) == 0) && (len((*z).encodedSignedTxns.encodedLsigs.Logic) == 0) && (len((*z).encodedSignedTxns.encodedLsigs.BitmaskLogic) == 0) && (len((*z).encodedSignedTxns.encodedLsigs.LogicArgs) == 0) && (len((*z).encodedSignedTxns.encodedLsigs.BitmaskLogicArgs) == 0) && (len((*z).encodedSignedTxns.AuthAddr) == 0) && (len((*z).encodedSignedTxns.BitmaskAuthAddr) == 0) && (len((*z).encodedSignedTxns.encodedTxns.TxType) == 0) && (len((*z).encodedSignedTxns.encodedTxns.BitmaskTxType) == 0) && ((*z).encodedSignedTxns.encodedTxns.TxTypeOffset == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Sender) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskSender) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Fee) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFee) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.FirstValid) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskFirstValid) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.LastValid) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLastValid) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Note) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskNote) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGenesisID) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskGroup) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.Lease) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskLease) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.RekeyTo) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedTxnHeaders.BitmaskRekeyTo) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VotePK) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.SelectionPK) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteFirst) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteFirst) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteLast) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskVoteLast) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.VoteKeyDilution) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskKeys) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedKeyregTxnFields.BitmaskNonparticipation) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Receiver) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskReceiver) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.Amount) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskAmount) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.CloseRemainderTo) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedPaymentTxnFields.BitmaskCloseRemainderTo) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.ConfigAsset) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.BitmaskConfigAsset) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Total) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskTotal) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Decimals) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDecimals) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskDefaultFrozen) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.UnitName) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskUnitName) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.AssetName) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskAssetName) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.URL) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskURL) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.MetadataHash) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskMetadataHash) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Manager) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskManager) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Reserve) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskReserve) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Freeze) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskFreeze) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.Clawback) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetConfigTxnFields.encodedAssetParams.BitmaskClawback) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.XferAsset) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskXferAsset) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetAmount) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetAmount) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetSender) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetSender) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetReceiver) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetReceiver) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.AssetCloseTo) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetTransferTxnFields.BitmaskAssetCloseTo) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAccount) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAccount) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.FreezeAsset) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskFreezeAsset) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedAssetFreezeTxnFields.BitmaskAssetFrozen) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationID) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationID) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.OnCompletion) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskOnCompletion) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApplicationArgs) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApplicationArgs) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.Accounts) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskAccounts) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignApps) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignApps) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ForeignAssets) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskForeignAssets) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumUint) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumUint) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.LocalNumByteSlice) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskLocalNumByteSlice) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumUint) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumUint) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.GlobalNumByteSlice) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskGlobalNumByteSlice) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ApprovalProgram) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskApprovalProgram) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ClearStateProgram) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskClearStateProgram) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.ExtraProgramPages) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedApplicationCallTxnFields.BitmaskExtraProgramPages) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertRound) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertRound) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.CertType) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.BitmaskCertType) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigCommit) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigCommit) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SignedWeight) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSignedWeight) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.SigProofs) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskSigProofs) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.PartProofs) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskPartProofs) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.Reveals) == 0) && (len((*z).encodedSignedTxns.encodedTxns.encodedCompactCertTxnFields.encodedCert.BitmaskReveals) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *txGroupsEncodingStubOld) MarshalMsg(b []byte) (o []byte) {
+ o = msgp.Require(b, z.Msgsize())
+ // omitempty: check for empty values
+ zb0002Len := uint32(1)
+ var zb0002Mask uint8 /* 2 bits */
+ if len((*z).TxnGroups) == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x2
+ }
+ // variable map header, size zb0002Len
+ o = append(o, 0x80|uint8(zb0002Len))
+ if zb0002Len != 0 {
+ if (zb0002Mask & 0x2) == 0 { // if not empty
+ // string "t"
+ o = append(o, 0xa1, 0x74)
+ if (*z).TxnGroups == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o = msgp.AppendArrayHeader(o, uint32(len((*z).TxnGroups)))
+ }
+ for zb0001 := range (*z).TxnGroups {
+ o = (*z).TxnGroups[zb0001].MarshalMsg(o)
+ }
+ }
+ }
+ return
+}
+
+func (_ *txGroupsEncodingStubOld) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*txGroupsEncodingStubOld)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *txGroupsEncodingStubOld) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var field []byte
+ _ = field
+ var zb0002 int
+ var zb0003 bool
+ zb0002, zb0003, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if _, ok := err.(msgp.TypeError); ok {
+ zb0002, zb0003, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0002 > 0 {
+ zb0002--
+ var zb0004 int
+ var zb0005 bool
+ zb0004, zb0005, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TxnGroups")
+ return
+ }
+ if zb0004 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0004), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "struct-from-array", "TxnGroups")
+ return
+ }
+ if zb0005 {
+ (*z).TxnGroups = nil
+ } else if (*z).TxnGroups != nil && cap((*z).TxnGroups) >= zb0004 {
+ (*z).TxnGroups = ((*z).TxnGroups)[:zb0004]
+ } else {
+ (*z).TxnGroups = make([]txnGroups, zb0004)
+ }
+ for zb0001 := range (*z).TxnGroups {
+ bts, err = (*z).TxnGroups[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "TxnGroups", zb0001)
+ return
+ }
+ }
+ }
+ if zb0002 > 0 {
+ err = msgp.ErrTooManyArrayFields(zb0002)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array")
+ return
+ }
+ }
+ } else {
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0003 {
+ (*z) = txGroupsEncodingStubOld{}
+ }
+ for zb0002 > 0 {
+ zb0002--
+ field, bts, err = msgp.ReadMapKeyZC(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ switch string(field) {
+ case "t":
+ var zb0006 int
+ var zb0007 bool
+ zb0006, zb0007, bts, err = msgp.ReadArrayHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "TxnGroups")
+ return
+ }
+ if zb0006 > maxEncodedTransactionGroups {
+ err = msgp.ErrOverflow(uint64(zb0006), uint64(maxEncodedTransactionGroups))
+ err = msgp.WrapError(err, "TxnGroups")
+ return
+ }
+ if zb0007 {
+ (*z).TxnGroups = nil
+ } else if (*z).TxnGroups != nil && cap((*z).TxnGroups) >= zb0006 {
+ (*z).TxnGroups = ((*z).TxnGroups)[:zb0006]
+ } else {
+ (*z).TxnGroups = make([]txnGroups, zb0006)
+ }
+ for zb0001 := range (*z).TxnGroups {
+ bts, err = (*z).TxnGroups[zb0001].UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "TxnGroups", zb0001)
+ return
+ }
+ }
+ default:
+ err = msgp.ErrNoField(string(field))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ }
+ }
+ }
+ o = bts
+ return
+}
+
+func (_ *txGroupsEncodingStubOld) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*txGroupsEncodingStubOld)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *txGroupsEncodingStubOld) Msgsize() (s int) {
+ s = 1 + 2 + msgp.ArrayHeaderSize
+ for zb0001 := range (*z).TxnGroups {
+ s += (*z).TxnGroups[zb0001].Msgsize()
+ }
+ return
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *txGroupsEncodingStubOld) MsgIsZero() bool {
+ return (len((*z).TxnGroups) == 0)
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z *txnGroups) MarshalMsg(b []byte) []byte {
+ return ((*(pooldata.SignedTxnSlice))(z)).MarshalMsg(b)
+}
+func (_ *txnGroups) CanMarshalMsg(z interface{}) bool {
+ _, ok := (z).(*txnGroups)
+ return ok
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *txnGroups) UnmarshalMsg(bts []byte) ([]byte, error) {
+ return ((*(pooldata.SignedTxnSlice))(z)).UnmarshalMsg(bts)
+}
+func (_ *txnGroups) CanUnmarshalMsg(z interface{}) bool {
+ _, ok := (z).(*txnGroups)
+ return ok
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z *txnGroups) Msgsize() int {
+ return ((*(pooldata.SignedTxnSlice))(z)).Msgsize()
+}
+
+// MsgIsZero returns whether this is a zero value
+func (z *txnGroups) MsgIsZero() bool {
+ return ((*(pooldata.SignedTxnSlice))(z)).MsgIsZero()
+}
diff --git a/txnsync/msgp_gen_test.go b/txnsync/msgp_gen_test.go
new file mode 100644
index 000000000..95b7d2451
--- /dev/null
+++ b/txnsync/msgp_gen_test.go
@@ -0,0 +1,1693 @@
+// +build !skip_msgp_testing
+
+package txnsync
+
+// Code generated by github.com/algorand/msgp DO NOT EDIT.
+
+import (
+ "testing"
+
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/algorand/msgp/msgp"
+)
+
+func TestMarshalUnmarshaladdresses(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := addresses{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingaddresses(t *testing.T) {
+ protocol.RunEncodingTest(t, &addresses{})
+}
+
+func BenchmarkMarshalMsgaddresses(b *testing.B) {
+ v := addresses{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgaddresses(b *testing.B) {
+ v := addresses{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshaladdresses(b *testing.B) {
+ v := addresses{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalappIndices(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := appIndices{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingappIndices(t *testing.T) {
+ protocol.RunEncodingTest(t, &appIndices{})
+}
+
+func BenchmarkMarshalMsgappIndices(b *testing.B) {
+ v := appIndices{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgappIndices(b *testing.B) {
+ v := appIndices{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalappIndices(b *testing.B) {
+ v := appIndices{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalapplicationArgs(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := applicationArgs{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingapplicationArgs(t *testing.T) {
+ protocol.RunEncodingTest(t, &applicationArgs{})
+}
+
+func BenchmarkMarshalMsgapplicationArgs(b *testing.B) {
+ v := applicationArgs{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgapplicationArgs(b *testing.B) {
+ v := applicationArgs{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalapplicationArgs(b *testing.B) {
+ v := applicationArgs{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalassetIndices(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := assetIndices{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingassetIndices(t *testing.T) {
+ protocol.RunEncodingTest(t, &assetIndices{})
+}
+
+func BenchmarkMarshalMsgassetIndices(b *testing.B) {
+ v := assetIndices{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgassetIndices(b *testing.B) {
+ v := assetIndices{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalassetIndices(b *testing.B) {
+ v := assetIndices{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalcertProofs(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := certProofs{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingcertProofs(t *testing.T) {
+ protocol.RunEncodingTest(t, &certProofs{})
+}
+
+func BenchmarkMarshalMsgcertProofs(b *testing.B) {
+ v := certProofs{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgcertProofs(b *testing.B) {
+ v := certProofs{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalcertProofs(b *testing.B) {
+ v := certProofs{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedApplicationCallTxnFields(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedApplicationCallTxnFields{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedApplicationCallTxnFields(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedApplicationCallTxnFields{})
+}
+
+func BenchmarkMarshalMsgencodedApplicationCallTxnFields(b *testing.B) {
+ v := encodedApplicationCallTxnFields{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedApplicationCallTxnFields(b *testing.B) {
+ v := encodedApplicationCallTxnFields{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedApplicationCallTxnFields(b *testing.B) {
+ v := encodedApplicationCallTxnFields{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedAssetConfigTxnFields(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedAssetConfigTxnFields{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedAssetConfigTxnFields(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedAssetConfigTxnFields{})
+}
+
+func BenchmarkMarshalMsgencodedAssetConfigTxnFields(b *testing.B) {
+ v := encodedAssetConfigTxnFields{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedAssetConfigTxnFields(b *testing.B) {
+ v := encodedAssetConfigTxnFields{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedAssetConfigTxnFields(b *testing.B) {
+ v := encodedAssetConfigTxnFields{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedAssetFreezeTxnFields(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedAssetFreezeTxnFields{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedAssetFreezeTxnFields(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedAssetFreezeTxnFields{})
+}
+
+func BenchmarkMarshalMsgencodedAssetFreezeTxnFields(b *testing.B) {
+ v := encodedAssetFreezeTxnFields{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedAssetFreezeTxnFields(b *testing.B) {
+ v := encodedAssetFreezeTxnFields{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedAssetFreezeTxnFields(b *testing.B) {
+ v := encodedAssetFreezeTxnFields{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedAssetParams(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedAssetParams{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedAssetParams(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedAssetParams{})
+}
+
+func BenchmarkMarshalMsgencodedAssetParams(b *testing.B) {
+ v := encodedAssetParams{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedAssetParams(b *testing.B) {
+ v := encodedAssetParams{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedAssetParams(b *testing.B) {
+ v := encodedAssetParams{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedAssetTransferTxnFields(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedAssetTransferTxnFields{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedAssetTransferTxnFields(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedAssetTransferTxnFields{})
+}
+
+func BenchmarkMarshalMsgencodedAssetTransferTxnFields(b *testing.B) {
+ v := encodedAssetTransferTxnFields{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedAssetTransferTxnFields(b *testing.B) {
+ v := encodedAssetTransferTxnFields{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedAssetTransferTxnFields(b *testing.B) {
+ v := encodedAssetTransferTxnFields{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedBloomFilter(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedBloomFilter{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedBloomFilter(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedBloomFilter{})
+}
+
+func BenchmarkMarshalMsgencodedBloomFilter(b *testing.B) {
+ v := encodedBloomFilter{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedBloomFilter(b *testing.B) {
+ v := encodedBloomFilter{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedBloomFilter(b *testing.B) {
+ v := encodedBloomFilter{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedCert(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedCert{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedCert(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedCert{})
+}
+
+func BenchmarkMarshalMsgencodedCert(b *testing.B) {
+ v := encodedCert{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedCert(b *testing.B) {
+ v := encodedCert{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedCert(b *testing.B) {
+ v := encodedCert{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedCompactCertTxnFields(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedCompactCertTxnFields{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedCompactCertTxnFields(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedCompactCertTxnFields{})
+}
+
+func BenchmarkMarshalMsgencodedCompactCertTxnFields(b *testing.B) {
+ v := encodedCompactCertTxnFields{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedCompactCertTxnFields(b *testing.B) {
+ v := encodedCompactCertTxnFields{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedCompactCertTxnFields(b *testing.B) {
+ v := encodedCompactCertTxnFields{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedKeyregTxnFields(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedKeyregTxnFields{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedKeyregTxnFields(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedKeyregTxnFields{})
+}
+
+func BenchmarkMarshalMsgencodedKeyregTxnFields(b *testing.B) {
+ v := encodedKeyregTxnFields{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedKeyregTxnFields(b *testing.B) {
+ v := encodedKeyregTxnFields{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedKeyregTxnFields(b *testing.B) {
+ v := encodedKeyregTxnFields{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedLsigs(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedLsigs{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedLsigs(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedLsigs{})
+}
+
+func BenchmarkMarshalMsgencodedLsigs(b *testing.B) {
+ v := encodedLsigs{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedLsigs(b *testing.B) {
+ v := encodedLsigs{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedLsigs(b *testing.B) {
+ v := encodedLsigs{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedMsigs(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedMsigs{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedMsigs(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedMsigs{})
+}
+
+func BenchmarkMarshalMsgencodedMsigs(b *testing.B) {
+ v := encodedMsigs{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedMsigs(b *testing.B) {
+ v := encodedMsigs{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedMsigs(b *testing.B) {
+ v := encodedMsigs{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedPaymentTxnFields(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedPaymentTxnFields{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedPaymentTxnFields(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedPaymentTxnFields{})
+}
+
+func BenchmarkMarshalMsgencodedPaymentTxnFields(b *testing.B) {
+ v := encodedPaymentTxnFields{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedPaymentTxnFields(b *testing.B) {
+ v := encodedPaymentTxnFields{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedPaymentTxnFields(b *testing.B) {
+ v := encodedPaymentTxnFields{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedSignedTxns(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedSignedTxns{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedSignedTxns(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedSignedTxns{})
+}
+
+func BenchmarkMarshalMsgencodedSignedTxns(b *testing.B) {
+ v := encodedSignedTxns{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedSignedTxns(b *testing.B) {
+ v := encodedSignedTxns{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedSignedTxns(b *testing.B) {
+ v := encodedSignedTxns{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedTxnHeaders(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedTxnHeaders{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedTxnHeaders(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedTxnHeaders{})
+}
+
+func BenchmarkMarshalMsgencodedTxnHeaders(b *testing.B) {
+ v := encodedTxnHeaders{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedTxnHeaders(b *testing.B) {
+ v := encodedTxnHeaders{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedTxnHeaders(b *testing.B) {
+ v := encodedTxnHeaders{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalencodedTxns(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := encodedTxns{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingencodedTxns(t *testing.T) {
+ protocol.RunEncodingTest(t, &encodedTxns{})
+}
+
+func BenchmarkMarshalMsgencodedTxns(b *testing.B) {
+ v := encodedTxns{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgencodedTxns(b *testing.B) {
+ v := encodedTxns{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalencodedTxns(b *testing.B) {
+ v := encodedTxns{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalpackedTransactionGroups(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := packedTransactionGroups{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingpackedTransactionGroups(t *testing.T) {
+ protocol.RunEncodingTest(t, &packedTransactionGroups{})
+}
+
+func BenchmarkMarshalMsgpackedTransactionGroups(b *testing.B) {
+ v := packedTransactionGroups{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgpackedTransactionGroups(b *testing.B) {
+ v := packedTransactionGroups{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalpackedTransactionGroups(b *testing.B) {
+ v := packedTransactionGroups{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalrelayedProposal(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := relayedProposal{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingrelayedProposal(t *testing.T) {
+ protocol.RunEncodingTest(t, &relayedProposal{})
+}
+
+func BenchmarkMarshalMsgrelayedProposal(b *testing.B) {
+ v := relayedProposal{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgrelayedProposal(b *testing.B) {
+ v := relayedProposal{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalrelayedProposal(b *testing.B) {
+ v := relayedProposal{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalrequestParams(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := requestParams{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingrequestParams(t *testing.T) {
+ protocol.RunEncodingTest(t, &requestParams{})
+}
+
+func BenchmarkMarshalMsgrequestParams(b *testing.B) {
+ v := requestParams{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgrequestParams(b *testing.B) {
+ v := requestParams{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalrequestParams(b *testing.B) {
+ v := requestParams{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshalrevealMap(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := revealMap{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingrevealMap(t *testing.T) {
+ protocol.RunEncodingTest(t, &revealMap{})
+}
+
+func BenchmarkMarshalMsgrevealMap(b *testing.B) {
+ v := revealMap{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgrevealMap(b *testing.B) {
+ v := revealMap{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshalrevealMap(b *testing.B) {
+ v := revealMap{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshaltimingParams(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := timingParams{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingtimingParams(t *testing.T) {
+ protocol.RunEncodingTest(t, &timingParams{})
+}
+
+func BenchmarkMarshalMsgtimingParams(b *testing.B) {
+ v := timingParams{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgtimingParams(b *testing.B) {
+ v := timingParams{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshaltimingParams(b *testing.B) {
+ v := timingParams{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshaltransactionBlockMessage(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := transactionBlockMessage{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingtransactionBlockMessage(t *testing.T) {
+ protocol.RunEncodingTest(t, &transactionBlockMessage{})
+}
+
+func BenchmarkMarshalMsgtransactionBlockMessage(b *testing.B) {
+ v := transactionBlockMessage{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgtransactionBlockMessage(b *testing.B) {
+ v := transactionBlockMessage{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshaltransactionBlockMessage(b *testing.B) {
+ v := transactionBlockMessage{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshaltxGroupsEncodingStub(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := txGroupsEncodingStub{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingtxGroupsEncodingStub(t *testing.T) {
+ protocol.RunEncodingTest(t, &txGroupsEncodingStub{})
+}
+
+func BenchmarkMarshalMsgtxGroupsEncodingStub(b *testing.B) {
+ v := txGroupsEncodingStub{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgtxGroupsEncodingStub(b *testing.B) {
+ v := txGroupsEncodingStub{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshaltxGroupsEncodingStub(b *testing.B) {
+ v := txGroupsEncodingStub{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func TestMarshalUnmarshaltxGroupsEncodingStubOld(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ v := txGroupsEncodingStubOld{}
+ bts := v.MarshalMsg(nil)
+ left, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
+ }
+
+ left, err = msgp.Skip(bts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(left) > 0 {
+ t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
+ }
+}
+
+func TestRandomizedEncodingtxGroupsEncodingStubOld(t *testing.T) {
+ protocol.RunEncodingTest(t, &txGroupsEncodingStubOld{})
+}
+
+func BenchmarkMarshalMsgtxGroupsEncodingStubOld(b *testing.B) {
+ v := txGroupsEncodingStubOld{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.MarshalMsg(nil)
+ }
+}
+
+func BenchmarkAppendMsgtxGroupsEncodingStubOld(b *testing.B) {
+ v := txGroupsEncodingStubOld{}
+ bts := make([]byte, 0, v.Msgsize())
+ bts = v.MarshalMsg(bts[0:0])
+ b.SetBytes(int64(len(bts)))
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bts = v.MarshalMsg(bts[0:0])
+ }
+}
+
+func BenchmarkUnmarshaltxGroupsEncodingStubOld(b *testing.B) {
+ v := txGroupsEncodingStubOld{}
+ bts := v.MarshalMsg(nil)
+ b.ReportAllocs()
+ b.SetBytes(int64(len(bts)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := v.UnmarshalMsg(bts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
diff --git a/txnsync/outgoing.go b/txnsync/outgoing.go
new file mode 100644
index 000000000..98697f311
--- /dev/null
+++ b/txnsync/outgoing.go
@@ -0,0 +1,334 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "context"
+ "errors"
+ "sort"
+ "time"
+
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/util/timers"
+)
+
+const messageTimeWindow = 20 * time.Millisecond
+
+var errTransactionSyncOutgoingMessageQueueFull = errors.New("transaction sync outgoing message queue is full")
+var errTransactionSyncOutgoingMessageSendFailed = errors.New("transaction sync failed to send message")
+
+// sentMessageMetadata is the message metadata for a message that is being sent. It includes some extra
+// pieces of information about the message itself, used for tracking the "content" of the message beyond
+// the point where it's being encoded.
+type sentMessageMetadata struct {
+ encodedMessageSize int
+ sentTransactionsIDs []transactions.Txid
+ message *transactionBlockMessage
+ peer *Peer
+ sentTimestamp time.Duration
+ sequenceNumber uint64
+ partialMessage bool
+ transactionGroups []pooldata.SignedTxGroup
+ projectedSequenceNumber uint64
+}
+
+// messageAsyncEncoder structure encapsulates the encoding and sending of a given message to the network. The encoding
+// could be a lengthy operation which does't need to be blocking the main loop. Moving the actual encoding into an
+// execution pool thread frees up the main loop, allowing smoother operation.
+type messageAsyncEncoder struct {
+ state *syncState
+ messageData sentMessageMetadata
+ roundClock timers.WallClock
+ peerDataExchangeRate uint64
+}
+
+// asyncMessageSent called via the network package to inform the txsync that a message was enqueued, and the associated sequence number.
+func (encoder *messageAsyncEncoder) asyncMessageSent(enqueued bool, sequenceNumber uint64) error {
+ if !enqueued {
+ encoder.state.log.Infof("unable to send message to peer. disconnecting from peer.")
+ return errTransactionSyncOutgoingMessageSendFailed
+ }
+ // record the sequence number here, so that we can store that later on.
+ encoder.messageData.sequenceNumber = sequenceNumber
+
+ select {
+ case encoder.state.outgoingMessagesCallbackCh <- encoder.messageData:
+ return nil
+ default:
+ // if we can't place it on the channel, return an error so that the node could disconnect from this peer.
+ encoder.state.log.Infof("unable to enqueue outgoing message confirmation; outgoingMessagesCallbackCh is full. disconnecting from peer.")
+ return errTransactionSyncOutgoingMessageQueueFull
+ }
+}
+
+// asyncEncodeAndSend encodes transaction groups and sends peer message asynchronously
+func (encoder *messageAsyncEncoder) asyncEncodeAndSend(interface{}) interface{} {
+ defer encoder.state.messageSendWaitGroup.Done()
+
+ var err error
+ if len(encoder.messageData.transactionGroups) > 0 {
+ encoder.messageData.message.TransactionGroups, err = encoder.state.encodeTransactionGroups(encoder.messageData.transactionGroups, encoder.peerDataExchangeRate)
+ if err != nil {
+ encoder.state.log.Warnf("unable to encode transaction groups : %v", err)
+ }
+ encoder.messageData.transactionGroups = nil // clear out to allow GC to reclaim
+ }
+
+ encodedMessage := encoder.messageData.message.MarshalMsg(getMessageBuffer())
+ encoder.messageData.encodedMessageSize = len(encodedMessage)
+ // now that the message is ready, we can discard the encoded transaction group slice to allow the GC to collect it.
+ releaseEncodedTransactionGroups(encoder.messageData.message.TransactionGroups.Bytes)
+ // record the timestamp here, before sending the raw bytes to the network :
+ // the time we spend on the network package might include the network processing time, which
+ // we want to make sure we avoid.
+ encoder.messageData.sentTimestamp = encoder.roundClock.Since()
+
+ encoder.state.node.SendPeerMessage(encoder.messageData.peer.networkPeer, encodedMessage, encoder.asyncMessageSent)
+ releaseMessageBuffer(encodedMessage)
+
+ encoder.messageData.message.TransactionGroups.Bytes = nil
+ // increase the metric for total messages sent.
+ txsyncOutgoingMessagesTotal.Inc(nil)
+ return nil
+}
+
+// enqueue add the given message encoding task to the execution pool, and increase the waitgroup as needed.
+func (encoder *messageAsyncEncoder) enqueue() {
+ encoder.state.messageSendWaitGroup.Add(1)
+ if err := encoder.state.threadpool.EnqueueBacklog(context.Background(), encoder.asyncEncodeAndSend, nil, nil); err != nil {
+ encoder.state.messageSendWaitGroup.Done()
+ }
+}
+
+// pendingTransactionGroupsSnapshot is used to represent a snapshot of a pending transaction groups along with the latestLocallyOriginatedGroupCounter value.
+// The goal is to ensure we're "capturing" this only once per `sendMessageLoop` call. In order to do so, we allocate that structure on the stack, and passing
+// a pointer to that structure downstream.
+type pendingTransactionGroupsSnapshot struct {
+ pendingTransactionsGroups []pooldata.SignedTxGroup
+ latestLocallyOriginatedGroupCounter uint64
+}
+
+func (s *syncState) sendMessageLoop(currentTime time.Duration, deadline timers.DeadlineMonitor, peers []*Peer) {
+ if len(peers) == 0 {
+ // no peers - no messages that need to be sent.
+ return
+ }
+ var pendingTransactions pendingTransactionGroupsSnapshot
+ profGetTxnsGroups := s.profiler.getElement(profElementGetTxnsGroups)
+ profAssembleMessage := s.profiler.getElement(profElementAssembleMessage)
+ var assembledBloomFilter bloomFilter
+ profGetTxnsGroups.start()
+ pendingTransactions.pendingTransactionsGroups, pendingTransactions.latestLocallyOriginatedGroupCounter = s.node.GetPendingTransactionGroups()
+ profGetTxnsGroups.end()
+ for _, peer := range peers {
+ msgEncoder := &messageAsyncEncoder{state: s, roundClock: s.clock, peerDataExchangeRate: peer.dataExchangeRate}
+ profAssembleMessage.start()
+ msgEncoder.messageData, assembledBloomFilter = s.assemblePeerMessage(peer, &pendingTransactions)
+ profAssembleMessage.end()
+ isPartialMessage := msgEncoder.messageData.partialMessage
+ // The message that we've just encoded is expected to be sent out with the next sequence number.
+ // However, since the enqueue method is using the execution pool, there is a remote chance that we
+ // would "garble" the message ordering. That's not a huge issue, but we need to be able to tell that
+ // so we can have accurate elapsed time measurements for the data exchange rate calculations.
+ msgEncoder.messageData.projectedSequenceNumber = peer.lastSentMessageSequenceNumber + 1
+ msgEncoder.enqueue()
+
+ // update the bloom filter right here, since we want to make sure the peer contains the
+ // correct sent bloom filter, regardless of the message sending timing. If and when we
+ // generate the next message, we need to ensure that we're aware of this bloom filter, since
+ // it would affect whether we re-generate another bloom filter or not.
+ peer.updateSentBoomFilter(assembledBloomFilter, s.round)
+
+ scheduleOffset, ops := peer.getNextScheduleOffset(s.isRelay, s.lastBeta, isPartialMessage, currentTime)
+ if (ops & peerOpsSetInterruptible) == peerOpsSetInterruptible {
+ if _, has := s.interruptablePeersMap[peer]; !has {
+ s.interruptablePeers = append(s.interruptablePeers, peer)
+ s.interruptablePeersMap[peer] = len(s.interruptablePeers) - 1
+ }
+ }
+ if (ops & peerOpsClearInterruptible) == peerOpsClearInterruptible {
+ if idx, has := s.interruptablePeersMap[peer]; has {
+ delete(s.interruptablePeersMap, peer)
+ s.interruptablePeers[idx] = nil
+ }
+ }
+ if (ops & peerOpsReschedule) == peerOpsReschedule {
+ s.scheduler.schedulePeer(peer, currentTime+scheduleOffset)
+ }
+
+ if deadline.Expired() {
+ // we ran out of time sending messages, stop sending any more messages.
+ break
+ }
+ }
+}
+
+func (s *syncState) assemblePeerMessage(peer *Peer, pendingTransactions *pendingTransactionGroupsSnapshot) (metaMessage sentMessageMetadata, assembledBloomFilter bloomFilter) {
+ metaMessage = sentMessageMetadata{
+ peer: peer,
+ message: &transactionBlockMessage{
+ Version: txnBlockMessageVersion,
+ Round: s.round,
+ },
+ }
+
+ bloomFilterSize := 0
+
+ msgOps := peer.getMessageConstructionOps(s.isRelay, s.fetchTransactions)
+
+ if msgOps&messageConstUpdateRequestParams == messageConstUpdateRequestParams {
+ // update the UpdatedRequestParams
+ offset, modulator := peer.getLocalRequestParams()
+ metaMessage.message.UpdatedRequestParams.Modulator = modulator
+ if modulator > 0 {
+ // for relays, the modulator is always one, which means the following would always be zero.
+ metaMessage.message.UpdatedRequestParams.Offset = byte(uint64(offset) % uint64(modulator))
+ }
+ }
+
+ if (msgOps&messageConstBloomFilter == messageConstBloomFilter) && len(pendingTransactions.pendingTransactionsGroups) > 0 {
+ var lastBloomFilter *bloomFilter
+ var excludeTransactions *transactionCache
+ // for relays, where we send a full bloom filter to everyone, we want to coordinate that with a single
+ // copy of the bloom filter, to prevent re-creation.
+ if s.isRelay {
+ lastBloomFilter = &s.lastBloomFilter
+ } else {
+ // for peers, we want to make sure we don't regenerate the same bloom filter as before.
+ lastBloomFilter = &peer.lastSentBloomFilter
+
+ // for non-relays, we want to be more picky and send bloom filter that excludes the transactions that were send from that relay
+ // ( since the relay already knows that it sent us these transactions ). we cannot do the same for relay->relay since it would
+ // conflict with the bloom filters being calculated only once.
+ excludeTransactions = peer.recentSentTransactions
+ }
+ filterTxns := pendingTransactions.pendingTransactionsGroups
+ minGroupCounter, lastGroupRound := peer.sentFilterParams.nextFilterGroup(metaMessage.message.UpdatedRequestParams)
+ if lastGroupRound != s.round {
+ minGroupCounter = 0
+ }
+ if minGroupCounter > 0 {
+ mgi := sort.Search(
+ len(filterTxns),
+ func(i int) bool {
+ return filterTxns[i].GroupCounter >= minGroupCounter
+ },
+ )
+ if mgi >= len(filterTxns) {
+ goto notxns
+ }
+ filterTxns = filterTxns[mgi:]
+ }
+ profMakeBloomFilter := s.profiler.getElement(profElementMakeBloomFilter)
+ profMakeBloomFilter.start()
+ // generate a bloom filter that matches the requests params.
+ assembledBloomFilter = s.makeBloomFilter(metaMessage.message.UpdatedRequestParams, filterTxns, excludeTransactions, lastBloomFilter)
+ // we check here to see if the bloom filter we need happen to be the same as the one that was previously sent to the peer.
+ // ( note that we check here againt the peer, whereas the hint to makeBloomFilter could be the cached one for the relay )
+ if !assembledBloomFilter.sameParams(peer.lastSentBloomFilter) && assembledBloomFilter.encodedLength > 0 {
+ if lastGroupRound != s.round {
+ assembledBloomFilter.encoded.ClearPrevious = 1
+ }
+ metaMessage.message.TxnBloomFilter = assembledBloomFilter.encoded
+ bloomFilterSize = assembledBloomFilter.encodedLength
+ }
+ profMakeBloomFilter.end()
+ if s.isRelay {
+ s.lastBloomFilter = assembledBloomFilter
+ }
+ }
+notxns:
+
+ if msgOps&messageConstTransactions == messageConstTransactions {
+ transactionGroups := pendingTransactions.pendingTransactionsGroups
+ if !s.isRelay {
+ // on non-relay, we need to filter out the non-locally originated messages since we don't want
+ // non-relays to send transaction that they received via the transaction sync back.
+ transactionGroups = s.locallyGeneratedTransactions(pendingTransactions)
+ }
+
+ profTxnsSelection := s.profiler.getElement(profElementTxnsSelection)
+ profTxnsSelection.start()
+ metaMessage.transactionGroups, metaMessage.sentTransactionsIDs, metaMessage.partialMessage = peer.selectPendingTransactions(transactionGroups, messageTimeWindow, s.round, bloomFilterSize)
+ profTxnsSelection.end()
+
+ // clear the last sent bloom filter on the end of a series of partial messages.
+ // this would ensure we generate a new bloom filter every beta, which is needed
+ // in order to avoid the bloom filter inherent false positive rate.
+ if !metaMessage.partialMessage {
+ peer.lastSentBloomFilter = bloomFilter{}
+ }
+ }
+
+ metaMessage.message.MsgSync.RefTxnBlockMsgSeq = peer.nextReceivedMessageSeq - 1
+ if peer.lastReceivedMessageTimestamp != 0 && peer.lastReceivedMessageLocalRound == s.round {
+ // adding a nanosecond to the elapsed time is meaningless for the data rate calculation, but would ensure that
+ // the ResponseElapsedTime field has a clear distinction between "being set" vs. "not being set"
+ metaMessage.message.MsgSync.ResponseElapsedTime = uint64((s.clock.Since() - peer.lastReceivedMessageTimestamp).Nanoseconds()) + 1
+ // reset the lastReceivedMessageTimestamp so that we won't be using that again on a subsequent outgoing message.
+ peer.lastReceivedMessageTimestamp = 0
+ }
+
+ // use the messages seq number that we've accepted so far, and let the other peer
+ // know about them. The getAcceptedMessages would delete the returned list from the peer's storage before
+ // returning.
+ metaMessage.message.MsgSync.AcceptedMsgSeq = peer.getAcceptedMessages()
+
+ if msgOps&messageConstNextMinDelay == messageConstNextMinDelay {
+ metaMessage.message.MsgSync.NextMsgMinDelay = uint64(s.lastBeta.Nanoseconds()) * 2
+ }
+ return
+}
+
+func (s *syncState) evaluateOutgoingMessage(msgData sentMessageMetadata) {
+ timestamp := msgData.sentTimestamp
+ // test to see if our message got re-ordered between the time we placed it on the execution pool queue and the time
+ // we received it back from the network:
+ if msgData.sequenceNumber != msgData.projectedSequenceNumber {
+ // yes, the order was changed. In this case, we will set the timestamp to zero. This would allow the
+ // incoming message handler to identify that we shouldn't use this timestamp for calculating the data exchange rate.
+ timestamp = 0
+ }
+ msgData.peer.updateMessageSent(msgData.message, msgData.sentTransactionsIDs, timestamp, msgData.sequenceNumber, msgData.encodedMessageSize)
+ s.log.outgoingMessage(msgStats{msgData.sequenceNumber, msgData.message.Round, len(msgData.sentTransactionsIDs), msgData.message.UpdatedRequestParams, len(msgData.message.TxnBloomFilter.BloomFilter), msgData.message.MsgSync.NextMsgMinDelay, msgData.peer.networkAddress()})
+}
+
+// locallyGeneratedTransactions return a subset of the given transactionGroups array by filtering out transactions that are not locally generated.
+func (s *syncState) locallyGeneratedTransactions(pendingTransactions *pendingTransactionGroupsSnapshot) (result []pooldata.SignedTxGroup) {
+ if pendingTransactions.latestLocallyOriginatedGroupCounter == pooldata.InvalidSignedTxGroupCounter || len(pendingTransactions.pendingTransactionsGroups) == 0 {
+ return []pooldata.SignedTxGroup{}
+ }
+ n := sort.Search(len(pendingTransactions.pendingTransactionsGroups), func(i int) bool {
+ return pendingTransactions.pendingTransactionsGroups[i].GroupCounter >= pendingTransactions.latestLocallyOriginatedGroupCounter
+ })
+ if n == len(pendingTransactions.pendingTransactionsGroups) {
+ n--
+ }
+ result = make([]pooldata.SignedTxGroup, n+1)
+
+ count := 0
+ for i := 0; i <= n; i++ {
+ txnGroup := pendingTransactions.pendingTransactionsGroups[i]
+ if !txnGroup.LocallyOriginated {
+ continue
+ }
+ result[count] = txnGroup
+ count++
+ }
+ return result[:count]
+}
diff --git a/txnsync/outgoing_test.go b/txnsync/outgoing_test.go
new file mode 100644
index 000000000..151c716b2
--- /dev/null
+++ b/txnsync/outgoing_test.go
@@ -0,0 +1,612 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "context"
+ "reflect"
+ "sync"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/logging"
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/algorand/go-algorand/util/execpool"
+ "github.com/algorand/go-algorand/util/timers"
+)
+
+type mockAsyncLogger struct {
+ logging.Logger
+ warnCalled *bool
+}
+
+func (m mockAsyncLogger) outgoingMessage(mstat msgStats) {
+}
+
+func (m mockAsyncLogger) incomingMessage(mstat msgStats) {
+}
+
+func (m mockAsyncLogger) Infof(string, ...interface{}) {}
+
+func (m mockAsyncLogger) Warnf(string, ...interface{}) {
+ if m.warnCalled != nil {
+ *m.warnCalled = true
+ }
+}
+
+func TestAsyncMessageSent(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ var s syncState
+ s.clock = timers.MakeMonotonicClock(time.Now())
+ s.log = mockAsyncLogger{}
+
+ asyncEncoder := messageAsyncEncoder{
+ state: &s,
+ messageData: sentMessageMetadata{
+ message: &transactionBlockMessage{
+ Version: txnBlockMessageVersion,
+ Round: 1,
+ },
+ peer: &Peer{},
+ },
+ roundClock: timers.MakeMonotonicClock(time.Now()),
+ }
+
+ oldTimestamp := asyncEncoder.messageData.sentTimestamp
+ a.Equal(asyncEncoder.asyncMessageSent(false, 0), errTransactionSyncOutgoingMessageSendFailed)
+ err := asyncEncoder.asyncMessageSent(true, 1337)
+ a.Equal(err, errTransactionSyncOutgoingMessageQueueFull)
+ a.Equal(asyncEncoder.messageData.sentTimestamp, oldTimestamp)
+ a.Equal(asyncEncoder.messageData.sequenceNumber, uint64(1337))
+
+ // Make this buffered for now so we catch the select statement
+ asyncEncoder.state.outgoingMessagesCallbackCh = make(chan sentMessageMetadata, 1)
+
+ err = asyncEncoder.asyncMessageSent(true, 1337)
+ a.Nil(err)
+ a.Equal(1, len(asyncEncoder.state.outgoingMessagesCallbackCh))
+}
+
+type mockAsyncNodeConnector struct {
+ NodeConnector
+ called *bool
+ largeTxnGroup bool
+}
+
+func (m mockAsyncNodeConnector) Random(rng uint64) uint64 {
+ // We need to be deterministic in our "randomness" for the tests
+ return 42
+}
+
+func (m mockAsyncNodeConnector) SendPeerMessage(netPeer interface{}, msg []byte, callback SendMessageCallback) {
+ *m.called = true
+}
+
+func (m mockAsyncNodeConnector) GetPendingTransactionGroups() (txGroups []pooldata.SignedTxGroup, latestLocallyOriginatedGroupCounter uint64) {
+ if m.largeTxnGroup {
+ rval := []pooldata.SignedTxGroup{}
+ for i := 0; i < 100000; i++ {
+ // Because we use this with non-relay nodes, the syncState will
+ // use the locallyGeneratedTransactions() function.
+ // To make sure we fill the values appropriately, we are going to
+ // set every value here to be locally originated
+ // Additionally, we want the encoded length to be 1000 (or something rather large)
+ // to make sure that we can attain partial messages (see TestSendMessageLoop test)
+ rval = append(rval, pooldata.SignedTxGroup{EncodedLength: 1000, LocallyOriginated: true})
+ }
+
+ return rval, 1
+ }
+ return []pooldata.SignedTxGroup{}, 1
+}
+
+// TestAsyncEncodeAndSendErr Tests response when encodeTransactionGroups doesn't return an error
+func TestAsyncEncodeAndSendNonErr(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ var s syncState
+ s.clock = timers.MakeMonotonicClock(time.Now())
+ warnCalled := false
+ s.log = mockAsyncLogger{warnCalled: &warnCalled}
+ sendPeerMessageCalled := false
+ s.node = mockAsyncNodeConnector{called: &sendPeerMessageCalled}
+ s.messageSendWaitGroup = sync.WaitGroup{}
+
+ txnGrps := []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ Transactions: []transactions.SignedTxn{
+ transactions.SignedTxn{
+ Txn: transactions.Transaction{
+ Type: protocol.AssetConfigTx,
+ },
+ },
+ },
+ },
+ }
+
+ asyncEncoder := messageAsyncEncoder{
+ state: &s,
+ messageData: sentMessageMetadata{
+ message: &transactionBlockMessage{
+ Version: txnBlockMessageVersion,
+ Round: 1,
+ },
+ transactionGroups: txnGrps,
+ peer: &Peer{},
+ },
+ roundClock: timers.MakeMonotonicClock(time.Now()),
+ }
+
+ asyncEncoder.state.messageSendWaitGroup.Add(1)
+
+ err := asyncEncoder.asyncEncodeAndSend(nil)
+
+ a.Nil(err)
+ a.False(warnCalled)
+ a.True(sendPeerMessageCalled)
+ a.Nil(asyncEncoder.messageData.transactionGroups)
+}
+
+// TestAsyncEncodeAndSendErr Tests response when encodeTransactionGroups returns an error
+func TestAsyncEncodeAndSendErr(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ var s syncState
+ s.clock = timers.MakeMonotonicClock(time.Now())
+ warnCalled := false
+ s.log = mockAsyncLogger{warnCalled: &warnCalled}
+ sendPeerMessageCalled := false
+ s.node = mockAsyncNodeConnector{called: &sendPeerMessageCalled}
+ s.messageSendWaitGroup = sync.WaitGroup{}
+
+ txnGrps := []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ Transactions: []transactions.SignedTxn{
+ transactions.SignedTxn{
+ Txn: transactions.Transaction{
+ Type: protocol.UnknownTx,
+ },
+ },
+ },
+ },
+ }
+
+ asyncEncoder := messageAsyncEncoder{
+ state: &s,
+ messageData: sentMessageMetadata{
+ message: &transactionBlockMessage{
+ Version: txnBlockMessageVersion,
+ Round: 1,
+ },
+ transactionGroups: txnGrps,
+ peer: &Peer{},
+ },
+ roundClock: timers.MakeMonotonicClock(time.Now()),
+ }
+
+ asyncEncoder.state.messageSendWaitGroup.Add(1)
+
+ err := asyncEncoder.asyncEncodeAndSend(nil)
+
+ a.Nil(err)
+ a.True(warnCalled)
+ a.True(sendPeerMessageCalled)
+
+}
+
+// TestAsyncEncodeAndSend Tests that SendPeerMessage is called in the node connector
+func TestAsyncEncodeAndSend(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ var s syncState
+ s.clock = timers.MakeMonotonicClock(time.Now())
+ s.log = mockAsyncLogger{}
+ sendPeerMessageCalled := false
+ s.node = mockAsyncNodeConnector{called: &sendPeerMessageCalled}
+ s.messageSendWaitGroup = sync.WaitGroup{}
+
+ asyncEncoder := messageAsyncEncoder{
+ state: &s,
+ messageData: sentMessageMetadata{
+ message: &transactionBlockMessage{
+ Version: txnBlockMessageVersion,
+ Round: 1,
+ },
+ peer: &Peer{},
+ },
+ roundClock: timers.MakeMonotonicClock(time.Now()),
+ }
+
+ asyncEncoder.state.messageSendWaitGroup.Add(1)
+
+ err := asyncEncoder.asyncEncodeAndSend(nil)
+ a.Nil(err)
+ a.True(sendPeerMessageCalled)
+ a.NotZero(asyncEncoder.messageData.sentTimestamp)
+
+}
+
+// TestAssemblePeerMessage_messageConstBloomFilter Tests assemblePeerMessage with messageConstBloomFilter msgOps
+func TestAssemblePeerMessage_messageConstBloomFilter(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ s := syncState{
+ node: mockAsyncNodeConnector{},
+ clock: timers.MakeMonotonicClock(time.Now()),
+ }
+
+ s.profiler = makeProfiler(1*time.Millisecond, s.clock, s.log, 1*time.Millisecond)
+
+ peer := Peer{}
+
+ pendingTransactions := pendingTransactionGroupsSnapshot{
+ pendingTransactionsGroups: []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{},
+ },
+ }
+
+ peer.setLocalRequestParams(111, 222)
+ peer.lastReceivedMessageTimestamp = 100
+ peer.lastReceivedMessageLocalRound = s.round
+
+ expectedFilter := s.makeBloomFilter(requestParams{Offset: 111, Modulator: 222}, pendingTransactions.pendingTransactionsGroups, nil, &s.lastBloomFilter)
+
+ s.isRelay = true
+ peer.isOutgoing = true
+ peer.state = peerStateLateBloom
+
+ metaMessage, _ := s.assemblePeerMessage(&peer, &pendingTransactions)
+
+ a.Equal(metaMessage.message.UpdatedRequestParams.Modulator, byte(222))
+ a.Equal(metaMessage.message.UpdatedRequestParams.Offset, byte(111))
+ a.Equal(metaMessage.peer, &peer)
+ a.Equal(metaMessage.message.Version, int32(txnBlockMessageVersion))
+ a.Equal(metaMessage.message.Round, s.round)
+ a.True(metaMessage.message.MsgSync.ResponseElapsedTime != 0)
+ a.Equal(s.lastBloomFilter, expectedFilter)
+}
+
+// TestAssemblePeerMessage_messageConstBloomFilterNonRelay Tests assemblePeerMessage with messageConstBloomFilter msgOps in a non-relay scenario
+func TestAssemblePeerMessage_messageConstBloomFilterNonRelay(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ s := syncState{
+ node: mockAsyncNodeConnector{largeTxnGroup: true},
+ clock: timers.MakeMonotonicClock(time.Now()),
+ }
+
+ s.profiler = makeProfiler(1*time.Millisecond, s.clock, s.log, 1*time.Millisecond)
+
+ peer := Peer{}
+
+ pendingTransactions := pendingTransactionGroupsSnapshot{
+ pendingTransactionsGroups: []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{},
+ },
+ }
+
+ peer.setLocalRequestParams(111, 222)
+ peer.lastReceivedMessageTimestamp = 100
+ peer.lastReceivedMessageLocalRound = s.round
+
+ expectedFilter := s.makeBloomFilter(requestParams{Offset: 111, Modulator: 222}, pendingTransactions.pendingTransactionsGroups, nil, &s.lastBloomFilter)
+
+ s.isRelay = false
+ s.fetchTransactions = true
+ peer.isOutgoing = true
+ peer.state = peerStateLateBloom
+
+ metaMessage, _ := s.assemblePeerMessage(&peer, &pendingTransactions)
+
+ a.Equal(metaMessage.message.UpdatedRequestParams.Modulator, byte(222))
+ a.Equal(metaMessage.message.UpdatedRequestParams.Offset, byte(111))
+ a.Equal(metaMessage.peer, &peer)
+ a.Equal(metaMessage.message.Version, int32(txnBlockMessageVersion))
+ a.Equal(metaMessage.message.Round, s.round)
+ a.True(metaMessage.message.MsgSync.ResponseElapsedTime != 0)
+ a.NotEqual(s.lastBloomFilter, expectedFilter)
+}
+
+// TestAssemblePeerMessage_messageConstNextMinDelay_messageConstUpdateRequestParams Tests assemblePeerMessage with messageConstNextMinDelay | messageConstUpdateRequestParams msgOps
+func TestAssemblePeerMessage_messageConstNextMinDelay_messageConstUpdateRequestParams(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ s := syncState{clock: timers.MakeMonotonicClock(time.Now())}
+
+ s.profiler = makeProfiler(1*time.Millisecond, s.clock, s.log, 1*time.Millisecond)
+
+ peer := Peer{}
+
+ pendingTransactions := pendingTransactionGroupsSnapshot{}
+
+ peer.setLocalRequestParams(111, 222)
+ peer.lastReceivedMessageTimestamp = 100
+ peer.lastReceivedMessageLocalRound = s.round
+
+ s.isRelay = true
+ s.lastBeta = 123 * time.Nanosecond
+
+ metaMessage, _ := s.assemblePeerMessage(&peer, &pendingTransactions)
+
+ a.Equal(metaMessage.message.UpdatedRequestParams.Modulator, byte(222))
+ a.Equal(metaMessage.message.UpdatedRequestParams.Offset, byte(111))
+ a.Equal(metaMessage.peer, &peer)
+ a.Equal(metaMessage.message.Version, int32(txnBlockMessageVersion))
+ a.Equal(metaMessage.message.Round, s.round)
+ a.True(metaMessage.message.MsgSync.ResponseElapsedTime != 0)
+ a.Equal(metaMessage.message.MsgSync.NextMsgMinDelay, uint64(s.lastBeta.Nanoseconds())*2)
+
+}
+
+// TestAssemblePeerMessage_messageConstTransactions Tests assemblePeerMessage messageConstTransactions msgOps
+func TestAssemblePeerMessage_messageConstTransactions(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ s := syncState{clock: timers.MakeMonotonicClock(time.Now())}
+
+ s.profiler = makeProfiler(1*time.Millisecond, s.clock, s.log, 1*time.Millisecond)
+
+ peer := Peer{}
+
+ pendingTransactions := pendingTransactionGroupsSnapshot{
+ latestLocallyOriginatedGroupCounter: 1,
+ pendingTransactionsGroups: []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ LocallyOriginated: true,
+ EncodedLength: 2,
+ },
+ },
+ }
+
+ peer.setLocalRequestParams(111, 222)
+ peer.lastReceivedMessageTimestamp = 100
+ peer.lastReceivedMessageLocalRound = s.round
+ peer.requestedTransactionsModulator = 2
+ peer.recentSentTransactions = makeTransactionCache(5, 10, 20)
+
+ s.isRelay = false
+ peer.isOutgoing = true
+ peer.state = peerStateHoldsoff
+
+ metaMessage, _ := s.assemblePeerMessage(&peer, &pendingTransactions)
+
+ a.Equal(len(metaMessage.transactionGroups), 1)
+ a.True(reflect.DeepEqual(metaMessage.transactionGroups[0], pendingTransactions.pendingTransactionsGroups[0]))
+
+}
+
+// TestLocallyGeneratedTransactions Separately tests that generating transactions are being
+// correctly made given a signed transaction group array.
+func TestLocallyGeneratedTransactions(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ pendingTransactions := &pendingTransactionGroupsSnapshot{}
+
+ s := syncState{}
+
+ pendingTransactions.latestLocallyOriginatedGroupCounter = 1
+
+ a.Equal(s.locallyGeneratedTransactions(pendingTransactions), []pooldata.SignedTxGroup{})
+
+ pendingTransactions.pendingTransactionsGroups = []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ LocallyOriginated: true,
+ EncodedLength: 2,
+ },
+ pooldata.SignedTxGroup{
+ LocallyOriginated: false,
+ EncodedLength: 1,
+ },
+ pooldata.SignedTxGroup{
+ LocallyOriginated: true,
+ EncodedLength: 3,
+ },
+ }
+
+ pendingTransactions.latestLocallyOriginatedGroupCounter = pooldata.InvalidSignedTxGroupCounter
+
+ a.Equal(s.locallyGeneratedTransactions(pendingTransactions), []pooldata.SignedTxGroup{})
+
+ pendingTransactions.latestLocallyOriginatedGroupCounter = 1
+
+ expected := []pooldata.SignedTxGroup{
+
+ pooldata.SignedTxGroup{
+ LocallyOriginated: true,
+ EncodedLength: 2,
+ },
+
+ pooldata.SignedTxGroup{
+ LocallyOriginated: true,
+ EncodedLength: 3,
+ },
+ }
+
+ a.Equal(s.locallyGeneratedTransactions(pendingTransactions), expected)
+
+}
+
+type mockBacklogThreadPool struct {
+ execpool.BacklogPool
+ enqueueCalled *int
+}
+
+func (b *mockBacklogThreadPool) EnqueueBacklog(enqueueCtx context.Context, t execpool.ExecFunc, arg interface{}, out chan interface{}) error {
+ if b.enqueueCalled != nil {
+ *b.enqueueCalled++
+ }
+
+ return nil
+}
+
+// TestEnqueue directly tests that enqueue will call the Done() function for the messageSendWaitGroup
+func TestEnqueue(t *testing.T) {
+
+ partitiontest.PartitionTest(t)
+
+ s := syncState{clock: timers.MakeMonotonicClock(time.Now())}
+ s.log = mockAsyncLogger{}
+ s.node = &mockNodeConnector{}
+ s.threadpool = execpool.MakeBacklog(execpool.MakePool(t), 5, execpool.LowPriority, t)
+
+ prof := makeProfiler(2*time.Millisecond, s.clock, s.log, 3*time.Millisecond)
+ s.profiler = prof
+
+ asyncEncoder := messageAsyncEncoder{
+ state: &s,
+ messageData: sentMessageMetadata{
+ message: &transactionBlockMessage{
+ Version: txnBlockMessageVersion,
+ Round: 1,
+ },
+ peer: &Peer{},
+ },
+ roundClock: timers.MakeMonotonicClock(time.Now()),
+ }
+
+ asyncEncoder.enqueue()
+
+ // Wait for the enqueued function to return the messageSendWaitGroup
+ s.messageSendWaitGroup.Wait()
+
+ // Dummy require to make sure we pass this test...the real value of this test
+ // is to make sure that the wait group is appropriately set
+ require.True(t, true)
+
+}
+
+// TestSendMessageLoop tests the send message loop
+func TestSendMessageLoop(t *testing.T) {
+
+ partitiontest.PartitionTest(t)
+
+ enqueueCalled := 0
+
+ s := syncState{
+ clock: timers.MakeMonotonicClock(time.Now()),
+ scheduler: makePeerScheduler(),
+ }
+ s.log = mockAsyncLogger{}
+ // Get a large amount of signed txns with a low data exchange rate
+ // to get partial messages to trigger peerOpsClearInterruptible
+ s.node = &mockAsyncNodeConnector{largeTxnGroup: true}
+ s.threadpool = &mockBacklogThreadPool{enqueueCalled: &enqueueCalled}
+
+ prof := makeProfiler(2*time.Millisecond, s.clock, s.log, 3*time.Millisecond)
+ s.profiler = prof
+ s.interruptablePeersMap = make(map[*Peer]int)
+
+ peers := []*Peer{
+ // peerOpsReschedule
+ &Peer{
+ recentSentTransactions: makeTransactionCache(10, 20, 10),
+ requestedTransactionsModulator: 2,
+ // Reduced rate to trigger partial messages
+ dataExchangeRate: 10,
+ // greater than 0 for state machine logic
+ nextStateTimestamp: 1 * time.Millisecond,
+ },
+ &Peer{
+ recentSentTransactions: makeTransactionCache(10, 20, 10),
+ requestedTransactionsModulator: 2,
+ // Reduced rate to trigger partial messages
+ dataExchangeRate: 10,
+ // greater than 0 for state machine logic
+ nextStateTimestamp: 1 * time.Millisecond,
+ },
+ }
+
+ // Add the peers to test that peerOpsClearInterruptible removes them
+
+ for _, p := range peers {
+ s.interruptablePeers = append(s.interruptablePeers, p)
+ s.interruptablePeersMap[p] = len(s.interruptablePeers) - 1
+ }
+
+ // The deadline is set to a ridiculously high number to make sure that we cycle through all our peers
+ // and not break
+ s.sendMessageLoop(s.clock.Since(), s.clock.DeadlineMonitorAt(s.clock.Since()+5*time.Minute), peers)
+
+ require.Equal(t, 2, enqueueCalled)
+ require.Equal(t, 0, len(s.interruptablePeersMap))
+
+}
+
+// TestEvaluateOutgoingMessage tests the evaluateOutgoingMessage function of syncState
+func TestEvaluateOutgoingMessage(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ s := syncState{clock: timers.MakeMonotonicClock(time.Now())}
+ s.log = mockAsyncLogger{}
+
+ peer := Peer{
+ recentSentTransactions: makeTransactionCache(10, 20, 10),
+ }
+
+ sentMessage := sentMessageMetadata{
+ sentTimestamp: time.Duration(time.Millisecond * 1234),
+ message: &transactionBlockMessage{Round: 3},
+ sequenceNumber: 42,
+ projectedSequenceNumber: 44,
+ encodedMessageSize: 23,
+ peer: &peer,
+ }
+
+ s.evaluateOutgoingMessage(sentMessage)
+ // This should be zero because sequenceNumber and projectedSequenceNumber are not equal
+ a.Equal(peer.lastSentMessageTimestamp, 0*time.Millisecond)
+
+ a.Equal(peer.lastSentMessageSequenceNumber, uint64(42))
+ a.Equal(peer.lastSentMessageRound, basics.Round(3))
+ a.Equal(peer.lastSentMessageSize, 23)
+
+ sentMessage.sequenceNumber = sentMessage.projectedSequenceNumber
+
+ s.evaluateOutgoingMessage(sentMessage)
+ a.Equal(peer.lastSentMessageTimestamp, 1234*time.Millisecond)
+
+ a.Equal(peer.lastSentMessageSequenceNumber, uint64(44))
+ a.Equal(peer.lastSentMessageRound, basics.Round(3))
+ a.Equal(peer.lastSentMessageSize, 23)
+}
diff --git a/txnsync/peer.go b/txnsync/peer.go
new file mode 100644
index 000000000..1aa04c574
--- /dev/null
+++ b/txnsync/peer.go
@@ -0,0 +1,849 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "math"
+ "sort"
+ "time"
+
+ "github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/data/transactions"
+)
+
+//msgp:ignore peerState
+type peerState int
+
+//msgp:ignore peersOps
+type peersOps int
+
+//msgp:ignore messageConstructionOps
+type messageConstructionOps int
+
+const maxIncomingBloomFilterHistory = 200
+
+// shortTermRecentTransactionsSentBufferLength is the size of the short term storage for the recently sent transaction ids.
+// it should be configured sufficiently high so that any number of transaction sent would not exceed that number before
+// the other peer has a chance of sending a feedback. ( when the feedback is received, we will store these IDs into the long-term cache )
+const shortTermRecentTransactionsSentBufferLength = 5000
+
+// pendingUnconfirmedRemoteMessages is the number of messages we would cache before receiving a feedback from the other
+// peer that these message have been accepted. The general guideline here is that if we have a message every 200ms on one side
+// and a message every 20ms on the other, then the ratio of 200/20 = 10, should be the number of required messages (min).
+const pendingUnconfirmedRemoteMessages = 20
+
+// longTermRecentTransactionsSentBufferLength is the size of the long term transaction id cache.
+const longTermRecentTransactionsSentBufferLength = 15000
+const minDataExchangeRateThreshold = 500 * 1024 // 500KB/s, which is ~3.9Mbps
+const maxDataExchangeRateThreshold = 100 * 1024 * 1024 / 8 // 100Mbps
+const defaultDataExchangeRate = minDataExchangeRateThreshold
+const defaultRelayToRelayDataExchangeRate = 10 * 1024 * 1024 / 8 // 10Mbps
+const bloomFilterRetryCount = 3 // number of bloom filters we would try against each transaction group before skipping it.
+const maxTransactionGroupTrackers = 15 // number of different bloom filter parameters we store before rolling over
+
+const (
+ // peerStateStartup is before the timeout for the sending the first message to the peer has reached.
+ // for an outgoing peer, it means that an incoming message arrived, and one or more messages need to be sent out.
+ peerStateStartup peerState = iota
+ // peerStateHoldsoff is set once a message was sent to a peer, and we're holding off before sending additional messages.
+ peerStateHoldsoff
+ // peerStateInterrupt is set once the holdoff period for the peer have expired.
+ peerStateInterrupt
+ // peerStateLateBloom is set for outgoing peers on relays, indicating that the next message should be a bloom filter only message.
+ peerStateLateBloom
+
+ peerOpsSendMessage peersOps = 1
+ peerOpsSetInterruptible peersOps = 2
+ peerOpsClearInterruptible peersOps = 4
+ peerOpsReschedule peersOps = 8
+
+ messageConstBloomFilter messageConstructionOps = 1
+ messageConstTransactions messageConstructionOps = 2
+ messageConstNextMinDelay messageConstructionOps = 4
+ messageConstUpdateRequestParams messageConstructionOps = 8
+
+ // defaultSignificantMessageThreshold is the minimal transmitted message size which would be used for recalculating the
+ // data exchange rate.
+ defaultSignificantMessageThreshold = 50000
+)
+
+// incomingBloomFilter stores an incoming bloom filter, along with the associated round number.
+// the round number allow us to prune filters from rounds n-2 and below.
+type incomingBloomFilter struct {
+ filter *testableBloomFilter
+ round basics.Round
+}
+
+// Peer contains peer-related data which extends the data "known" and managed by the network package.
+type Peer struct {
+ // networkPeer is the network package exported peer. It's created on construction and never change afterward.
+ networkPeer interface{}
+ // isOutgoing defines whether the peer is an outgoing peer or not. For relays, this is meaningful as these have
+ // slightly different message timing logic.
+ isOutgoing bool
+ // significantMessageThreshold is the minimal transmitted message size which would be used for recalculating the
+ // data exchange rate. When significantMessageThreshold is equal to math.MaxUint64, no data exchange rate updates would be
+ // performed.
+ significantMessageThreshold uint64
+ // state defines the peer state ( in terms of state machine state ). It's touched only by the sync main state machine
+ state peerState
+
+ log Logger
+
+ // lastRound is the latest round reported by the peer.
+ lastRound basics.Round
+
+ // incomingMessages contains the incoming messages from this peer. This heap help us to reorder the incoming messages so that
+ // we could process them in the tcp-transport order.
+ incomingMessages messageOrderingHeap
+
+ // nextReceivedMessageSeq is a counter containing the next message sequence number that we expect to see from this peer.
+ nextReceivedMessageSeq uint64 // the next message seq that we expect to receive from that peer; implies that all previous messages have been accepted.
+
+ // recentIncomingBloomFilters contains the recent list of bloom filters sent from the peer. When considering sending transactions, we check this
+ // array to determine if the peer already has this message.
+ recentIncomingBloomFilters []incomingBloomFilter
+
+ // recentSentTransactions contains the recently sent transactions. It's needed since we don't want to rely on the other peer's bloom filter while
+ // sending back-to-back messages.
+ recentSentTransactions *transactionCache
+ // recentSentTransactionsRound is the round associated with the cache of recently sent transactions. We keep this variable around so that we can
+ // flush the cache on every round so that we can give pending transaction another chance of being transmitted.
+ recentSentTransactionsRound basics.Round
+
+ // these two fields describe "what does that peer asked us to send it"
+ requestedTransactionsModulator byte
+ requestedTransactionsOffset byte
+
+ // lastSentMessageSequenceNumber is the last sequence number of the message that we sent.
+ lastSentMessageSequenceNumber uint64
+ // lastSentMessageRound is the round the last sent message was sent on. The timestamps are relative to the beginning of the round
+ // and therefore need to be evaluated togather.
+ lastSentMessageRound basics.Round
+ // lastSentMessageTimestamp the timestamp at which the last message was sent.
+ lastSentMessageTimestamp time.Duration
+ // lastSentMessageSize is the encoded message size of the last sent message
+ lastSentMessageSize int
+ // lastSentBloomFilter is the last bloom filter that was sent to this peer.
+ // This bloom filter could be stale if no bloom filter was included in the last message.
+ lastSentBloomFilter bloomFilter
+
+ // sentFilterParams records the Round and max txn group counter of the last filter sent to a peer (for each {Modulator,Offset}).
+ // From this an efficient next filter can be calculated for just the new txns, or a full filter after a Round turnover.
+ sentFilterParams sentFilters
+
+ // lastConfirmedMessageSeqReceived is the last message sequence number that was confirmed by the peer to have been accepted.
+ lastConfirmedMessageSeqReceived uint64
+ lastReceivedMessageLocalRound basics.Round
+ lastReceivedMessageTimestamp time.Duration
+ lastReceivedMessageSize int
+ lastReceivedMessageNextMsgMinDelay time.Duration
+
+ // dataExchangeRate is the combined upload/download rate in bytes/second
+ dataExchangeRate uint64
+
+ // these two fields describe "what does the local peer want the remote peer to send back"
+ localTransactionsModulator byte
+ localTransactionsBaseOffset byte
+
+ // lastTransactionSelectionTracker tracks the last transaction group counter that we've evaluated on the selectPendingTransactions method.
+ // it used to ensure that on subsequent calls, we won't need to scan the entire pending transactions array from the beginning.
+ // the implementation here is breaking it up per request params, so that we can apply the above logic per request params ( i.e. different
+ // offset/modulator ), as well as add retry attempts for multiple bloom filters.
+ lastTransactionSelectionTracker transactionGroupCounterTracker
+
+ // nextStateTimestamp indicates the next timestamp where the peer state would need to be changed.
+ // it used to allow sending partial message while retaining the "next-beta time", or, in the case of outgoing relays,
+ // its being used to hold when we need to send the last (bloom) message.
+ nextStateTimestamp time.Duration
+ // messageSeriesPendingTransactions contain the transactions we are sending in the current "message-series". It allows us to pick a given
+ // "snapshot" from the transaction pool, and send that "snapshot" to completion before attempting to re-iterate.
+ messageSeriesPendingTransactions []pooldata.SignedTxGroup
+
+ // transactionPoolAckCh is passed to the transaction handler when incoming transaction arrives. The channel is passed upstream, so that once
+ // a transaction is added to the transaction pool, we can get some feedback for that.
+ transactionPoolAckCh chan uint64
+
+ // transactionPoolAckMessages maintain a list of the recent incoming messages sequence numbers whose transactions were added fully to the transaction
+ // pool. This list is being flushed out every time we send a message to the peer.
+ transactionPoolAckMessages []uint64
+
+ // used by the selectPendingTransactions method, the lastSelectedTransactionsCount contains the number of entries selected on the previous iteration.
+ // this value is used to optimize the memory preallocation for the selection IDs array.
+ lastSelectedTransactionsCount int
+}
+
+// requestParamsGroupCounterState stores the latest group counters for a given set of request params.
+// we use this to ensure we can have multiple iteration of bloom filter scanning over each individual
+// transaction group. This method allow us to reduce the bloom filter errors while avoid scanning the
+// list of transactions redundently.
+//msgp:ignore transactionGroupCounterState
+type requestParamsGroupCounterState struct {
+ offset byte
+ modulator byte
+ groupCounters [bloomFilterRetryCount]uint64
+}
+
+// transactionGroupCounterTracker manages the group counter state for each request param.
+//msgp:ignore transactionGroupCounterTracker
+type transactionGroupCounterTracker []requestParamsGroupCounterState
+
+// get returns the group counter for a given set of request param.
+func (t *transactionGroupCounterTracker) get(offset, modulator byte) uint64 {
+ i := t.index(offset, modulator)
+ if i >= 0 {
+ return (*t)[i].groupCounters[0]
+ }
+ return 0
+}
+
+// set updates the group counter for a given set of request param. If no such request
+// param currently exists, it create it.
+func (t *transactionGroupCounterTracker) set(offset, modulator byte, counter uint64) {
+ i := t.index(offset, modulator)
+ if i >= 0 {
+ (*t)[i].groupCounters[0] = counter
+ return
+ }
+ // if it doesn't exists -
+ state := requestParamsGroupCounterState{
+ offset: offset,
+ modulator: modulator,
+ }
+ state.groupCounters[0] = counter
+
+ if len(*t) == maxTransactionGroupTrackers {
+ // shift all entries by one.
+ copy((*t)[0:], (*t)[1:])
+ (*t)[maxTransactionGroupTrackers-1] = state
+ } else {
+ *t = append(*t, state)
+ }
+}
+
+// roll the counters for a given requests params, so that we would go back and
+// rescan some of the previous transaction groups ( but not all !) when selectPendingTransactions is called.
+func (t *transactionGroupCounterTracker) roll(offset, modulator byte) {
+ i := t.index(offset, modulator)
+ if i < 0 {
+ return
+ }
+
+ if (*t)[i].groupCounters[1] >= (*t)[i].groupCounters[0] {
+ return
+ }
+ firstGroupCounter := (*t)[i].groupCounters[0]
+ copy((*t)[i].groupCounters[0:], (*t)[i].groupCounters[1:])
+ (*t)[i].groupCounters[bloomFilterRetryCount-1] = firstGroupCounter
+}
+
+// index is a helper method for the transactionGroupCounterTracker, helping to locate the index of
+// a requestParamsGroupCounterState in the array that matches the provided request params. The method
+// uses a linear search, which works best against small arrays.
+func (t *transactionGroupCounterTracker) index(offset, modulator byte) int {
+ for i, counter := range *t {
+ if counter.offset == offset && counter.modulator == modulator {
+ return i
+ }
+ }
+ return -1
+}
+
+func makePeer(networkPeer interface{}, isOutgoing bool, isLocalNodeRelay bool, cfg *config.Local, log Logger) *Peer {
+ p := &Peer{
+ networkPeer: networkPeer,
+ isOutgoing: isOutgoing,
+ recentSentTransactions: makeTransactionCache(shortTermRecentTransactionsSentBufferLength, longTermRecentTransactionsSentBufferLength, pendingUnconfirmedRemoteMessages),
+ dataExchangeRate: defaultDataExchangeRate,
+ transactionPoolAckCh: make(chan uint64, maxAcceptedMsgSeq),
+ transactionPoolAckMessages: make([]uint64, 0, maxAcceptedMsgSeq),
+ significantMessageThreshold: defaultSignificantMessageThreshold,
+ log: log,
+ }
+ if isLocalNodeRelay {
+ p.requestedTransactionsModulator = 1
+ p.dataExchangeRate = defaultRelayToRelayDataExchangeRate
+ }
+ if cfg.TransactionSyncDataExchangeRate > 0 {
+ p.dataExchangeRate = cfg.TransactionSyncDataExchangeRate
+ p.significantMessageThreshold = math.MaxUint64
+ }
+ if cfg.TransactionSyncSignificantMessageThreshold > 0 && cfg.TransactionSyncDataExchangeRate == 0 {
+ p.significantMessageThreshold = cfg.TransactionSyncSignificantMessageThreshold
+ }
+ // increase the number of total created peers.
+ txsyncCreatedPeersTotal.Inc(nil)
+ return p
+}
+
+// GetNetworkPeer returns the network peer associated with this particular peer.
+func (p *Peer) GetNetworkPeer() interface{} {
+ return p.networkPeer
+}
+
+// GetTransactionPoolAckChannel returns the transaction pool ack channel
+func (p *Peer) GetTransactionPoolAckChannel() chan uint64 {
+ return p.transactionPoolAckCh
+}
+
+// dequeuePendingTransactionPoolAckMessages removed the pending entries from transactionPoolAckCh and add them to transactionPoolAckMessages
+func (p *Peer) dequeuePendingTransactionPoolAckMessages() {
+ for {
+ select {
+ case msgSeq := <-p.transactionPoolAckCh:
+ if len(p.transactionPoolAckMessages) == maxAcceptedMsgSeq {
+ p.transactionPoolAckMessages = append(p.transactionPoolAckMessages[1:], msgSeq)
+ } else {
+ p.transactionPoolAckMessages = append(p.transactionPoolAckMessages, msgSeq)
+ }
+ default:
+ return
+ }
+ }
+}
+
+// outgoing related methods :
+
+// getAcceptedMessages returns the content of the transactionPoolAckMessages and clear the existing buffer.
+func (p *Peer) getAcceptedMessages() []uint64 {
+ p.dequeuePendingTransactionPoolAckMessages()
+ acceptedMessages := p.transactionPoolAckMessages
+ p.transactionPoolAckMessages = make([]uint64, 0, maxAcceptedMsgSeq)
+ return acceptedMessages
+}
+
+func (p *Peer) selectPendingTransactions(pendingTransactions []pooldata.SignedTxGroup, sendWindow time.Duration, round basics.Round, bloomFilterSize int) (selectedTxns []pooldata.SignedTxGroup, selectedTxnIDs []transactions.Txid, partialTransactionsSet bool) {
+ // if peer is too far back, don't send it any transactions ( or if the peer is not interested in transactions )
+ if p.lastRound < round.SubSaturate(1) || p.requestedTransactionsModulator == 0 {
+ return nil, nil, false
+ }
+
+ if len(p.messageSeriesPendingTransactions) > 0 {
+ pendingTransactions = p.messageSeriesPendingTransactions
+ }
+
+ if len(pendingTransactions) == 0 {
+ return nil, nil, false
+ }
+
+ // flush the recent sent transaction cache on the beginning of a new round to give pending transactions another
+ // chance of being transmitted.
+ if p.recentSentTransactionsRound != round {
+ p.recentSentTransactions.reset()
+ p.recentSentTransactionsRound = round
+ }
+
+ windowLengthBytes := int(uint64(sendWindow) * p.dataExchangeRate / uint64(time.Second))
+ windowLengthBytes -= bloomFilterSize
+
+ accumulatedSize := 0
+
+ lastTransactionSelectionGroupCounter := p.lastTransactionSelectionTracker.get(p.requestedTransactionsOffset, p.requestedTransactionsModulator)
+
+ startIndex := sort.Search(len(pendingTransactions), func(i int) bool {
+ return pendingTransactions[i].GroupCounter >= lastTransactionSelectionGroupCounter
+ })
+
+ selectedIDsSliceLength := len(pendingTransactions) - startIndex
+ if selectedIDsSliceLength > p.lastSelectedTransactionsCount*2 {
+ selectedIDsSliceLength = p.lastSelectedTransactionsCount * 2
+ }
+ selectedTxnIDs = make([]transactions.Txid, 0, selectedIDsSliceLength)
+ selectedTxns = make([]pooldata.SignedTxGroup, 0, selectedIDsSliceLength)
+
+ windowSizedReached := false
+ hasMorePendingTransactions := false
+
+ // create a list of all the bloom filters that might need to be tested. This list excludes bloom filters
+ // which has the same modulator and a different offset.
+ var effectiveBloomFilters []int
+ effectiveBloomFilters = make([]int, 0, len(p.recentIncomingBloomFilters))
+ for filterIdx := len(p.recentIncomingBloomFilters) - 1; filterIdx >= 0; filterIdx-- {
+ if p.recentIncomingBloomFilters[filterIdx].filter == nil {
+ continue
+ }
+ if p.recentIncomingBloomFilters[filterIdx].filter.encodingParams.Modulator != p.requestedTransactionsModulator || p.recentIncomingBloomFilters[filterIdx].filter.encodingParams.Offset != p.requestedTransactionsOffset {
+ continue
+ }
+ effectiveBloomFilters = append(effectiveBloomFilters, filterIdx)
+ }
+
+ // removedTxn := 0
+ grpIdx := startIndex
+scanLoop:
+ for ; grpIdx < len(pendingTransactions); grpIdx++ {
+ txID := pendingTransactions[grpIdx].GroupTransactionID
+
+ // check if the peer would be interested in these messages -
+ if p.requestedTransactionsModulator > 1 {
+ if txidToUint64(txID)%uint64(p.requestedTransactionsModulator) != uint64(p.requestedTransactionsOffset) {
+ continue
+ }
+ }
+
+ // filter out transactions that we already previously sent.
+ if p.recentSentTransactions.contained(txID) {
+ // we already sent that transaction. no need to send again.
+ continue
+ }
+
+ // check if the peer already received these messages from a different source other than us.
+ for _, filterIdx := range effectiveBloomFilters {
+ if p.recentIncomingBloomFilters[filterIdx].filter.test(txID) {
+ // removedTxn++
+ continue scanLoop
+ }
+ }
+
+ if windowSizedReached {
+ hasMorePendingTransactions = true
+ break
+ }
+ selectedTxns = append(selectedTxns, pendingTransactions[grpIdx])
+ selectedTxnIDs = append(selectedTxnIDs, txID)
+
+ // add the size of the transaction group
+ accumulatedSize += pendingTransactions[grpIdx].EncodedLength
+
+ if accumulatedSize > windowLengthBytes {
+ windowSizedReached = true
+ }
+ }
+
+ p.lastSelectedTransactionsCount = len(selectedTxnIDs)
+
+ // if we've over-allocated, resize the buffer; This becomes important on relays,
+ // as storing these arrays can consume considerable amount of memory.
+ if len(selectedTxnIDs)*2 < cap(selectedTxnIDs) {
+ exactBuffer := make([]transactions.Txid, len(selectedTxnIDs))
+ copy(exactBuffer, selectedTxnIDs)
+ selectedTxnIDs = exactBuffer
+ }
+
+ // update the lastTransactionSelectionGroupCounter if needed -
+ // if we selected any transaction to be sent, update the lastTransactionSelectionGroupCounter with the latest
+ // group counter. If the startIndex was *after* the last pending transaction, it means that we don't
+ // need to update the lastTransactionSelectionGroupCounter since it's already ahead of everything in the pending transactions.
+ if grpIdx >= 0 && startIndex < len(pendingTransactions) {
+ if grpIdx == len(pendingTransactions) {
+ if grpIdx > 0 {
+ p.lastTransactionSelectionTracker.set(p.requestedTransactionsOffset, p.requestedTransactionsModulator, pendingTransactions[grpIdx-1].GroupCounter+1)
+ }
+ } else {
+ p.lastTransactionSelectionTracker.set(p.requestedTransactionsOffset, p.requestedTransactionsModulator, pendingTransactions[grpIdx].GroupCounter)
+ }
+ }
+
+ if !hasMorePendingTransactions {
+ // we're done with the current sequence.
+ p.messageSeriesPendingTransactions = nil
+ }
+
+ // fmt.Printf("selectPendingTransactions : selected %d transactions, %d not needed and aborted after exceeding data length %d/%d more = %v\n", len(selectedTxnIDs), removedTxn, accumulatedSize, windowLengthBytes, hasMorePendingTransactions)
+
+ return selectedTxns, selectedTxnIDs, hasMorePendingTransactions
+}
+
+// getLocalRequestParams returns the local requests params
+func (p *Peer) getLocalRequestParams() (offset, modulator byte) {
+ return p.localTransactionsBaseOffset, p.localTransactionsModulator
+}
+
+// update the peer once the message was sent successfully.
+func (p *Peer) updateMessageSent(txMsg *transactionBlockMessage, selectedTxnIDs []transactions.Txid, timestamp time.Duration, sequenceNumber uint64, messageSize int) {
+ p.recentSentTransactions.addSlice(selectedTxnIDs, sequenceNumber, timestamp)
+ p.lastSentMessageSequenceNumber = sequenceNumber
+ p.lastSentMessageRound = txMsg.Round
+ p.lastSentMessageTimestamp = timestamp
+ p.lastSentMessageSize = messageSize
+}
+
+// update the peer's lastSentBloomFilter.
+func (p *Peer) updateSentBoomFilter(filter bloomFilter, round basics.Round) {
+ if filter.encodedLength > 0 {
+ p.lastSentBloomFilter = filter
+ p.sentFilterParams.setSentFilter(filter, round)
+ }
+}
+
+// setLocalRequestParams stores the peer request params.
+func (p *Peer) setLocalRequestParams(offset, modulator uint64) {
+ if modulator > 255 {
+ modulator = 255
+ }
+ p.localTransactionsModulator = byte(modulator)
+ if modulator != 0 {
+ p.localTransactionsBaseOffset = byte(offset % modulator)
+ }
+}
+
+// peers array functions
+
+// incomingPeersOnly scan the input peers array and return a subset of the peers that are incoming peers.
+func incomingPeersOnly(peers []*Peer) (incomingPeers []*Peer) {
+ incomingPeers = make([]*Peer, 0, len(peers))
+ for _, peer := range peers {
+ if !peer.isOutgoing {
+ incomingPeers = append(incomingPeers, peer)
+ }
+ }
+ return
+}
+
+// incoming related functions
+
+// addIncomingBloomFilter keeps the most recent {maxIncomingBloomFilterHistory} filters
+func (p *Peer) addIncomingBloomFilter(round basics.Round, incomingFilter *testableBloomFilter, currentRound basics.Round) {
+ minRound := currentRound.SubSaturate(2)
+ if round < minRound {
+ // ignore data from the past
+ return
+ }
+ bf := incomingBloomFilter{
+ round: round,
+ filter: incomingFilter,
+ }
+ elemOk := func(i int) bool {
+ ribf := p.recentIncomingBloomFilters[i]
+ if ribf.filter == nil {
+ return false
+ }
+ if ribf.round < minRound {
+ return false
+ }
+ if incomingFilter.clearPrevious && ribf.filter.encodingParams.Offset == incomingFilter.encodingParams.Offset && ribf.filter.encodingParams.Modulator == incomingFilter.encodingParams.Modulator {
+ return false
+ }
+ return true
+ }
+ // compact the prior list to the front of the array.
+ // order doesn't matter.
+ pos := 0
+ last := len(p.recentIncomingBloomFilters) - 1
+ oldestRound := currentRound + 1
+ firstOfOldest := -1
+ for pos <= last {
+ if elemOk(pos) {
+ if p.recentIncomingBloomFilters[pos].round < oldestRound {
+ oldestRound = p.recentIncomingBloomFilters[pos].round
+ firstOfOldest = pos
+ }
+ pos++
+ continue
+ }
+ p.recentIncomingBloomFilters[pos] = p.recentIncomingBloomFilters[last]
+ p.recentIncomingBloomFilters[last].filter = nil // GC
+ last--
+ }
+ p.recentIncomingBloomFilters = p.recentIncomingBloomFilters[:last+1]
+ // Simple case: append
+ if last+1 < maxIncomingBloomFilterHistory {
+ p.recentIncomingBloomFilters = append(p.recentIncomingBloomFilters, bf)
+ return
+ }
+ // Too much traffic case: replace the first thing we find of the oldest round
+ if firstOfOldest >= 0 {
+ p.recentIncomingBloomFilters[firstOfOldest] = bf
+ return
+ }
+ // This line should be unreachable, but putting in an error log to test that assumption.
+ p.log.Error("addIncomingBloomFilter failed to trim p.recentIncomingBloomFilters (new filter lost)")
+}
+
+func (p *Peer) updateRequestParams(modulator, offset byte) {
+ p.requestedTransactionsModulator = modulator
+ p.requestedTransactionsOffset = offset
+}
+
+// update the recentSentTransactions with the incoming transaction groups. This would prevent us from sending the received transactions back to the
+// peer that sent it to us. This comes in addition to the bloom filter, if being sent by the other peer.
+func (p *Peer) updateIncomingTransactionGroups(txnGroups []pooldata.SignedTxGroup) {
+ for _, txnGroup := range txnGroups {
+ if len(txnGroup.Transactions) > 0 {
+ // The GroupTransactionID field is not yet updated, so we'll be calculating it's value here and passing it.
+ p.recentSentTransactions.add(txnGroup.Transactions.ID())
+ }
+ }
+}
+
+func (p *Peer) updateIncomingMessageTiming(timings timingParams, currentRound basics.Round, currentTime time.Duration, incomingMessageSize int) {
+ p.lastConfirmedMessageSeqReceived = timings.RefTxnBlockMsgSeq
+ // if we received a message that references our previous message, see if they occurred on the same round
+ if p.lastConfirmedMessageSeqReceived == p.lastSentMessageSequenceNumber && p.lastSentMessageRound == currentRound && p.lastSentMessageTimestamp > 0 {
+ // if so, we might be able to calculate the bandwidth.
+ timeSinceLastMessageWasSent := currentTime - p.lastSentMessageTimestamp
+ networkMessageSize := uint64(p.lastSentMessageSize + incomingMessageSize)
+ if timings.ResponseElapsedTime != 0 && timeSinceLastMessageWasSent > time.Duration(timings.ResponseElapsedTime) && networkMessageSize >= p.significantMessageThreshold {
+ networkTrasmitTime := timeSinceLastMessageWasSent - time.Duration(timings.ResponseElapsedTime)
+ dataExchangeRate := uint64(time.Second) * networkMessageSize / uint64(networkTrasmitTime)
+
+ if dataExchangeRate < minDataExchangeRateThreshold {
+ dataExchangeRate = minDataExchangeRateThreshold
+ } else if dataExchangeRate > maxDataExchangeRateThreshold {
+ dataExchangeRate = maxDataExchangeRateThreshold
+ }
+ // clamp data exchange rate to realistic metrics
+ p.dataExchangeRate = dataExchangeRate
+ // fmt.Printf("incoming message : updating data exchange to %d; network msg size = %d+%d, transmit time = %v\n", dataExchangeRate, p.lastSentMessageSize, incomingMessageSize, networkTrasmitTime)
+ }
+
+ // given that we've (maybe) updated the data exchange rate, we need to clear out the lastSendMessage information
+ // so we won't use that again on a subsequent incoming message.
+ p.lastSentMessageSequenceNumber = 0
+ p.lastSentMessageRound = 0
+ p.lastSentMessageTimestamp = 0
+ p.lastSentMessageSize = 0
+ }
+ p.lastReceivedMessageLocalRound = currentRound
+ p.lastReceivedMessageTimestamp = currentTime
+ p.lastReceivedMessageSize = incomingMessageSize
+ p.lastReceivedMessageNextMsgMinDelay = time.Duration(timings.NextMsgMinDelay) * time.Nanosecond
+ p.recentSentTransactions.acknowledge(timings.AcceptedMsgSeq)
+}
+
+// advancePeerState is called when a peer schedule arrives, before we're doing any operation.
+// The method would determine whether a message need to be sent, and adjust the peer state
+// accordingly.
+func (p *Peer) advancePeerState(currenTime time.Duration, isRelay bool) (ops peersOps) {
+ if isRelay {
+ if p.isOutgoing {
+ // outgoing peers are "special", as they respond to messages rather then generating their own.
+ // we need to figure the special state needed for "late bloom filter message"
+ switch p.state {
+ case peerStateStartup:
+ p.nextStateTimestamp = currenTime + p.lastReceivedMessageNextMsgMinDelay
+ messagesCount := p.lastReceivedMessageNextMsgMinDelay / messageTimeWindow
+ if messagesCount <= 2 {
+ // we have time to send only a single message. This message need to include both transactions and bloom filter.
+ p.state = peerStateLateBloom
+ } else {
+ // we have enough time to send multiple messages, make the first n-1 message have no bloom filter, and have the last one
+ // include a bloom filter.
+ p.state = peerStateHoldsoff
+ }
+
+ // send a message
+ ops |= peerOpsSendMessage
+ case peerStateHoldsoff:
+ // calculate how more messages we can send ( if needed )
+ messagesCount := (p.nextStateTimestamp - currenTime) / messageTimeWindow
+ if messagesCount <= 2 {
+ // we have time to send only a single message. This message need to include both transactions and bloom filter.
+ p.state = peerStateLateBloom
+ }
+
+ // send a message
+ ops |= peerOpsSendMessage
+
+ // the rescehduling would be done in the sendMessageLoop, since we need to know if additional messages are needed.
+ case peerStateLateBloom:
+ // send a message
+ ops |= peerOpsSendMessage
+
+ default:
+ // this isn't expected, so we can just ignore this.
+ // todo : log
+ }
+ } else {
+ // non-outgoing
+ switch p.state {
+ case peerStateStartup:
+ p.state = peerStateHoldsoff
+ fallthrough
+ case peerStateHoldsoff:
+ // prepare the send message array.
+ ops |= peerOpsSendMessage
+ default: // peerStateInterrupt & peerStateLateBloom
+ // this isn't expected, so we can just ignore this.
+ // todo : log
+ }
+ }
+ } else {
+ switch p.state {
+ case peerStateStartup:
+ p.state = peerStateHoldsoff
+ ops |= peerOpsSendMessage
+
+ case peerStateHoldsoff:
+ if p.nextStateTimestamp == 0 {
+ p.state = peerStateInterrupt
+ ops |= peerOpsSetInterruptible | peerOpsReschedule
+ } else {
+ ops |= peerOpsSendMessage
+ }
+
+ case peerStateInterrupt:
+ p.state = peerStateHoldsoff
+ ops |= peerOpsSendMessage | peerOpsClearInterruptible
+
+ default: // peerStateLateBloom
+ // this isn't expected, so we can just ignore this.
+ // todo : log
+ }
+ }
+ return ops
+}
+
+// getMessageConstructionOps constructs the messageConstructionOps that would be needed when
+// sending a message back to the peer. The two arguments are:
+// - isRelay defines whether the local node is a relay.
+// - fetchTransactions defines whether the local node is interested in receiving transactions from
+// the peer ( this is essentially allow us to skip receiving transactions for non-relays that aren't going
+// to make any proposals )
+func (p *Peer) getMessageConstructionOps(isRelay bool, fetchTransactions bool) (ops messageConstructionOps) {
+ // on outgoing peers of relays, we want have some custom logic.
+ if isRelay {
+ if p.isOutgoing {
+ switch p.state {
+ case peerStateLateBloom:
+ if p.localTransactionsModulator != 0 {
+ ops |= messageConstBloomFilter
+ }
+ case peerStateHoldsoff:
+ ops |= messageConstTransactions
+ }
+ } else {
+ if p.requestedTransactionsModulator != 0 {
+ ops |= messageConstTransactions
+ if p.nextStateTimestamp == 0 && p.localTransactionsModulator != 0 {
+ ops |= messageConstBloomFilter
+ }
+ }
+ if p.nextStateTimestamp == 0 {
+ ops |= messageConstNextMinDelay
+ }
+ }
+ ops |= messageConstUpdateRequestParams
+ } else {
+ ops |= messageConstTransactions // send transactions to the other peer
+ if fetchTransactions {
+ switch p.localTransactionsModulator {
+ case 0:
+ // don't send bloom filter.
+ case 1:
+ // special optimization if we have just one relay that we're connected to:
+ // generate the bloom filter only once per 2*beta message.
+ // this would reduce the number of unneeded bloom filters generation dramatically.
+ // that single relay would know which messages it previously sent us, and would refrain from
+ // sending these again.
+ if p.nextStateTimestamp == 0 {
+ ops |= messageConstBloomFilter
+ }
+ default:
+ ops |= messageConstBloomFilter
+ }
+ ops |= messageConstUpdateRequestParams
+ }
+ }
+ return ops
+}
+
+// getNextScheduleOffset is called after a message was sent to the peer, and we need to evaluate the next
+// scheduling time.
+func (p *Peer) getNextScheduleOffset(isRelay bool, beta time.Duration, partialMessage bool, currentTime time.Duration) (offset time.Duration, ops peersOps) {
+ if partialMessage {
+ if isRelay {
+ if p.isOutgoing {
+ if p.state == peerStateHoldsoff {
+ // we have enough time to send another message.
+ return messageTimeWindow, peerOpsReschedule
+ }
+ } else {
+ // a partial message was sent to an incoming peer
+ if p.nextStateTimestamp > time.Duration(0) {
+ if currentTime+messageTimeWindow*2 < p.nextStateTimestamp {
+ // we have enough time to send another message
+ return messageTimeWindow, peerOpsReschedule
+ }
+ // we don't have enough time to send another message.
+ next := p.nextStateTimestamp
+ p.nextStateTimestamp = 0
+ return next - currentTime, peerOpsReschedule
+ }
+ p.nextStateTimestamp = currentTime + 2*beta
+ return messageTimeWindow, peerOpsReschedule
+ }
+ } else {
+ if p.nextStateTimestamp > time.Duration(0) {
+ if currentTime+messageTimeWindow*2 < p.nextStateTimestamp {
+ // we have enough time to send another message
+ return messageTimeWindow, peerOpsReschedule
+ }
+ // we don't have enough time, so don't get into "interrupt" state,
+ // since we're already sending messages.
+ next := p.nextStateTimestamp
+ p.nextStateTimestamp = 0
+ p.messageSeriesPendingTransactions = nil
+ // move to the next state.
+ p.state = peerStateHoldsoff
+ return next - currentTime, peerOpsReschedule | peerOpsClearInterruptible
+
+ }
+ // this is the first message
+ p.nextStateTimestamp = currentTime + 2*beta
+
+ return messageTimeWindow, peerOpsReschedule
+ }
+ } else {
+ if isRelay {
+ if p.isOutgoing {
+ if p.state == peerStateHoldsoff {
+ // even that we're done now, we need to send another message that would contain the bloom filter
+ p.state = peerStateLateBloom
+
+ bloomMessageExtrapolatedSendingTime := messageTimeWindow
+ // try to improve the sending time by using the last sent bloom filter as the expected message size.
+ if p.lastSentBloomFilter.containedTxnsRange.transactionsCount > 0 {
+ lastBloomFilterSize := uint64(p.lastSentBloomFilter.encodedLength)
+ bloomMessageExtrapolatedSendingTime = time.Duration(lastBloomFilterSize * p.dataExchangeRate)
+ }
+
+ next := p.nextStateTimestamp - bloomMessageExtrapolatedSendingTime - currentTime
+ p.nextStateTimestamp = 0
+ return next, peerOpsReschedule
+ }
+ p.nextStateTimestamp = 0
+ } else {
+ // we sent a message to an incoming connection. No more data to send.
+ if p.nextStateTimestamp > time.Duration(0) {
+ next := p.nextStateTimestamp
+ p.nextStateTimestamp = 0
+ return next - currentTime, peerOpsReschedule
+ }
+ p.nextStateTimestamp = 0
+ return beta * 2, peerOpsReschedule
+ }
+ } else {
+ if p.nextStateTimestamp > time.Duration(0) {
+ next := p.nextStateTimestamp
+ p.nextStateTimestamp = 0
+ return next - currentTime, peerOpsReschedule
+ }
+ return beta, peerOpsReschedule
+ }
+ }
+ return time.Duration(0), 0
+}
+
+func (p *Peer) networkAddress() string {
+ if peerAddress, supportInterface := p.networkPeer.(networkPeerAddress); supportInterface {
+ return peerAddress.GetAddress()
+ }
+ return ""
+}
diff --git a/txnsync/peer_test.go b/txnsync/peer_test.go
new file mode 100644
index 000000000..cc45cd9a4
--- /dev/null
+++ b/txnsync/peer_test.go
@@ -0,0 +1,1000 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "fmt"
+ "reflect"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "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/pooldata"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/logging"
+ "github.com/algorand/go-algorand/test/partitiontest"
+)
+
+// TestGetSetTransactionGroupCounterTracker tests the get/set capabilities for the counter
+func TestGetSetTransactionGroupCounterTracker(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ grp := transactionGroupCounterTracker{}
+
+ a.Equal(grp.get(0, 0), uint64(0))
+
+ grp.set(0, 0, 2)
+ a.Equal(grp.get(0, 0), uint64(2))
+ grp.set(1, 0, 5)
+ a.Equal(grp.get(1, 0), uint64(5))
+
+ grp = transactionGroupCounterTracker{}
+
+ for i := 0; i < maxTransactionGroupTrackers+1; i++ {
+ grp.set(byte(i+1), 0, uint64(i+1))
+ }
+
+ a.True(reflect.DeepEqual(grp[0], requestParamsGroupCounterState{offset: 2, groupCounters: [bloomFilterRetryCount]uint64{2, 0, 0}}))
+
+ for i := 1; i < maxTransactionGroupTrackers; i++ {
+ if !reflect.DeepEqual(grp[i], requestParamsGroupCounterState{offset: byte(i + 2), groupCounters: [bloomFilterRetryCount]uint64{uint64(i + 2), 0, 0}}) {
+ t.Errorf("For value %d got: %v", i, grp[i])
+ }
+ }
+
+}
+
+// TestIndexTransactionGroupCounterTracker tests the index function specifically
+func TestIndexTransactionGroupCounterTracker(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ grp := transactionGroupCounterTracker{
+ {
+ offset: 0,
+ modulator: 0,
+ groupCounters: [bloomFilterRetryCount]uint64{},
+ },
+ {
+ offset: 1,
+ modulator: 23,
+ groupCounters: [bloomFilterRetryCount]uint64{},
+ },
+ }
+
+ a := require.New(t)
+ a.Equal(grp.index(2, 2), -1)
+ a.Equal(grp.index(0, 0), 0)
+ a.Equal(grp.index(1, 23), 1)
+}
+
+// TestRollTransactionGroupCounterTracker tests that rolling works and doesn't panic
+func TestRollTransactionGroupCounterTracker(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ defer func() {
+ if r := recover(); r != nil {
+ a.False(true, "Something panicked during TestRollTransactionGroupCounterTracker")
+ }
+ }()
+
+ grp1 := transactionGroupCounterTracker{
+ {
+ offset: 0,
+ modulator: 0,
+ groupCounters: [bloomFilterRetryCount]uint64{},
+ },
+ }
+
+ grp1.roll(0, 0)
+ grp1.roll(0, 2)
+
+ grp2 := transactionGroupCounterTracker{
+ {
+ offset: 0,
+ modulator: 0,
+ groupCounters: [bloomFilterRetryCount]uint64{0, 1},
+ },
+ }
+
+ grp2.roll(0, 0)
+ grp2.roll(0, 2)
+ a.True(grp2[0].groupCounters[0] == 0)
+ a.True(grp2[0].groupCounters[1] == 1)
+
+ grp3 := transactionGroupCounterTracker{
+ {
+ offset: 0,
+ modulator: 0,
+ groupCounters: [bloomFilterRetryCount]uint64{2, 1, 0},
+ },
+ }
+
+ grp3.roll(0, 0)
+ a.Equal(grp3[0].groupCounters, [bloomFilterRetryCount]uint64{1, 0, 2})
+ grp3.roll(0, 1)
+
+}
+
+// TestGetNextScheduleOffset tests the state machine of getNextScheduleOffset
+func TestGetNextScheduleOffset(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ type args struct {
+ isRelay bool
+ beta time.Duration
+ partialMessage bool
+ currentTime time.Duration
+ }
+
+ type results struct {
+ offset time.Duration
+ ops peersOps
+ }
+
+ tests := []struct {
+ fxn func(p *Peer)
+ arg args
+ result results
+ postFxn func(s peerState) bool
+ }{
+ {
+ fxn: func(p *Peer) { p.nextStateTimestamp = 2 * time.Millisecond },
+ arg: args{false, time.Millisecond, false, 1 * time.Millisecond},
+ result: results{1 * time.Millisecond, peerOpsReschedule},
+ postFxn: func(s peerState) bool { return true },
+ },
+
+ {
+ fxn: func(p *Peer) { p.nextStateTimestamp = 0 * time.Millisecond },
+ arg: args{false, 3 * time.Millisecond, false, 1 * time.Millisecond},
+ result: results{3 * time.Millisecond, peerOpsReschedule},
+ postFxn: func(s peerState) bool { return true },
+ },
+
+ // --
+
+ {
+ fxn: func(p *Peer) { p.isOutgoing = false; p.nextStateTimestamp = 0 * time.Millisecond },
+ arg: args{true, 3 * time.Millisecond, false, 1 * time.Millisecond},
+ result: results{6 * time.Millisecond, peerOpsReschedule},
+ postFxn: func(s peerState) bool { return true },
+ },
+
+ {
+ fxn: func(p *Peer) { p.isOutgoing = false; p.nextStateTimestamp = 9 * time.Millisecond },
+ arg: args{true, 3 * time.Millisecond, false, 1 * time.Millisecond},
+ result: results{8 * time.Millisecond, peerOpsReschedule},
+ postFxn: func(s peerState) bool { return true },
+ },
+
+ // --
+
+ {
+ fxn: func(p *Peer) { p.isOutgoing = true; p.state = peerStateLateBloom },
+ arg: args{true, 3 * time.Millisecond, false, 1 * time.Millisecond},
+ result: results{0 * time.Millisecond, 0},
+ postFxn: func(s peerState) bool { return true },
+ },
+
+ {
+ fxn: func(p *Peer) {
+ p.isOutgoing = true
+ p.state = peerStateHoldsoff
+ p.lastSentBloomFilter.containedTxnsRange.transactionsCount = 0
+ p.nextStateTimestamp = 2 * messageTimeWindow
+ },
+ arg: args{true, 3 * time.Millisecond, false, 1 * time.Millisecond},
+ result: results{messageTimeWindow - 1*time.Millisecond, peerOpsReschedule},
+ postFxn: func(s peerState) bool { return s == peerStateLateBloom },
+ },
+
+ {
+ fxn: func(p *Peer) { p.nextStateTimestamp = 0 },
+ arg: args{false, 3 * time.Millisecond, true, 1 * time.Millisecond},
+ result: results{messageTimeWindow, peerOpsReschedule},
+ postFxn: func(s peerState) bool { return true },
+ },
+
+ {
+ fxn: func(p *Peer) { p.nextStateTimestamp = messageTimeWindow * 3 },
+ arg: args{false, 3 * time.Millisecond, true, 1 * time.Millisecond},
+ result: results{messageTimeWindow, peerOpsReschedule},
+ postFxn: func(s peerState) bool { return true },
+ },
+
+ {
+ fxn: func(p *Peer) { p.nextStateTimestamp = messageTimeWindow * 2 },
+ arg: args{false, 3 * time.Millisecond, true, 1 * time.Millisecond},
+ result: results{2*messageTimeWindow - 1*time.Millisecond, peerOpsReschedule | peerOpsClearInterruptible},
+ postFxn: func(s peerState) bool { return s == peerStateHoldsoff },
+ },
+
+ // --
+
+ {
+ fxn: func(p *Peer) { p.isOutgoing = true },
+ arg: args{true, 3 * time.Millisecond, true, 1 * time.Millisecond},
+ result: results{time.Duration(0), 0},
+ postFxn: func(s peerState) bool { return true },
+ },
+
+ {
+ fxn: func(p *Peer) { p.isOutgoing = true; p.state = peerStateHoldsoff },
+ arg: args{true, 3 * time.Millisecond, true, 1 * time.Millisecond},
+ result: results{messageTimeWindow, peerOpsReschedule},
+ postFxn: func(s peerState) bool { return true },
+ },
+
+ {
+ fxn: func(p *Peer) { p.isOutgoing = false; p.nextStateTimestamp = 0 },
+ arg: args{true, 3 * time.Millisecond, true, 1 * time.Millisecond},
+ result: results{messageTimeWindow, peerOpsReschedule},
+ postFxn: func(s peerState) bool { return true },
+ },
+
+ {
+ fxn: func(p *Peer) { p.isOutgoing = false; p.nextStateTimestamp = 9 * time.Millisecond },
+ arg: args{true, 3 * time.Millisecond, true, 1 * time.Millisecond},
+ result: results{8 * time.Millisecond, peerOpsReschedule},
+ postFxn: func(s peerState) bool { return true },
+ },
+ }
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+
+ for i, test := range tests {
+ t.Run(fmt.Sprint(i), func(t *testing.T) {
+ p := makePeer(nil, true, true, &config, log)
+ if test.fxn != nil {
+ test.fxn(p)
+ }
+
+ offset, ops := p.getNextScheduleOffset(test.arg.isRelay, test.arg.beta, test.arg.partialMessage, test.arg.currentTime)
+
+ r := results{offset, ops}
+
+ if !test.postFxn(p.state) {
+ t.Errorf("getNextScheduleOffset() state = %v", p.state)
+ }
+
+ if !reflect.DeepEqual(r, test.result) {
+ t.Errorf("getNextScheduleOffset() = %v, want %v", r, test.result)
+ }
+
+ })
+ }
+
+}
+
+// TestGetMessageConstructionOps tests the state machine of getMessageConstructionOps
+func TestGetMessageConstructionOps(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ type args struct {
+ isRelay bool
+ fetchTransactions bool
+ }
+
+ peerStateLateBloomState := peerStateLateBloom
+ peerStateHoldsoffState := peerStateHoldsoff
+
+ tests := []struct {
+ fxn func(p *Peer)
+ arg args
+ result messageConstructionOps
+ state *peerState
+ }{
+ {
+ fxn: func(p *Peer) {},
+ arg: args{false, false},
+ result: messageConstTransactions,
+ state: nil,
+ },
+ {
+ fxn: func(p *Peer) { p.localTransactionsModulator = 0 },
+ arg: args{false, true},
+ result: messageConstUpdateRequestParams | messageConstTransactions,
+ state: nil,
+ },
+ {
+ fxn: func(p *Peer) { p.localTransactionsModulator = 1; p.nextStateTimestamp = 1 },
+ arg: args{false, true},
+ result: messageConstUpdateRequestParams | messageConstTransactions,
+ state: nil,
+ },
+ {
+ fxn: func(p *Peer) { p.localTransactionsModulator = 1; p.nextStateTimestamp = 0 },
+ arg: args{false, true},
+ result: messageConstUpdateRequestParams | messageConstTransactions | messageConstBloomFilter,
+ state: nil,
+ },
+ {
+ fxn: func(p *Peer) { p.localTransactionsModulator = 1; p.nextStateTimestamp = 99 },
+ arg: args{false, true},
+ result: messageConstUpdateRequestParams | messageConstTransactions,
+ state: nil,
+ },
+ // --
+
+ {
+ fxn: func(p *Peer) { p.isOutgoing = false; p.requestedTransactionsModulator = 0; p.nextStateTimestamp = 0 },
+ arg: args{true, true},
+ result: messageConstUpdateRequestParams | messageConstNextMinDelay,
+ state: nil,
+ },
+ {
+ fxn: func(p *Peer) { p.isOutgoing = false; p.requestedTransactionsModulator = 0; p.nextStateTimestamp = 1 },
+ arg: args{true, true},
+ result: messageConstUpdateRequestParams,
+ state: nil,
+ },
+
+ {
+ fxn: func(p *Peer) {
+ p.isOutgoing = false
+ p.localTransactionsModulator = 1
+ p.requestedTransactionsModulator = 1
+ p.nextStateTimestamp = 0
+ },
+ arg: args{true, true},
+ result: messageConstUpdateRequestParams | messageConstNextMinDelay | messageConstTransactions | messageConstBloomFilter,
+ state: nil,
+ },
+ {
+ fxn: func(p *Peer) { p.isOutgoing = false; p.requestedTransactionsModulator = 1; p.nextStateTimestamp = 1 },
+ arg: args{true, true},
+ result: messageConstUpdateRequestParams | messageConstTransactions,
+ state: nil,
+ },
+
+ // --
+
+ {
+ fxn: func(p *Peer) { p.isOutgoing = true; p.state = peerStateLateBloom; p.localTransactionsModulator = 0 },
+ arg: args{true, true},
+ result: messageConstUpdateRequestParams,
+ state: &peerStateLateBloomState,
+ },
+
+ {
+ fxn: func(p *Peer) { p.isOutgoing = true; p.state = peerStateLateBloom; p.localTransactionsModulator = 1 },
+ arg: args{true, true},
+ result: messageConstUpdateRequestParams | messageConstBloomFilter,
+ state: &peerStateLateBloomState,
+ },
+
+ {
+ fxn: func(p *Peer) { p.isOutgoing = true; p.state = peerStateHoldsoff; p.localTransactionsModulator = 1 },
+ arg: args{true, true},
+ result: messageConstUpdateRequestParams | messageConstTransactions,
+ state: &peerStateHoldsoffState,
+ },
+ }
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+ for i, test := range tests {
+ t.Run(fmt.Sprint(i), func(t *testing.T) {
+ p := makePeer(nil, true, true, &config, log)
+ if test.fxn != nil {
+ test.fxn(p)
+ }
+
+ gotOps := p.getMessageConstructionOps(test.arg.isRelay, test.arg.fetchTransactions)
+
+ if test.state != nil && p.state != *test.state {
+ t.Errorf("getMessageConstructionOps() state = %v, want %v", p.state, test.state)
+ }
+
+ if gotOps != test.result {
+ t.Errorf("getMessageConstructionOps() = %v, want %v", gotOps, test.result)
+ }
+
+ })
+ }
+
+}
+
+// TestAdvancePeerState tests the state machine of advancePeerState
+func TestAdvancePeerState(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ type args struct {
+ currentTime time.Duration
+ isRelay bool
+ }
+
+ tests := []struct {
+ fxn func(p *Peer)
+ arg args
+ result peersOps
+ state peerState
+ }{
+ {
+ fxn: func(p *Peer) { p.state = peerStateStartup },
+ arg: args{time.Millisecond, false},
+ result: peerOpsSendMessage,
+ state: peerStateHoldsoff,
+ },
+ {
+ fxn: func(p *Peer) { p.state = peerStateHoldsoff; p.nextStateTimestamp = 0 },
+ arg: args{time.Millisecond, false},
+ result: peerOpsSetInterruptible | peerOpsReschedule,
+ state: peerStateInterrupt,
+ },
+ {
+ fxn: func(p *Peer) { p.state = peerStateHoldsoff; p.nextStateTimestamp = 1 },
+ arg: args{time.Millisecond, false},
+ result: peerOpsSendMessage,
+ state: peerStateHoldsoff,
+ },
+ {
+ fxn: func(p *Peer) { p.state = peerStateInterrupt },
+ arg: args{time.Millisecond, false},
+ result: peerOpsSendMessage | peerOpsClearInterruptible,
+ state: peerStateHoldsoff,
+ },
+ // --
+ {
+ fxn: func(p *Peer) { p.isOutgoing = false; p.state = peerStateStartup },
+ arg: args{time.Millisecond, true},
+ result: peerOpsSendMessage,
+ state: peerStateHoldsoff,
+ },
+ {
+ fxn: func(p *Peer) { p.isOutgoing = false; p.state = peerStateHoldsoff },
+ arg: args{time.Millisecond, true},
+ result: peerOpsSendMessage,
+ state: peerStateHoldsoff,
+ },
+ // --
+
+ {
+ fxn: func(p *Peer) {
+ p.isOutgoing = true
+ p.state = peerStateStartup
+ p.lastReceivedMessageNextMsgMinDelay = messageTimeWindow * 2
+ },
+ arg: args{time.Millisecond, true},
+ result: peerOpsSendMessage,
+ state: peerStateLateBloom,
+ },
+ {
+ fxn: func(p *Peer) {
+ p.isOutgoing = true
+ p.state = peerStateStartup
+ p.lastReceivedMessageNextMsgMinDelay = messageTimeWindow * 3
+ },
+ arg: args{time.Millisecond, true},
+ result: peerOpsSendMessage,
+ state: peerStateHoldsoff,
+ },
+
+ {
+ fxn: func(p *Peer) {
+ p.isOutgoing = true
+ p.state = peerStateHoldsoff
+ p.nextStateTimestamp = messageTimeWindow * 2
+ },
+ arg: args{0 * time.Millisecond, true},
+ result: peerOpsSendMessage,
+ state: peerStateLateBloom,
+ },
+
+ {
+ fxn: func(p *Peer) {
+ p.isOutgoing = true
+ p.state = peerStateHoldsoff
+ p.nextStateTimestamp = messageTimeWindow * 3
+ },
+ arg: args{0 * time.Millisecond, true},
+ result: peerOpsSendMessage,
+ state: peerStateHoldsoff,
+ },
+
+ {
+ fxn: func(p *Peer) { p.isOutgoing = true; p.state = peerStateLateBloom },
+ arg: args{time.Millisecond, true},
+ result: peerOpsSendMessage,
+ state: peerStateLateBloom,
+ },
+ }
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+ for i, test := range tests {
+ t.Run(string(rune(i)), func(t *testing.T) {
+ p := makePeer(nil, true, true, &config, log)
+ if test.fxn != nil {
+ test.fxn(p)
+ }
+
+ gotOps := p.advancePeerState(test.arg.currentTime, test.arg.isRelay)
+
+ if p.state != test.state {
+ t.Errorf("advancePeerState() state = %v, want %v", p.state, test.state)
+ }
+
+ if gotOps != test.result {
+ t.Errorf("advancePeerState() = %v, want %v", gotOps, test.result)
+ }
+
+ })
+ }
+}
+
+// TestUpdateIncomingMessageTiming tests updating the incoming message timing
+func TestUpdateIncomingMessageTiming(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+ p := makePeer(nil, true, true, &config, log)
+
+ currentRound := basics.Round(1)
+ currentTime := time.Millisecond * 123
+ currentMessageSize := int(p.significantMessageThreshold)
+ timing := timingParams{NextMsgMinDelay: 42}
+
+ // Test direct assignment
+
+ p.lastConfirmedMessageSeqReceived = p.lastSentMessageSequenceNumber + 1
+
+ p.updateIncomingMessageTiming(timing, currentRound, currentTime, currentMessageSize)
+
+ a.Equal(p.lastReceivedMessageLocalRound, currentRound)
+ a.Equal(p.lastReceivedMessageTimestamp, currentTime)
+ a.Equal(p.lastReceivedMessageSize, currentMessageSize)
+ a.Equal(p.lastReceivedMessageNextMsgMinDelay, time.Duration(timing.NextMsgMinDelay)*time.Nanosecond)
+
+ // Test entering if statement
+
+ p.lastConfirmedMessageSeqReceived = p.lastSentMessageSequenceNumber
+ p.lastSentMessageRound = currentRound
+ timing.ResponseElapsedTime = 1
+ p.lastSentMessageTimestamp = 1 * time.Millisecond
+ currentMessageSize = maxDataExchangeRateThreshold + 1
+ p.updateIncomingMessageTiming(timing, currentRound, currentTime, currentMessageSize)
+
+ a.Equal(uint64(maxDataExchangeRateThreshold), p.dataExchangeRate)
+
+ p.lastConfirmedMessageSeqReceived = p.lastSentMessageSequenceNumber
+ p.lastSentMessageRound = currentRound
+ timing.ResponseElapsedTime = 1
+ p.lastSentMessageTimestamp = 1 * time.Millisecond
+ p.lastSentMessageSize = 0
+ currentMessageSize = int(p.significantMessageThreshold)
+ currentTime = time.Millisecond * 1000
+ p.updateIncomingMessageTiming(timing, currentRound, currentTime, currentMessageSize)
+
+ a.Equal(uint64(minDataExchangeRateThreshold), p.dataExchangeRate)
+}
+
+// TestUpdateIncomingTransactionGroups tests updating the incoming transaction groups
+func TestUpdateIncomingTransactionGroups(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ var txnGroups []pooldata.SignedTxGroup
+
+ for i := 0; i < 10; i++ {
+
+ tmp := pooldata.SignedTxGroup{
+ Transactions: []transactions.SignedTxn{transactions.SignedTxn{
+ Sig: crypto.Signature{},
+ Msig: crypto.MultisigSig{},
+ Lsig: transactions.LogicSig{},
+ Txn: transactions.Transaction{},
+ AuthAddr: basics.Address{},
+ }},
+ LocallyOriginated: false,
+ GroupCounter: 0,
+ GroupTransactionID: transactions.Txid{byte(i)},
+ EncodedLength: 0,
+ }
+ txnGroups = append(txnGroups, tmp)
+ }
+
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+ p := makePeer(nil, true, true, &config, log)
+
+ p.recentSentTransactions.reset()
+
+ for i := 0; i < 10; i++ {
+ txid := transactions.Txid{byte(i)}
+ a.False(p.recentSentTransactions.contained(txid))
+ }
+
+}
+
+// TestUpdateRequestParams tests updating the request parameters
+func TestUpdateRequestParams(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+ p := makePeer(nil, true, true, &config, log)
+ oldModulator := p.requestedTransactionsModulator
+ oldOffset := p.requestedTransactionsOffset
+
+ p.updateRequestParams(oldModulator, oldOffset)
+ a.Equal(p.requestedTransactionsModulator, oldModulator)
+ a.Equal(p.requestedTransactionsOffset, oldOffset)
+
+ p.updateRequestParams(oldModulator+1, oldOffset+1)
+ a.Equal(p.requestedTransactionsModulator, oldModulator+1)
+ a.Equal(p.requestedTransactionsOffset, oldOffset+1)
+
+}
+
+// bloom.GenericFilter
+type nopFilter struct{}
+
+func (nf *nopFilter) Set(x []byte) {}
+func (nf *nopFilter) Test(x []byte) bool {
+ return false
+}
+func (nf *nopFilter) MarshalBinary() ([]byte, error) {
+ return nil, nil
+}
+func (nf *nopFilter) UnmarshalBinary(data []byte) error {
+ return nil
+}
+
+// TestAddIncomingBloomFilter tests adding an incoming bloom filter
+func TestAddIncomingBloomFilter(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+ p := makePeer(nil, true, true, &config, log)
+
+ for i := 0; i < 2*maxIncomingBloomFilterHistory; i++ {
+ bf := &testableBloomFilter{
+ encodingParams: requestParams{
+ _struct: struct{}{},
+ Offset: byte(i),
+ Modulator: 0,
+ },
+ filter: &nopFilter{},
+ }
+ p.addIncomingBloomFilter(basics.Round(i), bf, basics.Round(i))
+ }
+
+ // filters from current round, -1, and -2 are kept. => 3
+ a.Equal(3, len(p.recentIncomingBloomFilters))
+
+ for i := 0; i < 2*maxIncomingBloomFilterHistory; i++ {
+ bf := &testableBloomFilter{
+ encodingParams: requestParams{
+ _struct: struct{}{},
+ Offset: byte(i),
+ Modulator: 0,
+ },
+ filter: &nopFilter{},
+ }
+ p.addIncomingBloomFilter(basics.Round(i), bf, 0)
+ }
+
+ a.Equal(maxIncomingBloomFilterHistory, len(p.recentIncomingBloomFilters))
+}
+
+// TestSelectPendingTransactions tests selectPendingTransactions
+func TestSelectPendingTransactions(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ type args struct {
+ pendingTransactions []pooldata.SignedTxGroup
+ sendWindow time.Duration
+ round basics.Round
+ bloomFilterSize int
+ }
+
+ type results struct {
+ selectedTxns []pooldata.SignedTxGroup
+ selectedTxnIDs []transactions.Txid
+ partialTransactionsSet bool
+ }
+
+ tests := []struct {
+ name string
+ fxn func(p *Peer)
+ arg args
+ result results
+ }{
+ {"Case 1", func(p *Peer) { p.lastRound = 98 }, args{nil, time.Millisecond, 100, 0}, results{nil, nil, false}},
+ {"Case 2", func(p *Peer) { p.lastRound = 101; p.requestedTransactionsModulator = 0 }, args{nil, time.Millisecond, 100, 0}, results{nil, nil, false}},
+ {"Case 3", func(p *Peer) { p.lastRound = 200; p.messageSeriesPendingTransactions = nil }, args{[]pooldata.SignedTxGroup{}, time.Millisecond, 100, 0}, results{nil, nil, false}},
+ }
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ p := makePeer(nil, true, true, &config, log)
+ if test.fxn != nil {
+ test.fxn(p)
+ }
+ var r results
+ r.selectedTxns, r.selectedTxnIDs, r.partialTransactionsSet = p.selectPendingTransactions(test.arg.pendingTransactions, test.arg.sendWindow, test.arg.round, test.arg.bloomFilterSize)
+ if !reflect.DeepEqual(r, test.result) {
+ t.Errorf("selectPendingTransactions() gotSelectedTxns = %v, want %v", r, test.result)
+ }
+ })
+ }
+}
+
+// TestSelectedMessagesModulator tests the use of the modulator on the returned list
+func TestSelectedMessagesModulator(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ peer := Peer{}
+
+ peer.lastRound = 10
+ peer.requestedTransactionsModulator = 2
+ peer.requestedTransactionsOffset = 1
+ peer.lastSelectedTransactionsCount = 1
+ peer.dataExchangeRate = 1000
+ peer.recentSentTransactions = makeTransactionCache(10, 10, 0)
+
+ dig1 := crypto.Digest{0x1, 0, 0, 0, 0, 0, 0, 0, 0}
+ dig2 := crypto.Digest{0x2, 0, 0, 0, 0, 0, 0, 0, 0}
+ dig3 := crypto.Digest{0x3, 0, 0, 0, 0, 0, 0, 0, 0}
+ dig4 := crypto.Digest{0x4, 0, 0, 0, 0, 0, 0, 0, 0}
+ dig5 := crypto.Digest{0x5, 0, 0, 0, 0, 0, 0, 0, 0}
+ dig6 := crypto.Digest{0x6, 0, 0, 0, 0, 0, 0, 0, 0}
+
+ a.Equal(txidToUint64(transactions.Txid(dig1)), uint64(1))
+ a.Equal(txidToUint64(transactions.Txid(dig2)), uint64(2))
+ a.Equal(txidToUint64(transactions.Txid(dig3)), uint64(3))
+ a.Equal(txidToUint64(transactions.Txid(dig4)), uint64(4))
+ a.Equal(txidToUint64(transactions.Txid(dig5)), uint64(5))
+ a.Equal(txidToUint64(transactions.Txid(dig6)), uint64(6))
+
+ pendingTransations := []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{GroupCounter: 1, GroupTransactionID: transactions.Txid(dig1), EncodedLength: 1},
+ pooldata.SignedTxGroup{GroupCounter: 2, GroupTransactionID: transactions.Txid(dig2), EncodedLength: 1},
+ pooldata.SignedTxGroup{GroupCounter: 3, GroupTransactionID: transactions.Txid(dig3), EncodedLength: 1},
+ pooldata.SignedTxGroup{GroupCounter: 4, GroupTransactionID: transactions.Txid(dig4), EncodedLength: 1},
+ pooldata.SignedTxGroup{GroupCounter: 5, GroupTransactionID: transactions.Txid(dig5), EncodedLength: 1},
+ pooldata.SignedTxGroup{GroupCounter: 6, GroupTransactionID: transactions.Txid(dig6), EncodedLength: 1},
+ }
+
+ selectedTxns, _, _ := peer.selectPendingTransactions(pendingTransations, time.Millisecond, 5, 0)
+
+ a.Equal(len(selectedTxns), 2)
+ a.Equal(selectedTxns[0].GroupCounter, uint64(1))
+ a.Equal(selectedTxns[1].GroupCounter, uint64(3))
+
+}
+
+// TestGetAcceptedMessages tests get accepted messages
+func TestGetAcceptedMessages(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+ p := makePeer(nil, true, true, &config, log)
+
+ var testList []uint64
+ chPtr := &p.transactionPoolAckCh
+
+ for i := uint64(0); i < maxAcceptedMsgSeq; i++ {
+ *chPtr <- i
+ testList = append(testList, i)
+ }
+
+ a.Equal(len(*chPtr), 64)
+ a.Equal(p.getAcceptedMessages(), testList)
+ a.Equal(len(*chPtr), 0)
+ a.Equal(len(p.transactionPoolAckMessages), 0)
+
+}
+
+// TestDequeuePendingTransactionPoolAckMessages tests dequeuePendingTransactionPoolAckMessages
+func TestDequeuePendingTransactionPoolAckMessages(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+ p := makePeer(nil, true, true, &config, log)
+
+ ch := p.transactionPoolAckCh
+ var testList []uint64
+
+ for i := uint64(0); i < maxAcceptedMsgSeq; i++ {
+ ch <- i
+ testList = append(testList, i)
+ }
+
+ p.dequeuePendingTransactionPoolAckMessages()
+
+ a.Equal(p.transactionPoolAckMessages, testList)
+
+ testList = testList[:0]
+
+ ch = p.transactionPoolAckCh
+
+ // Note the +1
+ for i := uint64(0); i < (maxAcceptedMsgSeq + 1); i++ {
+ if i >= maxAcceptedMsgSeq {
+ // Channel is bounded at maxAcceptedMsgSeq so we need to flush it
+ p.dequeuePendingTransactionPoolAckMessages()
+ testList = append(testList[1:], i)
+ } else {
+ testList = append(testList, i)
+ }
+
+ ch <- i
+ }
+
+ p.dequeuePendingTransactionPoolAckMessages()
+
+ a.Equal(p.transactionPoolAckMessages, testList)
+
+}
+
+// TestUpdateMessageSent Tests whether we can update the messages sent fields
+func TestUpdateMessageSent(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+ p := makePeer(nil, true, true, &config, log)
+
+ txMsg := &transactionBlockMessage{
+ Version: txnBlockMessageVersion,
+ Round: 42,
+ }
+
+ txnIds := []transactions.Txid{transactions.Txid(crypto.Hash([]byte{0x31, 0x32}))}
+ timestamp := 10 * time.Second
+ sequenceNumber := uint64(23)
+ messageSize := 35
+ bFilter := bloomFilter{}
+
+ a.False(p.recentSentTransactions.contained(txnIds[0]))
+
+ p.updateMessageSent(txMsg, txnIds, timestamp, sequenceNumber, messageSize)
+
+ a.True(p.recentSentTransactions.contained(txnIds[0]))
+ a.Equal(p.lastSentMessageSequenceNumber, sequenceNumber)
+ a.Equal(p.lastSentMessageRound, txMsg.Round)
+ a.Equal(p.lastSentMessageTimestamp, timestamp)
+ a.Equal(p.lastSentMessageSize, messageSize)
+
+ p.updateSentBoomFilter(bFilter, 0)
+
+ a.Equal(p.lastSentBloomFilter, bFilter)
+
+}
+
+// TestIncomingPeersOnly Tests whether we can extract outgoing peers only
+func TestIncomingPeersOnly(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+ p1 := makePeer(nil, true, true, &config, log)
+ p2 := makePeer(nil, true, false, &config, log)
+ p3 := makePeer(nil, false, true, &config, log)
+ p4 := makePeer(nil, false, false, &config, log)
+
+ peers := []*Peer{p1, p2, p3, p4}
+
+ incomingPeers := incomingPeersOnly(peers)
+
+ a.Equal(len(incomingPeers), 2)
+ a.Equal(incomingPeers[0], p3)
+ a.Equal(incomingPeers[1], p4)
+}
+
+// TestLocalRequestParams Tests setting and getting local request params
+func TestLocalRequestParams(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+ p := makePeer(nil, true, true, &config, log)
+
+ p.setLocalRequestParams(256, 256)
+ offset, modulator := p.getLocalRequestParams()
+ a.Equal(offset, uint8(1))
+ a.Equal(modulator, uint8(255))
+
+ p.setLocalRequestParams(23, 256)
+ offset, modulator = p.getLocalRequestParams()
+ a.Equal(offset, uint8(23))
+ a.Equal(modulator, uint8(255))
+
+}
+
+// TestSimpleGetters Tests the "simple" getters for the Peer Object
+func TestSimpleGetters(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+ var sentinelInterface interface{}
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+ p := makePeer(sentinelInterface, true, true, &config, log)
+
+ a.Equal(p.GetNetworkPeer(), sentinelInterface)
+ a.Equal(p.GetTransactionPoolAckChannel(), p.transactionPoolAckCh)
+}
+
+// TestMakePeer Tests the Peer factory function
+func TestMakePeer(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ var sentinelInterface interface{}
+ config := config.GetDefaultLocal()
+ tlog := logging.TestingLog(t)
+ log := wrapLogger(tlog, &config)
+ p1 := makePeer(sentinelInterface, true, true, &config, log)
+
+ a.NotNil(p1)
+ a.Equal(p1.networkPeer, sentinelInterface)
+ a.Equal(p1.isOutgoing, true)
+ a.Equal(p1.recentSentTransactions, makeTransactionCache(shortTermRecentTransactionsSentBufferLength, longTermRecentTransactionsSentBufferLength, pendingUnconfirmedRemoteMessages))
+ a.Equal(p1.requestedTransactionsModulator, uint8(1))
+ a.Equal(p1.dataExchangeRate, uint64(defaultRelayToRelayDataExchangeRate))
+
+ // Check that we have different values if the local node relay is false
+ p2 := makePeer(sentinelInterface, true, false, &config, log)
+
+ a.NotNil(p2)
+ a.Equal(p1.networkPeer, sentinelInterface)
+ a.Equal(p1.isOutgoing, true)
+ a.Equal(p1.recentSentTransactions, makeTransactionCache(shortTermRecentTransactionsSentBufferLength, longTermRecentTransactionsSentBufferLength, pendingUnconfirmedRemoteMessages))
+ a.Equal(p2.requestedTransactionsModulator, uint8(0))
+ a.Equal(p2.dataExchangeRate, uint64(defaultDataExchangeRate))
+
+}
diff --git a/txnsync/peerscheduler.go b/txnsync/peerscheduler.go
new file mode 100644
index 000000000..fc1481c85
--- /dev/null
+++ b/txnsync/peerscheduler.go
@@ -0,0 +1,200 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "container/heap"
+ "sort"
+ "time"
+)
+
+//msgp:ignore peerBuckets
+type peerBuckets []peerBucket
+
+type peerScheduler struct {
+ peers peerBuckets
+ nextPeers map[*Peer][]int // nextPeers holds an array of ordered indices where this Peer object is on the peers peerBuckets
+ node NodeConnector
+}
+
+// makePeerScheduler initializes a peer scheduler object.
+func makePeerScheduler() peerScheduler {
+ return peerScheduler{
+ nextPeers: make(map[*Peer][]int),
+ }
+}
+
+//msgp:ignore peerBucket
+type peerBucket struct {
+ peer *Peer
+ next time.Duration
+}
+
+// Push implements heap.Interface
+func (p *peerScheduler) Push(x interface{}) {
+ entry := x.(peerBucket)
+ p.peers = append(p.peers, entry)
+ p.nextPeers[entry.peer] = append(p.nextPeers[entry.peer], len(p.peers)-1)
+
+ if len(p.nextPeers[entry.peer]) > 1 {
+ peerIndices := p.nextPeers[entry.peer]
+ sort.Slice(peerIndices, func(i, j int) bool {
+ return p.peers[peerIndices[i]].next < p.peers[peerIndices[j]].next
+ })
+ }
+
+}
+
+// Pop implements heap.Interface
+func (p *peerScheduler) Pop() interface{} {
+ end := len(p.peers) - 1
+ res := p.peers[end]
+
+ // delete from the map only if it's the last entry
+ peerIndices := p.nextPeers[res.peer]
+
+ if peerIndices[0] != end {
+ // this case is possible when the peer has two elements in p.peers.
+ // and both have the same next value.
+ for idx, x := range peerIndices {
+ if x == end {
+ peerIndices[0], peerIndices[idx] = peerIndices[idx], peerIndices[0]
+ break
+ }
+ }
+ }
+ // the peer index must be the first entry.
+ peerIndices = peerIndices[1:]
+
+ // store if non-empty.
+ if len(peerIndices) > 0 {
+ p.nextPeers[res.peer] = peerIndices
+ } else {
+ delete(p.nextPeers, res.peer)
+ }
+
+ p.peers[end] = peerBucket{}
+ p.peers = p.peers[0:end]
+ return res
+}
+
+// Len implements heap.Interface
+func (p *peerScheduler) Len() int {
+ return len(p.peers)
+}
+
+func (p *peerScheduler) replaceIndices(indices []int, i, j int) {
+
+ for idx, x := range indices {
+ if x == i {
+ indices[idx] = j
+ } else if x == j {
+ indices[idx] = i
+ }
+ }
+ sort.Slice(indices, func(i, j int) bool {
+ return p.peers[indices[i]].next < p.peers[indices[j]].next
+ })
+}
+
+// Swap implements heap.Interface
+func (p *peerScheduler) Swap(i, j int) {
+ p.peers[i], p.peers[j] = p.peers[j], p.peers[i]
+ if p.peers[i].peer == p.peers[j].peer {
+ indices := p.nextPeers[p.peers[i].peer]
+ sort.Slice(indices, func(x, y int) bool {
+ return p.peers[indices[x]].next < p.peers[indices[y]].next
+ })
+ return
+ }
+ p.replaceIndices(p.nextPeers[p.peers[i].peer], i, j)
+ p.replaceIndices(p.nextPeers[p.peers[j].peer], i, j)
+}
+
+// Less implements heap.Interface
+func (p *peerScheduler) Less(i, j int) bool {
+ return p.peers[i].next < p.peers[j].next
+}
+
+// refresh the current schedule by creating new schedule for each of the peers.
+func (p *peerScheduler) scheduleNewRound(peers []*Peer) {
+ // clear the existings peers list.
+ p.peers = make(peerBuckets, 0, len(peers))
+ p.nextPeers = make(map[*Peer][]int)
+ for _, peer := range peers {
+ peerEntry := peerBucket{peer: peer}
+ peerEntry.next = kickoffTime + time.Duration(p.node.Random(uint64(randomRange)))
+
+ p.peers = append(p.peers, peerEntry)
+ p.nextPeers[peer] = []int{len(p.peers) - 1}
+ }
+ heap.Init(p)
+}
+
+func (p *peerScheduler) nextDuration() time.Duration {
+ if len(p.peers) == 0 {
+ return time.Duration(0)
+ }
+ return p.peers[0].next
+}
+
+func (p *peerScheduler) getNextPeers() (outPeers []*Peer) {
+ next := p.nextDuration()
+
+ // pull out of the heap all the entries that have next smaller or equal to the above next.
+ for len(p.peers) > 0 && p.peers[0].next <= next {
+ bucket := heap.Remove(p, 0).(peerBucket)
+ outPeers = append(outPeers, bucket.peer)
+ }
+
+ // in many cases, we'll have only a single peer; however, in case we have multiple
+ // ( which is more likely when we're "running late" ), we want to make sure to remove
+ // duplicate ones.
+ if len(outPeers) > 1 {
+ // note that the algorithm here ensures that we retain the peer order from above
+ // while dropping off recurring peers.
+ peersMap := make(map[*Peer]bool, len(outPeers))
+ offset := 0
+ peersMap[outPeers[0]] = true
+ for i := 1; i < len(outPeers); i++ {
+ if peersMap[outPeers[i]] {
+ // we already had this peer.
+ offset++
+ continue
+ }
+ // we haven't seen this peer.
+ outPeers[i-offset] = outPeers[i]
+ peersMap[outPeers[i]] = true
+ }
+ outPeers = outPeers[:len(outPeers)-offset]
+ }
+ return
+}
+
+func (p *peerScheduler) schedulePeer(peer *Peer, next time.Duration) {
+ bucket := peerBucket{peer: peer, next: next}
+ heap.Push(p, bucket)
+}
+
+func (p *peerScheduler) peerDuration(peer *Peer) time.Duration {
+ peerIndices := p.nextPeers[peer]
+ if len(peerIndices) == 0 {
+ return time.Duration(0)
+ }
+ bucket := heap.Remove(p, peerIndices[0]).(peerBucket)
+ return bucket.next
+}
diff --git a/txnsync/peerscheduler_test.go b/txnsync/peerscheduler_test.go
new file mode 100644
index 000000000..7da6a0dd0
--- /dev/null
+++ b/txnsync/peerscheduler_test.go
@@ -0,0 +1,283 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "math"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/test/partitiontest"
+)
+
+// TestBasics tests that the push, pop, len, swap and less functions perform appropriately
+func TestBasics(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ ps := makePeerScheduler()
+
+ require.Equal(t, 0, ps.Len())
+
+ peers := []Peer{
+ Peer{
+ lastSentMessageSequenceNumber: 123,
+ },
+ Peer{
+ lastSentMessageSequenceNumber: 456,
+ },
+ }
+
+ ps.Push(peerBucket{&peers[0], 0 * time.Millisecond})
+ ps.Push(peerBucket{&peers[1], 1 * time.Millisecond})
+
+ require.Equal(t, 2, ps.Len())
+
+ require.Equal(t, uint64(123), ps.peers[0].peer.lastSentMessageSequenceNumber)
+ require.Equal(t, uint64(456), ps.peers[1].peer.lastSentMessageSequenceNumber)
+ require.True(t, ps.Less(0, 1))
+
+ ps.Swap(0, 1)
+ require.Equal(t, uint64(123), ps.peers[1].peer.lastSentMessageSequenceNumber)
+ require.Equal(t, uint64(456), ps.peers[0].peer.lastSentMessageSequenceNumber)
+ require.True(t, ps.Less(1, 0))
+
+ backPeer := ps.Pop().(peerBucket)
+
+ require.Equal(t, uint64(123), backPeer.peer.lastSentMessageSequenceNumber)
+
+ backPeer = ps.Pop().(peerBucket)
+
+ require.Equal(t, uint64(456), backPeer.peer.lastSentMessageSequenceNumber)
+
+ require.Equal(t, 0, ps.Len())
+}
+
+// TestSchedulerBasics tests the basic scheduler helper functions
+func TestSchedulerBasics(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ ps := makePeerScheduler()
+
+ peers := []Peer{
+ Peer{
+ lastSentMessageSequenceNumber: 123,
+ },
+ Peer{
+ lastSentMessageSequenceNumber: 456,
+ },
+ Peer{
+ lastSentMessageSequenceNumber: 789,
+ },
+ }
+
+ require.Equal(t, 0*time.Millisecond, ps.nextDuration())
+ ps.schedulePeer(&peers[0], 2*time.Millisecond)
+ ps.schedulePeer(&peers[1], 1*time.Millisecond)
+ ps.schedulePeer(&peers[2], 3*time.Millisecond)
+
+ require.Equal(t, 3, ps.Len())
+
+ require.Equal(t, 1*time.Millisecond, ps.nextDuration())
+
+ require.Equal(t, 3*time.Millisecond, ps.peerDuration(&peers[2]))
+ require.Equal(t, 2, ps.Len())
+
+ require.Equal(t, 1*time.Millisecond, ps.peerDuration(&peers[1]))
+ require.Equal(t, 1, ps.Len())
+
+ require.Equal(t, 2*time.Millisecond, ps.peerDuration(&peers[0]))
+ require.Equal(t, 0, ps.Len())
+
+ require.Equal(t, 0*time.Millisecond, ps.peerDuration(&peers[0]))
+}
+
+// TestScheduleNewRound tests the scheduleNewRound method
+func TestScheduleNewRound(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ ps := makePeerScheduler()
+ ps.node = &mockNodeConnector{}
+
+ peers := []Peer{
+ Peer{
+ lastSentMessageSequenceNumber: 123,
+ },
+ Peer{
+ lastSentMessageSequenceNumber: 456,
+ },
+ Peer{
+ lastSentMessageSequenceNumber: 789,
+ },
+ }
+
+ peers2 := []Peer{
+ Peer{
+ lastSentMessageSequenceNumber: 321,
+ },
+ Peer{
+ lastSentMessageSequenceNumber: 654,
+ },
+ Peer{
+ lastSentMessageSequenceNumber: 987,
+ },
+ Peer{
+ lastSentMessageSequenceNumber: 146,
+ },
+ }
+
+ ps.schedulePeer(&peers[0], 2*time.Millisecond)
+ ps.schedulePeer(&peers[1], 1*time.Millisecond)
+ ps.schedulePeer(&peers[2], 3*time.Millisecond)
+ require.Equal(t, 3, ps.Len())
+
+ ps.scheduleNewRound([]*Peer{&peers2[0], &peers2[1], &peers2[2], &peers2[3]})
+ require.Equal(t, 4, ps.Len())
+
+}
+
+// TestNextPeers tests that the nextPeers function
+func TestNextPeers(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ ps := makePeerScheduler()
+ ps.node = &mockNodeConnector{}
+
+ peers := []Peer{
+ Peer{
+ lastSentMessageSequenceNumber: 1,
+ },
+ Peer{
+ lastSentMessageSequenceNumber: 2,
+ },
+ Peer{
+ lastSentMessageSequenceNumber: 3,
+ },
+ }
+
+ ps.schedulePeer(&peers[0], 1*time.Millisecond)
+ ps.schedulePeer(&peers[1], 2*time.Millisecond)
+ ps.schedulePeer(&peers[1], 2*time.Millisecond)
+ ps.schedulePeer(&peers[2], 2*time.Millisecond)
+
+ require.Equal(t, 4, ps.Len())
+
+ outPeers := ps.getNextPeers()
+
+ require.Equal(t, 3, ps.Len())
+ require.Equal(t, 1, len(outPeers))
+ require.Equal(t, uint64(1), outPeers[0].lastSentMessageSequenceNumber)
+
+ outPeers = ps.getNextPeers()
+
+ require.Equal(t, 0, ps.Len())
+ require.Equal(t, 2, len(outPeers))
+ require.Equal(t, uint64(3), outPeers[0].lastSentMessageSequenceNumber)
+ require.Equal(t, uint64(2), outPeers[1].lastSentMessageSequenceNumber)
+
+}
+
+func TestNextPeersLargeSet(t *testing.T) {
+
+ partitiontest.PartitionTest(t)
+
+ ps := makePeerScheduler()
+ ps.node = &mockNodeConnector{}
+
+ numPeers := 100
+ dupTimesPerPeer := 3
+ numTimeSamples := 10
+
+ peers := make([]*Peer, 0, numPeers)
+ for x := 1; x <= numPeers; x++ {
+ peer := Peer{lastSentMessageSequenceNumber: uint64(x)}
+ peers = append(peers, &peer)
+ }
+ require.Equal(t, int64(0), int64(ps.nextDuration()))
+
+ // Add peers with random next values
+ ps.scheduleNewRound(peers)
+ checkMonotonicNexts(&ps, t)
+ checkIndexMatch(&ps, t)
+
+ // Add nexts with defined values to guarantee duplicate values
+ for dups := 0; dups < dupTimesPerPeer; dups++ {
+ for x := 1; x <= numTimeSamples; x++ {
+ for p := 0; p < len(peers); p++ {
+ val := int64(math.Abs(math.Sin(float64(x))) * 100.00)
+ ps.schedulePeer(peers[p], time.Millisecond*time.Duration(val))
+ }
+ }
+ }
+ outPeers := ps.getNextPeers()
+ require.Equal(t, numPeers, len(outPeers))
+ checkMonotonicNexts(&ps, t)
+ checkIndexMatch(&ps, t)
+
+ // Repeatedly schedule and remove peers, and varify the invariants are honored
+ for dups := 0; dups < dupTimesPerPeer; dups++ {
+ for x := 1; x <= numTimeSamples*numPeers; {
+ for p := 0; p < len(peers); p++ {
+ val := int64(math.Abs(math.Sin(float64(x))) * 10.00)
+ ps.schedulePeer(peers[p], time.Millisecond*time.Duration(val))
+ x++
+ }
+ checkMonotonicNexts(&ps, t)
+ checkIndexMatch(&ps, t)
+ outPeers := ps.getNextPeers()
+ require.GreaterOrEqual(t, len(outPeers), 0)
+ }
+ }
+
+ // Drain the peers and make sure goes down to 0 without errors
+ for _, peerB := range ps.peers {
+ prev := int64(0)
+ for {
+ dur := int64(ps.peerDuration(peerB.peer))
+ if dur == 0 {
+ break
+ }
+ require.GreaterOrEqual(t, dur, prev)
+ prev = dur
+ }
+ checkMonotonicNexts(&ps, t)
+ checkIndexMatch(&ps, t)
+ }
+}
+
+func checkMonotonicNexts(ps *peerScheduler, t *testing.T) {
+ for _, s := range ps.nextPeers {
+ prevIdx := -1
+ for _, idx := range s {
+ if prevIdx == -1 {
+ prevIdx = idx
+ }
+ require.LessOrEqual(t, int64(ps.peers[prevIdx].next), int64(ps.peers[idx].next))
+ prevIdx = idx
+ }
+ }
+}
+
+func checkIndexMatch(ps *peerScheduler, t *testing.T) {
+ for peer, s := range ps.nextPeers {
+ for _, peerIdx := range s {
+ require.Equal(t, peer, ps.peers[peerIdx].peer)
+
+ }
+ }
+}
diff --git a/txnsync/profiler.go b/txnsync/profiler.go
new file mode 100644
index 000000000..0332faa3a
--- /dev/null
+++ b/txnsync/profiler.go
@@ -0,0 +1,210 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "time"
+
+ "github.com/algorand/go-algorand/logging"
+ "github.com/algorand/go-algorand/logging/telemetryspec"
+ "github.com/algorand/go-algorand/util/timers"
+)
+
+//msgp:ignore profElements
+type profElements int
+
+const (
+ profElementIdle = iota
+ profElementTxChange
+ profElementNewRound
+ profElementPeerState
+ profElementIncomingMsg
+ profElementOutgoingMsg
+ profElementNextOffset
+
+ // detached elements
+ profElementGetTxnsGroups
+ profElementAssembleMessage
+ profElementMakeBloomFilter
+ profElementTxnsSelection
+
+ profElementLast
+ profFirstDetachedElement = profElementGetTxnsGroups
+)
+
+// The profiler struct provides profiling information regarding the main loop performance
+// characteristics. Using it provides statistics information about the recent duty cycle utilization,
+// that could be used when trying to throttle the accuracy and performance of the transaction sync.
+type profiler struct {
+ // clock used as the source clock for measurements.
+ clock timers.WallClock
+ // elements contains the elements we want to measure. The user of this struct would not interact
+ // with this variable directly. Instead, he/she would use getElement to get the element for a specific
+ // profElements and use the start()/end() methods on that element.
+ elements []*element
+ // log is used to report the outcome of the measuring.
+ log logging.Logger
+
+ // profile contains all the elements indices, in order of arrival. It allows us to maintain a moving window.
+ profile []int
+ // profileSum is the total amount of time tracked by the profile array.
+ profileSum time.Duration
+ // profileSpan is the max span of the array ( or - the window ) that we would like to maintain.
+ profileSpan time.Duration
+ // lastProfileLog is the last time we've logged to the telemetry.
+ lastProfileLog time.Duration
+ // logInterval defines what is the frequency at which we send an event to the telemetry. Zero to disable.
+ logInterval time.Duration
+}
+
+// element represent a single tracked element that would be profiled.
+type element struct {
+ // id is the index of the element in the profiler's elements array.
+ id int
+ // lastStart is the timestamp of the last time we called "start"
+ lastStart time.Duration
+ // profiler points to the parent profiler.
+ profiler *profiler
+ // times contains the times we've monitored for this element.
+ times []time.Duration
+ // total is the total accumulated time for this element ( i.e. sum(times) )
+ total time.Duration
+ // detached indicate whether this is a detached elements or not. Detached elements don't add to the total amount of time
+ // counted by the profiler, allowing them to overlap with other elements.
+ detached bool
+}
+
+func makeProfiler(span time.Duration, clock timers.WallClock, log logging.Logger, logInterval time.Duration) *profiler {
+ prof := &profiler{
+ profileSpan: span,
+ clock: clock,
+ log: log,
+ logInterval: logInterval,
+ }
+ prof.createElements()
+ return prof
+}
+
+func (p *profiler) createElements() {
+ for element := 0; element < profElementLast; element++ {
+ p.createElement(element >= profFirstDetachedElement)
+ }
+}
+
+func (p *profiler) createElement(detached bool) *element {
+ i := len(p.elements)
+ e := &element{
+ id: i,
+ profiler: p,
+ detached: detached,
+ }
+ p.elements = append(p.elements, e)
+ return e
+}
+
+func (p *profiler) getElement(el profElements) *element {
+ return p.elements[el]
+}
+
+func (p *profiler) prune() {
+ for p.profileSum > p.profileSpan {
+ // remove the first elements from the profile.
+ i := p.profile[0]
+ e := p.elements[i]
+ dt := e.times[0]
+
+ e.total -= dt
+ if !e.detached {
+ p.profileSum -= dt
+ }
+
+ p.profile = p.profile[1:]
+ e.times = e.times[1:]
+ }
+}
+
+func (p *profiler) maybeLogProfile() {
+ // do we have the log profile enabled ?
+ if p.logInterval == 0 {
+ return
+ }
+ // do we have enough samples ? ( i.e. at least 50% sample time )
+ if p.profileSum < p.profileSpan/2 {
+ return
+ }
+ // have we sent metrics recently ?
+ curTime := p.clock.Since()
+ if curTime-p.lastProfileLog <= p.logInterval {
+ return
+ }
+ p.lastProfileLog = curTime
+ p.logProfile()
+}
+
+func (p *profiler) logProfile() {
+ metrics := telemetryspec.TransactionSyncProfilingMetrics{
+ TotalOps: uint64(len(p.profile)),
+ IdleOps: uint64(len(p.elements[profElementIdle].times)),
+ TransactionPoolChangedOps: uint64(len(p.elements[profElementTxChange].times)),
+ NewRoundOps: uint64(len(p.elements[profElementNewRound].times)),
+ PeerStateOps: uint64(len(p.elements[profElementPeerState].times)),
+ IncomingMsgOps: uint64(len(p.elements[profElementIncomingMsg].times)),
+ OutgoingMsgOps: uint64(len(p.elements[profElementOutgoingMsg].times)),
+ NextOffsetOps: uint64(len(p.elements[profElementNextOffset].times)),
+ GetTxnGroupsOps: uint64(len(p.elements[profElementGetTxnsGroups].times)),
+ AssembleMessageOps: uint64(len(p.elements[profElementAssembleMessage].times)),
+ MakeBloomFilterOps: uint64(len(p.elements[profElementMakeBloomFilter].times)),
+ SelectPendingTransactionsOps: uint64(len(p.elements[profElementTxnsSelection].times)),
+
+ TotalDuration: p.profileSum,
+ IdlePercent: float64(p.elements[profElementIdle].total) * 100.0 / float64(p.profileSum),
+ TransactionPoolChangedPercent: float64(p.elements[profElementTxChange].total) * 100.0 / float64(p.profileSum),
+ NewRoundPercent: float64(p.elements[profElementNewRound].total) * 100.0 / float64(p.profileSum),
+ PeerStatePercent: float64(p.elements[profElementPeerState].total) * 100.0 / float64(p.profileSum),
+ IncomingMsgPercent: float64(p.elements[profElementIncomingMsg].total) * 100.0 / float64(p.profileSum),
+ OutgoingMsgPercent: float64(p.elements[profElementOutgoingMsg].total) * 100.0 / float64(p.profileSum),
+ NextOffsetPercent: float64(p.elements[profElementNextOffset].total) * 100.0 / float64(p.profileSum),
+ GetTxnGroupsPercent: float64(p.elements[profElementGetTxnsGroups].total) * 100.0 / float64(p.profileSum),
+ AssembleMessagePercent: float64(p.elements[profElementAssembleMessage].total) * 100.0 / float64(p.profileSum),
+ MakeBloomFilterPercent: float64(p.elements[profElementMakeBloomFilter].total) * 100.0 / float64(p.profileSum),
+ SelectPendingTransactionsPercent: float64(p.elements[profElementTxnsSelection].total) * 100.0 / float64(p.profileSum),
+ }
+
+ p.log.Metrics(telemetryspec.Transaction, metrics, struct{}{})
+}
+
+func (e *element) start() {
+ if e.profiler.logInterval > 0 {
+ e.lastStart = e.profiler.clock.Since()
+ }
+}
+
+func (e *element) end() {
+ if e.profiler.logInterval == 0 {
+ return
+ }
+ diff := e.profiler.clock.Since() - e.lastStart
+ e.total += diff
+ e.times = append(e.times, diff)
+ e.profiler.profile = append(e.profiler.profile, e.id)
+
+ if !e.detached {
+ e.profiler.profileSum += diff
+ e.profiler.prune()
+ e.profiler.maybeLogProfile()
+ }
+}
diff --git a/txnsync/profiler_test.go b/txnsync/profiler_test.go
new file mode 100644
index 000000000..6ac4e0f06
--- /dev/null
+++ b/txnsync/profiler_test.go
@@ -0,0 +1,269 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/logging/telemetryspec"
+ "github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/algorand/go-algorand/util/timers"
+)
+
+// Create a logger that hooks the "Metrics" function to signal that we have
+// indeed sent some metrics
+type metricsLogger struct {
+ Logger
+ sentLogger *bool
+}
+
+func makeMetricsLogger(sentLogger *bool) metricsLogger {
+ return metricsLogger{
+ sentLogger: sentLogger,
+ }
+}
+
+func (n metricsLogger) Metrics(category telemetryspec.Category, metrics telemetryspec.MetricDetails, details interface{}) {
+ *n.sentLogger = true
+}
+
+// TestPrune Test the prune capabilities of the profiler. We want to simulate
+// the conditions to show that the profiler will "remove" elements when needed.
+func TestPrune(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ prof := makeProfiler(2*time.Millisecond, nil, nil, 3*time.Millisecond)
+ a := require.New(t)
+
+ a.NotNil(prof)
+ a.NotNil(prof.elements)
+
+ prof.profileSum = 2
+ prof.profileSpan = 1
+
+ prof.profile = append(prof.profile, 0)
+
+ firstElement := &prof.elements[0]
+
+ (*firstElement).detached = false
+
+ (*firstElement).times = append((*firstElement).times, time.Duration(2), time.Duration(2))
+ (*firstElement).total = time.Duration(4)
+
+ a.Equal(len(prof.profile), 1)
+ a.Equal(len((*firstElement).times), 2)
+
+ prof.prune()
+
+ a.Equal(len(prof.profile), 0)
+ a.Equal(len((*firstElement).times), 1)
+ a.Equal((*firstElement).total, time.Duration(2))
+
+}
+
+// TestProfilerStartEndZero Test functionality if the log interval is 0
+func TestProfilerStartEndZero(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ var s syncState
+ s.clock = timers.MakeMonotonicClock(time.Now())
+ prof := makeProfiler(2*time.Millisecond, s.clock, nil, 0*time.Millisecond)
+ a := require.New(t)
+
+ a.NotNil(prof)
+ a.NotNil(prof.elements)
+
+ firstElement := &prof.elements[0]
+
+ oldLastStart := (*firstElement).lastStart
+ oldTotal := (*firstElement).total
+
+ (*firstElement).start()
+ time.Sleep(5 * time.Millisecond)
+ (*firstElement).end()
+
+ a.Equal(oldLastStart, (*firstElement).lastStart)
+ a.Equal(oldTotal, (*firstElement).total)
+
+}
+
+// TestProfilerStartEndEnabled Test profiler functionality if log interval is non-zero.
+// This test will assume that a successful start()-end() call
+// will produce a non-zero profile sum.
+//
+// This test forces "detached element" logic to be run.
+func TestProfilerStartEndEnabled(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ var s syncState
+ s.clock = timers.MakeMonotonicClock(time.Now())
+ tmp := false
+ // Need to supply logger just in case log profile is called
+ nl := makeMetricsLogger(&tmp)
+ prof := makeProfiler(2*time.Millisecond, s.clock, nl, 3*time.Millisecond)
+
+ a := require.New(t)
+
+ a.NotNil(prof)
+ a.NotNil(prof.elements)
+
+ element := prof.getElement(0)
+
+ // Ensure that we trip the if statement
+ element.detached = false
+
+ a.Equal(element.total, time.Duration(0))
+ a.Equal(len(element.times), 0)
+ a.Equal(len(element.profiler.profile), 0)
+ a.Equal(element.profiler.profileSum, time.Duration(0))
+
+ element.start()
+ element.end()
+ a.NotEqual(element.total, time.Duration(0))
+ a.Equal(len(element.times), 1)
+ a.Equal(len(element.profiler.profile), 1)
+ a.NotEqual(element.profiler.profileSum, time.Duration(0))
+
+}
+
+// TestProfilerStartEndDisabled Test start-end functionality with detached elements.
+func TestProfilerStartEndDisabled(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ var s syncState
+ s.clock = timers.MakeMonotonicClock(time.Now())
+ prof := makeProfiler(2*time.Millisecond, s.clock, nil, 3*time.Millisecond)
+ a := require.New(t)
+
+ a.NotNil(prof)
+ a.NotNil(prof.elements)
+
+ element := prof.getElement(0)
+
+ // Set to true so we don't trip the if statement for now
+ element.detached = true
+
+ a.Equal(element.total, time.Duration(0))
+ a.Equal(len(element.times), 0)
+ a.Equal(len(element.profiler.profile), 0)
+
+ element.start()
+ element.end()
+ a.NotEqual(element.total, time.Duration(0))
+ a.Equal(len(element.times), 1)
+ a.Equal(len(element.profiler.profile), 1)
+
+}
+
+// TestMaybeLogProfile Test that Metrics are only sent when all conditions are met and not
+// sent if they are not.
+func TestMaybeLogProfile(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ sentMetrics := false
+
+ var s syncState
+ nl := makeMetricsLogger(&sentMetrics)
+ s.clock = timers.MakeMonotonicClock(time.Now())
+ prof := makeProfiler(2*time.Millisecond, s.clock, nl, 3*time.Millisecond)
+
+ a := require.New(t)
+
+ a.NotNil(prof)
+ a.NotNil(prof.elements)
+
+ // --
+ prof.logInterval = 0
+ prof.maybeLogProfile()
+ a.False(sentMetrics)
+ prof.logInterval = 1
+
+ // --
+
+ prof.profileSum = 1
+ prof.profileSpan = 4
+ prof.maybeLogProfile()
+ a.False(sentMetrics)
+
+ prof.profileSum = 4
+ prof.profileSpan = 4
+
+ // --
+ prof.logInterval = 2147483647 // Make this stupidly high to make sure we hit the if statement
+ prof.lastProfileLog = prof.clock.Since()
+ prof.maybeLogProfile()
+ a.False(sentMetrics)
+
+ // The last call to maybeLogProfile should set lastProfileLog to cur time
+ prof.logInterval = 1 * time.Nanosecond
+ // Sleep some time so we are above 1 ns of duration with a high degree of certainty
+ time.Sleep(200 * time.Millisecond)
+
+ prof.maybeLogProfile()
+ a.True(sentMetrics)
+
+}
+
+// TestGetElement Tests that getting an element returns it properly
+func TestGetElement(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ var s syncState
+ prof := makeProfiler(2*time.Millisecond, s.clock, s.log, 3*time.Millisecond)
+ a := require.New(t)
+
+ a.NotNil(prof)
+ a.NotNil(prof.elements)
+
+ for i := 0; i < profElementLast; i++ {
+ e := prof.getElement(profElements(i))
+
+ a.Equal(e.id, i)
+ }
+
+}
+
+// TestMakeProfiler Ensures that makeProfiler() returns a valid profiler.
+func TestMakeProfiler(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ var s syncState
+ prof := makeProfiler(2*time.Millisecond, s.clock, s.log, 3*time.Millisecond)
+ a := require.New(t)
+
+ a.NotNil(prof)
+ a.NotNil(prof.elements)
+
+ a.Equal(prof.profileSpan, 2*time.Millisecond)
+ a.Equal(prof.logInterval, 3*time.Millisecond)
+ a.Equal(len(prof.elements), profElementLast)
+
+ for i, e := range prof.elements {
+ a.Equal(e.id, i)
+ a.Equal(e.profiler, prof)
+
+ if i < profFirstDetachedElement {
+ a.False(e.detached)
+ } else {
+ a.True(e.detached)
+ }
+ }
+
+}
diff --git a/txnsync/sent_filter.go b/txnsync/sent_filter.go
new file mode 100644
index 000000000..603a73a12
--- /dev/null
+++ b/txnsync/sent_filter.go
@@ -0,0 +1,82 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "github.com/algorand/go-algorand/data/basics"
+)
+
+//msgp:ignore sentFilterStat
+type sentFilterStat struct {
+ // .Modulator .Offset
+ EncodingParams requestParams
+
+ // lastCounter is the group counter of the last txn group included in a sent filter
+ lastCounter uint64
+
+ round basics.Round
+}
+
+// sentFilters is the set of filter stats for one peer to another peer.
+// There should be at most one entry per (Modulator,Offset)
+//msgp:ignore sentFilters
+type sentFilters []sentFilterStat
+
+const maxSentFilterSet = 10
+
+func (sf *sentFilters) setSentFilter(filter bloomFilter, round basics.Round) {
+ encodingParams := filter.encoded.EncodingParams
+ for i, sfs := range *sf {
+ if sfs.EncodingParams == encodingParams {
+ (*sf)[i].lastCounter = filter.containedTxnsRange.lastCounter
+ (*sf)[i].round = round
+ return
+ }
+ }
+ nsf := sentFilterStat{
+ EncodingParams: encodingParams,
+ lastCounter: filter.containedTxnsRange.lastCounter,
+ round: round,
+ }
+ *sf = append(*sf, nsf)
+ // trim oldest content if we're too long
+ for len(*sf) > maxSentFilterSet {
+ oldestRound := round
+ popCandidate := -1
+ for i, sfs := range *sf {
+ if sfs.round < oldestRound {
+ oldestRound = sfs.round
+ popCandidate = i
+ }
+ }
+ if popCandidate >= 0 {
+ last := len(*sf) - 1
+ (*sf)[popCandidate] = (*sf)[last]
+ *sf = (*sf)[:last]
+ break
+ }
+ }
+}
+
+func (sf *sentFilters) nextFilterGroup(encodingParams requestParams) (lastCounter uint64, round basics.Round) {
+ for _, sfs := range *sf {
+ if sfs.EncodingParams == encodingParams {
+ return sfs.lastCounter + 1, sfs.round
+ }
+ }
+ return 0, 0 // include everything since the start
+}
diff --git a/txnsync/sent_filter_test.go b/txnsync/sent_filter_test.go
new file mode 100644
index 000000000..f441dc76d
--- /dev/null
+++ b/txnsync/sent_filter_test.go
@@ -0,0 +1,57 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "testing"
+
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/stretchr/testify/require"
+)
+
+func TestSentFilterSet(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ var sf sentFilters
+
+ ep := requestParams{Offset: 4, Modulator: 255}
+ bf := bloomFilter{
+ containedTxnsRange: transactionsRange{1, 42, 99},
+ encoded: encodedBloomFilter{EncodingParams: ep},
+ }
+
+ // what goes in ..
+ sf.setSentFilter(bf, basics.Round(13))
+
+ // .. comes out
+ lastCounter, lcRound := sf.nextFilterGroup(ep)
+ a.Equal(uint64(42+1), lastCounter)
+ a.Equal(basics.Round(13), lcRound)
+
+ for i := 0; i < maxSentFilterSet; i++ {
+ bf.encoded.EncodingParams.Offset++
+ sf.setSentFilter(bf, basics.Round(14+i))
+ }
+
+ // first oldest entry will have been lost
+ lastCounter, lcRound = sf.nextFilterGroup(ep)
+ a.Equal(uint64(0), lastCounter)
+ a.Equal(basics.Round(0), lcRound)
+}
diff --git a/txnsync/service.go b/txnsync/service.go
new file mode 100644
index 000000000..d131b2805
--- /dev/null
+++ b/txnsync/service.go
@@ -0,0 +1,78 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "context"
+ "sync"
+
+ "github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/logging"
+ "github.com/algorand/go-algorand/util/execpool"
+)
+
+// Service is the transaction sync main service object.
+type Service struct {
+ ctx context.Context
+ cancelCtx context.CancelFunc
+ waitGroup sync.WaitGroup
+
+ state syncState
+}
+
+// MakeTransactionSyncService creates a new Service object
+func MakeTransactionSyncService(log logging.Logger, conn NodeConnector, isRelay bool, genesisID string, genesisHash crypto.Digest, cfg config.Local, threadpool execpool.BacklogPool) *Service {
+ s := &Service{
+ state: syncState{
+ node: conn,
+ log: wrapLogger(log, &cfg),
+ isRelay: isRelay,
+ genesisID: genesisID,
+ genesisHash: genesisHash,
+ config: cfg,
+ threadpool: threadpool,
+ scheduler: makePeerScheduler(),
+ },
+ }
+ s.state.service = s
+ s.state.xorBuilder.MaxIterations = 10
+ return s
+}
+
+// Start starts the transaction sync
+func (s *Service) Start() {
+ s.ctx, s.cancelCtx = context.WithCancel(context.Background())
+ s.waitGroup.Add(1)
+
+ go s.state.mainloop(s.ctx, &s.waitGroup)
+}
+
+// Stop stops the transaction sync
+func (s *Service) Stop() {
+ // cancel the context
+ s.cancelCtx()
+ // wait until the mainloop exists.
+ s.waitGroup.Wait()
+ // clear the context, as we won't be using it anymore.
+ s.cancelCtx, s.ctx = nil, nil
+}
+
+// GetIncomingMessageHandler returns the message handler.
+func (s *Service) GetIncomingMessageHandler() IncomingMessageHandler {
+ return s.state.asyncIncomingMessageHandler
+}
diff --git a/txnsync/service_test.go b/txnsync/service_test.go
new file mode 100644
index 000000000..182f83539
--- /dev/null
+++ b/txnsync/service_test.go
@@ -0,0 +1,165 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "encoding/binary"
+ "math/rand"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/logging"
+ "github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/algorand/go-algorand/util/execpool"
+ "github.com/algorand/go-algorand/util/timers"
+)
+
+type mockLogger struct {
+ logging.Logger
+}
+
+type mockNodeConnector struct {
+ NodeConnector
+ calledEvents *bool
+ peerInfo PeerInfo
+ updatingPeers bool
+ transactionPoolSize int
+}
+
+func makeMockNodeConnector(calledEvents *bool) mockNodeConnector {
+ return mockNodeConnector{calledEvents: calledEvents}
+}
+
+func (fn *mockNodeConnector) Events() <-chan Event {
+ if fn.calledEvents != nil {
+ *fn.calledEvents = true
+ }
+ return nil
+}
+
+func (fn *mockNodeConnector) GetCurrentRoundSettings() (out RoundSettings) { return }
+
+func (fn *mockNodeConnector) Clock() (out timers.WallClock) {
+ return timers.MakeMonotonicClock(time.Now())
+}
+
+func (fn *mockNodeConnector) Random(rng uint64) uint64 {
+ var xb [8]byte
+ rand.Read(xb[:])
+ rv := binary.LittleEndian.Uint64(xb[:])
+ return rv % rng
+}
+
+func (fn *mockNodeConnector) GetPeers() []PeerInfo { return nil }
+
+func (fn *mockNodeConnector) GetPeer(interface{}) (out PeerInfo) {
+ return fn.peerInfo
+}
+
+func (fn *mockNodeConnector) UpdatePeers(txsyncPeers []*Peer, netPeers []interface{}, peersAverageDataExchangeRate uint64) {
+ fn.updatingPeers = true
+}
+func (fn *mockNodeConnector) SendPeerMessage(netPeer interface{}, msg []byte, callback SendMessageCallback) {
+}
+func (fn *mockNodeConnector) GetPendingTransactionGroups() (txGroups []pooldata.SignedTxGroup, latestLocallyOriginatedGroupCounter uint64) {
+ return
+}
+func (fn *mockNodeConnector) IncomingTransactionGroups(peer *Peer, messageSeq uint64, txGroups []pooldata.SignedTxGroup) (transactionPoolSize int) {
+ return fn.transactionPoolSize
+}
+func (fn *mockNodeConnector) NotifyMonitor() chan struct{} { return nil }
+
+type mockThreadPool struct {
+ execpool.BacklogPool
+}
+
+// TestStartStopTransactionSyncService test that we can start and stop the transaction sync service
+func TestStartStopTransactionSyncService(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ calledEventsInNodeConnector := false
+
+ a := require.New(t)
+
+ mLogger := mockLogger{}
+ mNodeConnector := makeMockNodeConnector(&calledEventsInNodeConnector)
+ cfg := config.GetDefaultLocal()
+ mThreadPool := mockThreadPool{}
+
+ hashDigest := crypto.Hash([]byte{0x41, 0x6b, 0x69, 0x6b, 0x69})
+
+ service := MakeTransactionSyncService(mLogger, &mNodeConnector, true, "GENID", hashDigest, cfg, mThreadPool)
+
+ a.NotNil(service)
+
+ service.Start()
+ service.Stop()
+
+ a.True(calledEventsInNodeConnector)
+
+ a.Nil(service.cancelCtx)
+ a.Nil(service.ctx)
+
+}
+
+// TestMakeTransactionSyncService tests that an appropriate transaction sync service was made
+func TestMakeTransactionSyncService(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ a := require.New(t)
+
+ mLogger := mockLogger{}
+ mNodeConnector := &mockNodeConnector{}
+ cfg := config.GetDefaultLocal()
+ mThreadPool := mockThreadPool{}
+
+ hashDigest := crypto.Hash([]byte{0x41, 0x6b, 0x69, 0x6b, 0x69})
+
+ service1 := MakeTransactionSyncService(mLogger, mNodeConnector, true, "GENID", hashDigest, cfg, mThreadPool)
+
+ a.NotNil(service1)
+
+ a.Equal(service1.state.node, mNodeConnector)
+ a.Equal(service1.state.log, wrapLogger(mLogger, &cfg))
+ a.Equal(service1.state.isRelay, true)
+ a.Equal(service1.state.genesisID, "GENID")
+ a.Equal(service1.state.genesisHash, hashDigest)
+ a.Equal(service1.state.config, cfg)
+ a.Equal(service1.state.threadpool, mThreadPool)
+ a.Equal(service1.state.service, service1)
+ a.Equal(service1.state.xorBuilder.MaxIterations, 10)
+
+ service2 := MakeTransactionSyncService(mLogger, mNodeConnector, false, "GENID2", hashDigest, cfg, mThreadPool)
+
+ a.NotNil(service1)
+
+ a.Equal(service2.state.node, mNodeConnector)
+ a.Equal(service2.state.log, wrapLogger(mLogger, &cfg))
+ a.Equal(service2.state.isRelay, false)
+ a.Equal(service2.state.genesisID, "GENID2")
+ a.Equal(service2.state.genesisHash, hashDigest)
+ a.Equal(service2.state.config, cfg)
+ a.Equal(service2.state.threadpool, mThreadPool)
+ a.Equal(service2.state.service, service2)
+ a.Equal(service2.state.xorBuilder.MaxIterations, 10)
+
+}
diff --git a/txnsync/transactionCache.go b/txnsync/transactionCache.go
new file mode 100644
index 000000000..69569547d
--- /dev/null
+++ b/txnsync/transactionCache.go
@@ -0,0 +1,374 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "sort"
+ "time"
+
+ "github.com/algorand/go-algorand/data/transactions"
+)
+
+// cachedEntriesPerMap is the number of entries the longTermTransactionCache will have in each of it's
+// buckets. When looking up an entry, we don't want to have too many entries, hence, the number of maps we
+// maintain shouldn't be too high. On the flip side, keeping small number of maps means that we drop out
+// large portion of our cache. The number 917 here was picked as a sufficiently large prime number, which
+// would mean that if longTermRecentTransactionsSentBufferLength=15K, then we would have about 16 maps.
+const cachedEntriesPerMap = 917
+
+// cacheHistoryDuration is the time we will keep a transaction in the cache, assuming that the cache
+// storage would not get recycled first. When applied to transactions maps in the longTermTransactionCache, this
+// applies to the timestamp of the most recent transaction in the map.
+const cacheHistoryDuration = 10 * time.Second
+
+// transactionCache is a cache of recently sent transactions ids, allowing to limit the size of the historical kept transactions.
+// transactionCache has FIFO replacement.
+// implementation is a simple cyclic-buffer with a map to accelerate lookups.
+// internally, it's being manages as two tier cache, where the long-term cache is bigger and requires acknowledgements.
+//msgp:ignore transactionCache
+type transactionCache struct {
+ shortTermCache shortTermTransactionCache
+ longTermCache longTermTransactionCache
+ ackPendingTxids []ackPendingTxids
+}
+
+//msgp:ignore ackPendingTxids
+type ackPendingTxids struct {
+ txids []transactions.Txid
+ seq uint64
+ timestamp time.Duration
+}
+
+// shortTermCacheEntry is used as the data container of a double linked list item
+// in the shortTermTransactionCache object.
+//msgp:ignore shortTermCacheEntry
+type shortTermCacheEntry struct {
+ txid transactions.Txid // the transaction ID
+ prev *shortTermCacheEntry // previous entry in the circular linked list
+ next *shortTermCacheEntry // next entry in the circular linked list
+}
+
+//msgp:ignore shortTermTransactionCache
+type shortTermTransactionCache struct {
+ size int // the maximum number of elements in the short term cache
+ head *shortTermCacheEntry // pointer to first element in the linked list; the head is the "oldest" entry in the list, and would get pruned first.
+ free *shortTermCacheEntry // pointer to a free element list
+ transactionsMap map[transactions.Txid]*shortTermCacheEntry // map of the entries included
+}
+
+//msgp:ignore longTermTransactionCache
+type longTermTransactionCache struct {
+ current int
+ transactionsMap []map[transactions.Txid]bool
+ timestamps []time.Duration
+}
+
+// detach remove the entry from the list it's currently part of.
+// the return value is false if the item is the only entry in the list
+// or true otherwise.
+func (ce *shortTermCacheEntry) detach() bool {
+ if ce.next == ce.prev {
+ return false
+ }
+ ce.prev.next = ce.next
+ ce.next.prev = ce.prev
+ return true
+}
+
+// addToList add the element to the tail of the list who's head is provided.
+func (ce *shortTermCacheEntry) addToList(head *shortTermCacheEntry) {
+ tail := head.prev
+ tail.next = ce
+ head.prev = ce
+ ce.prev = tail
+ ce.next = head
+}
+
+// makeTransactionCache creates the transaction cache
+func makeTransactionCache(shortTermSize, longTermSize, pendingAckTxids int) *transactionCache {
+ txnCache := &transactionCache{
+ shortTermCache: shortTermTransactionCache{
+ size: shortTermSize,
+ transactionsMap: make(map[transactions.Txid]*shortTermCacheEntry, shortTermSize),
+ },
+ ackPendingTxids: make([]ackPendingTxids, 0, pendingAckTxids),
+ longTermCache: longTermTransactionCache{
+ transactionsMap: make([]map[transactions.Txid]bool, (longTermSize+cachedEntriesPerMap-1)/cachedEntriesPerMap),
+ timestamps: make([]time.Duration, (longTermSize+cachedEntriesPerMap-1)/cachedEntriesPerMap),
+ },
+ }
+ // initialize only the first entry; the rest would be created dynamically.
+ txnCache.longTermCache.transactionsMap[0] = make(map[transactions.Txid]bool, cachedEntriesPerMap)
+ return txnCache
+}
+
+// add adds a single trasaction ID to the short term cache.
+func (lru *transactionCache) add(txid transactions.Txid) {
+ lru.shortTermCache.add(txid)
+}
+
+// addSlice adds a slice to both the short term cache as well as the pending ack transaction ids.
+func (lru *transactionCache) addSlice(txids []transactions.Txid, msgSeq uint64, timestamp time.Duration) {
+ for _, txid := range txids {
+ lru.shortTermCache.add(txid)
+ }
+ // verify that the new msgSeq is bigger than the previous we have.
+ if len(lru.ackPendingTxids) > 0 {
+ if lru.ackPendingTxids[len(lru.ackPendingTxids)-1].seq >= msgSeq {
+ return
+ }
+ }
+
+ if len(lru.ackPendingTxids) == cap(lru.ackPendingTxids) {
+ // roll this array without reallocation.
+ copy(lru.ackPendingTxids, lru.ackPendingTxids[1:])
+ // update the last entry of the array.
+ lru.ackPendingTxids[len(lru.ackPendingTxids)-1] = ackPendingTxids{txids: txids, seq: msgSeq, timestamp: timestamp}
+ } else {
+ lru.ackPendingTxids = append(lru.ackPendingTxids, ackPendingTxids{txids: txids, seq: msgSeq, timestamp: timestamp})
+ }
+
+ // clear the entries that are too old.
+ lastValidEntry := -1
+ for i, entry := range lru.ackPendingTxids {
+ if entry.timestamp < timestamp-cacheHistoryDuration {
+ lastValidEntry = i
+ } else {
+ break
+ }
+ }
+ if lastValidEntry >= 0 {
+ // copy the elements
+ var i int
+ for i = 0; i < len(lru.ackPendingTxids)-1-lastValidEntry; i++ {
+ lru.ackPendingTxids[i] = lru.ackPendingTxids[i+lastValidEntry+1]
+ }
+ // clear the rest of the entries.
+ for ; i < len(lru.ackPendingTxids); i++ {
+ lru.ackPendingTxids[i] = ackPendingTxids{}
+ }
+ // reset the slice
+ lru.ackPendingTxids = lru.ackPendingTxids[:len(lru.ackPendingTxids)-lastValidEntry-1]
+ }
+}
+
+// contained checks if a given transaction ID is contained in either the short term or long term cache
+func (lru *transactionCache) contained(txid transactions.Txid) bool {
+ return lru.shortTermCache.contained(txid) || lru.longTermCache.contained(txid)
+}
+
+// reset clears the short term cache
+func (lru *transactionCache) reset() {
+ lru.shortTermCache.reset()
+}
+
+// acknowledge process a given slice of previously sent message sequence numbers. The transaction IDs that
+// were previously sent with these sequence numbers are being added to the long term cache.
+func (lru *transactionCache) acknowledge(seqs []uint64) {
+ for _, seq := range seqs {
+ i := sort.Search(len(lru.ackPendingTxids), func(i int) bool {
+ return lru.ackPendingTxids[i].seq >= seq
+ })
+ // if not found, skip it.
+ if i >= len(lru.ackPendingTxids) || seq != lru.ackPendingTxids[i].seq {
+ continue
+ }
+ lru.longTermCache.add(lru.ackPendingTxids[i].txids, lru.ackPendingTxids[i].timestamp)
+ lru.longTermCache.prune(lru.ackPendingTxids[i].timestamp - cacheHistoryDuration)
+ // clear out the entry at lru.ackPendingTxids[i] so that the GC could reclaim it.
+ lru.ackPendingTxids[i] = ackPendingTxids{}
+ // and delete the entry from the array
+ lru.ackPendingTxids = append(lru.ackPendingTxids[:i], lru.ackPendingTxids[i+1:]...)
+ }
+}
+
+// add a given transaction ID to the short term cache.
+func (st *shortTermTransactionCache) add(txid transactions.Txid) {
+ entry, exists := st.transactionsMap[txid]
+ if exists {
+ // promote
+ if entry.next != entry.prev {
+ // disconnect the current one; no need to test return code since we know
+ // there will be more elements on the list.
+ entry.detach()
+
+ // there are other elements on the list.
+ // if the given entry happen to be the first entry, then pick
+ // the next entry.
+ if entry == st.head {
+ st.head = entry.next
+ }
+ // add to the tail of the list.
+ entry.addToList(st.head)
+ } else { //nolint:staticcheck
+ // no other elements on the list -
+ // nothing to do in this case.
+ }
+ return
+ }
+
+ mapLen := len(st.transactionsMap)
+ if mapLen >= st.size {
+ // we reached size, delete the oldest entry.
+ t := st.head
+
+ // disconnect the current one; no need to test return code since we know
+ // there will be more elements on the list.
+ t.detach()
+
+ // replace the first entry with the next one.
+ st.head = t.next
+
+ // delete the current value from the map.
+ delete(st.transactionsMap, t.txid)
+
+ // copy the new transaction id into the existing object.
+ copy(t.txid[:], txid[:])
+
+ // place the new entry as the last entry on the list.
+ t.addToList(st.head)
+
+ // add the new entry to the map
+ st.transactionsMap[txid] = t
+ return
+ }
+
+ // grab an entry from the free list ( if any )
+ entry = st.free
+ if entry != nil {
+ if entry.detach() {
+ st.free = entry.next
+ } else {
+ st.free = nil
+ }
+ copy(entry.txid[:], txid[:])
+ } else {
+ // the free list doesn't have an entry - allocate a new one.
+ entry = &shortTermCacheEntry{
+ txid: txid,
+ }
+ }
+ if st.head == nil {
+ st.head = entry
+ entry.next = entry
+ entry.prev = entry
+ } else {
+ entry.addToList(st.head)
+ }
+ st.transactionsMap[txid] = entry
+}
+
+// contained checks if the given transaction id presents in the short term cache
+func (st *shortTermTransactionCache) contained(txid transactions.Txid) bool {
+ return st.transactionsMap[txid] != nil
+}
+
+// reset clears the short term cache
+func (st *shortTermTransactionCache) reset() {
+ if st.head == nil {
+ return
+ }
+ st.transactionsMap = make(map[transactions.Txid]*shortTermCacheEntry, st.size)
+ if st.free == nil {
+ st.free = st.head
+ st.head = nil
+ return
+ }
+ used := st.head
+ free := st.free
+ free.prev.next = used
+ used.prev.next = free
+ lastFree := free.prev
+ free.prev = used.prev
+ used.prev = lastFree
+ st.head = nil
+}
+
+// contained checks if the given transaction id presents in the log term cache
+func (lt *longTermTransactionCache) contained(txid transactions.Txid) bool {
+ for i := lt.current; i >= 0; i-- {
+ if lt.transactionsMap[i][txid] {
+ return true
+ }
+ }
+ for i := len(lt.transactionsMap) - 1; i > lt.current; i-- {
+ if lt.transactionsMap[i][txid] {
+ return true
+ }
+ }
+ return false
+}
+
+// add a given slice of transaction IDs to the long term transaction cache, at a given timestamp.
+func (lt *longTermTransactionCache) add(slice []transactions.Txid, timestamp time.Duration) {
+ for {
+ lt.timestamps[lt.current] = timestamp
+ availableEntries := cachedEntriesPerMap - len(lt.transactionsMap[lt.current])
+ txMap := lt.transactionsMap[lt.current]
+ if txMap == nil {
+ txMap = make(map[transactions.Txid]bool, cachedEntriesPerMap)
+ }
+ if len(slice) <= availableEntries {
+ // just add them all.
+ for _, txid := range slice {
+ txMap[txid] = true
+ }
+ lt.transactionsMap[lt.current] = txMap
+ return
+ }
+
+ // otherwise, add as many as we can fit -
+ for i := 0; i < availableEntries; i++ {
+ txMap[slice[i]] = true
+ }
+ lt.transactionsMap[lt.current] = txMap
+
+ // remove the ones we've already added from the slice.
+ slice = slice[availableEntries:]
+
+ // move to the next map.
+ lt.current = (lt.current + 1) % len(lt.transactionsMap)
+
+ // if full, reset bucket.
+ if len(lt.transactionsMap[lt.current]) >= cachedEntriesPerMap || lt.transactionsMap[lt.current] == nil {
+ // reset.
+ lt.transactionsMap[lt.current] = make(map[transactions.Txid]bool, cachedEntriesPerMap)
+ }
+ }
+}
+
+// prune the long term cache by clearing out all the cached transaction IDs maps that are dated before the given
+// timestamp
+func (lt *longTermTransactionCache) prune(timestamp time.Duration) {
+ // find the index of the first entry where the timestamp is still valid.
+ latestValidIndex := sort.Search(len(lt.transactionsMap), func(i int) bool {
+ arrayIndex := (i + lt.current + 1) % len(lt.transactionsMap)
+ return lt.timestamps[arrayIndex] > timestamp
+ })
+
+ // find the first non-empty map index.
+ firstValidIndex := sort.Search(len(lt.transactionsMap), func(i int) bool {
+ arrayIndex := (i + lt.current + 1) % len(lt.transactionsMap)
+ return lt.timestamps[arrayIndex] != time.Duration(0)
+ })
+
+ for i := firstValidIndex - 1; i < latestValidIndex; i++ {
+ arrayIndex := (i + lt.current + 1) % len(lt.transactionsMap)
+ lt.timestamps[arrayIndex] = time.Duration(0)
+ lt.transactionsMap[lt.current] = nil
+ }
+}
diff --git a/txnsync/transactionCache_test.go b/txnsync/transactionCache_test.go
new file mode 100644
index 000000000..daf6cb8bc
--- /dev/null
+++ b/txnsync/transactionCache_test.go
@@ -0,0 +1,333 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "reflect"
+ "strconv"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/test/partitiontest"
+)
+
+// TestTransactionCache General smoke test for the transaction cache
+func TestTransactionCache(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ var txid transactions.Txid
+ a := makeTransactionCache(5, 10, 20)
+ for repeat := 0; repeat < 2; repeat++ {
+ // add 5
+ for i := 0; i < 5; i++ {
+ txid[0] = byte(i)
+ a.add(txid)
+ }
+
+ // all 5 still there
+ for i := 0; i < 5; i++ {
+ txid[0] = byte(i)
+ require.True(t, a.contained(txid), "txid: %v", txid[:])
+ }
+
+ // repeatedly adding existing data doesn't lose anything
+ txid[0] = 1
+ a.add(txid)
+ a.add(txid)
+ a.add(txid)
+ for i := 0; i < 5; i++ {
+ txid[0] = byte(i)
+ require.True(t, a.contained(txid), "txid: %v", txid[:])
+ }
+
+ // adding a sixth forgets the first
+ txid[0] = 5
+ a.add(txid)
+ for i := 1; i < 6; i++ {
+ txid[0] = byte(i)
+ require.True(t, a.contained(txid), "txid: %v", txid[:])
+ }
+ txid[0] = 0
+ require.False(t, a.contained(txid))
+
+ // adding a seventh forgets the third
+ txid[0] = 6
+ a.add(txid)
+ for i := 3; i < 7; i++ {
+ txid[0] = byte(i)
+ require.True(t, a.contained(txid), "txid: %v", txid[:])
+ }
+ txid[0] = 1
+ require.True(t, a.contained(txid), "txid: %v", txid[:])
+ txid[0] = 2
+ require.False(t, a.contained(txid))
+ a.reset()
+ }
+}
+
+// TestTransactionCacheResetting is a simple reset testing, ensuring we know how to recycle entries from the free list.
+func TestTransactionCacheResetting(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ var txid transactions.Txid
+ a := makeTransactionCache(5, 10, 20)
+ // add 5
+ for i := 0; i < 5; i++ {
+ txid[0] = byte(i)
+ a.add(txid)
+ }
+ // re-add the first one again, to promote it.
+ txid[0] = 0
+ a.add(txid)
+ a.reset()
+ // add 3
+ for i := 0; i < 3; i++ {
+ txid[0] = byte(i)
+ a.add(txid)
+ }
+ a.reset()
+ // add 2
+ for i := 0; i < 2; i++ {
+ txid[0] = byte(i)
+ a.add(txid)
+ }
+ // verify the two are there.
+ for i := 0; i < 2; i++ {
+ txid[0] = byte(i)
+ require.True(t, a.contained(txid), "txid: %v", txid[:])
+ }
+}
+
+// TestTransactionCacheAddSlice tests addSlice functionality of the transaction cache
+func TestTransactionCacheAddSlice(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ tc := makeTransactionCache(5, 10, 20)
+ curTimestamp := time.Duration(0)
+ msgSeq := uint64(0)
+ slice := make([]transactions.Txid, 10)
+ for i := 0; i < 50; i++ {
+ tc.addSlice(slice, msgSeq, curTimestamp)
+ curTimestamp += cacheHistoryDuration / 10
+ msgSeq++
+ require.LessOrEqual(t, len(tc.ackPendingTxids), 11)
+ }
+ curTimestamp += cacheHistoryDuration
+ tc.addSlice(slice, msgSeq, curTimestamp)
+ require.LessOrEqual(t, len(tc.ackPendingTxids), 1)
+}
+
+// TestAddSliceSeqReturn Tests that if the ackPendingTxIds is bigger that the msgSeq then we return
+func TestAddSliceSeqReturn(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ tc := makeTransactionCache(5, 10, 20)
+ curTimestamp := time.Duration(cacheHistoryDuration)
+ msgSeq := uint64(1)
+ slice := make([]transactions.Txid, 10)
+ tc.addSlice(slice, msgSeq, curTimestamp)
+
+ tcLen := len(tc.ackPendingTxids)
+
+ tc.addSlice(slice, 0, curTimestamp)
+ require.Equal(t, tcLen, len(tc.ackPendingTxids))
+ msgSeq++
+ tc.addSlice(slice, msgSeq, curTimestamp+(cacheHistoryDuration/10))
+ require.Equal(t, tcLen+1, len(tc.ackPendingTxids))
+
+}
+
+// TestAddSliceCapacity tests that we correctly copy the ackPendingTxids when at capacity
+func TestAddSliceCapacity(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ tc := makeTransactionCache(5, 10, 5)
+
+ curTimestamp := time.Duration(0)
+ msgSeq := uint64(0)
+ slice := make([]transactions.Txid, 10)
+ for i := 0; i < 50; i++ {
+ tc.addSlice(slice, msgSeq, curTimestamp)
+ curTimestamp += cacheHistoryDuration / 10
+ msgSeq++
+ require.LessOrEqual(t, len(tc.ackPendingTxids), 6)
+ }
+
+}
+
+func (ce *shortTermCacheEntry) getLength() int {
+ length := 0
+ if ce == nil {
+ return length
+ }
+ length++
+ cur := ce
+ for ; cur != nil && ce != cur.next; cur = cur.next {
+ length++
+ }
+ return length
+}
+
+// TestShortTermCacheReset tests that the short term cache is reset
+func TestShortTermCacheReset(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ tc := makeTransactionCache(5, 10, 5)
+ require.Nil(t, tc.shortTermCache.head)
+ require.Nil(t, tc.shortTermCache.free)
+ require.Equal(t, 0, len(tc.shortTermCache.transactionsMap))
+
+ var txid transactions.Txid
+ for i := 0; i < 5; i++ {
+ txid[0] = byte(i)
+ tc.add(txid)
+ }
+ require.Equal(t, 5, tc.shortTermCache.head.getLength())
+
+ require.Nil(t, tc.shortTermCache.free)
+ require.NotNil(t, tc.shortTermCache.head)
+ require.Equal(t, 5, len(tc.shortTermCache.transactionsMap))
+
+ tc.reset()
+ require.Equal(t, 0, tc.shortTermCache.head.getLength())
+ require.Equal(t, 5, tc.shortTermCache.free.getLength())
+
+ require.Nil(t, tc.shortTermCache.head)
+ require.NotNil(t, tc.shortTermCache.free)
+ require.Equal(t, 0, len(tc.shortTermCache.transactionsMap))
+
+ for i := 0; i < 2; i++ {
+ txid[0] = byte(i)
+ tc.add(txid)
+ }
+
+ tc.reset()
+ require.Equal(t, 5, tc.shortTermCache.free.getLength())
+}
+
+// TestCacheAcknowledge tests that the acknowledge function correctly adds entries
+func TestCacheAcknowledge(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ tc := makeTransactionCache(5, 10, 5)
+
+ curTimestamp := time.Duration(0)
+ msgSeq := uint64(0)
+ slice := make([]transactions.Txid, 10)
+ for i := 0; i < 5; i++ {
+ tc.addSlice(slice, msgSeq, curTimestamp)
+ curTimestamp += cacheHistoryDuration / 20
+ msgSeq++
+ require.LessOrEqual(t, len(tc.ackPendingTxids), 5)
+ }
+
+ require.Equal(t, 1, len(tc.longTermCache.transactionsMap))
+ require.Equal(t, 0, tc.longTermCache.current)
+
+ // The 10 is purposely past the range for the checking
+ seqs := []uint64{10, 1, 2, 3}
+ tc.acknowledge(seqs)
+ require.Equal(t, 2, len(tc.ackPendingTxids))
+ require.Equal(t, uint64(0), tc.ackPendingTxids[0].seq)
+ require.Equal(t, uint64(4), tc.ackPendingTxids[1].seq)
+
+}
+
+// TestCacheAddAndContains tests adding to the long term cache and if we can test if it contains it
+func TestCacheAddAndContains(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ tc := makeTransactionCache(5, 2*cachedEntriesPerMap, 5)
+
+ // We want two scenarios: Smaller than cachedEntriesPerMap and bigger
+ smallSlice := make([]transactions.Txid, cachedEntriesPerMap/2)
+
+ // Fill with random numbers
+ for i := 0; i < cachedEntriesPerMap/2; i++ {
+ tx := &smallSlice[i]
+ tx[0] = byte((i + 37) % 255)
+ tx[1] = byte((i + 2) % 255)
+ tx[2] = byte((i + 42) % 255)
+ tx[3] = byte((i + 23) % 255)
+ }
+
+ bigSlice := make([]transactions.Txid, 2*cachedEntriesPerMap)
+
+ // Fill with sequential numbers
+ for i := 0; i < 2*cachedEntriesPerMap; i++ {
+ tx := &bigSlice[i]
+ bs := []byte(strconv.Itoa(i))
+ d := crypto.Hash(bs)
+
+ *tx = transactions.Txid(d)
+ }
+
+ curTimestamp := time.Duration(0)
+
+ ltc := &tc.longTermCache
+ require.Equal(t, 2, len(ltc.transactionsMap))
+
+ require.Equal(t, 0, ltc.current)
+
+ ltc.add(smallSlice, curTimestamp)
+
+ require.Equal(t, 0, ltc.current)
+
+ sliceMap := make(map[transactions.Txid]bool)
+ for _, txid := range smallSlice {
+ sliceMap[txid] = true
+ }
+
+ require.True(t, reflect.DeepEqual(sliceMap, ltc.transactionsMap[0]))
+
+ ltc.add(bigSlice, curTimestamp)
+
+ // Given that we already added small slice, we should "overflow"
+ // and expect that the transaction map contains a modified version of big slice
+
+ slice := bigSlice
+ for {
+ availableEntries := cachedEntriesPerMap - len(sliceMap)
+ if len(slice) <= availableEntries {
+ for _, txid := range slice {
+ sliceMap[txid] = true
+ }
+ break
+ }
+
+ for i := 0; i < availableEntries; i++ {
+ sliceMap[slice[i]] = true
+ }
+
+ slice = slice[availableEntries:]
+
+ if len(sliceMap) >= cachedEntriesPerMap {
+ sliceMap = make(map[transactions.Txid]bool)
+ }
+
+ }
+
+ require.Equal(t, 0, ltc.current)
+ require.True(t, reflect.DeepEqual(sliceMap, ltc.transactionsMap[0]))
+
+ bs := []byte(strconv.Itoa(cachedEntriesPerMap))
+ d := crypto.Hash(bs)
+ targetTxID := transactions.Txid(d)
+
+ require.True(t, ltc.contained(targetTxID))
+
+}
diff --git a/txnsync/txngroups.go b/txnsync/txngroups.go
new file mode 100644
index 000000000..fdec93785
--- /dev/null
+++ b/txnsync/txngroups.go
@@ -0,0 +1,224 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "errors"
+ "fmt"
+
+ "github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/util/compress"
+)
+
+// Deflate performance constants measured by BenchmarkTxnGroupCompression
+const estimatedDeflateCompressionSpeed = 121123260.0 // bytes per second of how fast Deflate compresses data
+const estimatedDeflateCompressionGains = 0.32 // fraction of data reduced by Deflate on txnsync msgs
+
+const minEncodedTransactionGroupsCompressionThreshold = 1000
+
+const maxCompressionRatio = 20 // don't allow more than 95% compression
+
+func (s *syncState) encodeTransactionGroups(inTxnGroups []pooldata.SignedTxGroup, dataExchangeRate uint64) (packedTransactionGroups, error) {
+ txnCount := 0
+ for _, txGroup := range inTxnGroups {
+ txnCount += len(txGroup.Transactions)
+ }
+ stub := txGroupsEncodingStub{
+ TotalTransactionsCount: uint64(txnCount),
+ TransactionGroupCount: uint64(len(inTxnGroups)),
+ TransactionGroupSizes: make([]byte, 0, len(inTxnGroups)),
+ }
+
+ bitmaskLen := bytesNeededBitmask(int(stub.TotalTransactionsCount))
+ index := 0
+ for _, txGroup := range inTxnGroups {
+ if len(txGroup.Transactions) > 1 {
+ for _, txn := range txGroup.Transactions {
+ if err := stub.deconstructSignedTransaction(index, &txn); err != nil {
+ return packedTransactionGroups{}, fmt.Errorf("failed to encodeTransactionGroups: %w", err)
+ }
+ index++
+ }
+ stub.TransactionGroupSizes = append(stub.TransactionGroupSizes, byte(len(txGroup.Transactions)-1))
+ }
+ }
+ compactNibblesArray(&stub.TransactionGroupSizes)
+ for _, txGroup := range inTxnGroups {
+ if len(txGroup.Transactions) == 1 {
+ for _, txn := range txGroup.Transactions {
+ if !txn.Txn.Group.MsgIsZero() {
+ if len(stub.BitmaskGroup) == 0 {
+ stub.BitmaskGroup = make(bitmask, bitmaskLen)
+ }
+ stub.BitmaskGroup.setBit(index)
+ }
+ if err := stub.deconstructSignedTransaction(index, &txn); err != nil {
+ return packedTransactionGroups{}, fmt.Errorf("failed to encodeTransactionGroups: %w", err)
+ }
+ index++
+ }
+ }
+ }
+ stub.finishDeconstructSignedTransactions()
+
+ encoded := stub.MarshalMsg(getMessageBuffer())
+
+ // check if time saved by compression: estimatedDeflateCompressionGains * len(msg) / dataExchangeRate
+ // is greater than by time spent during compression: len(msg) / estimatedDeflateCompressionSpeed
+ if len(encoded) > minEncodedTransactionGroupsCompressionThreshold && float32(dataExchangeRate) < (estimatedDeflateCompressionGains*estimatedDeflateCompressionSpeed) {
+ compressedBytes, compressionFormat := s.compressTransactionGroupsBytes(encoded)
+ if compressionFormat != compressionFormatNone {
+ packedGroups := packedTransactionGroups{
+ Bytes: compressedBytes,
+ CompressionFormat: compressionFormat,
+ LenDecompressedBytes: uint64(len(encoded)),
+ }
+ releaseMessageBuffer(encoded)
+ return packedGroups, nil
+ }
+ }
+
+ return packedTransactionGroups{
+ Bytes: encoded,
+ CompressionFormat: compressionFormatNone,
+ }, nil
+}
+
+func (s *syncState) compressTransactionGroupsBytes(uncompressedData []byte) ([]byte, byte) {
+ b := getMessageBuffer()
+ if cap(b) < len(uncompressedData) {
+ releaseMessageBuffer(b)
+ b = make([]byte, 0, len(uncompressedData))
+ }
+ _, compressedData, err := compress.Compress(uncompressedData, b, 1)
+ if err != nil {
+ if errors.Is(err, compress.ErrShortBuffer) {
+ s.log.Debugf("compression had negative effect, made message bigger: original msg length: %d", len(uncompressedData))
+ } else {
+ s.log.Warnf("failed to compress %d bytes txnsync msg: %v", len(uncompressedData), err)
+ }
+ releaseMessageBuffer(b)
+ return uncompressedData, compressionFormatNone
+ }
+ if len(uncompressedData) > len(compressedData)*maxCompressionRatio {
+ s.log.Infof("compression exceeded compression ratio: compressed data len: %d", len(compressedData))
+ releaseMessageBuffer(b)
+ return uncompressedData, compressionFormatNone
+ } else if len(uncompressedData) <= len(compressedData) {
+ // compression wasn't effective and ended up spending more data.
+ releaseMessageBuffer(b)
+ return uncompressedData, compressionFormatNone
+ }
+ return compressedData, compressionFormatDeflate
+}
+
+func decodeTransactionGroups(ptg packedTransactionGroups, genesisID string, genesisHash crypto.Digest) (txnGroups []pooldata.SignedTxGroup, err error) {
+ data := ptg.Bytes
+ if len(data) == 0 {
+ return nil, nil
+ }
+
+ switch ptg.CompressionFormat {
+ case compressionFormatNone:
+ case compressionFormatDeflate:
+ data, err = decompressTransactionGroupsBytes(data, ptg.LenDecompressedBytes)
+ if err != nil {
+ return
+ }
+ defer releaseMessageBuffer(data)
+ default:
+ return nil, fmt.Errorf("invalid compressionFormat, %d", ptg.CompressionFormat)
+ }
+ var stub txGroupsEncodingStub
+ _, err = stub.UnmarshalMsg(data)
+ if err != nil {
+ return nil, err
+ }
+
+ if stub.TransactionGroupCount > maxEncodedTransactionGroups {
+ return nil, errors.New("invalid TransactionGroupCount")
+ }
+
+ if stub.TotalTransactionsCount > uint64(maxEncodedTransactionGroups*config.MaxTxGroupSize) {
+ return nil, errors.New("invalid TotalTransactionsCount")
+ }
+
+ stx := make([]transactions.SignedTxn, stub.TotalTransactionsCount)
+
+ err = stub.reconstructSignedTransactions(stx, genesisID, genesisHash)
+ if err != nil {
+ return nil, err
+ }
+
+ txnGroups = make([]pooldata.SignedTxGroup, stub.TransactionGroupCount)
+ for txnCounter, txnGroupIndex := 0, 0; txnCounter < int(stub.TotalTransactionsCount); txnGroupIndex++ {
+ size := 1
+ if txnGroupIndex < len(stub.TransactionGroupSizes)*2 {
+ nibble, err := getNibble(stub.TransactionGroupSizes, txnGroupIndex)
+ if err != nil {
+ return nil, err
+ }
+ size = int(nibble) + 1
+ }
+ txnGroups[txnGroupIndex].Transactions = stx[txnCounter : txnCounter+size]
+ txnCounter += size
+ }
+
+ err = addGroupHashes(txnGroups, int(stub.TotalTransactionsCount), stub.BitmaskGroup)
+ if err != nil {
+ return nil, err
+ }
+
+ return txnGroups, nil
+}
+
+func decompressTransactionGroupsBytes(data []byte, lenDecompressedBytes uint64) (decoded []byte, err error) {
+ compressionRatio := lenDecompressedBytes / uint64(len(data)) // data should have been compressed between 0 and 95%
+ if lenDecompressedBytes > maxEncodedTransactionGroupBytes || compressionRatio <= 0 || compressionRatio >= maxCompressionRatio {
+ return nil, fmt.Errorf("invalid lenDecompressedBytes: %d, len(data): %d", lenDecompressedBytes, len(data))
+ }
+
+ out := getMessageBuffer()
+ if uint64(cap(out)) < lenDecompressedBytes {
+ releaseMessageBuffer(out)
+ out = make([]byte, 0, lenDecompressedBytes)
+ }
+
+ decoded, err = compress.Decompress(data, out)
+ if err != nil {
+ releaseMessageBuffer(out)
+ decoded = nil
+ return
+ }
+ if uint64(len(decoded)) != lenDecompressedBytes {
+ releaseMessageBuffer(out)
+ decoded = nil
+ return nil, fmt.Errorf("lenDecompressedBytes didn't match: expected %d, actual %d", lenDecompressedBytes, len(decoded))
+ }
+ return
+}
+
+func releaseEncodedTransactionGroups(buffer []byte) {
+ if buffer == nil {
+ return
+ }
+
+ releaseMessageBuffer(buffer)
+}
diff --git a/txnsync/txngroups_test.go b/txnsync/txngroups_test.go
new file mode 100644
index 000000000..6306494f3
--- /dev/null
+++ b/txnsync/txngroups_test.go
@@ -0,0 +1,530 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package txnsync
+
+import (
+ "context"
+ "database/sql"
+ "flag"
+ "io"
+ "io/ioutil"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/data/bookkeeping"
+ "github.com/algorand/go-algorand/data/pooldata"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/ledger/ledgercore"
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/rpcs"
+ "github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/algorand/go-algorand/util/db"
+)
+
+var blockDBFilename = flag.String("db", "", "Location of block db")
+var startRound = flag.Int("start", 0, "Starting round")
+var endRound = flag.Int("end", 10, "Ending round")
+
+func TestNibble(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ var b []byte
+ for i := 0; i < 10; i++ {
+ b = append(b, byte(i))
+ }
+ compactNibblesArray(&b)
+ for i := 0; i < 10; i++ {
+ val, err := getNibble(b, i)
+ require.NoError(t, err)
+ require.Equal(t, byte(i), val)
+ }
+}
+
+// old encoding method
+func encodeTransactionGroupsOld(inTxnGroups []pooldata.SignedTxGroup) []byte {
+ stub := txGroupsEncodingStubOld{
+ TxnGroups: make([]txnGroups, len(inTxnGroups)),
+ }
+ for i := range inTxnGroups {
+ stub.TxnGroups[i] = txnGroups(inTxnGroups[i].Transactions)
+ }
+
+ return stub.MarshalMsg(protocol.GetEncodingBuf()[:0])
+}
+
+// old decoding method
+func decodeTransactionGroupsOld(bytes []byte) (txnGroups []pooldata.SignedTxGroup, err error) {
+ if len(bytes) == 0 {
+ return nil, nil
+ }
+ var stub txGroupsEncodingStubOld
+ _, err = stub.UnmarshalMsg(bytes)
+ if err != nil {
+ return nil, err
+ }
+ txnGroups = make([]pooldata.SignedTxGroup, len(stub.TxnGroups))
+ for i := range stub.TxnGroups {
+ txnGroups[i].Transactions = pooldata.SignedTxnSlice(stub.TxnGroups[i])
+ }
+ return txnGroups, nil
+}
+
+func TestTxnGroupEncodingSmall(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ genesisHash := crypto.Hash([]byte("gh"))
+ genesisID := "gID"
+
+ inTxnGroups := []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ Transactions: []transactions.SignedTxn{
+ {
+ Txn: transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: basics.Address(crypto.Hash([]byte("2"))),
+ Fee: basics.MicroAlgos{Raw: 100},
+ GenesisHash: genesisHash,
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: basics.Address(crypto.Hash([]byte("4"))),
+ Amount: basics.MicroAlgos{Raw: 1000},
+ },
+ },
+ Sig: crypto.Signature{1},
+ },
+ },
+ },
+ pooldata.SignedTxGroup{
+ Transactions: []transactions.SignedTxn{
+ {
+ Txn: transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: basics.Address(crypto.Hash([]byte("1"))),
+ Fee: basics.MicroAlgos{Raw: 100},
+ GenesisHash: genesisHash,
+ GenesisID: genesisID,
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: basics.Address(crypto.Hash([]byte("2"))),
+ Amount: basics.MicroAlgos{Raw: 1000},
+ },
+ },
+ Sig: crypto.Signature{2},
+ },
+ {
+ Txn: transactions.Transaction{
+ Type: protocol.KeyRegistrationTx,
+ Header: transactions.Header{
+ Sender: basics.Address(crypto.Hash([]byte("1"))),
+ GenesisHash: genesisHash,
+ GenesisID: genesisID,
+ },
+ },
+ Sig: crypto.Signature{3},
+ },
+ },
+ },
+ pooldata.SignedTxGroup{
+ Transactions: []transactions.SignedTxn{
+ {
+ Txn: transactions.Transaction{
+ Type: protocol.AssetConfigTx,
+ Header: transactions.Header{
+ Sender: basics.Address(crypto.Hash([]byte("1"))),
+ Fee: basics.MicroAlgos{Raw: 100},
+ GenesisHash: genesisHash,
+ },
+ },
+ Sig: crypto.Signature{4},
+ },
+ {
+ Txn: transactions.Transaction{
+ Type: protocol.AssetFreezeTx,
+ Header: transactions.Header{
+ Sender: basics.Address(crypto.Hash([]byte("1"))),
+ GenesisHash: genesisHash,
+ },
+ },
+ Sig: crypto.Signature{5},
+ },
+ {
+ Txn: transactions.Transaction{
+ Type: protocol.CompactCertTx,
+ Header: transactions.Header{
+ Sender: basics.Address(crypto.Hash([]byte("1"))),
+ GenesisHash: genesisHash,
+ },
+ },
+ Msig: crypto.MultisigSig{Version: 1},
+ },
+ },
+ },
+ }
+ err := addGroupHashes(inTxnGroups, 6, []byte{1})
+ require.NoError(t, err)
+ var s syncState
+ ptg, err := s.encodeTransactionGroups(inTxnGroups, 1000000000)
+ require.NoError(t, err)
+ require.Equal(t, ptg.CompressionFormat, compressionFormatNone)
+ out, err := decodeTransactionGroups(ptg, genesisID, genesisHash)
+ require.NoError(t, err)
+ require.ElementsMatch(t, inTxnGroups, out)
+}
+
+// txnGroupsData fetches a sample dataset of txns, specify numBlocks up to 969
+func txnGroupsData(numBlocks int) (txnGroups []pooldata.SignedTxGroup, genesisID string, genesisHash crypto.Digest, err error) {
+ dat, err := ioutil.ReadFile("../test/testdata/mainnetblocks")
+ if err != nil {
+ return
+ }
+ dec := protocol.NewDecoderBytes(dat)
+ blocksData := make([]rpcs.EncodedBlockCert, numBlocks)
+ for i := 0; i < len(blocksData); i++ {
+ err = dec.Decode(&blocksData[i])
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return
+ }
+ }
+
+ for _, blockData := range blocksData {
+ block := blockData.Block
+ genesisID = block.GenesisID()
+ genesisHash = block.GenesisHash()
+ var payset [][]transactions.SignedTxnWithAD
+ payset, err = block.DecodePaysetGroups()
+ if err != nil {
+ return
+ }
+ for _, txns := range payset {
+ var txnGroup pooldata.SignedTxGroup
+ for _, txn := range txns {
+ txnGroup.Transactions = append(txnGroup.Transactions, txn.SignedTxn)
+ }
+ txnGroups = append(txnGroups, txnGroup)
+ }
+ }
+ return
+}
+
+func TestTxnGroupEncodingLarge(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ txnGroups, genesisID, genesisHash, err := txnGroupsData(969)
+ require.NoError(t, err)
+
+ var s syncState
+ ptg, err := s.encodeTransactionGroups(txnGroups, 0)
+ require.NoError(t, err)
+ require.Equal(t, ptg.CompressionFormat, compressionFormatDeflate)
+ out, err := decodeTransactionGroups(ptg, genesisID, genesisHash)
+ require.NoError(t, err)
+ require.ElementsMatch(t, txnGroups, out)
+
+ encodedGroupsBytes := encodeTransactionGroupsOld(txnGroups)
+ out, err = decodeTransactionGroupsOld(encodedGroupsBytes)
+ require.NoError(t, err)
+ require.ElementsMatch(t, txnGroups, out)
+
+ // check dataset
+ count := make(map[protocol.TxType]int)
+ sigs := 0
+ msigs := 0
+ lsigs := 0
+ for _, txg := range txnGroups {
+ for _, txn := range txg.Transactions {
+ count[txn.Txn.Type]++
+ if !txn.Sig.MsgIsZero() {
+ sigs++
+ }
+ if !txn.Msig.MsgIsZero() {
+ msigs++
+ }
+ if !txn.Lsig.MsgIsZero() {
+ lsigs++
+ }
+ }
+ }
+ require.Equal(t, 2, len(count))
+ require.Equal(t, 18351, count["axfer"])
+ require.Equal(t, 1663, count["pay"])
+ require.Equal(t, 20005, sigs)
+ require.Equal(t, 9, msigs)
+ require.Equal(t, 0, lsigs)
+}
+
+func BenchmarkTxnGroupEncoding(b *testing.B) {
+ txnGroups, _, _, err := txnGroupsData(4)
+ require.NoError(b, err)
+ var size int
+ var s syncState
+
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ ptg, err := s.encodeTransactionGroups(txnGroups, 1000000000)
+ require.NoError(b, err)
+ size = len(ptg.Bytes)
+ releaseEncodedTransactionGroups(ptg.Bytes)
+ }
+
+ b.ReportMetric(float64(size), "encodedDataBytes")
+}
+
+func BenchmarkTxnGroupCompression(b *testing.B) {
+ txnGroups, _, _, err := txnGroupsData(4)
+ require.NoError(b, err)
+ var size int
+ var s syncState
+ ptg, err := s.encodeTransactionGroups(txnGroups, 1000000000)
+ require.NoError(b, err)
+ require.Equal(b, ptg.CompressionFormat, compressionFormatNone)
+
+ b.ReportAllocs()
+ b.ResetTimer()
+ loopStartTime := time.Now()
+ for i := 0; i < b.N; i++ {
+ compressedGroupBytes, compressionFormat := s.compressTransactionGroupsBytes(ptg.Bytes)
+ require.Equal(b, compressionFormat, compressionFormatDeflate)
+ size = len(compressedGroupBytes)
+ }
+ loopDuration := time.Since(loopStartTime)
+ b.StopTimer()
+ b.ReportMetric(float64(len(ptg.Bytes)*b.N)/loopDuration.Seconds(), "estimatedGzipCompressionSpeed")
+ b.ReportMetric(float64(len(ptg.Bytes)-size)/float64(len(ptg.Bytes)), "estimatedGzipCompressionGains")
+}
+
+func BenchmarkTxnGroupDecoding(b *testing.B) {
+ txnGroups, genesisID, genesisHash, err := txnGroupsData(4)
+ require.NoError(b, err)
+
+ var s syncState
+ ptg, err := s.encodeTransactionGroups(txnGroups, 1000000000)
+ require.NoError(b, err)
+ require.Equal(b, ptg.CompressionFormat, compressionFormatNone)
+ require.NoError(b, err)
+
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err = decodeTransactionGroups(ptg, genesisID, genesisHash)
+ require.NoError(b, err)
+ }
+}
+
+func BenchmarkTxnGroupDecompression(b *testing.B) {
+ txnGroups, _, _, err := txnGroupsData(4)
+ require.NoError(b, err)
+
+ var s syncState
+ ptg, err := s.encodeTransactionGroups(txnGroups, 0)
+ require.NoError(b, err)
+ require.Equal(b, ptg.CompressionFormat, compressionFormatDeflate)
+
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err = decompressTransactionGroupsBytes(ptg.Bytes, ptg.LenDecompressedBytes)
+ require.NoError(b, err)
+ }
+}
+
+func BenchmarkTxnGroupEncodingOld(b *testing.B) {
+ txnGroups, _, _, err := txnGroupsData(4)
+ require.NoError(b, err)
+ var encodedGroupsBytes []byte
+
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ encodedGroupsBytes = encodeTransactionGroupsOld(txnGroups)
+ releaseEncodedTransactionGroups(encodedGroupsBytes)
+ }
+
+ b.ReportMetric(float64(len(encodedGroupsBytes)), "encodedDataBytes")
+}
+
+func BenchmarkTxnGroupDecodingOld(b *testing.B) {
+ txnGroups, _, _, err := txnGroupsData(4)
+ require.NoError(b, err)
+
+ encodedGroupsBytes := encodeTransactionGroupsOld(txnGroups)
+
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err = decodeTransactionGroupsOld(encodedGroupsBytes)
+ require.NoError(b, err)
+ }
+}
+
+// TestTxnGroupEncodingReflection generates random
+// txns of each type using reflection
+func TestTxnGroupEncodingReflection(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ for i := 0; i < 10; i++ {
+ v0, err := protocol.RandomizeObject(&transactions.SignedTxn{})
+ require.NoError(t, err)
+ stx, ok := v0.(*transactions.SignedTxn)
+ require.True(t, ok)
+
+ var txns []transactions.SignedTxn
+ for _, txType := range protocol.TxnTypes {
+ txn := *stx
+ txn.Txn.PaymentTxnFields = transactions.PaymentTxnFields{}
+ txn.Txn.KeyregTxnFields = transactions.KeyregTxnFields{}
+ txn.Txn.AssetConfigTxnFields = transactions.AssetConfigTxnFields{}
+ txn.Txn.AssetTransferTxnFields = transactions.AssetTransferTxnFields{}
+ txn.Txn.AssetFreezeTxnFields = transactions.AssetFreezeTxnFields{}
+ txn.Txn.ApplicationCallTxnFields = transactions.ApplicationCallTxnFields{}
+ txn.Txn.CompactCertTxnFields = transactions.CompactCertTxnFields{}
+ txn.Txn.Type = txType
+ txn.Lsig.Logic = []byte("logic")
+ switch i % 3 {
+ case 0: // only have normal sig
+ txn.Msig = crypto.MultisigSig{}
+ txn.Lsig = transactions.LogicSig{}
+ case 1: // only have multi sig
+ txn.Sig = crypto.Signature{}
+ txn.Lsig = transactions.LogicSig{}
+ case 2: // only have logic sig
+ txn.Msig = crypto.MultisigSig{}
+ txn.Sig = crypto.Signature{}
+ }
+ switch txType {
+ case protocol.UnknownTx:
+ continue
+ case protocol.PaymentTx:
+ v0, err := protocol.RandomizeObject(&txn.Txn.PaymentTxnFields)
+ require.NoError(t, err)
+ PaymentTxnFields, ok := v0.(*transactions.PaymentTxnFields)
+ require.True(t, ok)
+ txn.Txn.PaymentTxnFields = *PaymentTxnFields
+ case protocol.KeyRegistrationTx:
+ v0, err := protocol.RandomizeObject(&txn.Txn.KeyregTxnFields)
+ require.NoError(t, err)
+ KeyregTxnFields, ok := v0.(*transactions.KeyregTxnFields)
+ require.True(t, ok)
+ txn.Txn.KeyregTxnFields = *KeyregTxnFields
+ case protocol.AssetConfigTx:
+ v0, err := protocol.RandomizeObject(&txn.Txn.AssetConfigTxnFields)
+ require.NoError(t, err)
+ AssetConfigTxnFields, ok := v0.(*transactions.AssetConfigTxnFields)
+ require.True(t, ok)
+ txn.Txn.AssetConfigTxnFields = *AssetConfigTxnFields
+ case protocol.AssetTransferTx:
+ v0, err := protocol.RandomizeObject(&txn.Txn.AssetTransferTxnFields)
+ require.NoError(t, err)
+ AssetTransferTxnFields, ok := v0.(*transactions.AssetTransferTxnFields)
+ require.True(t, ok)
+ txn.Txn.AssetTransferTxnFields = *AssetTransferTxnFields
+ case protocol.AssetFreezeTx:
+ v0, err := protocol.RandomizeObject(&txn.Txn.AssetFreezeTxnFields)
+ require.NoError(t, err)
+ AssetFreezeTxnFields, ok := v0.(*transactions.AssetFreezeTxnFields)
+ require.True(t, ok)
+ txn.Txn.AssetFreezeTxnFields = *AssetFreezeTxnFields
+ case protocol.ApplicationCallTx:
+ v0, err := protocol.RandomizeObject(&txn.Txn.ApplicationCallTxnFields)
+ require.NoError(t, err)
+ ApplicationCallTxnFields, ok := v0.(*transactions.ApplicationCallTxnFields)
+ require.True(t, ok)
+ txn.Txn.ApplicationCallTxnFields = *ApplicationCallTxnFields
+ txn.Txn.ApplicationCallTxnFields.OnCompletion = 1
+ case protocol.CompactCertTx:
+ v0, err := protocol.RandomizeObject(&txn.Txn.CompactCertTxnFields)
+ require.NoError(t, err)
+ CompactCertTxnFields, ok := v0.(*transactions.CompactCertTxnFields)
+ require.True(t, ok)
+ txn.Txn.CompactCertTxnFields = *CompactCertTxnFields
+ default:
+ require.Fail(t, "unsupported txntype for txnsync msg encoding")
+ }
+ txn.Txn.Group = crypto.Digest{}
+ txns = append(txns, txn)
+ }
+ txnGroups := []pooldata.SignedTxGroup{
+ pooldata.SignedTxGroup{
+ Transactions: txns,
+ },
+ }
+ err = addGroupHashes(txnGroups, len(txns), []byte{1})
+ require.NoError(t, err)
+ var s syncState
+ ptg, err := s.encodeTransactionGroups(txnGroups, 0)
+ require.NoError(t, err)
+ out, err := decodeTransactionGroups(ptg, stx.Txn.GenesisID, stx.Txn.GenesisHash)
+ require.NoError(t, err)
+ require.ElementsMatch(t, txnGroups, out)
+ }
+}
+
+// pass in flag -db to specify db, start round, end round
+func TestTxnGroupEncodingArchival(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ if *blockDBFilename == "" {
+ t.Skip("no archival node db was provided")
+ }
+ blockDBs, err := db.OpenPair(*blockDBFilename, false)
+ require.NoError(t, err)
+ for r := basics.Round(*startRound); r < basics.Round(*endRound); r++ {
+ var block bookkeeping.Block
+ err = blockDBs.Rdb.Atomic(func(ctx context.Context, tx *sql.Tx) error {
+ var buf []byte
+ err = tx.QueryRow("SELECT blkdata FROM blocks WHERE rnd=?", r).Scan(&buf)
+ if err != nil {
+ if err == sql.ErrNoRows {
+ err = ledgercore.ErrNoEntry{Round: r}
+ }
+ return err
+ }
+ return protocol.Decode(buf, &block)
+ })
+ require.NoError(t, err)
+
+ var txnGroups []pooldata.SignedTxGroup
+ genesisID := block.GenesisID()
+ genesisHash := block.GenesisHash()
+ var payset [][]transactions.SignedTxnWithAD
+ payset, err := block.DecodePaysetGroups()
+ require.NoError(t, err)
+ for _, txns := range payset {
+ var txnGroup pooldata.SignedTxGroup
+ for _, txn := range txns {
+ txnGroup.Transactions = append(txnGroup.Transactions, txn.SignedTxn)
+ }
+ txnGroups = append(txnGroups, txnGroup)
+ }
+
+ var s syncState
+ ptg, err := s.encodeTransactionGroups(txnGroups, 0)
+ require.NoError(t, err)
+ out, err := decodeTransactionGroups(ptg, genesisID, genesisHash)
+ require.NoError(t, err)
+ require.ElementsMatch(t, txnGroups, out)
+ }
+}
diff --git a/util/bloom/bloom.go b/util/bloom/bloom.go
index eeffc88ef..cee316e32 100644
--- a/util/bloom/bloom.go
+++ b/util/bloom/bloom.go
@@ -118,22 +118,31 @@ func BinaryMarshalLength(numElements int, falsePositiveRate float64) int64 {
return filterBytes + 8 // adding 8 to match 4 prefix array, plus 4 bytes for the numHashes uint32
}
-// UnmarshalBinary restores the state of the filter from raw data
-func UnmarshalBinary(data []byte) (*Filter, error) {
- f := &Filter{}
+// UnmarshalBinary implements encoding.BinaryUnmarshaller interface
+func (f *Filter) UnmarshalBinary(data []byte) error {
if len(data) <= 8 {
- return nil, errors.New("short data")
+ return errors.New("short data")
}
f.numHashes = binary.BigEndian.Uint32(data[0:4])
if f.numHashes > maxHashes {
- return nil, errors.New("too many hashes")
+ return errors.New("too many hashes")
}
copy(f.prefix[:], data[4:8])
f.data = data[8:]
f.preimageStagingBuffer = make([]byte, len(f.prefix), len(f.prefix)+32)
f.hashStagingBuffer = make([]uint32, f.numHashes+3)
copy(f.preimageStagingBuffer, f.prefix[:])
- return f, nil
+ return nil
+}
+
+// UnmarshalBinary restores the state of the filter from raw data
+func UnmarshalBinary(data []byte) (*Filter, error) {
+ f := &Filter{}
+ err := f.UnmarshalBinary(data)
+ if err != nil {
+ f = nil
+ }
+ return f, err
}
// MarshalJSON defines how this filter should be encoded to JSON
diff --git a/util/bloom/bloom_test.go b/util/bloom/bloom_test.go
index 2380b8d87..12799e6a3 100644
--- a/util/bloom/bloom_test.go
+++ b/util/bloom/bloom_test.go
@@ -56,7 +56,7 @@ func TestOptimal(t *testing.T) {
numFP := []int{100, 25, 5}
if testing.Short() {
- numElementsCases = []int{2000, 200000}
+ numElementsCases = []int{2000, 20000}
fpRateCases = []float64{0.001, 0.00001}
numFP = []int{100, 25}
}
@@ -99,6 +99,7 @@ func closeEnough(a, b, maxerr float64) (bool, float64) {
}
// based on "github.com/willf/bloom"
+// Changes here might need to be replicated to xor_test.go estimateFalsePositiveRateXor()
func (f *Filter) estimateFalsePositiveRate(numAdded uint32, numFP int) float64 {
x := make([]byte, 4)
for i := uint32(0); i < numAdded; i++ {
@@ -182,18 +183,21 @@ func TestMarshalJSON(t *testing.T) {
}
}
-func BenchmarkCreateLargeFilter(b *testing.B) {
+const largeFilterElements = 150000
+
+// BenchmarkCreateLargeBloomFilter should have the same structure as xor_test.go BenchmarkCreateLargeXorFilter
+func BenchmarkCreateLargeBloomFilter(b *testing.B) {
// dialing mu=25000; 3 servers; so each mailbox is 75000 real and 75000 noise
// for a total of 150000 elements in the dialing bloom filter
- numElements := 150000
for i := 0; i < b.N; i++ {
- numBits, numHashes := Optimal(numElements, 1e-10)
+ numBits, numHashes := Optimal(largeFilterElements, 1e-10)
f := New(numBits, numHashes, 1234)
x := make([]byte, 4)
- for i := uint32(0); i < uint32(numElements); i++ {
+ for i := uint32(0); i < uint32(largeFilterElements); i++ {
binary.BigEndian.PutUint32(x, i)
f.Set(x)
}
+ f.MarshalBinary()
}
}
@@ -351,24 +355,26 @@ func BenchmarkBloomFilterSet(b *testing.B) {
}
}
+const filterTestElements = 1000000
+
+// See also BenchmarkXorFilterTest
func BenchmarkBloomFilterTest(b *testing.B) {
- bfElements := 1000000
- sizeBits, numHashes := Optimal(bfElements, 0.01)
+ sizeBits, numHashes := Optimal(filterTestElements, 0.01)
prefix := uint32(0)
bf := New(sizeBits, numHashes, prefix)
- dataset := make([][]byte, bfElements)
- for n := 0; n < bfElements; n++ {
+ dataset := make([][]byte, filterTestElements)
+ for n := 0; n < filterTestElements; n++ {
hash := crypto.Hash([]byte{byte(n), byte(n >> 8), byte(n >> 16), byte(n >> 24)})
dataset[n] = hash[:]
}
// set half of them.
- for n := 0; n < bfElements/2; n++ {
+ for n := 0; n < filterTestElements/2; n++ {
bf.Set(dataset[n])
}
b.ResetTimer()
for x := 0; x < b.N; x++ {
- bf.Test(dataset[x%bfElements])
+ bf.Test(dataset[x%filterTestElements])
}
}
diff --git a/util/bloom/generic.go b/util/bloom/generic.go
new file mode 100644
index 000000000..991edb5aa
--- /dev/null
+++ b/util/bloom/generic.go
@@ -0,0 +1,27 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package bloom
+
+// GenericFilter is the interface for either bloom.Filter or bloom.XorFilter
+type GenericFilter interface {
+ // The input x is expected to be a slice with a length of 8 bytes or more.
+ Set(x []byte)
+ // The input x is expected to be a slice with a length of 8 bytes or more.
+ Test(x []byte) bool
+ MarshalBinary() ([]byte, error)
+ UnmarshalBinary(data []byte) error
+}
diff --git a/util/bloom/xor.go b/util/bloom/xor.go
new file mode 100644
index 000000000..b79dbfa5f
--- /dev/null
+++ b/util/bloom/xor.go
@@ -0,0 +1,277 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package bloom
+
+import (
+ "encoding/binary"
+ "encoding/json"
+ "errors"
+
+ "github.com/algorand/xorfilter"
+)
+
+// XorBuilder is a local alias for xorfilter.Builder
+type XorBuilder = xorfilter.Builder
+
+// XorFilter is a faster more efficient alternative to a Bloom filter
+// An XorFilter object can be used as is or with optional adittional setup.
+type XorFilter struct {
+ xor *xorfilter.Xor32
+ holding []uint64
+
+ b *XorBuilder
+}
+
+// NewXor returns an XorFilter with an internal map created with a size hint and an optional *XorBuilder (may be nil)
+// The Builder is not thread safe and should only be used by one thread at a time.
+func NewXor(hint int, builder *XorBuilder) *XorFilter {
+ return &XorFilter{
+ b: builder,
+ holding: make([]uint64, 0, hint),
+ }
+}
+
+// Set adds the value to the filter.
+func (xf *XorFilter) Set(x []byte) {
+ k := binary.BigEndian.Uint64(x)
+ xf.holding = append(xf.holding, k)
+}
+
+// Test checks whether x is present in the filter.
+// May return (rare) erroneous true values, but false is precise.
+func (xf *XorFilter) Test(x []byte) bool {
+ k := binary.BigEndian.Uint64(x)
+ if xf.xor != nil {
+ return xf.xor.Contains(k)
+ }
+ return false
+}
+
+const sizeofInt32 = 4
+
+// MarshalBinary implements encoding.BinaryMarshaller interface
+func (xf *XorFilter) MarshalBinary() ([]byte, error) {
+ if len(xf.holding) != 0 {
+ var err error
+ if xf.b != nil {
+ xf.xor, err = xf.b.Populate32(xf.holding)
+ } else {
+ xf.xor, err = xorfilter.Populate32(xf.holding)
+ }
+ if err != nil {
+ return nil, err
+ }
+ }
+ if xf.xor == nil || (len(xf.xor.Fingerprints) == 0) {
+ // TODO: some other encoding for empty set?
+ return nil, nil
+ }
+ out := make([]byte, binary.MaxVarintLen64+binary.MaxVarintLen32+binary.MaxVarintLen32+(len(xf.xor.Fingerprints)*sizeofInt32))
+ pos := 0
+ pos += binary.PutUvarint(out[pos:], xf.xor.Seed)
+ pos += binary.PutUvarint(out[pos:], uint64(xf.xor.BlockLength))
+ pos += binary.PutUvarint(out[pos:], uint64(len(xf.xor.Fingerprints)))
+ for _, v := range xf.xor.Fingerprints {
+ binary.LittleEndian.PutUint32(out[pos:], v)
+ pos += sizeofInt32
+ }
+ out = out[:pos]
+ return out, nil
+}
+
+// ErrBadBinary is returned when UnmarshalBinary fails
+var ErrBadBinary = errors.New("bad XorFilter binary")
+
+// TODO: make this an option to UnmarshalBinary, or a settable global, ...
+const maxFingerprints = 1000000
+
+// UnmarshalBinary implements encoding.BinaryUnmarshaller interface
+func (xf *XorFilter) UnmarshalBinary(data []byte) error {
+ pos := 0
+ var dp int
+ xor := new(xorfilter.Xor32)
+ xor.Seed, dp = binary.Uvarint(data[pos:])
+ if dp <= 0 {
+ return ErrBadBinary
+ }
+ pos += dp
+ blockLength, dp := binary.Uvarint(data[pos:])
+ if dp <= 0 {
+ return ErrBadBinary
+ }
+ xor.BlockLength = uint32(blockLength)
+ pos += dp
+ lenFingerprints, dp := binary.Uvarint(data[pos:])
+ if dp <= 0 {
+ return ErrBadBinary
+ }
+ pos += dp
+ if lenFingerprints > 0 {
+ if lenFingerprints > maxFingerprints {
+ return ErrBadBinary
+ }
+ if (lenFingerprints * sizeofInt32) > uint64(len(data)-pos) {
+ return ErrBadBinary
+ }
+ xor.Fingerprints = make([]uint32, lenFingerprints)
+ for i := 0; i < int(lenFingerprints); i++ {
+ xor.Fingerprints[i] = binary.LittleEndian.Uint32(data[pos:])
+ pos += sizeofInt32
+ }
+ xf.xor = xor
+ } else {
+ xf.xor = nil
+ }
+ return nil
+}
+
+// MarshalJSON implements encoding/json.Marshaller interface
+func (xf *XorFilter) MarshalJSON() ([]byte, error) {
+ data, err := xf.MarshalBinary()
+ if err != nil {
+ return nil, err
+ }
+ return json.Marshal(data)
+}
+
+// UnmarshalJSON implements encoding/json.Unmarshaler interface
+func (xf *XorFilter) UnmarshalJSON(data []byte) error {
+ var blob []byte
+ err := json.Unmarshal(data, &blob)
+ if err != nil {
+ return err
+ }
+ return xf.UnmarshalBinary(blob)
+}
+
+// XorFilter8 is a faster more efficient alternative to a Bloom filter
+// An XorFilter8 object can be used as is or with optional adittional setup.
+// XorFilter8 uses 1/4 the space of XorFilter (32 bit)
+type XorFilter8 struct {
+ xor *xorfilter.Xor8
+ holding []uint64
+
+ b *XorBuilder
+}
+
+// NewXor8 returns an XorFilter8 with an internal map created with a size hint and an optional *XorBuilder (may be nil)
+// The Builder is not thread safe and should only be used by one thread at a time.
+func NewXor8(hint int, builder *XorBuilder) *XorFilter8 {
+ return &XorFilter8{
+ b: builder,
+ }
+}
+
+// Set adds the value to the filter.
+func (xf *XorFilter8) Set(x []byte) {
+ k := binary.BigEndian.Uint64(x)
+ xf.holding = append(xf.holding, k)
+}
+
+// Test checks whether x is present in the filter.
+// May return (rare) erroneous true values, but false is precise.
+func (xf *XorFilter8) Test(x []byte) bool {
+ k := binary.BigEndian.Uint64(x)
+ if xf.xor != nil {
+ return xf.xor.Contains(k)
+ }
+ return false
+}
+
+// MarshalBinary implements encoding.BinaryMarshaller interface
+func (xf *XorFilter8) MarshalBinary() ([]byte, error) {
+ if len(xf.holding) != 0 {
+ var err error
+ if xf.b != nil {
+ xf.xor, err = xf.b.Populate(xf.holding)
+ } else {
+ xf.xor, err = xorfilter.Populate(xf.holding)
+ }
+ if err != nil {
+ return nil, err
+ }
+ }
+ if xf.xor == nil || (len(xf.xor.Fingerprints) == 0) {
+ // TODO: some other encoding for empty set?
+ return nil, nil
+ }
+ out := make([]byte, binary.MaxVarintLen64+binary.MaxVarintLen32+binary.MaxVarintLen32+(len(xf.xor.Fingerprints)))
+ pos := 0
+ pos += binary.PutUvarint(out[pos:], xf.xor.Seed)
+ pos += binary.PutUvarint(out[pos:], uint64(xf.xor.BlockLength))
+ pos += binary.PutUvarint(out[pos:], uint64(len(xf.xor.Fingerprints)))
+ copy(out[pos:], xf.xor.Fingerprints)
+ pos += len(xf.xor.Fingerprints)
+ out = out[:pos]
+ return out, nil
+}
+
+// UnmarshalBinary implements encoding.BinaryUnmarshaller interface
+func (xf *XorFilter8) UnmarshalBinary(data []byte) error {
+ pos := 0
+ var dp int
+ xor := new(xorfilter.Xor8)
+ xor.Seed, dp = binary.Uvarint(data[pos:])
+ if dp <= 0 {
+ return ErrBadBinary
+ }
+ pos += dp
+ blockLength, dp := binary.Uvarint(data[pos:])
+ if dp <= 0 {
+ return ErrBadBinary
+ }
+ xor.BlockLength = uint32(blockLength)
+ pos += dp
+ lenFingerprints, dp := binary.Uvarint(data[pos:])
+ if dp <= 0 {
+ return ErrBadBinary
+ }
+ pos += dp
+ if lenFingerprints > 0 {
+ if lenFingerprints > maxFingerprints {
+ return ErrBadBinary
+ }
+ if lenFingerprints > uint64(len(data)-pos) {
+ return ErrBadBinary
+ }
+ xor.Fingerprints = make([]byte, lenFingerprints)
+ copy(xor.Fingerprints, data[pos:])
+ xf.xor = xor
+ } else {
+ xf.xor = nil
+ }
+ return nil
+}
+
+// MarshalJSON implements encoding/json.Marshaller interface
+func (xf *XorFilter8) MarshalJSON() ([]byte, error) {
+ data, err := xf.MarshalBinary()
+ if err != nil {
+ return nil, err
+ }
+ return json.Marshal(data)
+}
+
+// UnmarshalJSON implements encoding/json.Unmarshaler interface
+func (xf *XorFilter8) UnmarshalJSON(data []byte) error {
+ var blob []byte
+ err := json.Unmarshal(data, &blob)
+ if err != nil {
+ return err
+ }
+ return xf.UnmarshalBinary(blob)
+}
diff --git a/util/bloom/xor_test.go b/util/bloom/xor_test.go
new file mode 100644
index 000000000..0ad839bc7
--- /dev/null
+++ b/util/bloom/xor_test.go
@@ -0,0 +1,322 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package bloom
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "math/rand"
+ "runtime"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/xorfilter"
+
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/test/partitiontest"
+)
+
+func TestXorBloom(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ numElementsCases := []int{2000, 20000, 200000}
+ fpRateCases := []float64{0.0042} //, 0.00001, 0.0000001}
+ numFP := []int{100, 25, 5}
+ if testing.Short() {
+ numElementsCases = []int{2000, 20000}
+ numFP = []int{100, 25}
+ }
+ for _, numElements := range numElementsCases {
+ for i, fpRate := range fpRateCases {
+ actualRate := estimateFalsePositiveRateXor(t, numElements, numFP[i])
+ if actualRate < fpRate {
+ t.Logf("\tOK: numElements=%v want %v, got %v", numElements, fpRate, actualRate)
+ continue
+ }
+
+ t.Errorf("numElements=%v want %v, got %v", numElements, fpRate, actualRate)
+ }
+ }
+}
+
+// like bloom_test.go estimateFalsePositiveRate()
+// based on "github.com/willf/bloom"
+func estimateFalsePositiveRateXor(t *testing.T, numAdded int, numFP int) float64 {
+ var xf XorFilter
+ maxDuration := 5 * time.Second
+ if testing.Short() {
+ maxDuration = 100 * time.Millisecond
+ }
+ x := make([]byte, 8)
+ for i := 0; i < numAdded; i++ {
+ binary.BigEndian.PutUint32(x, uint32(i))
+ xf.Set(x)
+ }
+
+ xord, err := xf.MarshalBinary()
+ require.NoError(t, err)
+ var nxf XorFilter8
+ err = nxf.UnmarshalBinary(xord)
+ require.NoError(t, err)
+
+ start := time.Now()
+ falsePositives := 0
+ numRounds := 0
+ for i := 0; falsePositives < numFP; i++ {
+ binary.BigEndian.PutUint32(x, uint32(numAdded+i+1))
+ if nxf.Test(x) {
+ falsePositives++
+ }
+ numRounds++
+ if numRounds%10000 == 0 {
+ dt := time.Now().Sub(start)
+ if dt > maxDuration {
+ t.Logf("t %s > max duration %s without finding false positive rate", dt, maxDuration)
+ break
+ }
+ }
+ }
+
+ return float64(falsePositives) / float64(numRounds)
+}
+
+func TestByte32FalsePositive(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ t.Parallel()
+ var filterSizes = []int{1000, 5000, 10000, 50000, 100000}
+ for _, filterSetSize := range filterSizes {
+ //const filterSetSize = 100000
+ txids := make([][]byte, filterSetSize)
+ store := make([]byte, 32*filterSetSize)
+ rand.Read(store)
+ for i := 0; i < filterSetSize; i++ {
+ txids[i] = store[i*32 : (i+1)*32]
+ }
+
+ notIn := func(t []byte) bool {
+ for _, v := range txids {
+ if bytes.Equal(t, v) {
+ return false
+ }
+ }
+ return true
+ }
+
+ var xf XorFilter
+
+ fpRate := 0.01
+ //fpRate := 0.004
+ numBits, numHashes := Optimal(filterSetSize, fpRate)
+ bf := New(numBits, numHashes, 0x12345678)
+
+ for _, v := range txids {
+ xf.Set(v)
+ bf.Set(v)
+ }
+
+ xord, err := xf.MarshalBinary()
+ require.NoError(t, err)
+ var nxf XorFilter
+ err = nxf.UnmarshalBinary(xord)
+ require.NoError(t, err)
+
+ bloomData, err := bf.MarshalBinary()
+ require.NoError(t, err)
+
+ t.Logf("filter for %d * [32]byte, bloom %d bytes, xor8 %d bytes",
+ filterSetSize, len(bloomData), len(xord))
+
+ xfalsePositives := 0
+ bfalsePositives := 0
+ const testN = 100000
+ var tt [32]byte
+ for i := 0; i < testN; i++ {
+ rand.Read(tt[:])
+ xhit := nxf.Test(tt[:])
+ bhit := bf.Test(tt[:])
+ if xhit || bhit {
+ falsePositive := notIn(tt[:])
+ if xhit && falsePositive {
+ xfalsePositives++
+ }
+ if bhit && falsePositive {
+ bfalsePositives++
+ }
+ }
+ }
+
+ t.Logf("false positives bloom %d/%d, xor %d/%d", bfalsePositives, testN, xfalsePositives, testN)
+ bfp := float64(bfalsePositives) / float64(testN)
+ xfp := float64(xfalsePositives) / float64(testN)
+ if bfp > (fpRate * 1.2) {
+ t.Errorf("bloom false positive too high: %f", bfp)
+ }
+ if xfp > (fpRate * 1.2) {
+ t.Errorf("xor false positive too high: %f", xfp)
+ }
+ }
+}
+
+type GenericFilterFactory func() GenericFilter
+
+func memTestFilter(t *testing.T, filterFactory GenericFilterFactory, filterSetSize int) {
+ // setup
+ txids := make([][]byte, filterSetSize)
+ store := make([]byte, 32*filterSetSize)
+ rand.Read(store)
+ for i := 0; i < filterSetSize; i++ {
+ txids[i] = store[i*32 : (i+1)*32]
+ }
+ runtime.GC()
+
+ var memAfterSetup runtime.MemStats
+ runtime.ReadMemStats(&memAfterSetup)
+
+ f := filterFactory()
+ for _, v := range txids {
+ f.Set(v)
+ }
+ data, err := f.MarshalBinary()
+ require.NoError(t, err)
+
+ var memAfterSerialize runtime.MemStats
+ runtime.ReadMemStats(&memAfterSerialize)
+
+ nf := filterFactory()
+ err = nf.UnmarshalBinary(data)
+ require.NoError(t, err)
+
+ var memAfterDeserialize runtime.MemStats
+ runtime.ReadMemStats(&memAfterDeserialize)
+
+ t.Logf("build mem[%d]: %s", filterSetSize, memDelta(&memAfterSetup, &memAfterSerialize))
+ t.Logf("load mem[%d]: %s", filterSetSize, memDelta(&memAfterSerialize, &memAfterDeserialize))
+}
+
+func memDelta(a, b *runtime.MemStats) string {
+ dMallocs := b.Mallocs - a.Mallocs
+ dFrees := b.Frees - a.Frees
+ dAllocated := b.HeapAlloc - a.HeapAlloc
+ return fmt.Sprintf("%d mallocs, %d frees, %d bytes allocated", dMallocs, dFrees, dAllocated)
+}
+
+func TestMemXor(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ t.Parallel()
+ var xb xorfilter.Builder
+ xff := func() GenericFilter {
+ xf := NewXor(5000, &xb)
+ return xf
+ }
+ memTestFilter(t, xff, 5000)
+ memTestFilter(t, xff, 5000)
+}
+
+func TestMemBloom(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ t.Parallel()
+ fpRate := 0.004
+ filterSetSize := 5000
+ numBits, numHashes := Optimal(filterSetSize, fpRate)
+ bff := func() GenericFilter {
+ return New(numBits, numHashes, 0x12345678)
+ }
+ memTestFilter(t, bff, filterSetSize)
+}
+
+// TestFilterSize tests different sizes of inputs against xor8 and xor32 and check
+// that the generated marshaled byte representation aligns with the expected size.
+func TestFilterSize(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ var builder XorBuilder
+ for size := 1000; size < 50000; size = ((size + size/2) / 100) * 100 {
+ xor := NewXor(size, &builder)
+ for i := 0; i < size; i++ {
+ digest := crypto.Hash([]byte{byte(i), byte(i >> 8), byte(i >> 16)})
+ xor.Set(digest[:])
+ }
+ out, err := xor.MarshalBinary()
+ require.NoError(t, err)
+ bytesElement := float32(len(out)) / float32(size)
+ fmt.Printf("Xor32 filter for %d elements takes %d bytes, %f bytes/element\n", size, len(out), bytesElement)
+ require.GreaterOrEqual(t, bytesElement, float32(4.9))
+ require.LessOrEqual(t, bytesElement, float32(5.1))
+ }
+ for size := 1000; size < 50000; size = ((size + size/2) / 100) * 100 {
+ xor := NewXor8(size, &builder)
+ for i := 0; i < size; i++ {
+ digest := crypto.Hash([]byte{byte(i), byte(i >> 8), byte(i >> 16)})
+ xor.Set(digest[:])
+ }
+ out, err := xor.MarshalBinary()
+ require.NoError(t, err)
+ bytesElement := float32(len(out)) / float32(size)
+ fmt.Printf("Xor8 filter for %d elements takes %d bytes, %f bytes/element\n", size, len(out), bytesElement)
+ require.GreaterOrEqual(t, bytesElement, float32(1.23))
+ require.LessOrEqual(t, bytesElement, float32(1.28))
+ }
+}
+
+// BenchmarkCreateLargeXorFilter should have the same structure as bloom_test.go BenchmarkCreateLargeBloomFilter
+func BenchmarkCreateLargeXorFilter(b *testing.B) {
+ // dialing mu=25000; 3 servers; so each mailbox is 75000 real and 75000 noise
+ // for a total of 150000 elements in the dialing bloom filter
+ var xb xorfilter.Builder
+ for i := 0; i < b.N; i++ {
+ xf := NewXor(largeFilterElements, &xb)
+ x := make([]byte, 8)
+ for i := uint32(0); i < uint32(largeFilterElements); i++ {
+ binary.BigEndian.PutUint32(x, i)
+ xf.Set(x)
+ }
+ xf.MarshalBinary()
+ }
+}
+
+// See Also BenchmarkBloomFilterTest
+func BenchmarkXorFilterTest(b *testing.B) {
+ // sizeBits, numHashes := Optimal(filterTestElements, 0.01)
+ // prefix := uint32(0)
+ // bf := New(sizeBits, numHashes, prefix)
+ var xf XorFilter
+ dataset := make([][]byte, filterTestElements)
+ for n := 0; n < filterTestElements; n++ {
+ hash := crypto.Hash([]byte{byte(n), byte(n >> 8), byte(n >> 16), byte(n >> 24)})
+ dataset[n] = hash[:]
+ }
+ // set half of them.
+ for n := 0; n < filterTestElements/2; n++ {
+ xf.Set(dataset[n])
+ }
+
+ xord, err := xf.MarshalBinary()
+ require.NoError(b, err)
+ var nxf XorFilter
+ err = nxf.UnmarshalBinary(xord)
+ require.NoError(b, err)
+
+ b.ResetTimer()
+ for x := 0; x < b.N; x++ {
+ nxf.Test(dataset[x%filterTestElements])
+ }
+}
diff --git a/util/compress/deflate.go b/util/compress/deflate.go
new file mode 100644
index 000000000..188885b5a
--- /dev/null
+++ b/util/compress/deflate.go
@@ -0,0 +1,174 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package compress
+
+// #cgo CFLAGS: -Wall -std=c99 -I${SRCDIR}/libdeflate
+// #cgo amd64 CFLAGS: -DX86 -D__x86_64__ -D__i386__
+// #cgo arm64 CFLAGS: -DARM
+// #cgo arm CFLAGS: -DARM
+// #cgo linux,amd64 CFLAGS: -march=sandybridge
+// #cgo darwin,amd64 CFLAGS: -march=tremont
+// #include <stdint.h>
+// int isNull(void * c) {
+// if(!c) {
+// return 1;
+// }
+// return 0;
+// };
+//
+// #ifdef X86
+// #include "lib/x86/cpu_features.c"
+// #endif
+// #ifdef ARM
+// #include "lib/arm/cpu_features.c"
+// #endif
+// #define dispatch crc32_dispatch
+// #include "lib/crc32.c"
+// #undef dispatch
+// #define dispatch compress_dispatch
+// #define bitbuf_t compress_bitbuf_t
+// #include "lib/deflate_compress.c"
+// #undef bitbuf_t
+// #undef dispatch
+// #undef BITBUF_NBITS
+// #include "lib/deflate_decompress.c"
+// #include "lib/gzip_compress.c"
+// #include "lib/gzip_decompress.c"
+// #include "lib/utils.c"
+import "C"
+
+import (
+ "errors"
+ "runtime"
+ "unsafe"
+)
+
+var (
+ // ErrOutOfMemory is returned when we fail to allocate the compressor/decompressor
+ ErrOutOfMemory = errors.New("out of memory")
+ // ErrShortBuffer is returned when the output buffer is too small to fit the compressed/decompressed data
+ ErrShortBuffer = errors.New("short buffer")
+ // ErrNoInput is returned when no input buffer data is provided
+ ErrNoInput = errors.New("empty input")
+ // ErrBadData is returned when the compressed data is corrupted
+ ErrBadData = errors.New("data was corrupted, invalid or unsupported")
+ // ErrInsufficientSpace is returned when the provided output buffer is found to be too small during the decompression
+ ErrInsufficientSpace = errors.New("decompression failed: buffer too short. Retry with larger buffer")
+ // ErrShortOutput should not be generated using the current libdeflate usage, but remain here for compatibility
+ ErrShortOutput = errors.New("buffer too long: decompressed to fewer bytes than expected, indicating possible error in decompression. Make sure your out buffer has the exact length of the decompressed data or pass nil for out")
+ // ErrPartiallyConsumedData is returned if only a subset of the input data was consumed during the decompression
+ ErrPartiallyConsumedData = errors.New("partially consumed data")
+
+ // ErrUnknown returned when the libdeflate returns unexpected enum error
+ ErrUnknown = errors.New("unknown error code from decompressor library")
+)
+
+// Compress the input buffer into the output buffer.
+func Compress(in, out []byte, compressLevel int) (int, []byte, error) {
+ if len(in) == 0 {
+ return 0, out, ErrNoInput
+ }
+ if cap(out) == 0 {
+ return 0, out, ErrShortBuffer
+ }
+
+ if compressLevel < 1 {
+ compressLevel = 1
+ } else if compressLevel > 12 {
+ compressLevel = 12
+ }
+
+ c := C.libdeflate_alloc_compressor(C.int(compressLevel))
+ if C.isNull(unsafe.Pointer(c)) == 1 {
+ return 0, out, ErrOutOfMemory
+ }
+ defer func() {
+ C.libdeflate_free_compressor(c)
+ }()
+ inAddr := startMemAddr(in)
+ outAddr := startMemAddr(out)
+
+ written := int(C.libdeflate_gzip_compress(c, unsafe.Pointer(inAddr), C.size_t(len(in)), unsafe.Pointer(outAddr), C.size_t(cap(out))))
+
+ if written == 0 {
+ return written, out, ErrShortBuffer
+ }
+ return written, out[:written], nil
+}
+
+// Decompress decompresses the input buffer data into the output buffer.
+func Decompress(in, out []byte) ([]byte, error) {
+ if len(in) == 0 {
+ return out, ErrNoInput
+ }
+ if cap(out) == 0 {
+ return out, ErrShortBuffer
+ }
+ dc := C.libdeflate_alloc_decompressor()
+ if C.isNull(unsafe.Pointer(dc)) == 1 {
+ return out, ErrOutOfMemory
+ }
+ defer func() {
+ C.libdeflate_free_decompressor(dc)
+ }()
+
+ inAddr := startMemAddr(in)
+ outAddr := startMemAddr(out)
+
+ var actualInBytes C.size_t
+ var actualOutBytes C.size_t
+ r := C.libdeflate_gzip_decompress_ex(dc, unsafe.Pointer(inAddr), C.size_t(len(in)), unsafe.Pointer(outAddr), C.size_t(cap(out)), &actualInBytes, &actualOutBytes)
+
+ runtime.KeepAlive(&actualInBytes)
+ runtime.KeepAlive(&actualOutBytes)
+ switch r {
+ case C.LIBDEFLATE_SUCCESS:
+ if actualInBytes != C.size_t(len(in)) {
+ // return an error if not all the data was consumed.
+ return out, ErrPartiallyConsumedData
+ }
+ return out[:actualOutBytes], nil
+ case C.LIBDEFLATE_BAD_DATA:
+ return out, ErrBadData
+ case C.LIBDEFLATE_SHORT_OUTPUT:
+ return out, ErrShortOutput
+ case C.LIBDEFLATE_INSUFFICIENT_SPACE:
+ return out, ErrInsufficientSpace
+ default:
+ return out, ErrUnknown
+ }
+}
+
+func startMemAddr(b []byte) *byte {
+ if len(b) > 0 {
+ return &b[0]
+ }
+
+ b = append(b, 0)
+ ptr := &b[0]
+
+ return ptr
+}
+
+func init() {
+ // initialize dispatch tables. This is important since we want to avoid race conditions when running the dispatch over multiple cores.
+ decompressedBuffer := []byte{1, 2, 3, 4}
+ compressedBuffer := make([]byte, 128)
+ _, compressedOutput, _ := Compress(decompressedBuffer, compressedBuffer, 9)
+ decompressedBuffer = make([]byte, 128)
+ Decompress(compressedOutput, decompressedBuffer) //nolint:errcheck // static call that won't fail
+}
diff --git a/util/compress/deflate_test.go b/util/compress/deflate_test.go
new file mode 100644
index 000000000..cf16e72a1
--- /dev/null
+++ b/util/compress/deflate_test.go
@@ -0,0 +1,123 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package compress
+
+import (
+ "bytes"
+ "compress/gzip"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/test/partitiontest"
+)
+
+func TestTrivialCompression(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ bufLen := 10240
+ buffer := make([]byte, bufLen)
+ for i := range buffer {
+ buffer[i] = byte(i % 256)
+ }
+
+ compressedBuffer := make([]byte, 0, bufLen)
+ len, compressedOutput, err := Compress(buffer, compressedBuffer, 9)
+ require.NoError(t, err)
+ require.NotZero(t, len)
+ require.Equal(t, compressedBuffer[:len], compressedOutput)
+
+ decompressedBuffer := make([]byte, 0, bufLen)
+ decompressedOutput, err := Decompress(compressedOutput, decompressedBuffer)
+ require.NoError(t, err)
+ require.Equal(t, decompressedOutput, buffer)
+}
+
+func BenchmarkCompression(b *testing.B) {
+ bufLen := 1024000
+ buffer := make([]byte, bufLen)
+ outBuffer := make([]byte, 0, bufLen)
+ for i := range buffer {
+ buffer[i] = byte(i % 256)
+ }
+ var targetLength int
+ b.Run("compress/gzip", func(b *testing.B) {
+ for k := 0; k < b.N; k++ {
+ outBuffer := bytes.NewBuffer(outBuffer)
+ writer := gzip.NewWriter(outBuffer)
+ writer.Write(buffer)
+ writer.Close()
+ targetLength = outBuffer.Len()
+ }
+ })
+ // figure out desired compression level.
+ compressionLevel := 1
+ for {
+ len, _, _ := Compress(buffer, outBuffer, compressionLevel)
+ if len <= targetLength+128 || compressionLevel > 11 {
+ break
+ }
+ compressionLevel++
+ }
+ b.Run("deflateCompression", func(b *testing.B) {
+ for k := 0; k < b.N; k++ {
+ Compress(buffer, outBuffer[:cap(outBuffer)], compressionLevel)
+ }
+ })
+}
+
+func BenchmarkDecompression(b *testing.B) {
+ bufLen := 1024000
+ decompressedBuffer := make([]byte, bufLen)
+ for i := range decompressedBuffer {
+ decompressedBuffer[i] = byte(i % 256)
+ }
+
+ // create the compress/gzip compressed buffer.
+ gzipCompressedBuffer := bytes.NewBuffer([]byte{})
+ writer := gzip.NewWriter(gzipCompressedBuffer)
+ writer.Write(decompressedBuffer)
+ writer.Close()
+ gzipCompressedBytes := gzipCompressedBuffer.Bytes()
+
+ // create the deflate compressed buffer.
+ deflateCompressedBuffer := make([]byte, 0, bufLen)
+ _, deflateCompressedBuffer, _ = Compress(decompressedBuffer, deflateCompressedBuffer, 1)
+
+ b.Run("compress/gzip", func(b *testing.B) {
+ for k := 0; k < b.N; k++ {
+ stage := make([]byte, 1024)
+ reader, err := gzip.NewReader(bytes.NewBuffer(gzipCompressedBytes))
+ require.NoError(b, err)
+ for {
+ n, err := reader.Read(stage[:])
+ if n == 0 || err != nil {
+ break
+ }
+ }
+ reader.Close()
+ gzipCompressedBuffer.Reset()
+ }
+ })
+
+ b.Run("deflateCompression", func(b *testing.B) {
+ outBuffer := make([]byte, 0, bufLen)
+ for k := 0; k < b.N; k++ {
+ Decompress(deflateCompressedBuffer, outBuffer[:cap(outBuffer)])
+ }
+ })
+}
diff --git a/util/compress/libdeflate/.cirrus.yml b/util/compress/libdeflate/.cirrus.yml
new file mode 100644
index 000000000..602f0a68a
--- /dev/null
+++ b/util/compress/libdeflate/.cirrus.yml
@@ -0,0 +1,8 @@
+task:
+ freebsd_instance:
+ matrix:
+ - image_family: freebsd-11-3-snap
+ - image_family: freebsd-12-1-snap
+ install_script: pkg install -y gmake
+ script:
+ - gmake check
diff --git a/util/compress/libdeflate/.github/workflows/ci.yml b/util/compress/libdeflate/.github/workflows/ci.yml
new file mode 100644
index 000000000..ff7cfdbb4
--- /dev/null
+++ b/util/compress/libdeflate/.github/workflows/ci.yml
@@ -0,0 +1,123 @@
+name: CI
+on: [pull_request]
+env:
+ CFLAGS: -Werror
+
+jobs:
+ x86_64-build-and-test:
+ name: Build and test (x86_64, ${{ matrix.os }}, ${{ matrix.compiler }})
+ strategy:
+ matrix:
+ os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04]
+ compiler: [gcc, clang]
+ exclude:
+ # clang 3.8.0-2ubuntu4 crashes with:
+ # "fatal error: error in backend: Cannot select: 0x21025a0: v64i8 = X86ISD::VBROADCAST 0x2101fb0"
+ - os: ubuntu-16.04
+ compiler: clang
+ runs-on: ${{ matrix.os }}
+ env:
+ CC: ${{ matrix.compiler }}
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y clang llvm libz-dev valgrind
+ - run: scripts/run_tests.sh
+
+ other-arch-build-and-test:
+ name: Build and test (${{ matrix.arch }}, Debian Buster, ${{ matrix.compiler }})
+ strategy:
+ matrix:
+ arch: [armv6, armv7, aarch64, s390x, ppc64le]
+ compiler: [gcc, clang]
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: uraimo/run-on-arch-action@v2.0.5
+ with:
+ arch: ${{ matrix.arch }}
+ distro: buster
+ githubToken: ${{ github.token }}
+ install: |
+ apt-get update
+ apt-get install -y build-essential clang llvm libz-dev valgrind
+ run: |
+ # Valgrind and ASAN crash on at least s390x, ppc64le, and aarch64
+ # here. (It's probably something related to the QEMU user-mode
+ # emulation that run-on-arch-action uses.)
+ export SKIP_VALGRIND=1
+ export SKIP_ASAN=1
+
+ case ${{ matrix.arch }} in
+ s390x)
+ # On s390x, in freestanding builds the shared library links to an
+ # external symbol __clzdi2, even when -static-libgcc is used.
+ export SKIP_FREESTANDING=1
+ ;;
+ aarch64)
+ # "ldd: exited with unknown exit code (139)"
+ if [ ${{ matrix.compiler }} = clang ]; then
+ export SKIP_SHARED_LIB=1
+ fi
+ ;;
+ esac
+
+ export CC=${{ matrix.compiler }}
+ scripts/run_tests.sh
+
+ macos-build-and-test:
+ name: Build and test (macOS)
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v2
+ - run: make all check
+
+ windows-build-and-test:
+ name: Build and test (Windows)
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@v2
+ - shell: bash
+ run: |
+ PATH="C:\\msys64\\mingw64\\bin:C:\\msys64\\usr\\bin:$PATH" \
+ make CC=gcc all check
+
+ run-clang-static-analyzer:
+ name: Run clang static analyzer
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y clang-tools
+ - name: Run clang static analyzer
+ run: make scan-build
+
+ run-shellcheck:
+ name: Run shellcheck
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y shellcheck
+ - name: Run shellcheck
+ run: make shellcheck
+
+ cross-compile-for-windows:
+ name: Cross compile for Windows
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y gcc-mingw-w64-i686 gcc-mingw-w64-x86-64 libz-mingw-w64-dev
+ - name: 32-bit build
+ run: make CC=i686-w64-mingw32-gcc all test_programs
+ - name: 64-bit build
+ run: make CC=x86_64-w64-mingw32-gcc all test_programs
diff --git a/util/compress/libdeflate/.gitignore b/util/compress/libdeflate/.gitignore
new file mode 100644
index 000000000..f0b086118
--- /dev/null
+++ b/util/compress/libdeflate/.gitignore
@@ -0,0 +1,21 @@
+*.a
+*.def
+*.dll
+*.dllobj
+*.dylib
+*.exe
+*.exp
+*.lib
+*.o
+*.obj
+*.so
+*.so.*
+/.build-config
+/programs/config.h
+/benchmark
+/checksum
+/gzip
+/gunzip
+/test_*
+tags
+cscope*
diff --git a/util/compress/libdeflate/COPYING b/util/compress/libdeflate/COPYING
new file mode 100644
index 000000000..1f1b81cd5
--- /dev/null
+++ b/util/compress/libdeflate/COPYING
@@ -0,0 +1,21 @@
+Copyright 2016 Eric Biggers
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation files
+(the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/util/compress/libdeflate/Makefile b/util/compress/libdeflate/Makefile
new file mode 100644
index 000000000..276d75d09
--- /dev/null
+++ b/util/compress/libdeflate/Makefile
@@ -0,0 +1,372 @@
+#
+# Use 'make help' to list available targets.
+#
+# Define V=1 to enable "verbose" mode, showing all executed commands.
+#
+# Define USE_SHARED_LIB to link the binaries to the shared library version of
+# libdeflate rather than to the static library version.
+#
+# Define DECOMPRESSION_ONLY to omit all compression code, building a
+# decompression-only library. If doing this, you must also build a specific
+# library target such as 'libdeflate.a', as the programs will no longer compile.
+#
+# Define DISABLE_GZIP to disable support for the gzip wrapper format.
+#
+# Define DISABLE_ZLIB to disable support for the zlib wrapper format.
+#
+# Define PREFIX to override the installation prefix, like './configure --prefix'
+# in autotools-based projects (default: /usr/local)
+#
+# Define BINDIR to override where to install binaries, like './configure
+# --bindir' in autotools-based projects (default: PREFIX/bin)
+#
+# Define INCDIR to override where to install headers, like './configure
+# --includedir' in autotools-based projects (default: PREFIX/include)
+#
+# Define LIBDIR to override where to install libraries, like './configure
+# --libdir' in autotools-based projects (default: PREFIX/lib)
+#
+# Define DESTDIR to override the installation destination directory
+# (default: empty string)
+#
+# Define FREESTANDING to build a freestanding library, i.e. a library that
+# doesn't link to any libc functions like malloc(), free(), and memcpy().
+# All users will need to call libdeflate_set_memory_allocator().
+#
+# You can also specify a custom CC, CFLAGS, CPPFLAGS, and/or LDFLAGS.
+#
+##############################################################################
+
+#### Common compiler flags. You can add additional flags by defining CFLAGS
+#### in the environment or on the 'make' command line.
+####
+#### The default optimization flags can be overridden, e.g. via CFLAGS="-O3" or
+#### CFLAGS="-O0 -fno-omit-frame-pointer". But this usually isn't recommended;
+#### you're unlikely to get significantly better performance even with -O3.
+
+cc-option = $(shell if $(CC) $(1) -c -x c /dev/null -o /dev/null \
+ 1>&2 2>/dev/null; then echo $(1); fi)
+
+override CFLAGS := \
+ -O2 -fomit-frame-pointer -std=c99 -I. -Wall -Wundef \
+ $(call cc-option,-Wpedantic) \
+ $(call cc-option,-Wdeclaration-after-statement) \
+ $(call cc-option,-Wmissing-prototypes) \
+ $(call cc-option,-Wstrict-prototypes) \
+ $(call cc-option,-Wvla) \
+ $(call cc-option,-Wimplicit-fallthrough) \
+ $(CFLAGS)
+
+FREESTANDING :=
+ifdef FREESTANDING
+override CPPFLAGS += -DFREESTANDING
+LIB_CFLAGS += -ffreestanding -nostdlib
+endif
+
+# Don't use this option except for testing; it isn't a stable interface.
+TEST_SUPPORT__DO_NOT_USE :=
+ifdef TEST_SUPPORT__DO_NOT_USE
+override CPPFLAGS += -DTEST_SUPPORT__DO_NOT_USE
+endif
+
+##############################################################################
+
+PREFIX ?= /usr/local
+BINDIR ?= $(PREFIX)/bin
+INCDIR ?= $(PREFIX)/include
+LIBDIR ?= $(PREFIX)/lib
+
+SOVERSION := 0
+
+STATIC_LIB_SUFFIX := .a
+PROG_SUFFIX :=
+PROG_CFLAGS :=
+HARD_LINKS := 1
+
+# Compiling for Windows with MinGW?
+ifneq ($(findstring -mingw,$(shell $(CC) -dumpmachine 2>/dev/null)),)
+ STATIC_LIB_SUFFIX := static.lib
+ SHARED_LIB := libdeflate.dll
+ SHARED_LIB_SYMLINK :=
+ SHARED_LIB_CFLAGS :=
+ SHARED_LIB_LDFLAGS := -Wl,--out-implib,libdeflate.lib \
+ -Wl,--output-def,libdeflate.def \
+ -Wl,--add-stdcall-alias
+ PROG_SUFFIX := .exe
+ PROG_CFLAGS := -static -municode
+ HARD_LINKS :=
+ override CFLAGS := $(CFLAGS) $(call cc-option,-Wno-pedantic-ms-format)
+
+ # If AR was not already overridden, then derive it from $(CC).
+ # Note that CC may take different forms, e.g. "cc", "gcc",
+ # "x86_64-w64-mingw32-gcc", or "x86_64-w64-mingw32-gcc-6.3.1".
+ # On Windows it may also have a .exe extension.
+ ifeq ($(AR),ar)
+ AR := $(shell echo $(CC) | \
+ sed -E 's/g?cc(-?[0-9]+(\.[0-9]+)*)?(\.exe)?$$/ar\3/')
+ endif
+
+# macOS?
+else ifeq ($(shell uname),Darwin)
+ SHARED_LIB := libdeflate.$(SOVERSION).dylib
+ SHARED_LIB_SYMLINK := libdeflate.dylib
+ SHARED_LIB_CFLAGS := -fPIC
+ SHARED_LIB_LDFLAGS := -install_name $(SHARED_LIB)
+
+# Linux, FreeBSD, etc.
+else
+ SHARED_LIB := libdeflate.so.$(SOVERSION)
+ SHARED_LIB_SYMLINK := libdeflate.so
+ SHARED_LIB_CFLAGS := -fPIC
+ SHARED_LIB_LDFLAGS := -Wl,-soname=$(SHARED_LIB)
+endif
+
+##############################################################################
+
+#### Quiet make is enabled by default. Define V=1 to disable.
+
+ifneq ($(findstring s,$(MAKEFLAGS)),s)
+ifneq ($(V),1)
+ QUIET_CC = @echo ' CC ' $@;
+ QUIET_CCLD = @echo ' CCLD ' $@;
+ QUIET_AR = @echo ' AR ' $@;
+ QUIET_LN = @echo ' LN ' $@;
+ QUIET_CP = @echo ' CP ' $@;
+ QUIET_GEN = @echo ' GEN ' $@;
+endif
+endif
+
+##############################################################################
+
+# Rebuild if a user-specified setting that affects the build changed.
+.build-config: FORCE
+ @flags=$$( \
+ echo 'USE_SHARED_LIB=$(USE_SHARED_LIB)'; \
+ echo 'DECOMPRESSION_ONLY=$(DECOMPRESSION_ONLY)'; \
+ echo 'DISABLE_GZIP=$(DISABLE_GZIP)'; \
+ echo 'DISABLE_ZLIB=$(DISABLE_ZLIB)'; \
+ echo 'FREESTANDING=$(FREESTANDING)'; \
+ echo 'CC=$(CC)'; \
+ echo 'CFLAGS=$(CFLAGS)'; \
+ echo 'CPPFLAGS=$(CPPFLAGS)'; \
+ echo 'LDFLAGS=$(LDFLAGS)'; \
+ ); \
+ if [ "$$flags" != "`cat $@ 2>/dev/null`" ]; then \
+ [ -e $@ ] && echo "Rebuilding due to new settings"; \
+ echo "$$flags" > $@; \
+ fi
+
+##############################################################################
+
+COMMON_HEADERS := $(wildcard common/*.h) libdeflate.h
+DEFAULT_TARGETS :=
+
+#### Library
+
+STATIC_LIB := libdeflate$(STATIC_LIB_SUFFIX)
+
+LIB_CFLAGS += $(CFLAGS) -fvisibility=hidden -D_ANSI_SOURCE
+
+LIB_HEADERS := $(wildcard lib/*.h) $(wildcard lib/*/*.h)
+
+LIB_SRC := lib/deflate_decompress.c lib/utils.c \
+ $(wildcard lib/*/cpu_features.c)
+
+DECOMPRESSION_ONLY :=
+ifndef DECOMPRESSION_ONLY
+ LIB_SRC += lib/deflate_compress.c
+endif
+
+DISABLE_ZLIB :=
+ifndef DISABLE_ZLIB
+ LIB_SRC += lib/adler32.c lib/zlib_decompress.c
+ ifndef DECOMPRESSION_ONLY
+ LIB_SRC += lib/zlib_compress.c
+ endif
+endif
+
+DISABLE_GZIP :=
+ifndef DISABLE_GZIP
+ LIB_SRC += lib/crc32.c lib/gzip_decompress.c
+ ifndef DECOMPRESSION_ONLY
+ LIB_SRC += lib/gzip_compress.c
+ endif
+endif
+
+STATIC_LIB_OBJ := $(LIB_SRC:.c=.o)
+SHARED_LIB_OBJ := $(LIB_SRC:.c=.shlib.o)
+
+# Compile static library object files
+$(STATIC_LIB_OBJ): %.o: %.c $(LIB_HEADERS) $(COMMON_HEADERS) .build-config
+ $(QUIET_CC) $(CC) -o $@ -c $(CPPFLAGS) $(LIB_CFLAGS) $<
+
+# Compile shared library object files
+$(SHARED_LIB_OBJ): %.shlib.o: %.c $(LIB_HEADERS) $(COMMON_HEADERS) .build-config
+ $(QUIET_CC) $(CC) -o $@ -c $(CPPFLAGS) $(LIB_CFLAGS) \
+ $(SHARED_LIB_CFLAGS) -DLIBDEFLATE_DLL $<
+
+# Create static library
+$(STATIC_LIB):$(STATIC_LIB_OBJ)
+ $(QUIET_AR) $(AR) cr $@ $+
+
+DEFAULT_TARGETS += $(STATIC_LIB)
+
+# Create shared library
+$(SHARED_LIB):$(SHARED_LIB_OBJ)
+ $(QUIET_CCLD) $(CC) -o $@ $(LDFLAGS) $(LIB_CFLAGS) \
+ $(SHARED_LIB_LDFLAGS) -shared $+
+
+DEFAULT_TARGETS += $(SHARED_LIB)
+
+ifdef SHARED_LIB_SYMLINK
+# Create the symlink libdeflate.so => libdeflate.so.$SOVERSION
+$(SHARED_LIB_SYMLINK):$(SHARED_LIB)
+ $(QUIET_LN) ln -sf $+ $@
+DEFAULT_TARGETS += $(SHARED_LIB_SYMLINK)
+endif
+
+##############################################################################
+
+#### Programs
+
+PROG_CFLAGS += $(CFLAGS) \
+ -D_POSIX_C_SOURCE=200809L \
+ -D_FILE_OFFSET_BITS=64 \
+ -DHAVE_CONFIG_H
+
+ALL_PROG_COMMON_HEADERS := programs/config.h \
+ programs/prog_util.h \
+ programs/test_util.h
+PROG_COMMON_SRC := programs/prog_util.c \
+ programs/tgetopt.c
+NONTEST_PROG_SRC := programs/gzip.c
+TEST_PROG_COMMON_SRC := programs/test_util.c
+TEST_PROG_SRC := programs/benchmark.c \
+ programs/checksum.c \
+ $(filter-out $(TEST_PROG_COMMON_SRC),$(wildcard programs/test_*.c))
+
+NONTEST_PROGRAMS := $(NONTEST_PROG_SRC:programs/%.c=%$(PROG_SUFFIX))
+DEFAULT_TARGETS += $(NONTEST_PROGRAMS)
+TEST_PROGRAMS := $(TEST_PROG_SRC:programs/%.c=%$(PROG_SUFFIX))
+
+PROG_COMMON_OBJ := $(PROG_COMMON_SRC:%.c=%.o)
+NONTEST_PROG_OBJ := $(NONTEST_PROG_SRC:%.c=%.o)
+TEST_PROG_COMMON_OBJ := $(TEST_PROG_COMMON_SRC:%.c=%.o)
+TEST_PROG_OBJ := $(TEST_PROG_SRC:%.c=%.o)
+
+ALL_PROG_OBJ := $(PROG_COMMON_OBJ) $(NONTEST_PROG_OBJ) \
+ $(TEST_PROG_COMMON_OBJ) $(TEST_PROG_OBJ)
+
+# Generate autodetected configuration header
+programs/config.h:scripts/detect.sh .build-config
+ $(QUIET_GEN) CC="$(CC)" CFLAGS="$(PROG_CFLAGS)" $< > $@
+
+# Compile program object files
+$(ALL_PROG_OBJ): %.o: %.c $(ALL_PROG_COMMON_HEADERS) $(COMMON_HEADERS) \
+ .build-config
+ $(QUIET_CC) $(CC) -o $@ -c $(CPPFLAGS) $(PROG_CFLAGS) $<
+
+# Link the programs.
+#
+# Note: the test programs are not compiled by default. One reason is that the
+# test programs must be linked with zlib for doing comparisons.
+
+ifdef USE_SHARED_LIB
+LIB := $(SHARED_LIB)
+else
+LIB := $(STATIC_LIB)
+endif
+
+$(NONTEST_PROGRAMS): %$(PROG_SUFFIX): programs/%.o $(PROG_COMMON_OBJ) $(LIB)
+ $(QUIET_CCLD) $(CC) -o $@ $(LDFLAGS) $(PROG_CFLAGS) $+
+
+$(TEST_PROGRAMS): %$(PROG_SUFFIX): programs/%.o $(PROG_COMMON_OBJ) \
+ $(TEST_PROG_COMMON_OBJ) $(LIB)
+ $(QUIET_CCLD) $(CC) -o $@ $(LDFLAGS) $(PROG_CFLAGS) $+ -lz
+
+ifdef HARD_LINKS
+# Hard link gunzip to gzip
+gunzip$(PROG_SUFFIX):gzip$(PROG_SUFFIX)
+ $(QUIET_LN) ln -f $< $@
+else
+# No hard links; copy gzip to gunzip
+gunzip$(PROG_SUFFIX):gzip$(PROG_SUFFIX)
+ $(QUIET_CP) cp -f $< $@
+endif
+
+DEFAULT_TARGETS += gunzip$(PROG_SUFFIX)
+
+##############################################################################
+
+all:$(DEFAULT_TARGETS)
+
+# Install the files. Note: not all versions of the 'install' program have the
+# '-D' and '-t' options, so don't use them; use portable commands only.
+install:all
+ install -d $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCDIR) $(DESTDIR)$(BINDIR)
+ install -m644 $(STATIC_LIB) $(DESTDIR)$(LIBDIR)
+ install -m755 $(SHARED_LIB) $(DESTDIR)$(LIBDIR)
+ install -m644 libdeflate.h $(DESTDIR)$(INCDIR)
+ install -m755 gzip$(PROG_SUFFIX) \
+ $(DESTDIR)$(BINDIR)/libdeflate-gzip$(PROG_SUFFIX)
+ ln -f $(DESTDIR)$(BINDIR)/libdeflate-gzip$(PROG_SUFFIX) \
+ $(DESTDIR)$(BINDIR)/libdeflate-gunzip$(PROG_SUFFIX)
+ if [ -n "$(SHARED_LIB_SYMLINK)" ]; then \
+ ln -sf $(SHARED_LIB) \
+ $(DESTDIR)$(LIBDIR)/$(SHARED_LIB_SYMLINK); \
+ fi
+
+uninstall:
+ rm -f $(DESTDIR)$(LIBDIR)/$(STATIC_LIB) \
+ $(DESTDIR)$(LIBDIR)/$(SHARED_LIB) \
+ $(DESTDIR)$(INCDIR)/libdeflate.h \
+ $(DESTDIR)$(BINDIR)/libdeflate-gzip$(PROG_SUFFIX) \
+ $(DESTDIR)$(BINDIR)/libdeflate-gunzip$(PROG_SUFFIX)
+ if [ -n "$(SHARED_LIB_SYMLINK)" ]; then \
+ rm -f $(DESTDIR)$(LIBDIR)/$(SHARED_LIB_SYMLINK); \
+ fi
+
+test_programs:$(TEST_PROGRAMS)
+
+# A minimal 'make check' target. This only runs some quick tests;
+# use scripts/run_tests.sh if you want to run the full tests.
+check:test_programs
+ LD_LIBRARY_PATH=. ./benchmark$(PROG_SUFFIX) < ./benchmark$(PROG_SUFFIX)
+ for prog in test_*; do \
+ LD_LIBRARY_PATH=. ./$$prog || exit 1; \
+ done
+
+# Run the clang static analyzer.
+scan-build:
+ scan-build --status-bugs make all test_programs
+
+# Run shellcheck on all shell scripts.
+shellcheck:
+ shellcheck scripts/*.sh
+
+help:
+ @echo "Available targets:"
+ @echo "------------------"
+ @for target in $(DEFAULT_TARGETS) $(TEST_PROGRAMS); do \
+ echo -e "$$target"; \
+ done
+
+clean:
+ rm -f *.a *.dll *.exe *.exp *.dylib *.so \
+ lib/*.o lib/*/*.o \
+ lib/*.obj lib/*/*.obj \
+ lib/*.dllobj lib/*/*.dllobj \
+ programs/*.o programs/*.obj \
+ $(DEFAULT_TARGETS) $(TEST_PROGRAMS) programs/config.h \
+ libdeflate.lib libdeflate.def libdeflatestatic.lib \
+ .build-config
+
+realclean: clean
+ rm -f tags cscope*
+
+FORCE:
+
+.PHONY: all install uninstall test_programs check scan-build shellcheck help \
+ clean realclean
+
+.DEFAULT_GOAL = all
diff --git a/util/compress/libdeflate/Makefile.msc b/util/compress/libdeflate/Makefile.msc
new file mode 100644
index 000000000..14496187f
--- /dev/null
+++ b/util/compress/libdeflate/Makefile.msc
@@ -0,0 +1,65 @@
+#
+# Makefile for the Microsoft toolchain
+#
+# Usage:
+# nmake /f Makefile.msc
+#
+
+.SUFFIXES: .c .obj .dllobj
+
+CC = cl
+LD = link
+AR = lib
+CFLAGS = /MD /O2 -I.
+LDFLAGS =
+
+STATIC_LIB = libdeflatestatic.lib
+SHARED_LIB = libdeflate.dll
+IMPORT_LIB = libdeflate.lib
+
+STATIC_LIB_OBJ = \
+ lib/adler32.obj \
+ lib/crc32.obj \
+ lib/deflate_compress.obj \
+ lib/deflate_decompress.obj \
+ lib/gzip_compress.obj \
+ lib/gzip_decompress.obj \
+ lib/utils.obj \
+ lib/x86/cpu_features.obj \
+ lib/zlib_compress.obj \
+ lib/zlib_decompress.obj
+
+SHARED_LIB_OBJ = $(STATIC_LIB_OBJ:.obj=.dllobj)
+
+PROG_COMMON_OBJ = programs/prog_util.obj \
+ programs/tgetopt.obj \
+ $(STATIC_LIB)
+
+PROG_CFLAGS = $(CFLAGS) -Iprograms
+
+all: $(STATIC_LIB) $(SHARED_LIB) $(IMPORT_LIB) gzip.exe gunzip.exe
+
+.c.obj:
+ $(CC) -c /Fo$@ $(CFLAGS) $**
+
+.c.dllobj:
+ $(CC) -c /Fo$@ $(CFLAGS) /DLIBDEFLATE_DLL $**
+
+$(STATIC_LIB): $(STATIC_LIB_OBJ)
+ $(AR) $(ARFLAGS) -out:$@ $(STATIC_LIB_OBJ)
+
+$(SHARED_LIB): $(SHARED_LIB_OBJ)
+ $(LD) $(LDFLAGS) -out:$@ -dll -implib:$(IMPORT_LIB) $(SHARED_LIB_OBJ)
+
+$(IMPORT_LIB): $(SHARED_LIB)
+
+gzip.exe:programs/gzip.obj $(PROG_COMMON_OBJ)
+ $(LD) $(LDFLAGS) -out:$@ $**
+
+gunzip.exe:gzip.exe
+ copy $** $@
+
+clean:
+ -del *.dll *.exe *.exp libdeflate.lib libdeflatestatic.lib gzip.lib \
+ lib\*.obj lib\x86\*.obj lib\*.dllobj lib\x86\*.dllobj \
+ programs\*.obj 2>nul
diff --git a/util/compress/libdeflate/NEWS b/util/compress/libdeflate/NEWS
new file mode 100644
index 000000000..b1704dd18
--- /dev/null
+++ b/util/compress/libdeflate/NEWS
@@ -0,0 +1,200 @@
+Version 1.7:
+ Added support for compression level 0, "no compression".
+
+ Added an ARM CRC32 instruction accelerated implementation of CRC32.
+
+ Added support for linking the programs to the shared library version of
+ libdeflate rather than to the static library version.
+
+ Made the compression level affect the minimum input size at which
+ compression is attempted.
+
+ Fixed undefined behavior in x86 Adler32 implementation.
+ (No miscompilations were observed in practice.)
+
+ Fixed undefined behavior in x86 CPU feature code.
+ (No miscompilations were observed in practice.)
+
+ Fixed installing shared lib symlink on macOS.
+
+ Documented third-party bindings.
+
+ Made a lot of improvements to the testing scripts and the CI
+ configuration file.
+
+ Lots of other small improvements and cleanups.
+
+Version 1.6:
+ Prevented gcc 10 from miscompiling libdeflate (workaround for
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94994).
+
+ Removed workaround for gcc 5 and earlier producing slow code on
+ ARM32. If this affects you, please upgrade your compiler.
+
+ New API function: libdeflate_zlib_decompress_ex(). It provides
+ the actual size of the stream that was decompressed, like the
+ gzip and DEFLATE equivalents.
+
+ libdeflate_zlib_decompress() now accepts trailing bytes after
+ the end of the stream, like the gzip and DEFLATE equivalents.
+
+ Added support for custom memory allocators.
+ (New API function: libdeflate_set_memory_allocator())
+
+ Added support for building the library in freestanding mode.
+
+ Building libdeflate no longer requires CPPFLAGS=-Icommon.
+
+Version 1.5:
+ Fixed up stdcall support on 32-bit Windows: the functions are
+ now exported using both suffixed and non-suffixed names, and
+ fixed libdeflate.h to be MSVC-compatible again.
+
+Version 1.4:
+ The 32-bit Windows build of libdeflate now uses the "stdcall"
+ calling convention instead of "cdecl". If you're calling
+ libdeflate.dll directly from C or C++, you'll need to recompile
+ your code. If you're calling it from another language, or
+ calling it indirectly using LoadLibrary(), you'll need to update
+ your code to use the stdcall calling convention.
+
+ The Makefile now supports building libdeflate as a shared
+ library (.dylib) on macOS.
+
+ Fixed a bug where support for certain optimizations and optional
+ features (file access hints and more precise timestamps) was
+ incorrectly omitted when libdeflate was compiled with -Werror.
+
+ Added 'make check' target to the Makefile.
+
+ Added CI configuration files.
+
+Version 1.3:
+ `make install` now supports customizing the directories into
+ which binaries, headers, and libraries are installed.
+
+ `make install` now installs into /usr/local by default.
+ To change it, use e.g. `make install PREFIX=/usr`.
+
+ `make install` now works on more platforms.
+
+ The Makefile now supports overriding the optimization flags.
+
+ The compression functions now correctly handle an output data
+ buffer >= 4 GiB in size, and `gzip` and `gunzip` now correctly
+ handle multi-gigabyte files (if enough memory is available).
+
+Version 1.2:
+ Slight improvements to decompression speed.
+
+ Added an AVX-512BW implementation of Adler-32.
+
+ The Makefile now supports a user-specified installation PREFIX.
+
+ Fixed build error with some Visual Studio versions.
+
+Version 1.1:
+ Fixed crash in CRC-32 code when the prebuilt libdeflate for
+ 32-bit Windows was called by a program built with Visual Studio.
+
+ Improved the worst-case decompression speed of malicious data.
+
+ Fixed build error when compiling for an ARM processor without
+ hardware floating point support.
+
+ Improved performance on the PowerPC64 architecture.
+
+ Added soname to libdeflate.so, to make packaging easier.
+
+ Added 'make install' target to the Makefile.
+
+ The Makefile now supports user-specified CPPFLAGS.
+
+ The Windows binary releases now include the import library for
+ libdeflate.dll. libdeflate.lib is now the import library, and
+ libdeflatestatic.lib is the static library.
+
+Version 1.0:
+ Added support for multi-member gzip files.
+
+ Moved architecture-specific code into subdirectories. If you
+ aren't using the provided Makefile to build libdeflate, you now
+ need to compile lib/*.c and lib/*/*.c instead of just lib/*.c.
+
+ Added an ARM PMULL implementation of CRC-32, which speeds up
+ gzip compression and decompression on 32-bit and 64-bit ARM
+ processors that have the Cryptography Extensions.
+
+ Improved detection of CPU features, resulting in accelerated
+ functions being used in more cases. This includes:
+
+ - Detect CPU features on 32-bit x86, not just 64-bit as was
+ done previously.
+
+ - Detect CPU features on ARM, both 32 and 64-bit.
+ (Limited to Linux only currently.)
+
+Version 0.8:
+ Build fixes for certain platforms and compilers.
+
+ libdeflate now produces the same output on all CPU architectures.
+
+ Improved documentation for building libdeflate on Windows.
+
+Version 0.7:
+ Fixed a very rare bug that caused data to be compressed incorrectly.
+ The bug affected compression levels 7 and below since libdeflate v0.2.
+ Although there have been no user reports of the bug, and I believe it
+ would have been highly unlikely to encounter on realistic data, it could
+ occur on data specially crafted to reproduce it.
+
+ Fixed a compilation error when building with clang 3.7.
+
+Version 0.6:
+ Various improvements to the gzip program's behavior.
+
+ Faster CRC-32 on AVX-capable processors.
+
+ Other minor changes.
+
+Version 0.5:
+ The CRC-32 checksum algorithm has been optimized with carryless
+ multiplication instructions for x86_64 (PCLMUL). This speeds up gzip
+ compression and decompression.
+
+ Build fixes for certain platforms and compilers.
+
+ Added more test programs and scripts.
+
+ libdeflate is now entirely MIT-licensed.
+
+Version 0.4:
+ The Adler-32 checksum algorithm has been optimized with vector
+ instructions for x86_64 (SSE2 and AVX2) and ARM (NEON). This speeds up
+ zlib compression and decompression.
+
+ To avoid naming collisions, functions and definitions in libdeflate's
+ API have been renamed to be prefixed with "libdeflate_" or
+ "LIBDEFLATE_". Programs using the old API will need to be updated.
+
+ Various bug fixes and other improvements.
+
+Version 0.3:
+ Some bug fixes and other minor changes.
+
+Version 0.2:
+ Implemented a new block splitting algorithm which typically improves the
+ compression ratio slightly at all compression levels.
+
+ The compressor now outputs each block using the cheapest type (dynamic
+ Huffman, static Huffman, or uncompressed).
+
+ The gzip program has received an overhaul and now behaves more like the
+ standard version.
+
+ Build system updates, including: some build options were changed and
+ some build options were removed, and the default 'make' target now
+ includes the gzip program as well as the library.
+
+Version 0.1:
+ Initial official release.
diff --git a/util/compress/libdeflate/README.md b/util/compress/libdeflate/README.md
new file mode 100644
index 000000000..9342e9e9b
--- /dev/null
+++ b/util/compress/libdeflate/README.md
@@ -0,0 +1,283 @@
+# Overview
+
+libdeflate is a library for fast, whole-buffer DEFLATE-based compression and
+decompression.
+
+The supported formats are:
+
+- DEFLATE (raw)
+- zlib (a.k.a. DEFLATE with a zlib wrapper)
+- gzip (a.k.a. DEFLATE with a gzip wrapper)
+
+libdeflate is heavily optimized. It is significantly faster than the zlib
+library, both for compression and decompression, and especially on x86
+processors. In addition, libdeflate provides optional high compression modes
+that provide a better compression ratio than the zlib's "level 9".
+
+libdeflate itself is a library, but the following command-line programs which
+use this library are also provided:
+
+* gzip (or gunzip), a program which mostly behaves like the standard equivalent,
+ except that it does not yet have good streaming support and therefore does not
+ yet support very large files
+* benchmark, a program for benchmarking in-memory compression and decompression
+
+## Table of Contents
+
+- [Building](#building)
+ - [For UNIX](#for-unix)
+ - [For macOS](#for-macos)
+ - [For Windows](#for-windows)
+ - [Using Cygwin](#using-cygwin)
+ - [Using MSYS2](#using-msys2)
+- [API](#api)
+- [Bindings for other programming languages](#bindings-for-other-programming-languages)
+- [DEFLATE vs. zlib vs. gzip](#deflate-vs-zlib-vs-gzip)
+- [Compression levels](#compression-levels)
+- [Motivation](#motivation)
+- [License](#license)
+
+
+# Building
+
+## For UNIX
+
+Just run `make`, then (if desired) `make install`. You need GNU Make and either
+GCC or Clang. GCC is recommended because it builds slightly faster binaries.
+
+By default, the following targets are built: the static library `libdeflate.a`,
+the shared library `libdeflate.so`, the `gzip` program, and the `gunzip` program
+(which is actually just a hard link to `gzip`). Benchmarking and test programs
+such as `benchmark` are not built by default. You can run `make help` to
+display the available build targets.
+
+There are also many options which can be set on the `make` command line, e.g. to
+omit library features or to customize the directories into which `make install`
+installs files. See the Makefile for details.
+
+## For macOS
+
+Prebuilt macOS binaries can be installed with [Homebrew](https://brew.sh):
+
+ brew install libdeflate
+
+But if you need to build the binaries yourself, see the section for UNIX above.
+
+## For Windows
+
+Prebuilt Windows binaries can be downloaded from
+https://github.com/ebiggers/libdeflate/releases. But if you need to build the
+binaries yourself, MinGW (gcc) is the recommended compiler to use. If you're
+performing the build *on* Windows (as opposed to cross-compiling for Windows on
+Linux, for example), you'll need to follow the directions in **one** of the two
+sections below to set up a minimal UNIX-compatible environment using either
+Cygwin or MSYS2, then do the build. (Other MinGW distributions may not work, as
+they often omit basic UNIX tools such as `sh`.)
+
+Alternatively, libdeflate may be built using the Visual Studio toolchain by
+running `nmake /f Makefile.msc`. However, while this is supported in the sense
+that it will produce working binaries, it is not recommended because the
+binaries built with MinGW will be significantly faster.
+
+Also note that 64-bit binaries are faster than 32-bit binaries and should be
+preferred whenever possible.
+
+### Using Cygwin
+
+Run the Cygwin installer, available from https://cygwin.com/setup-x86_64.exe.
+When you get to the package selection screen, choose the following additional
+packages from category "Devel":
+
+- git
+- make
+- mingw64-i686-binutils
+- mingw64-i686-gcc-g++
+- mingw64-x86_64-binutils
+- mingw64-x86_64-gcc-g++
+
+(You may skip the mingw64-i686 packages if you don't need to build 32-bit
+binaries.)
+
+After the installation finishes, open a Cygwin terminal. Then download
+libdeflate's source code (if you haven't already) and `cd` into its directory:
+
+ git clone https://github.com/ebiggers/libdeflate
+ cd libdeflate
+
+(Note that it's not required to use `git`; an alternative is to extract a .zip
+or .tar.gz archive of the source code downloaded from the releases page.
+Also, in case you need to find it in the file browser, note that your home
+directory in Cygwin is usually located at `C:\cygwin64\home\<your username>`.)
+
+Then, to build 64-bit binaries:
+
+ make CC=x86_64-w64-mingw32-gcc
+
+or to build 32-bit binaries:
+
+ make CC=i686-w64-mingw32-gcc
+
+### Using MSYS2
+
+Run the MSYS2 installer, available from http://www.msys2.org/. After
+installing, open an MSYS2 shell and run:
+
+ pacman -Syu
+
+Say `y`, then when it's finished, close the shell window and open a new one.
+Then run the same command again:
+
+ pacman -Syu
+
+Then, install the packages needed to build libdeflate:
+
+ pacman -S git \
+ make \
+ mingw-w64-i686-binutils \
+ mingw-w64-i686-gcc \
+ mingw-w64-x86_64-binutils \
+ mingw-w64-x86_64-gcc
+
+(You may skip the mingw-w64-i686 packages if you don't need to build 32-bit
+binaries.)
+
+Then download libdeflate's source code (if you haven't already):
+
+ git clone https://github.com/ebiggers/libdeflate
+
+(Note that it's not required to use `git`; an alternative is to extract a .zip
+or .tar.gz archive of the source code downloaded from the releases page.
+Also, in case you need to find it in the file browser, note that your home
+directory in MSYS2 is usually located at `C:\msys64\home\<your username>`.)
+
+Then, to build 64-bit binaries, open "MSYS2 MinGW 64-bit" from the Start menu
+and run the following commands:
+
+ cd libdeflate
+ make clean
+ make
+
+Or to build 32-bit binaries, do the same but use "MSYS2 MinGW 32-bit" instead.
+
+# API
+
+libdeflate has a simple API that is not zlib-compatible. You can create
+compressors and decompressors and use them to compress or decompress buffers.
+See libdeflate.h for details.
+
+There is currently no support for streaming. This has been considered, but it
+always significantly increases complexity and slows down fast paths.
+Unfortunately, at this point it remains a future TODO. So: if your application
+compresses data in "chunks", say, less than 1 MB in size, then libdeflate is a
+great choice for you; that's what it's designed to do. This is perfect for
+certain use cases such as transparent filesystem compression. But if your
+application compresses large files as a single compressed stream, similarly to
+the `gzip` program, then libdeflate isn't for you.
+
+Note that with chunk-based compression, you generally should have the
+uncompressed size of each chunk stored outside of the compressed data itself.
+This enables you to allocate an output buffer of the correct size without
+guessing. However, libdeflate's decompression routines do optionally provide
+the actual number of output bytes in case you need it.
+
+Windows developers: note that the calling convention of libdeflate.dll is
+"stdcall" -- the same as the Win32 API. If you call into libdeflate.dll using a
+non-C/C++ language, or dynamically using LoadLibrary(), make sure to use the
+stdcall convention. Using the wrong convention may crash your application.
+(Note: older versions of libdeflate used the "cdecl" convention instead.)
+
+# Bindings for other programming languages
+
+The libdeflate project itself only provides a C library. If you need to use
+libdeflate from a programming language other than C or C++, consider using the
+following bindings:
+
+* C#: [LibDeflate.NET](https://github.com/jzebedee/LibDeflate.NET)
+* Go: [go-libdeflate](https://github.com/4kills/go-libdeflate)
+* Java: [libdeflate-java](https://github.com/astei/libdeflate-java)
+* Julia: [LibDeflate.jl](https://github.com/jakobnissen/LibDeflate.jl)
+* Python: [deflate](https://github.com/dcwatson/deflate)
+* Ruby: [libdeflate-ruby](https://github.com/kaorimatz/libdeflate-ruby)
+* Rust: [libdeflater](https://github.com/adamkewley/libdeflater)
+
+Note: these are third-party projects which haven't necessarily been vetted by
+the authors of libdeflate. Please direct all questions, bugs, and improvements
+for these bindings to their authors.
+
+# DEFLATE vs. zlib vs. gzip
+
+The DEFLATE format ([rfc1951](https://www.ietf.org/rfc/rfc1951.txt)), the zlib
+format ([rfc1950](https://www.ietf.org/rfc/rfc1950.txt)), and the gzip format
+([rfc1952](https://www.ietf.org/rfc/rfc1952.txt)) are commonly confused with
+each other as well as with the [zlib software library](http://zlib.net), which
+actually supports all three formats. libdeflate (this library) also supports
+all three formats.
+
+Briefly, DEFLATE is a raw compressed stream, whereas zlib and gzip are different
+wrappers for this stream. Both zlib and gzip include checksums, but gzip can
+include extra information such as the original filename. Generally, you should
+choose a format as follows:
+
+- If you are compressing whole files with no subdivisions, similar to the `gzip`
+ program, you probably should use the gzip format.
+- Otherwise, if you don't need the features of the gzip header and footer but do
+ still want a checksum for corruption detection, you probably should use the
+ zlib format.
+- Otherwise, you probably should use raw DEFLATE. This is ideal if you don't
+ need checksums, e.g. because they're simply not needed for your use case or
+ because you already compute your own checksums that are stored separately from
+ the compressed stream.
+
+Note that gzip and zlib streams can be distinguished from each other based on
+their starting bytes, but this is not necessarily true of raw DEFLATE streams.
+
+# Compression levels
+
+An often-underappreciated fact of compression formats such as DEFLATE is that
+there are an enormous number of different ways that a given input could be
+compressed. Different algorithms and different amounts of computation time will
+result in different compression ratios, while remaining equally compatible with
+the decompressor.
+
+For this reason, the commonly used zlib library provides nine compression
+levels. Level 1 is the fastest but provides the worst compression; level 9
+provides the best compression but is the slowest. It defaults to level 6.
+libdeflate uses this same design but is designed to improve on both zlib's
+performance *and* compression ratio at every compression level. In addition,
+libdeflate's levels go [up to 12](https://xkcd.com/670/) to make room for a
+minimum-cost-path based algorithm (sometimes called "optimal parsing") that can
+significantly improve on zlib's compression ratio.
+
+If you are using DEFLATE (or zlib, or gzip) in your application, you should test
+different levels to see which works best for your application.
+
+# Motivation
+
+Despite DEFLATE's widespread use mainly through the zlib library, in the
+compression community this format from the early 1990s is often considered
+obsolete. And in a few significant ways, it is.
+
+So why implement DEFLATE at all, instead of focusing entirely on
+bzip2/LZMA/xz/LZ4/LZX/ZSTD/Brotli/LZHAM/LZFSE/[insert cool new format here]?
+
+To do something better, you need to understand what came before. And it turns
+out that most ideas from DEFLATE are still relevant. Many of the newer formats
+share a similar structure as DEFLATE, with different tweaks. The effects of
+trivial but very useful tweaks, such as increasing the sliding window size, are
+often confused with the effects of nontrivial but less useful tweaks. And
+actually, many of these formats are similar enough that common algorithms and
+optimizations (e.g. those dealing with LZ77 matchfinding) can be reused.
+
+In addition, comparing compressors fairly is difficult because the performance
+of a compressor depends heavily on optimizations which are not intrinsic to the
+compression format itself. In this respect, the zlib library sometimes compares
+poorly to certain newer code because zlib is not well optimized for modern
+processors. libdeflate addresses this by providing an optimized DEFLATE
+implementation which can be used for benchmarking purposes. And, of course,
+real applications can use it as well.
+
+# License
+
+libdeflate is [MIT-licensed](COPYING).
+
+I am not aware of any patents or patent applications relevant to libdeflate.
diff --git a/util/compress/libdeflate/common/common_defs.h b/util/compress/libdeflate/common/common_defs.h
new file mode 100644
index 000000000..d56c5cf9b
--- /dev/null
+++ b/util/compress/libdeflate/common/common_defs.h
@@ -0,0 +1,334 @@
+/*
+ * common_defs.h
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef COMMON_COMMON_DEFS_H
+#define COMMON_COMMON_DEFS_H
+
+#ifdef __GNUC__
+# include "compiler_gcc.h"
+#elif defined(_MSC_VER)
+# include "compiler_msc.h"
+#else
+# pragma message("Unrecognized compiler. Please add a header file for your compiler. Compilation will proceed, but performance may suffer!")
+#endif
+
+/* ========================================================================== */
+/* Type definitions */
+/* ========================================================================== */
+
+#include <stddef.h> /* size_t */
+
+#ifndef __bool_true_false_are_defined
+# include <stdbool.h> /* bool */
+#endif
+
+/* Fixed-width integer types */
+#include <stdint.h>
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+typedef int8_t s8;
+typedef int16_t s16;
+typedef int32_t s32;
+typedef int64_t s64;
+
+/*
+ * Word type of the target architecture. Use 'size_t' instead of 'unsigned
+ * long' to account for platforms such as Windows that use 32-bit 'unsigned
+ * long' on 64-bit architectures.
+ */
+typedef size_t machine_word_t;
+
+/* Number of bytes in a word */
+#define WORDBYTES ((int)sizeof(machine_word_t))
+
+/* Number of bits in a word */
+#define WORDBITS (8 * WORDBYTES)
+
+/* ========================================================================== */
+/* Optional compiler features */
+/* ========================================================================== */
+
+/* LIBEXPORT - export a function from a shared library */
+#ifndef LIBEXPORT
+# define LIBEXPORT
+#endif
+
+/* inline - suggest that a function be inlined */
+#ifndef inline
+# define inline
+#endif
+
+/* forceinline - force a function to be inlined, if possible */
+#ifndef forceinline
+# define forceinline inline
+#endif
+
+/* restrict - annotate a non-aliased pointer */
+#ifndef restrict
+# define restrict
+#endif
+
+/* likely(expr) - hint that an expression is usually true */
+#ifndef likely
+# define likely(expr) (expr)
+#endif
+
+/* unlikely(expr) - hint that an expression is usually false */
+#ifndef unlikely
+# define unlikely(expr) (expr)
+#endif
+
+/* prefetchr(addr) - prefetch into L1 cache for read */
+#ifndef prefetchr
+# define prefetchr(addr)
+#endif
+
+/* prefetchw(addr) - prefetch into L1 cache for write */
+#ifndef prefetchw
+# define prefetchw(addr)
+#endif
+
+/* Does the compiler support the 'target' function attribute? */
+#ifndef COMPILER_SUPPORTS_TARGET_FUNCTION_ATTRIBUTE
+# define COMPILER_SUPPORTS_TARGET_FUNCTION_ATTRIBUTE 0
+#endif
+
+/* Which targets are supported with the 'target' function attribute? */
+#ifndef COMPILER_SUPPORTS_BMI2_TARGET
+# define COMPILER_SUPPORTS_BMI2_TARGET 0
+#endif
+#ifndef COMPILER_SUPPORTS_AVX_TARGET
+# define COMPILER_SUPPORTS_AVX_TARGET 0
+#endif
+#ifndef COMPILER_SUPPORTS_AVX512BW_TARGET
+# define COMPILER_SUPPORTS_AVX512BW_TARGET 0
+#endif
+
+/*
+ * Which targets are supported with the 'target' function attribute and have
+ * intrinsics that work within 'target'-ed functions?
+ */
+#ifndef COMPILER_SUPPORTS_SSE2_TARGET_INTRINSICS
+# define COMPILER_SUPPORTS_SSE2_TARGET_INTRINSICS 0
+#endif
+#ifndef COMPILER_SUPPORTS_PCLMUL_TARGET_INTRINSICS
+# define COMPILER_SUPPORTS_PCLMUL_TARGET_INTRINSICS 0
+#endif
+#ifndef COMPILER_SUPPORTS_AVX2_TARGET_INTRINSICS
+# define COMPILER_SUPPORTS_AVX2_TARGET_INTRINSICS 0
+#endif
+#ifndef COMPILER_SUPPORTS_AVX512BW_TARGET_INTRINSICS
+# define COMPILER_SUPPORTS_AVX512BW_TARGET_INTRINSICS 0
+#endif
+#ifndef COMPILER_SUPPORTS_NEON_TARGET_INTRINSICS
+# define COMPILER_SUPPORTS_NEON_TARGET_INTRINSICS 0
+#endif
+#ifndef COMPILER_SUPPORTS_PMULL_TARGET_INTRINSICS
+# define COMPILER_SUPPORTS_PMULL_TARGET_INTRINSICS 0
+#endif
+#ifndef COMPILER_SUPPORTS_CRC32_TARGET_INTRINSICS
+# define COMPILER_SUPPORTS_CRC32_TARGET_INTRINSICS 0
+#endif
+
+/* _aligned_attribute(n) - declare that the annotated variable, or variables of
+ * the annotated type, are to be aligned on n-byte boundaries */
+#ifndef _aligned_attribute
+#endif
+
+/* ========================================================================== */
+/* Miscellaneous macros */
+/* ========================================================================== */
+
+#define ARRAY_LEN(A) (sizeof(A) / sizeof((A)[0]))
+#define MIN(a, b) ((a) <= (b) ? (a) : (b))
+#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+#define STATIC_ASSERT(expr) ((void)sizeof(char[1 - 2 * !(expr)]))
+#define ALIGN(n, a) (((n) + (a) - 1) & ~((a) - 1))
+
+/* ========================================================================== */
+/* Endianness handling */
+/* ========================================================================== */
+
+/*
+ * CPU_IS_LITTLE_ENDIAN() - a macro which evaluates to 1 if the CPU is little
+ * endian or 0 if it is big endian. The macro should be defined in a way such
+ * that the compiler can evaluate it at compilation time. If not defined, a
+ * fallback is used.
+ */
+#ifndef CPU_IS_LITTLE_ENDIAN
+static forceinline int CPU_IS_LITTLE_ENDIAN(void)
+{
+ union {
+ unsigned int v;
+ unsigned char b;
+ } u;
+ u.v = 1;
+ return u.b;
+}
+#endif
+
+/* bswap16(n) - swap the bytes of a 16-bit integer */
+#ifndef bswap16
+static forceinline u16 bswap16(u16 n)
+{
+ return (n << 8) | (n >> 8);
+}
+#endif
+
+/* bswap32(n) - swap the bytes of a 32-bit integer */
+#ifndef bswap32
+static forceinline u32 bswap32(u32 n)
+{
+ return ((n & 0x000000FF) << 24) |
+ ((n & 0x0000FF00) << 8) |
+ ((n & 0x00FF0000) >> 8) |
+ ((n & 0xFF000000) >> 24);
+}
+#endif
+
+/* bswap64(n) - swap the bytes of a 64-bit integer */
+#ifndef bswap64
+static forceinline u64 bswap64(u64 n)
+{
+ return ((n & 0x00000000000000FF) << 56) |
+ ((n & 0x000000000000FF00) << 40) |
+ ((n & 0x0000000000FF0000) << 24) |
+ ((n & 0x00000000FF000000) << 8) |
+ ((n & 0x000000FF00000000) >> 8) |
+ ((n & 0x0000FF0000000000) >> 24) |
+ ((n & 0x00FF000000000000) >> 40) |
+ ((n & 0xFF00000000000000) >> 56);
+}
+#endif
+
+#define le16_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? (n) : bswap16(n))
+#define le32_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? (n) : bswap32(n))
+#define le64_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? (n) : bswap64(n))
+#define be16_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? bswap16(n) : (n))
+#define be32_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? bswap32(n) : (n))
+#define be64_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? bswap64(n) : (n))
+
+/* ========================================================================== */
+/* Unaligned memory accesses */
+/* ========================================================================== */
+
+/*
+ * UNALIGNED_ACCESS_IS_FAST should be defined to 1 if unaligned memory accesses
+ * can be performed efficiently on the target platform.
+ */
+#ifndef UNALIGNED_ACCESS_IS_FAST
+# define UNALIGNED_ACCESS_IS_FAST 0
+#endif
+
+/* ========================================================================== */
+/* Bit scan functions */
+/* ========================================================================== */
+
+/*
+ * Bit Scan Reverse (BSR) - find the 0-based index (relative to the least
+ * significant end) of the *most* significant 1 bit in the input value. The
+ * input value must be nonzero!
+ */
+
+#ifndef bsr32
+static forceinline unsigned
+bsr32(u32 n)
+{
+ unsigned i = 0;
+ while ((n >>= 1) != 0)
+ i++;
+ return i;
+}
+#endif
+
+#ifndef bsr64
+static forceinline unsigned
+bsr64(u64 n)
+{
+ unsigned i = 0;
+ while ((n >>= 1) != 0)
+ i++;
+ return i;
+}
+#endif
+
+static forceinline unsigned
+bsrw(machine_word_t n)
+{
+ STATIC_ASSERT(WORDBITS == 32 || WORDBITS == 64);
+ if (WORDBITS == 32)
+ return bsr32(n);
+ else
+ return bsr64(n);
+}
+
+/*
+ * Bit Scan Forward (BSF) - find the 0-based index (relative to the least
+ * significant end) of the *least* significant 1 bit in the input value. The
+ * input value must be nonzero!
+ */
+
+#ifndef bsf32
+static forceinline unsigned
+bsf32(u32 n)
+{
+ unsigned i = 0;
+ while ((n & 1) == 0) {
+ i++;
+ n >>= 1;
+ }
+ return i;
+}
+#endif
+
+#ifndef bsf64
+static forceinline unsigned
+bsf64(u64 n)
+{
+ unsigned i = 0;
+ while ((n & 1) == 0) {
+ i++;
+ n >>= 1;
+ }
+ return i;
+}
+#endif
+
+static forceinline unsigned
+bsfw(machine_word_t n)
+{
+ STATIC_ASSERT(WORDBITS == 32 || WORDBITS == 64);
+ if (WORDBITS == 32)
+ return bsf32(n);
+ else
+ return bsf64(n);
+}
+
+#endif /* COMMON_COMMON_DEFS_H */
diff --git a/util/compress/libdeflate/common/compiler_gcc.h b/util/compress/libdeflate/common/compiler_gcc.h
new file mode 100644
index 000000000..2a45b05f3
--- /dev/null
+++ b/util/compress/libdeflate/common/compiler_gcc.h
@@ -0,0 +1,201 @@
+/*
+ * compiler_gcc.h - definitions for the GNU C Compiler. This also handles clang
+ * and the Intel C Compiler (icc).
+ *
+ * TODO: icc is not well tested, so some things are currently disabled even
+ * though they maybe can be enabled on some icc versions.
+ */
+
+#if !defined(__clang__) && !defined(__INTEL_COMPILER)
+# define GCC_PREREQ(major, minor) \
+ (__GNUC__ > (major) || \
+ (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
+#else
+# define GCC_PREREQ(major, minor) 0
+#endif
+
+/* Note: only check the clang version when absolutely necessary!
+ * "Vendors" such as Apple can use different version numbers. */
+#ifdef __clang__
+# ifdef __apple_build_version__
+# define CLANG_PREREQ(major, minor, apple_version) \
+ (__apple_build_version__ >= (apple_version))
+# else
+# define CLANG_PREREQ(major, minor, apple_version) \
+ (__clang_major__ > (major) || \
+ (__clang_major__ == (major) && __clang_minor__ >= (minor)))
+# endif
+#else
+# define CLANG_PREREQ(major, minor, apple_version) 0
+#endif
+
+#ifndef __has_attribute
+# define __has_attribute(attribute) 0
+#endif
+#ifndef __has_feature
+# define __has_feature(feature) 0
+#endif
+#ifndef __has_builtin
+# define __has_builtin(builtin) 0
+#endif
+
+#ifdef _WIN32
+# define LIBEXPORT __declspec(dllexport)
+#else
+# define LIBEXPORT __attribute__((visibility("default")))
+#endif
+
+#define inline inline
+#define forceinline inline __attribute__((always_inline))
+#define restrict __restrict__
+#define likely(expr) __builtin_expect(!!(expr), 1)
+#define unlikely(expr) __builtin_expect(!!(expr), 0)
+#define prefetchr(addr) __builtin_prefetch((addr), 0)
+#define prefetchw(addr) __builtin_prefetch((addr), 1)
+#define _aligned_attribute(n) __attribute__((aligned(n)))
+
+#define COMPILER_SUPPORTS_TARGET_FUNCTION_ATTRIBUTE \
+ (GCC_PREREQ(4, 4) || __has_attribute(target))
+
+#if COMPILER_SUPPORTS_TARGET_FUNCTION_ATTRIBUTE
+
+# if defined(__i386__) || defined(__x86_64__)
+
+# define COMPILER_SUPPORTS_PCLMUL_TARGET \
+ (GCC_PREREQ(4, 4) || __has_builtin(__builtin_ia32_pclmulqdq128))
+
+# define COMPILER_SUPPORTS_AVX_TARGET \
+ (GCC_PREREQ(4, 6) || __has_builtin(__builtin_ia32_maxps256))
+
+# define COMPILER_SUPPORTS_BMI2_TARGET \
+ (GCC_PREREQ(4, 7) || __has_builtin(__builtin_ia32_pdep_di))
+
+# define COMPILER_SUPPORTS_AVX2_TARGET \
+ (GCC_PREREQ(4, 7) || __has_builtin(__builtin_ia32_psadbw256))
+
+# define COMPILER_SUPPORTS_AVX512BW_TARGET \
+ (GCC_PREREQ(5, 1) || __has_builtin(__builtin_ia32_psadbw512))
+
+ /*
+ * Prior to gcc 4.9 (r200349) and clang 3.8 (r239883), x86 intrinsics
+ * not available in the main target could not be used in 'target'
+ * attribute functions. Unfortunately clang has no feature test macro
+ * for this so we have to check its version.
+ */
+# if GCC_PREREQ(4, 9) || CLANG_PREREQ(3, 8, 7030000)
+# define COMPILER_SUPPORTS_SSE2_TARGET_INTRINSICS 1
+# define COMPILER_SUPPORTS_PCLMUL_TARGET_INTRINSICS \
+ COMPILER_SUPPORTS_PCLMUL_TARGET
+# define COMPILER_SUPPORTS_AVX2_TARGET_INTRINSICS \
+ COMPILER_SUPPORTS_AVX2_TARGET
+# define COMPILER_SUPPORTS_AVX512BW_TARGET_INTRINSICS \
+ COMPILER_SUPPORTS_AVX512BW_TARGET
+# endif
+
+# elif defined(__arm__) || defined(__aarch64__)
+
+ /*
+ * Determine whether NEON and crypto intrinsics are supported.
+ *
+ * With gcc prior to 6.1, (r230411 for arm32, r226563 for arm64), neither
+ * was available unless enabled in the main target.
+ *
+ * But even after that, to include <arm_neon.h> (which contains both the
+ * basic NEON intrinsics and the crypto intrinsics) the main target still
+ * needs to have:
+ * - gcc: hardware floating point support
+ * - clang: NEON support (but not necessarily crypto support)
+ */
+# if (GCC_PREREQ(6, 1) && defined(__ARM_FP)) || \
+ (defined(__clang__) && defined(__ARM_NEON))
+# define COMPILER_SUPPORTS_NEON_TARGET_INTRINSICS 1
+ /*
+ * The crypto intrinsics are broken on arm32 with clang, even when using
+ * -mfpu=crypto-neon-fp-armv8, because clang's <arm_neon.h> puts them
+ * behind __aarch64__. Undefine __ARM_FEATURE_CRYPTO in that case...
+ */
+# if defined(__clang__) && defined(__arm__)
+# undef __ARM_FEATURE_CRYPTO
+# elif __has_builtin(__builtin_neon_vmull_p64) || !defined(__clang__)
+# define COMPILER_SUPPORTS_PMULL_TARGET_INTRINSICS 1
+# endif
+# endif
+
+ /*
+ * Determine whether CRC32 intrinsics are supported.
+ *
+ * With gcc r274827 or later (gcc 10.1+, 9.3+, or 8.4+), or with clang,
+ * they work as expected. (Well, not quite. There's still a bug, but we
+ * have to work around it later when including arm_acle.h.)
+ */
+# if GCC_PREREQ(10, 1) || \
+ (GCC_PREREQ(9, 3) && !GCC_PREREQ(10, 0)) || \
+ (GCC_PREREQ(8, 4) && !GCC_PREREQ(9, 0)) || \
+ (defined(__clang__) && __has_builtin(__builtin_arm_crc32b))
+# define COMPILER_SUPPORTS_CRC32_TARGET_INTRINSICS 1
+# endif
+
+# endif /* __arm__ || __aarch64__ */
+
+#endif /* COMPILER_SUPPORTS_TARGET_FUNCTION_ATTRIBUTE */
+
+/*
+ * Prior to gcc 5.1 and clang 3.9, emmintrin.h only defined vectors of signed
+ * integers (e.g. __v4si), not vectors of unsigned integers (e.g. __v4su). But
+ * we need the unsigned ones in order to avoid signed integer overflow, which is
+ * undefined behavior. Add the missing definitions for the unsigned ones if
+ * needed.
+ */
+#if (GCC_PREREQ(4, 0) && !GCC_PREREQ(5, 1)) || \
+ (defined(__clang__) && !CLANG_PREREQ(3, 9, 8020000)) || \
+ defined(__INTEL_COMPILER)
+typedef unsigned long long __v2du __attribute__((__vector_size__(16)));
+typedef unsigned int __v4su __attribute__((__vector_size__(16)));
+typedef unsigned short __v8hu __attribute__((__vector_size__(16)));
+typedef unsigned char __v16qu __attribute__((__vector_size__(16)));
+typedef unsigned long long __v4du __attribute__((__vector_size__(32)));
+typedef unsigned int __v8su __attribute__((__vector_size__(32)));
+typedef unsigned short __v16hu __attribute__((__vector_size__(32)));
+typedef unsigned char __v32qu __attribute__((__vector_size__(32)));
+#endif
+
+#ifdef __INTEL_COMPILER
+typedef int __v16si __attribute__((__vector_size__(64)));
+typedef short __v32hi __attribute__((__vector_size__(64)));
+typedef char __v64qi __attribute__((__vector_size__(64)));
+#endif
+
+/* Newer gcc supports __BYTE_ORDER__. Older gcc doesn't. */
+#ifdef __BYTE_ORDER__
+# define CPU_IS_LITTLE_ENDIAN() (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#endif
+
+#if GCC_PREREQ(4, 8) || __has_builtin(__builtin_bswap16)
+# define bswap16 __builtin_bswap16
+#endif
+
+#if GCC_PREREQ(4, 3) || __has_builtin(__builtin_bswap32)
+# define bswap32 __builtin_bswap32
+#endif
+
+#if GCC_PREREQ(4, 3) || __has_builtin(__builtin_bswap64)
+# define bswap64 __builtin_bswap64
+#endif
+
+#if defined(__x86_64__) || defined(__i386__) || \
+ defined(__ARM_FEATURE_UNALIGNED) || defined(__powerpc64__) || \
+ /*
+ * For all compilation purposes, WebAssembly behaves like any other CPU
+ * instruction set. Even though WebAssembly engine might be running on top
+ * of different actual CPU architectures, the WebAssembly spec itself
+ * permits unaligned access and it will be fast on most of those platforms,
+ * and simulated at the engine level on others, so it's worth treating it
+ * as a CPU architecture with fast unaligned access.
+ */ defined(__wasm__)
+# define UNALIGNED_ACCESS_IS_FAST 1
+#endif
+
+#define bsr32(n) (31 - __builtin_clz(n))
+#define bsr64(n) (63 - __builtin_clzll(n))
+#define bsf32(n) __builtin_ctz(n)
+#define bsf64(n) __builtin_ctzll(n)
diff --git a/util/compress/libdeflate/common/compiler_msc.h b/util/compress/libdeflate/common/compiler_msc.h
new file mode 100644
index 000000000..18cfa128f
--- /dev/null
+++ b/util/compress/libdeflate/common/compiler_msc.h
@@ -0,0 +1,80 @@
+/*
+ * compiler_msc.h - definitions for the Microsoft C Compiler
+ */
+
+#include <stdint.h>
+#include <stdlib.h> /* for _byteswap_*() */
+
+#define LIBEXPORT __declspec(dllexport)
+
+/*
+ * Old versions (e.g. VS2010) of MSC don't have the C99 header stdbool.h.
+ * Beware: the below replacement isn't fully standard, since normally any value
+ * != 0 should be implicitly cast to a bool with value 1... but that doesn't
+ * happen if bool is really just an 'int'.
+ */
+typedef int bool;
+#define true 1
+#define false 0
+#define __bool_true_false_are_defined 1
+
+/* Define ssize_t */
+#ifdef _WIN64
+typedef long long ssize_t;
+#else
+typedef int ssize_t;
+#endif
+
+/* Assume a little endian architecture with fast unaligned access */
+#define CPU_IS_LITTLE_ENDIAN() 1
+#define UNALIGNED_ACCESS_IS_FAST 1
+
+/* __restrict has nonstandard behavior; don't use it */
+#define restrict
+
+/* ... but we can use __inline and __forceinline */
+#define inline __inline
+#define forceinline __forceinline
+
+/* Byte swap functions */
+#define bswap16 _byteswap_ushort
+#define bswap32 _byteswap_ulong
+#define bswap64 _byteswap_uint64
+
+/* Bit scan functions (32-bit) */
+
+static forceinline unsigned
+bsr32(uint32_t n)
+{
+ _BitScanReverse(&n, n);
+ return n;
+}
+#define bsr32 bsr32
+
+static forceinline unsigned
+bsf32(uint32_t n)
+{
+ _BitScanForward(&n, n);
+ return n;
+}
+#define bsf32 bsf32
+
+#ifdef _M_X64 /* Bit scan functions (64-bit) */
+
+static forceinline unsigned
+bsr64(uint64_t n)
+{
+ _BitScanReverse64(&n, n);
+ return n;
+}
+#define bsr64 bsr64
+
+static forceinline unsigned
+bsf64(uint64_t n)
+{
+ _BitScanForward64(&n, n);
+ return n;
+}
+#define bsf64 bsf64
+
+#endif /* _M_X64 */
diff --git a/util/compress/libdeflate/lib/adler32.c b/util/compress/libdeflate/lib/adler32.c
new file mode 100644
index 000000000..32ab0ceb5
--- /dev/null
+++ b/util/compress/libdeflate/lib/adler32.c
@@ -0,0 +1,130 @@
+/*
+ * adler32.c - Adler-32 checksum algorithm
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "lib_common.h"
+#include "libdeflate.h"
+
+/* The Adler-32 divisor, or "base", value. */
+#define DIVISOR 65521
+
+/*
+ * MAX_CHUNK_SIZE is the most bytes that can be processed without the
+ * possibility of s2 overflowing when it is represented as an unsigned 32-bit
+ * integer. This value was computed using the following Python script:
+ *
+ * divisor = 65521
+ * count = 0
+ * s1 = divisor - 1
+ * s2 = divisor - 1
+ * while True:
+ * s1 += 0xFF
+ * s2 += s1
+ * if s2 > 0xFFFFFFFF:
+ * break
+ * count += 1
+ * print(count)
+ *
+ * Note that to get the correct worst-case value, we must assume that every byte
+ * has value 0xFF and that s1 and s2 started with the highest possible values
+ * modulo the divisor.
+ */
+#define MAX_CHUNK_SIZE 5552
+
+typedef u32 (*adler32_func_t)(u32, const u8 *, size_t);
+
+/* Include architecture-specific implementations if available */
+#undef DEFAULT_IMPL
+#undef DISPATCH
+#if defined(__arm__) || defined(__aarch64__)
+# include "arm/adler32_impl.h"
+#elif defined(__i386__) || defined(__x86_64__)
+# include "x86/adler32_impl.h"
+#endif
+
+/* Define a generic implementation if needed */
+#ifndef DEFAULT_IMPL
+#define DEFAULT_IMPL adler32_generic
+static u32 adler32_generic(u32 adler, const u8 *p, size_t size)
+{
+ u32 s1 = adler & 0xFFFF;
+ u32 s2 = adler >> 16;
+ const u8 * const end = p + size;
+
+ while (p != end) {
+ size_t chunk_size = MIN(end - p, MAX_CHUNK_SIZE);
+ const u8 *chunk_end = p + chunk_size;
+ size_t num_unrolled_iterations = chunk_size / 4;
+
+ while (num_unrolled_iterations--) {
+ s1 += *p++;
+ s2 += s1;
+ s1 += *p++;
+ s2 += s1;
+ s1 += *p++;
+ s2 += s1;
+ s1 += *p++;
+ s2 += s1;
+ }
+ while (p != chunk_end) {
+ s1 += *p++;
+ s2 += s1;
+ }
+ s1 %= DIVISOR;
+ s2 %= DIVISOR;
+ }
+
+ return (s2 << 16) | s1;
+}
+#endif /* !DEFAULT_IMPL */
+
+#ifdef DISPATCH
+static u32 dispatch(u32, const u8 *, size_t);
+
+static volatile adler32_func_t adler32_impl = dispatch;
+
+/* Choose the fastest implementation at runtime */
+static u32 dispatch(u32 adler, const u8 *buffer, size_t size)
+{
+ adler32_func_t f = arch_select_adler32_func();
+
+ if (f == NULL)
+ f = DEFAULT_IMPL;
+
+ adler32_impl = f;
+ return adler32_impl(adler, buffer, size);
+}
+#else
+# define adler32_impl DEFAULT_IMPL /* only one implementation, use it */
+#endif
+
+LIBDEFLATEEXPORT u32 LIBDEFLATEAPI
+libdeflate_adler32(u32 adler, const void *buffer, size_t size)
+{
+ if (buffer == NULL) /* return initial value */
+ return 1;
+ return adler32_impl(adler, buffer, size);
+}
diff --git a/util/compress/libdeflate/lib/adler32_vec_template.h b/util/compress/libdeflate/lib/adler32_vec_template.h
new file mode 100644
index 000000000..4eb8c2a82
--- /dev/null
+++ b/util/compress/libdeflate/lib/adler32_vec_template.h
@@ -0,0 +1,124 @@
+/*
+ * adler32_vec_template.h - template for vectorized Adler-32 implementations
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This file contains a template for vectorized Adler-32 implementations.
+ *
+ * The inner loop between reductions modulo 65521 of an unvectorized Adler-32
+ * implementation looks something like this:
+ *
+ * do {
+ * s1 += *p;
+ * s2 += s1;
+ * } while (++p != chunk_end);
+ *
+ * For vectorized calculation of s1, we only need to sum the input bytes. They
+ * can be accumulated into multiple counters which are eventually summed
+ * together.
+ *
+ * For vectorized calculation of s2, the basic idea is that for each iteration
+ * that processes N bytes, we can perform the following vectorizable
+ * calculation:
+ *
+ * s2 += N*byte_1 + (N-1)*byte_2 + (N-2)*byte_3 + ... + 1*byte_N
+ *
+ * Or, equivalently, we can sum the byte_1...byte_N for each iteration into N
+ * separate counters, then do the multiplications by N...1 just once at the end
+ * rather than once per iteration.
+ *
+ * Also, we must account for how previous bytes will affect s2 by doing the
+ * following at beginning of each iteration:
+ *
+ * s2 += s1 * N
+ *
+ * Furthermore, like s1, "s2" can actually be multiple counters which are
+ * eventually summed together.
+ */
+
+static u32 ATTRIBUTES
+FUNCNAME(u32 adler, const u8 *p, size_t size)
+{
+ u32 s1 = adler & 0xFFFF;
+ u32 s2 = adler >> 16;
+ const u8 * const end = p + size;
+ const u8 *vend;
+ const size_t max_chunk_size =
+ MIN(MAX_CHUNK_SIZE, IMPL_MAX_CHUNK_SIZE) -
+ (MIN(MAX_CHUNK_SIZE, IMPL_MAX_CHUNK_SIZE) %
+ IMPL_SEGMENT_SIZE);
+
+ /* Process a byte at a time until the needed alignment is reached */
+ if (p != end && (uintptr_t)p % IMPL_ALIGNMENT) {
+ do {
+ s1 += *p++;
+ s2 += s1;
+ } while (p != end && (uintptr_t)p % IMPL_ALIGNMENT);
+ s1 %= DIVISOR;
+ s2 %= DIVISOR;
+ }
+
+ /*
+ * Process "chunks" of bytes using vector instructions. Chunk sizes are
+ * limited to MAX_CHUNK_SIZE, which guarantees that s1 and s2 never
+ * overflow before being reduced modulo DIVISOR. For vector processing,
+ * chunk sizes are also made evenly divisible by IMPL_SEGMENT_SIZE and
+ * may be further limited to IMPL_MAX_CHUNK_SIZE.
+ */
+ STATIC_ASSERT(IMPL_SEGMENT_SIZE % IMPL_ALIGNMENT == 0);
+ vend = end - ((size_t)(end - p) % IMPL_SEGMENT_SIZE);
+ while (p != vend) {
+ size_t chunk_size = MIN((size_t)(vend - p), max_chunk_size);
+
+ s2 += s1 * chunk_size;
+
+ FUNCNAME_CHUNK((const void *)p, (const void *)(p + chunk_size),
+ &s1, &s2);
+
+ p += chunk_size;
+ s1 %= DIVISOR;
+ s2 %= DIVISOR;
+ }
+
+ /* Process any remaining bytes */
+ if (p != end) {
+ do {
+ s1 += *p++;
+ s2 += s1;
+ } while (p != end);
+ s1 %= DIVISOR;
+ s2 %= DIVISOR;
+ }
+
+ return (s2 << 16) | s1;
+}
+
+#undef FUNCNAME
+#undef FUNCNAME_CHUNK
+#undef ATTRIBUTES
+#undef IMPL_ALIGNMENT
+#undef IMPL_SEGMENT_SIZE
+#undef IMPL_MAX_CHUNK_SIZE
diff --git a/util/compress/libdeflate/lib/arm/adler32_impl.h b/util/compress/libdeflate/lib/arm/adler32_impl.h
new file mode 100644
index 000000000..17e56c004
--- /dev/null
+++ b/util/compress/libdeflate/lib/arm/adler32_impl.h
@@ -0,0 +1,125 @@
+/*
+ * arm/adler32_impl.h - ARM implementations of Adler-32 checksum algorithm
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef LIB_ARM_ADLER32_IMPL_H
+#define LIB_ARM_ADLER32_IMPL_H
+
+#include "cpu_features.h"
+
+/* NEON implementation */
+#undef DISPATCH_NEON
+#if !defined(DEFAULT_IMPL) && \
+ (defined(__ARM_NEON) || (ARM_CPU_FEATURES_ENABLED && \
+ COMPILER_SUPPORTS_NEON_TARGET_INTRINSICS))
+# define FUNCNAME adler32_neon
+# define FUNCNAME_CHUNK adler32_neon_chunk
+# define IMPL_ALIGNMENT 16
+# define IMPL_SEGMENT_SIZE 32
+/* Prevent unsigned overflow of the 16-bit precision byte counters */
+# define IMPL_MAX_CHUNK_SIZE (32 * (0xFFFF / 0xFF))
+# ifdef __ARM_NEON
+# define ATTRIBUTES
+# define DEFAULT_IMPL adler32_neon
+# else
+# ifdef __arm__
+# define ATTRIBUTES __attribute__((target("fpu=neon")))
+# else
+# define ATTRIBUTES __attribute__((target("+simd")))
+# endif
+# define DISPATCH 1
+# define DISPATCH_NEON 1
+# endif
+# include <arm_neon.h>
+static forceinline ATTRIBUTES void
+adler32_neon_chunk(const uint8x16_t *p, const uint8x16_t * const end,
+ u32 *s1, u32 *s2)
+{
+ uint32x4_t v_s1 = (uint32x4_t) { 0, 0, 0, 0 };
+ uint32x4_t v_s2 = (uint32x4_t) { 0, 0, 0, 0 };
+ uint16x8_t v_byte_sums_a = (uint16x8_t) { 0, 0, 0, 0, 0, 0, 0, 0 };
+ uint16x8_t v_byte_sums_b = (uint16x8_t) { 0, 0, 0, 0, 0, 0, 0, 0 };
+ uint16x8_t v_byte_sums_c = (uint16x8_t) { 0, 0, 0, 0, 0, 0, 0, 0 };
+ uint16x8_t v_byte_sums_d = (uint16x8_t) { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ do {
+ const uint8x16_t bytes1 = *p++;
+ const uint8x16_t bytes2 = *p++;
+ uint16x8_t tmp;
+
+ v_s2 += v_s1;
+
+ /* Vector Pairwise Add Long (u8 => u16) */
+ tmp = vpaddlq_u8(bytes1);
+
+ /* Vector Pairwise Add and Accumulate Long (u8 => u16) */
+ tmp = vpadalq_u8(tmp, bytes2);
+
+ /* Vector Pairwise Add and Accumulate Long (u16 => u32) */
+ v_s1 = vpadalq_u16(v_s1, tmp);
+
+ /* Vector Add Wide (u8 => u16) */
+ v_byte_sums_a = vaddw_u8(v_byte_sums_a, vget_low_u8(bytes1));
+ v_byte_sums_b = vaddw_u8(v_byte_sums_b, vget_high_u8(bytes1));
+ v_byte_sums_c = vaddw_u8(v_byte_sums_c, vget_low_u8(bytes2));
+ v_byte_sums_d = vaddw_u8(v_byte_sums_d, vget_high_u8(bytes2));
+
+ } while (p != end);
+
+ /* Vector Shift Left (u32) */
+ v_s2 = vqshlq_n_u32(v_s2, 5);
+
+ /* Vector Multiply Accumulate Long (u16 => u32) */
+ v_s2 = vmlal_u16(v_s2, vget_low_u16(v_byte_sums_a), (uint16x4_t) { 32, 31, 30, 29 });
+ v_s2 = vmlal_u16(v_s2, vget_high_u16(v_byte_sums_a), (uint16x4_t) { 28, 27, 26, 25 });
+ v_s2 = vmlal_u16(v_s2, vget_low_u16(v_byte_sums_b), (uint16x4_t) { 24, 23, 22, 21 });
+ v_s2 = vmlal_u16(v_s2, vget_high_u16(v_byte_sums_b), (uint16x4_t) { 20, 19, 18, 17 });
+ v_s2 = vmlal_u16(v_s2, vget_low_u16(v_byte_sums_c), (uint16x4_t) { 16, 15, 14, 13 });
+ v_s2 = vmlal_u16(v_s2, vget_high_u16(v_byte_sums_c), (uint16x4_t) { 12, 11, 10, 9 });
+ v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_byte_sums_d), (uint16x4_t) { 8, 7, 6, 5 });
+ v_s2 = vmlal_u16(v_s2, vget_high_u16(v_byte_sums_d), (uint16x4_t) { 4, 3, 2, 1 });
+
+ *s1 += v_s1[0] + v_s1[1] + v_s1[2] + v_s1[3];
+ *s2 += v_s2[0] + v_s2[1] + v_s2[2] + v_s2[3];
+}
+# include "../adler32_vec_template.h"
+#endif /* NEON implementation */
+
+#ifdef DISPATCH
+static inline adler32_func_t
+arch_select_adler32_func(void)
+{
+ u32 features = get_cpu_features();
+
+#ifdef DISPATCH_NEON
+ if (features & ARM_CPU_FEATURE_NEON)
+ return adler32_neon;
+#endif
+ return NULL;
+}
+#endif /* DISPATCH */
+
+#endif /* LIB_ARM_ADLER32_IMPL_H */
diff --git a/util/compress/libdeflate/lib/arm/cpu_features.c b/util/compress/libdeflate/lib/arm/cpu_features.c
new file mode 100644
index 000000000..60b1be3ee
--- /dev/null
+++ b/util/compress/libdeflate/lib/arm/cpu_features.c
@@ -0,0 +1,133 @@
+/*
+ * arm/cpu_features.c - feature detection for ARM processors
+ *
+ * Copyright 2018 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * ARM processors don't have a standard way for unprivileged programs to detect
+ * processor features. But, on Linux we can read the AT_HWCAP and AT_HWCAP2
+ * values from /proc/self/auxv.
+ *
+ * Ideally we'd use the C library function getauxval(), but it's not guaranteed
+ * to be available: it was only added to glibc in 2.16, and in Android it was
+ * added to API level 18 for ARM and level 21 for AArch64.
+ */
+
+#include "../cpu_features_common.h" /* must be included first */
+#include "cpu_features.h"
+
+#if ARM_CPU_FEATURES_ENABLED
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#define AT_HWCAP 16
+#define AT_HWCAP2 26
+
+volatile u32 _cpu_features = 0;
+
+static void scan_auxv(unsigned long *hwcap, unsigned long *hwcap2)
+{
+ int fd;
+ unsigned long auxbuf[32];
+ int filled = 0;
+ int i;
+
+ fd = open("/proc/self/auxv", O_RDONLY);
+ if (fd < 0)
+ return;
+
+ for (;;) {
+ do {
+ int ret = read(fd, &((char *)auxbuf)[filled],
+ sizeof(auxbuf) - filled);
+ if (ret <= 0) {
+ if (ret < 0 && errno == EINTR)
+ continue;
+ goto out;
+ }
+ filled += ret;
+ } while (filled < 2 * sizeof(long));
+
+ i = 0;
+ do {
+ unsigned long type = auxbuf[i];
+ unsigned long value = auxbuf[i + 1];
+
+ if (type == AT_HWCAP)
+ *hwcap = value;
+ else if (type == AT_HWCAP2)
+ *hwcap2 = value;
+ i += 2;
+ filled -= 2 * sizeof(long);
+ } while (filled >= 2 * sizeof(long));
+
+ memmove(auxbuf, &auxbuf[i], filled);
+ }
+out:
+ close(fd);
+}
+
+static const struct cpu_feature arm_cpu_feature_table[] = {
+ {ARM_CPU_FEATURE_NEON, "neon"},
+ {ARM_CPU_FEATURE_PMULL, "pmull"},
+ {ARM_CPU_FEATURE_CRC32, "crc32"},
+};
+
+void setup_cpu_features(void)
+{
+ u32 features = 0;
+ unsigned long hwcap = 0;
+ unsigned long hwcap2 = 0;
+
+ scan_auxv(&hwcap, &hwcap2);
+
+#ifdef __arm__
+ STATIC_ASSERT(sizeof(long) == 4);
+ if (hwcap & (1 << 12)) /* HWCAP_NEON */
+ features |= ARM_CPU_FEATURE_NEON;
+ if (hwcap2 & (1 << 1)) /* HWCAP2_PMULL */
+ features |= ARM_CPU_FEATURE_PMULL;
+ if (hwcap2 & (1 << 4)) /* HWCAP2_CRC32 */
+ features |= ARM_CPU_FEATURE_CRC32;
+#else
+ STATIC_ASSERT(sizeof(long) == 8);
+ if (hwcap & (1 << 1)) /* HWCAP_ASIMD */
+ features |= ARM_CPU_FEATURE_NEON;
+ if (hwcap & (1 << 4)) /* HWCAP_PMULL */
+ features |= ARM_CPU_FEATURE_PMULL;
+ if (hwcap & (1 << 7)) /* HWCAP_CRC32 */
+ features |= ARM_CPU_FEATURE_CRC32;
+#endif
+
+ disable_cpu_features_for_testing(&features, arm_cpu_feature_table,
+ ARRAY_LEN(arm_cpu_feature_table));
+
+ _cpu_features = features | ARM_CPU_FEATURES_KNOWN;
+}
+
+#endif /* ARM_CPU_FEATURES_ENABLED */
diff --git a/util/compress/libdeflate/lib/arm/cpu_features.h b/util/compress/libdeflate/lib/arm/cpu_features.h
new file mode 100644
index 000000000..69d723598
--- /dev/null
+++ b/util/compress/libdeflate/lib/arm/cpu_features.h
@@ -0,0 +1,40 @@
+/*
+ * arm/cpu_features.h - feature detection for ARM processors
+ */
+
+#ifndef LIB_ARM_CPU_FEATURES_H
+#define LIB_ARM_CPU_FEATURES_H
+
+#include "../lib_common.h"
+
+#if (defined(__arm__) || defined(__aarch64__)) && \
+ defined(__linux__) && \
+ COMPILER_SUPPORTS_TARGET_FUNCTION_ATTRIBUTE && \
+ !defined(FREESTANDING)
+# define ARM_CPU_FEATURES_ENABLED 1
+#else
+# define ARM_CPU_FEATURES_ENABLED 0
+#endif
+
+#if ARM_CPU_FEATURES_ENABLED
+
+#define ARM_CPU_FEATURE_NEON 0x00000001
+#define ARM_CPU_FEATURE_PMULL 0x00000002
+#define ARM_CPU_FEATURE_CRC32 0x00000004
+
+#define ARM_CPU_FEATURES_KNOWN 0x80000000
+
+extern volatile u32 _cpu_features;
+
+void setup_cpu_features(void);
+
+static inline u32 get_cpu_features(void)
+{
+ if (_cpu_features == 0)
+ setup_cpu_features();
+ return _cpu_features;
+}
+
+#endif /* ARM_CPU_FEATURES_ENABLED */
+
+#endif /* LIB_ARM_CPU_FEATURES_H */
diff --git a/util/compress/libdeflate/lib/arm/crc32_impl.h b/util/compress/libdeflate/lib/arm/crc32_impl.h
new file mode 100644
index 000000000..238a85a80
--- /dev/null
+++ b/util/compress/libdeflate/lib/arm/crc32_impl.h
@@ -0,0 +1,247 @@
+/*
+ * arm/crc32_impl.h
+ *
+ * Copyright 2017 Jun He <jun.he@linaro.org>
+ * Copyright 2018 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef LIB_ARM_CRC32_IMPL_H
+#define LIB_ARM_CRC32_IMPL_H
+
+#include "cpu_features.h"
+
+/* Implementation using ARM CRC32 instructions */
+#undef DISPATCH_ARM
+#if !defined(DEFAULT_IMPL) && \
+ (defined(__ARM_FEATURE_CRC32) || \
+ (ARM_CPU_FEATURES_ENABLED && COMPILER_SUPPORTS_CRC32_TARGET_INTRINSICS))
+# ifdef __ARM_FEATURE_CRC32
+# define ATTRIBUTES
+# define DEFAULT_IMPL crc32_arm
+# else
+# ifdef __arm__
+# ifdef __clang__
+# define ATTRIBUTES __attribute__((target("armv8-a,crc")))
+# else
+# define ATTRIBUTES __attribute__((target("arch=armv8-a+crc")))
+# endif
+# else
+# ifdef __clang__
+# define ATTRIBUTES __attribute__((target("crc")))
+# else
+# define ATTRIBUTES __attribute__((target("+crc")))
+# endif
+# endif
+# define DISPATCH 1
+# define DISPATCH_ARM 1
+# endif
+
+/*
+ * gcc's (as of 10.1) version of arm_acle.h for arm32, and clang's (as of
+ * 10.0.1) version of arm_acle.h for both arm32 and arm64, have a bug where they
+ * only define the CRC32 functions like __crc32b() when __ARM_FEATURE_CRC32 is
+ * defined. That prevents them from being used via __attribute__((target)) when
+ * the main target doesn't have CRC32 support enabled. The actual built-ins
+ * like __builtin_arm_crc32b() are available and work, however; it's just the
+ * wrappers in arm_acle.h like __crc32b() that erroneously don't get defined.
+ * Work around this by manually defining __ARM_FEATURE_CRC32.
+ */
+#ifndef __ARM_FEATURE_CRC32
+# define __ARM_FEATURE_CRC32 1
+#endif
+#include <arm_acle.h>
+
+static u32 ATTRIBUTES
+crc32_arm(u32 remainder, const u8 *p, size_t size)
+{
+ while (size != 0 && (uintptr_t)p & 7) {
+ remainder = __crc32b(remainder, *p++);
+ size--;
+ }
+
+ while (size >= 32) {
+ remainder = __crc32d(remainder, le64_bswap(*((u64 *)p + 0)));
+ remainder = __crc32d(remainder, le64_bswap(*((u64 *)p + 1)));
+ remainder = __crc32d(remainder, le64_bswap(*((u64 *)p + 2)));
+ remainder = __crc32d(remainder, le64_bswap(*((u64 *)p + 3)));
+ p += 32;
+ size -= 32;
+ }
+
+ while (size >= 8) {
+ remainder = __crc32d(remainder, le64_bswap(*(u64 *)p));
+ p += 8;
+ size -= 8;
+ }
+
+ while (size != 0) {
+ remainder = __crc32b(remainder, *p++);
+ size--;
+ }
+
+ return remainder;
+}
+#undef ATTRIBUTES
+#endif /* Implementation using ARM CRC32 instructions */
+
+/*
+ * CRC-32 folding with ARM Crypto extension-PMULL
+ *
+ * This works the same way as the x86 PCLMUL version.
+ * See x86/crc32_pclmul_template.h for an explanation.
+ */
+#undef DISPATCH_PMULL
+#if !defined(DEFAULT_IMPL) && \
+ (defined(__ARM_FEATURE_CRYPTO) || \
+ (ARM_CPU_FEATURES_ENABLED && \
+ COMPILER_SUPPORTS_PMULL_TARGET_INTRINSICS)) && \
+ /* not yet tested on big endian, probably needs changes to work there */ \
+ (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+# define FUNCNAME crc32_pmull
+# define FUNCNAME_ALIGNED crc32_pmull_aligned
+# ifdef __ARM_FEATURE_CRYPTO
+# define ATTRIBUTES
+# define DEFAULT_IMPL crc32_pmull
+# else
+# ifdef __arm__
+# define ATTRIBUTES __attribute__((target("fpu=crypto-neon-fp-armv8")))
+# else
+# ifdef __clang__
+# define ATTRIBUTES __attribute__((target("crypto")))
+# else
+# define ATTRIBUTES __attribute__((target("+crypto")))
+# endif
+# endif
+# define DISPATCH 1
+# define DISPATCH_PMULL 1
+# endif
+
+#include <arm_neon.h>
+
+static forceinline ATTRIBUTES uint8x16_t
+clmul_00(uint8x16_t a, uint8x16_t b)
+{
+ return (uint8x16_t)vmull_p64((poly64_t)vget_low_u8(a),
+ (poly64_t)vget_low_u8(b));
+}
+
+static forceinline ATTRIBUTES uint8x16_t
+clmul_10(uint8x16_t a, uint8x16_t b)
+{
+ return (uint8x16_t)vmull_p64((poly64_t)vget_low_u8(a),
+ (poly64_t)vget_high_u8(b));
+}
+
+static forceinline ATTRIBUTES uint8x16_t
+clmul_11(uint8x16_t a, uint8x16_t b)
+{
+ return (uint8x16_t)vmull_high_p64((poly64x2_t)a, (poly64x2_t)b);
+}
+
+static forceinline ATTRIBUTES uint8x16_t
+fold_128b(uint8x16_t dst, uint8x16_t src, uint8x16_t multipliers)
+{
+ return dst ^ clmul_00(src, multipliers) ^ clmul_11(src, multipliers);
+}
+
+static forceinline ATTRIBUTES u32
+crc32_pmull_aligned(u32 remainder, const uint8x16_t *p, size_t nr_segs)
+{
+ /* Constants precomputed by gen_crc32_multipliers.c. Do not edit! */
+ const uint8x16_t multipliers_4 =
+ (uint8x16_t)(uint64x2_t){ 0x8F352D95, 0x1D9513D7 };
+ const uint8x16_t multipliers_1 =
+ (uint8x16_t)(uint64x2_t){ 0xAE689191, 0xCCAA009E };
+ const uint8x16_t final_multiplier =
+ (uint8x16_t)(uint64x2_t){ 0xB8BC6765 };
+ const uint8x16_t mask32 = (uint8x16_t)(uint32x4_t){ 0xFFFFFFFF };
+ const uint8x16_t barrett_reduction_constants =
+ (uint8x16_t)(uint64x2_t){ 0x00000001F7011641,
+ 0x00000001DB710641 };
+ const uint8x16_t zeroes = (uint8x16_t){ 0 };
+
+ const uint8x16_t * const end = p + nr_segs;
+ const uint8x16_t * const end512 = p + (nr_segs & ~3);
+ uint8x16_t x0, x1, x2, x3;
+
+ x0 = *p++ ^ (uint8x16_t)(uint32x4_t){ remainder };
+ if (nr_segs >= 4) {
+ x1 = *p++;
+ x2 = *p++;
+ x3 = *p++;
+
+ /* Fold 512 bits at a time */
+ while (p != end512) {
+ x0 = fold_128b(*p++, x0, multipliers_4);
+ x1 = fold_128b(*p++, x1, multipliers_4);
+ x2 = fold_128b(*p++, x2, multipliers_4);
+ x3 = fold_128b(*p++, x3, multipliers_4);
+ }
+
+ /* Fold 512 bits => 128 bits */
+ x1 = fold_128b(x1, x0, multipliers_1);
+ x2 = fold_128b(x2, x1, multipliers_1);
+ x0 = fold_128b(x3, x2, multipliers_1);
+ }
+
+ /* Fold 128 bits at a time */
+ while (p != end)
+ x0 = fold_128b(*p++, x0, multipliers_1);
+
+ /* Fold 128 => 96 bits, implicitly appending 32 zeroes */
+ x0 = vextq_u8(x0, zeroes, 8) ^ clmul_10(x0, multipliers_1);
+
+ /* Fold 96 => 64 bits */
+ x0 = vextq_u8(x0, zeroes, 4) ^ clmul_00(x0 & mask32, final_multiplier);
+
+ /* Reduce 64 => 32 bits using Barrett reduction */
+ x1 = x0;
+ x0 = clmul_00(x0 & mask32, barrett_reduction_constants);
+ x0 = clmul_10(x0 & mask32, barrett_reduction_constants);
+ return vgetq_lane_u32((uint32x4_t)(x0 ^ x1), 1);
+}
+#define IMPL_ALIGNMENT 16
+#define IMPL_SEGMENT_SIZE 16
+#include "../crc32_vec_template.h"
+#endif /* PMULL implementation */
+
+#ifdef DISPATCH
+static inline crc32_func_t
+arch_select_crc32_func(void)
+{
+ u32 features = get_cpu_features();
+
+#ifdef DISPATCH_ARM
+ if (features & ARM_CPU_FEATURE_CRC32)
+ return crc32_arm;
+#endif
+#ifdef DISPATCH_PMULL
+ if (features & ARM_CPU_FEATURE_PMULL)
+ return crc32_pmull;
+#endif
+ return NULL;
+}
+#endif /* DISPATCH */
+
+#endif /* LIB_ARM_CRC32_IMPL_H */
diff --git a/util/compress/libdeflate/lib/arm/matchfinder_impl.h b/util/compress/libdeflate/lib/arm/matchfinder_impl.h
new file mode 100644
index 000000000..da0d2fd79
--- /dev/null
+++ b/util/compress/libdeflate/lib/arm/matchfinder_impl.h
@@ -0,0 +1,86 @@
+/*
+ * arm/matchfinder_impl.h - ARM implementations of matchfinder functions
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef LIB_ARM_MATCHFINDER_IMPL_H
+#define LIB_ARM_MATCHFINDER_IMPL_H
+
+#ifdef __ARM_NEON
+# include <arm_neon.h>
+static forceinline void
+matchfinder_init_neon(mf_pos_t *data, size_t size)
+{
+ int16x8_t *p = (int16x8_t *)data;
+ int16x8_t v = (int16x8_t) {
+ MATCHFINDER_INITVAL, MATCHFINDER_INITVAL, MATCHFINDER_INITVAL,
+ MATCHFINDER_INITVAL, MATCHFINDER_INITVAL, MATCHFINDER_INITVAL,
+ MATCHFINDER_INITVAL, MATCHFINDER_INITVAL,
+ };
+
+ STATIC_ASSERT(MATCHFINDER_MEM_ALIGNMENT % sizeof(*p) == 0);
+ STATIC_ASSERT(MATCHFINDER_SIZE_ALIGNMENT % (4 * sizeof(*p)) == 0);
+ STATIC_ASSERT(sizeof(mf_pos_t) == 2);
+
+ do {
+ p[0] = v;
+ p[1] = v;
+ p[2] = v;
+ p[3] = v;
+ p += 4;
+ size -= 4 * sizeof(*p);
+ } while (size != 0);
+}
+#define matchfinder_init matchfinder_init_neon
+
+static forceinline void
+matchfinder_rebase_neon(mf_pos_t *data, size_t size)
+{
+ int16x8_t *p = (int16x8_t *)data;
+ int16x8_t v = (int16x8_t) {
+ (u16)-MATCHFINDER_WINDOW_SIZE, (u16)-MATCHFINDER_WINDOW_SIZE,
+ (u16)-MATCHFINDER_WINDOW_SIZE, (u16)-MATCHFINDER_WINDOW_SIZE,
+ (u16)-MATCHFINDER_WINDOW_SIZE, (u16)-MATCHFINDER_WINDOW_SIZE,
+ (u16)-MATCHFINDER_WINDOW_SIZE, (u16)-MATCHFINDER_WINDOW_SIZE,
+ };
+
+ STATIC_ASSERT(MATCHFINDER_MEM_ALIGNMENT % sizeof(*p) == 0);
+ STATIC_ASSERT(MATCHFINDER_SIZE_ALIGNMENT % (4 * sizeof(*p)) == 0);
+ STATIC_ASSERT(sizeof(mf_pos_t) == 2);
+
+ do {
+ p[0] = vqaddq_s16(p[0], v);
+ p[1] = vqaddq_s16(p[1], v);
+ p[2] = vqaddq_s16(p[2], v);
+ p[3] = vqaddq_s16(p[3], v);
+ p += 4;
+ size -= 4 * sizeof(*p);
+ } while (size != 0);
+}
+#define matchfinder_rebase matchfinder_rebase_neon
+
+#endif /* __ARM_NEON */
+
+#endif /* LIB_ARM_MATCHFINDER_IMPL_H */
diff --git a/util/compress/libdeflate/lib/bt_matchfinder.h b/util/compress/libdeflate/lib/bt_matchfinder.h
new file mode 100644
index 000000000..a994a571c
--- /dev/null
+++ b/util/compress/libdeflate/lib/bt_matchfinder.h
@@ -0,0 +1,363 @@
+/*
+ * bt_matchfinder.h - Lempel-Ziv matchfinding with a hash table of binary trees
+ *
+ * Originally public domain; changes after 2016-09-07 are copyrighted.
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This is a Binary Trees (bt) based matchfinder.
+ *
+ * The main data structure is a hash table where each hash bucket contains a
+ * binary tree of sequences whose first 4 bytes share the same hash code. Each
+ * sequence is identified by its starting position in the input buffer. Each
+ * binary tree is always sorted such that each left child represents a sequence
+ * lexicographically lesser than its parent and each right child represents a
+ * sequence lexicographically greater than its parent.
+ *
+ * The algorithm processes the input buffer sequentially. At each byte
+ * position, the hash code of the first 4 bytes of the sequence beginning at
+ * that position (the sequence being matched against) is computed. This
+ * identifies the hash bucket to use for that position. Then, a new binary tree
+ * node is created to represent the current sequence. Then, in a single tree
+ * traversal, the hash bucket's binary tree is searched for matches and is
+ * re-rooted at the new node.
+ *
+ * Compared to the simpler algorithm that uses linked lists instead of binary
+ * trees (see hc_matchfinder.h), the binary tree version gains more information
+ * at each node visitation. Ideally, the binary tree version will examine only
+ * 'log(n)' nodes to find the same matches that the linked list version will
+ * find by examining 'n' nodes. In addition, the binary tree version can
+ * examine fewer bytes at each node by taking advantage of the common prefixes
+ * that result from the sort order, whereas the linked list version may have to
+ * examine up to the full length of the match at each node.
+ *
+ * However, it is not always best to use the binary tree version. It requires
+ * nearly twice as much memory as the linked list version, and it takes time to
+ * keep the binary trees sorted, even at positions where the compressor does not
+ * need matches. Generally, when doing fast compression on small buffers,
+ * binary trees are the wrong approach. They are best suited for thorough
+ * compression and/or large buffers.
+ *
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef LIB_BT_MATCHFINDER_H
+#define LIB_BT_MATCHFINDER_H
+
+#include "matchfinder_common.h"
+
+#define BT_MATCHFINDER_HASH3_ORDER 16
+#define BT_MATCHFINDER_HASH3_WAYS 2
+#define BT_MATCHFINDER_HASH4_ORDER 16
+
+#define BT_MATCHFINDER_TOTAL_HASH_SIZE \
+ (((1UL << BT_MATCHFINDER_HASH3_ORDER) * BT_MATCHFINDER_HASH3_WAYS + \
+ (1UL << BT_MATCHFINDER_HASH4_ORDER)) * sizeof(mf_pos_t))
+
+/* Representation of a match found by the bt_matchfinder */
+struct lz_match {
+
+ /* The number of bytes matched. */
+ u16 length;
+
+ /* The offset back from the current position that was matched. */
+ u16 offset;
+};
+
+struct bt_matchfinder {
+
+ /* The hash table for finding length 3 matches */
+ mf_pos_t hash3_tab[1UL << BT_MATCHFINDER_HASH3_ORDER][BT_MATCHFINDER_HASH3_WAYS];
+
+ /* The hash table which contains the roots of the binary trees for
+ * finding length 4+ matches */
+ mf_pos_t hash4_tab[1UL << BT_MATCHFINDER_HASH4_ORDER];
+
+ /* The child node references for the binary trees. The left and right
+ * children of the node for the sequence with position 'pos' are
+ * 'child_tab[pos * 2]' and 'child_tab[pos * 2 + 1]', respectively. */
+ mf_pos_t child_tab[2UL * MATCHFINDER_WINDOW_SIZE];
+
+}
+#ifdef _aligned_attribute
+_aligned_attribute(MATCHFINDER_MEM_ALIGNMENT)
+#endif
+;
+
+/* Prepare the matchfinder for a new input buffer. */
+static forceinline void
+bt_matchfinder_init(struct bt_matchfinder *mf)
+{
+ STATIC_ASSERT(BT_MATCHFINDER_TOTAL_HASH_SIZE %
+ MATCHFINDER_SIZE_ALIGNMENT == 0);
+
+ matchfinder_init((mf_pos_t *)mf, BT_MATCHFINDER_TOTAL_HASH_SIZE);
+}
+
+static forceinline void
+bt_matchfinder_slide_window(struct bt_matchfinder *mf)
+{
+ STATIC_ASSERT(sizeof(*mf) % MATCHFINDER_SIZE_ALIGNMENT == 0);
+
+ matchfinder_rebase((mf_pos_t *)mf, sizeof(*mf));
+}
+
+static forceinline mf_pos_t *
+bt_left_child(struct bt_matchfinder *mf, s32 node)
+{
+ return &mf->child_tab[2 * (node & (MATCHFINDER_WINDOW_SIZE - 1)) + 0];
+}
+
+static forceinline mf_pos_t *
+bt_right_child(struct bt_matchfinder *mf, s32 node)
+{
+ return &mf->child_tab[2 * (node & (MATCHFINDER_WINDOW_SIZE - 1)) + 1];
+}
+
+/* The minimum permissible value of 'max_len' for bt_matchfinder_get_matches()
+ * and bt_matchfinder_skip_position(). There must be sufficiently many bytes
+ * remaining to load a 32-bit integer from the *next* position. */
+#define BT_MATCHFINDER_REQUIRED_NBYTES 5
+
+/* Advance the binary tree matchfinder by one byte, optionally recording
+ * matches. @record_matches should be a compile-time constant. */
+static forceinline struct lz_match *
+bt_matchfinder_advance_one_byte(struct bt_matchfinder * const restrict mf,
+ const u8 * const restrict in_base,
+ const ptrdiff_t cur_pos,
+ const u32 max_len,
+ const u32 nice_len,
+ const u32 max_search_depth,
+ u32 * const restrict next_hashes,
+ u32 * const restrict best_len_ret,
+ struct lz_match * restrict lz_matchptr,
+ const bool record_matches)
+{
+ const u8 *in_next = in_base + cur_pos;
+ u32 depth_remaining = max_search_depth;
+ const s32 cutoff = cur_pos - MATCHFINDER_WINDOW_SIZE;
+ u32 next_hashseq;
+ u32 hash3;
+ u32 hash4;
+ s32 cur_node;
+#if BT_MATCHFINDER_HASH3_WAYS >= 2
+ s32 cur_node_2;
+#endif
+ const u8 *matchptr;
+ mf_pos_t *pending_lt_ptr, *pending_gt_ptr;
+ u32 best_lt_len, best_gt_len;
+ u32 len;
+ u32 best_len = 3;
+
+ STATIC_ASSERT(BT_MATCHFINDER_HASH3_WAYS >= 1 &&
+ BT_MATCHFINDER_HASH3_WAYS <= 2);
+
+ next_hashseq = get_unaligned_le32(in_next + 1);
+
+ hash3 = next_hashes[0];
+ hash4 = next_hashes[1];
+
+ next_hashes[0] = lz_hash(next_hashseq & 0xFFFFFF, BT_MATCHFINDER_HASH3_ORDER);
+ next_hashes[1] = lz_hash(next_hashseq, BT_MATCHFINDER_HASH4_ORDER);
+ prefetchw(&mf->hash3_tab[next_hashes[0]]);
+ prefetchw(&mf->hash4_tab[next_hashes[1]]);
+
+ cur_node = mf->hash3_tab[hash3][0];
+ mf->hash3_tab[hash3][0] = cur_pos;
+#if BT_MATCHFINDER_HASH3_WAYS >= 2
+ cur_node_2 = mf->hash3_tab[hash3][1];
+ mf->hash3_tab[hash3][1] = cur_node;
+#endif
+ if (record_matches && cur_node > cutoff) {
+ u32 seq3 = load_u24_unaligned(in_next);
+ if (seq3 == load_u24_unaligned(&in_base[cur_node])) {
+ lz_matchptr->length = 3;
+ lz_matchptr->offset = in_next - &in_base[cur_node];
+ lz_matchptr++;
+ }
+ #if BT_MATCHFINDER_HASH3_WAYS >= 2
+ else if (cur_node_2 > cutoff &&
+ seq3 == load_u24_unaligned(&in_base[cur_node_2]))
+ {
+ lz_matchptr->length = 3;
+ lz_matchptr->offset = in_next - &in_base[cur_node_2];
+ lz_matchptr++;
+ }
+ #endif
+ }
+
+ cur_node = mf->hash4_tab[hash4];
+ mf->hash4_tab[hash4] = cur_pos;
+
+ pending_lt_ptr = bt_left_child(mf, cur_pos);
+ pending_gt_ptr = bt_right_child(mf, cur_pos);
+
+ if (cur_node <= cutoff) {
+ *pending_lt_ptr = MATCHFINDER_INITVAL;
+ *pending_gt_ptr = MATCHFINDER_INITVAL;
+ *best_len_ret = best_len;
+ return lz_matchptr;
+ }
+
+ best_lt_len = 0;
+ best_gt_len = 0;
+ len = 0;
+
+ for (;;) {
+ matchptr = &in_base[cur_node];
+
+ if (matchptr[len] == in_next[len]) {
+ len = lz_extend(in_next, matchptr, len + 1, max_len);
+ if (!record_matches || len > best_len) {
+ if (record_matches) {
+ best_len = len;
+ lz_matchptr->length = len;
+ lz_matchptr->offset = in_next - matchptr;
+ lz_matchptr++;
+ }
+ if (len >= nice_len) {
+ *pending_lt_ptr = *bt_left_child(mf, cur_node);
+ *pending_gt_ptr = *bt_right_child(mf, cur_node);
+ *best_len_ret = best_len;
+ return lz_matchptr;
+ }
+ }
+ }
+
+ if (matchptr[len] < in_next[len]) {
+ *pending_lt_ptr = cur_node;
+ pending_lt_ptr = bt_right_child(mf, cur_node);
+ cur_node = *pending_lt_ptr;
+ best_lt_len = len;
+ if (best_gt_len < len)
+ len = best_gt_len;
+ } else {
+ *pending_gt_ptr = cur_node;
+ pending_gt_ptr = bt_left_child(mf, cur_node);
+ cur_node = *pending_gt_ptr;
+ best_gt_len = len;
+ if (best_lt_len < len)
+ len = best_lt_len;
+ }
+
+ if (cur_node <= cutoff || !--depth_remaining) {
+ *pending_lt_ptr = MATCHFINDER_INITVAL;
+ *pending_gt_ptr = MATCHFINDER_INITVAL;
+ *best_len_ret = best_len;
+ return lz_matchptr;
+ }
+ }
+}
+
+/*
+ * Retrieve a list of matches with the current position.
+ *
+ * @mf
+ * The matchfinder structure.
+ * @in_base
+ * Pointer to the next byte in the input buffer to process _at the last
+ * time bt_matchfinder_init() or bt_matchfinder_slide_window() was called_.
+ * @cur_pos
+ * The current position in the input buffer relative to @in_base (the
+ * position of the sequence being matched against).
+ * @max_len
+ * The maximum permissible match length at this position. Must be >=
+ * BT_MATCHFINDER_REQUIRED_NBYTES.
+ * @nice_len
+ * Stop searching if a match of at least this length is found.
+ * Must be <= @max_len.
+ * @max_search_depth
+ * Limit on the number of potential matches to consider. Must be >= 1.
+ * @next_hashes
+ * The precomputed hash codes for the sequence beginning at @in_next.
+ * These will be used and then updated with the precomputed hashcodes for
+ * the sequence beginning at @in_next + 1.
+ * @best_len_ret
+ * If a match of length >= 4 was found, then the length of the longest such
+ * match is written here; otherwise 3 is written here. (Note: this is
+ * redundant with the 'struct lz_match' array, but this is easier for the
+ * compiler to optimize when inlined and the caller immediately does a
+ * check against 'best_len'.)
+ * @lz_matchptr
+ * An array in which this function will record the matches. The recorded
+ * matches will be sorted by strictly increasing length and (non-strictly)
+ * increasing offset. The maximum number of matches that may be found is
+ * 'nice_len - 2'.
+ *
+ * The return value is a pointer to the next available slot in the @lz_matchptr
+ * array. (If no matches were found, this will be the same as @lz_matchptr.)
+ */
+static forceinline struct lz_match *
+bt_matchfinder_get_matches(struct bt_matchfinder *mf,
+ const u8 *in_base,
+ ptrdiff_t cur_pos,
+ u32 max_len,
+ u32 nice_len,
+ u32 max_search_depth,
+ u32 next_hashes[2],
+ u32 *best_len_ret,
+ struct lz_match *lz_matchptr)
+{
+ return bt_matchfinder_advance_one_byte(mf,
+ in_base,
+ cur_pos,
+ max_len,
+ nice_len,
+ max_search_depth,
+ next_hashes,
+ best_len_ret,
+ lz_matchptr,
+ true);
+}
+
+/*
+ * Advance the matchfinder, but don't record any matches.
+ *
+ * This is very similar to bt_matchfinder_get_matches() because both functions
+ * must do hashing and tree re-rooting.
+ */
+static forceinline void
+bt_matchfinder_skip_position(struct bt_matchfinder *mf,
+ const u8 *in_base,
+ ptrdiff_t cur_pos,
+ u32 nice_len,
+ u32 max_search_depth,
+ u32 next_hashes[2])
+{
+ u32 best_len;
+ bt_matchfinder_advance_one_byte(mf,
+ in_base,
+ cur_pos,
+ nice_len,
+ nice_len,
+ max_search_depth,
+ next_hashes,
+ &best_len,
+ NULL,
+ false);
+}
+
+#endif /* LIB_BT_MATCHFINDER_H */
diff --git a/util/compress/libdeflate/lib/cpu_features_common.h b/util/compress/libdeflate/lib/cpu_features_common.h
new file mode 100644
index 000000000..570b62dbb
--- /dev/null
+++ b/util/compress/libdeflate/lib/cpu_features_common.h
@@ -0,0 +1,88 @@
+/*
+ * cpu_features_common.h - code shared by all lib/$arch/cpu_features.c
+ *
+ * Copyright 2020 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef LIB_CPU_FEATURES_COMMON_H
+#define LIB_CPU_FEATURES_COMMON_H
+
+#if defined(TEST_SUPPORT__DO_NOT_USE) && !defined(FREESTANDING)
+# define _GNU_SOURCE 1 /* for strdup() and strtok_r() */
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+#include "lib_common.h"
+
+struct cpu_feature {
+ u32 bit;
+ const char *name;
+};
+
+#if defined(TEST_SUPPORT__DO_NOT_USE) && !defined(FREESTANDING)
+/* Disable any features that are listed in $LIBDEFLATE_DISABLE_CPU_FEATURES. */
+static inline void
+disable_cpu_features_for_testing(u32 *features,
+ const struct cpu_feature *feature_table,
+ size_t feature_table_length)
+{
+ char *env_value, *strbuf, *p, *saveptr = NULL;
+ size_t i;
+
+ env_value = getenv("LIBDEFLATE_DISABLE_CPU_FEATURES");
+ if (!env_value)
+ return;
+ strbuf = strdup(env_value);
+ if (!strbuf)
+ abort();
+ p = strtok_r(strbuf, ",", &saveptr);
+ while (p) {
+ for (i = 0; i < feature_table_length; i++) {
+ if (strcmp(p, feature_table[i].name) == 0) {
+ *features &= ~feature_table[i].bit;
+ break;
+ }
+ }
+ if (i == feature_table_length) {
+ fprintf(stderr,
+ "unrecognized feature in LIBDEFLATE_DISABLE_CPU_FEATURES: \"%s\"\n",
+ p);
+ abort();
+ }
+ p = strtok_r(NULL, ",", &saveptr);
+ }
+ free(strbuf);
+}
+#else /* TEST_SUPPORT__DO_NOT_USE */
+static inline void
+disable_cpu_features_for_testing(u32 *features,
+ const struct cpu_feature *feature_table,
+ size_t feature_table_length)
+{
+}
+#endif /* !TEST_SUPPORT__DO_NOT_USE */
+
+#endif /* LIB_CPU_FEATURES_COMMON_H */
diff --git a/util/compress/libdeflate/lib/crc32.c b/util/compress/libdeflate/lib/crc32.c
new file mode 100644
index 000000000..6adacc5dc
--- /dev/null
+++ b/util/compress/libdeflate/lib/crc32.c
@@ -0,0 +1,313 @@
+/*
+ * crc32.c - CRC-32 checksum algorithm for the gzip format
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * High-level description of CRC
+ * =============================
+ *
+ * Consider a bit sequence 'bits[1...len]'. Interpret 'bits' as the "message"
+ * polynomial M(x) with coefficients in GF(2) (the field of integers modulo 2),
+ * where the coefficient of 'x^i' is 'bits[len - i]'. Then, compute:
+ *
+ * R(x) = M(x)*x^n mod G(x)
+ *
+ * where G(x) is a selected "generator" polynomial of degree 'n'. The remainder
+ * R(x) is a polynomial of max degree 'n - 1'. The CRC of 'bits' is R(x)
+ * interpreted as a bitstring of length 'n'.
+ *
+ * CRC used in gzip
+ * ================
+ *
+ * In the gzip format (RFC 1952):
+ *
+ * - The bitstring to checksum is formed from the bytes of the uncompressed
+ * data by concatenating the bits from the bytes in order, proceeding
+ * from the low-order bit to the high-order bit within each byte.
+ *
+ * - The generator polynomial G(x) is: x^32 + x^26 + x^23 + x^22 + x^16 +
+ * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1.
+ * Consequently, the CRC length is 32 bits ("CRC-32").
+ *
+ * - The highest order 32 coefficients of M(x)*x^n are inverted.
+ *
+ * - All 32 coefficients of R(x) are inverted.
+ *
+ * The two inversions cause added leading and trailing zero bits to affect the
+ * resulting CRC, whereas with a regular CRC such bits would have no effect on
+ * the CRC.
+ *
+ * Computation and optimizations
+ * =============================
+ *
+ * We can compute R(x) through "long division", maintaining only 32 bits of
+ * state at any given time. Multiplication by 'x' can be implemented as
+ * right-shifting by 1 (assuming the polynomial<=>bitstring mapping where the
+ * highest order bit represents the coefficient of x^0), and both addition and
+ * subtraction can be implemented as bitwise exclusive OR (since we are working
+ * in GF(2)). Here is an unoptimized implementation:
+ *
+ * static u32 crc32_gzip(const u8 *buffer, size_t size)
+ * {
+ * u32 remainder = 0;
+ * const u32 divisor = 0xEDB88320;
+ *
+ * for (size_t i = 0; i < size * 8 + 32; i++) {
+ * int bit;
+ * u32 multiple;
+ *
+ * if (i < size * 8)
+ * bit = (buffer[i / 8] >> (i % 8)) & 1;
+ * else
+ * bit = 0; // one of the 32 appended 0 bits
+ *
+ * if (i < 32) // the first 32 bits are inverted
+ * bit ^= 1;
+ *
+ * if (remainder & 1)
+ * multiple = divisor;
+ * else
+ * multiple = 0;
+ *
+ * remainder >>= 1;
+ * remainder |= (u32)bit << 31;
+ * remainder ^= multiple;
+ * }
+ *
+ * return ~remainder;
+ * }
+ *
+ * In this implementation, the 32-bit integer 'remainder' maintains the
+ * remainder of the currently processed portion of the message (with 32 zero
+ * bits appended) when divided by the generator polynomial. 'remainder' is the
+ * representation of R(x), and 'divisor' is the representation of G(x) excluding
+ * the x^32 coefficient. For each bit to process, we multiply R(x) by 'x^1',
+ * then add 'x^0' if the new bit is a 1. If this causes R(x) to gain a nonzero
+ * x^32 term, then we subtract G(x) from R(x).
+ *
+ * We can speed this up by taking advantage of the fact that XOR is commutative
+ * and associative, so the order in which we combine the inputs into 'remainder'
+ * is unimportant. And since each message bit we add doesn't affect the choice
+ * of 'multiple' until 32 bits later, we need not actually add each message bit
+ * until that point:
+ *
+ * static u32 crc32_gzip(const u8 *buffer, size_t size)
+ * {
+ * u32 remainder = ~0;
+ * const u32 divisor = 0xEDB88320;
+ *
+ * for (size_t i = 0; i < size * 8; i++) {
+ * int bit;
+ * u32 multiple;
+ *
+ * bit = (buffer[i / 8] >> (i % 8)) & 1;
+ * remainder ^= bit;
+ * if (remainder & 1)
+ * multiple = divisor;
+ * else
+ * multiple = 0;
+ * remainder >>= 1;
+ * remainder ^= multiple;
+ * }
+ *
+ * return ~remainder;
+ * }
+ *
+ * With the above implementation we get the effect of 32 appended 0 bits for
+ * free; they never affect the choice of a divisor, nor would they change the
+ * value of 'remainder' if they were to be actually XOR'ed in. And by starting
+ * with a remainder of all 1 bits, we get the effect of complementing the first
+ * 32 message bits.
+ *
+ * The next optimization is to process the input in multi-bit units. Suppose
+ * that we insert the next 'n' message bits into the remainder. Then we get an
+ * intermediate remainder of length '32 + n' bits, and the CRC of the extra 'n'
+ * bits is the amount by which the low 32 bits of the remainder will change as a
+ * result of cancelling out those 'n' bits. Taking n=8 (one byte) and
+ * precomputing a table containing the CRC of each possible byte, we get
+ * crc32_slice1() defined below.
+ *
+ * As a further optimization, we could increase the multi-bit unit size to 16.
+ * However, that is inefficient because the table size explodes from 256 entries
+ * (1024 bytes) to 65536 entries (262144 bytes), which wastes memory and won't
+ * fit in L1 cache on typical processors.
+ *
+ * However, we can actually process 4 bytes at a time using 4 different tables
+ * with 256 entries each. Logically, we form a 64-bit intermediate remainder
+ * and cancel out the high 32 bits in 8-bit chunks. Bits 32-39 are cancelled
+ * out by the CRC of those bits, whereas bits 40-47 are be cancelled out by the
+ * CRC of those bits with 8 zero bits appended, and so on. This method is
+ * implemented in crc32_slice4(), defined below.
+ *
+ * In crc32_slice8(), this method is extended to 8 bytes at a time. The
+ * intermediate remainder (which we never actually store explicitly) is 96 bits.
+ *
+ * On CPUs that support fast carryless multiplication, CRCs can be computed even
+ * more quickly via "folding". See e.g. the x86 PCLMUL implementation.
+ */
+
+#include "lib_common.h"
+#include "libdeflate.h"
+
+typedef u32 (*crc32_func_t)(u32, const u8 *, size_t);
+
+/* Include architecture-specific implementations if available */
+#undef CRC32_SLICE1
+#undef CRC32_SLICE4
+#undef CRC32_SLICE8
+#undef DEFAULT_IMPL
+#undef DISPATCH
+#if defined(__arm__) || defined(__aarch64__)
+# include "arm/crc32_impl.h"
+#elif defined(__i386__) || defined(__x86_64__)
+# include "x86/crc32_impl.h"
+#endif
+
+/*
+ * Define a generic implementation (crc32_slice8()) if needed. crc32_slice1()
+ * may also be needed as a fallback for architecture-specific implementations.
+ */
+
+#ifndef DEFAULT_IMPL
+# define CRC32_SLICE8 1
+# define DEFAULT_IMPL crc32_slice8
+#endif
+
+#if defined(CRC32_SLICE1) || defined(CRC32_SLICE4) || defined(CRC32_SLICE8)
+#include "crc32_table.h"
+static forceinline u32
+crc32_update_byte(u32 remainder, u8 next_byte)
+{
+ return (remainder >> 8) ^ crc32_table[(u8)remainder ^ next_byte];
+}
+#endif
+
+#ifdef CRC32_SLICE1
+static u32
+crc32_slice1(u32 remainder, const u8 *buffer, size_t size)
+{
+ size_t i;
+
+ STATIC_ASSERT(ARRAY_LEN(crc32_table) >= 0x100);
+
+ for (i = 0; i < size; i++)
+ remainder = crc32_update_byte(remainder, buffer[i]);
+ return remainder;
+}
+#endif /* CRC32_SLICE1 */
+
+#ifdef CRC32_SLICE4
+static u32
+crc32_slice4(u32 remainder, const u8 *buffer, size_t size)
+{
+ const u8 *p = buffer;
+ const u8 *end = buffer + size;
+ const u8 *end32;
+
+ STATIC_ASSERT(ARRAY_LEN(crc32_table) >= 0x400);
+
+ for (; ((uintptr_t)p & 3) && p != end; p++)
+ remainder = crc32_update_byte(remainder, *p);
+
+ end32 = p + ((end - p) & ~3);
+ for (; p != end32; p += 4) {
+ u32 v = le32_bswap(*(const u32 *)p);
+ remainder =
+ crc32_table[0x300 + (u8)((remainder ^ v) >> 0)] ^
+ crc32_table[0x200 + (u8)((remainder ^ v) >> 8)] ^
+ crc32_table[0x100 + (u8)((remainder ^ v) >> 16)] ^
+ crc32_table[0x000 + (u8)((remainder ^ v) >> 24)];
+ }
+
+ for (; p != end; p++)
+ remainder = crc32_update_byte(remainder, *p);
+
+ return remainder;
+}
+#endif /* CRC32_SLICE4 */
+
+#ifdef CRC32_SLICE8
+static u32
+crc32_slice8(u32 remainder, const u8 *buffer, size_t size)
+{
+ const u8 *p = buffer;
+ const u8 *end = buffer + size;
+ const u8 *end64;
+
+ STATIC_ASSERT(ARRAY_LEN(crc32_table) >= 0x800);
+
+ for (; ((uintptr_t)p & 7) && p != end; p++)
+ remainder = crc32_update_byte(remainder, *p);
+
+ end64 = p + ((end - p) & ~7);
+ for (; p != end64; p += 8) {
+ u32 v1 = le32_bswap(*(const u32 *)(p + 0));
+ u32 v2 = le32_bswap(*(const u32 *)(p + 4));
+ remainder =
+ crc32_table[0x700 + (u8)((remainder ^ v1) >> 0)] ^
+ crc32_table[0x600 + (u8)((remainder ^ v1) >> 8)] ^
+ crc32_table[0x500 + (u8)((remainder ^ v1) >> 16)] ^
+ crc32_table[0x400 + (u8)((remainder ^ v1) >> 24)] ^
+ crc32_table[0x300 + (u8)(v2 >> 0)] ^
+ crc32_table[0x200 + (u8)(v2 >> 8)] ^
+ crc32_table[0x100 + (u8)(v2 >> 16)] ^
+ crc32_table[0x000 + (u8)(v2 >> 24)];
+ }
+
+ for (; p != end; p++)
+ remainder = crc32_update_byte(remainder, *p);
+
+ return remainder;
+}
+#endif /* CRC32_SLICE8 */
+
+#ifdef DISPATCH
+static u32 dispatch(u32, const u8 *, size_t);
+
+static volatile crc32_func_t crc32_impl = dispatch;
+
+/* Choose the fastest implementation at runtime */
+static u32 dispatch(u32 remainder, const u8 *buffer, size_t size)
+{
+ crc32_func_t f = arch_select_crc32_func();
+
+ if (f == NULL)
+ f = DEFAULT_IMPL;
+
+ crc32_impl = f;
+ return crc32_impl(remainder, buffer, size);
+}
+#else
+# define crc32_impl DEFAULT_IMPL /* only one implementation, use it */
+#endif
+
+LIBDEFLATEEXPORT u32 LIBDEFLATEAPI
+libdeflate_crc32(u32 remainder, const void *buffer, size_t size)
+{
+ if (buffer == NULL) /* return initial value */
+ return 0;
+ return ~crc32_impl(~remainder, buffer, size);
+}
diff --git a/util/compress/libdeflate/lib/crc32_table.h b/util/compress/libdeflate/lib/crc32_table.h
new file mode 100644
index 000000000..05421b982
--- /dev/null
+++ b/util/compress/libdeflate/lib/crc32_table.h
@@ -0,0 +1,526 @@
+/*
+ * crc32_table.h - data table to accelerate CRC-32 computation
+ *
+ * THIS FILE WAS AUTOMATICALLY GENERATED BY gen_crc32_table.c. DO NOT EDIT.
+ */
+
+#include <stdint.h>
+
+static const uint32_t crc32_table[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+#if defined(CRC32_SLICE4) || defined(CRC32_SLICE8)
+ 0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3,
+ 0x646cc504, 0x7d77f445, 0x565aa786, 0x4f4196c7,
+ 0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb,
+ 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, 0x87981ccf,
+ 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+ 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496,
+ 0x821b9859, 0x9b00a918, 0xb02dfadb, 0xa936cb9a,
+ 0xe6775d5d, 0xff6c6c1c, 0xd4413fdf, 0xcd5a0e9e,
+ 0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761,
+ 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+ 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69,
+ 0x39316bae, 0x202a5aef, 0x0b07092c, 0x121c386d,
+ 0xdf4636f3, 0xc65d07b2, 0xed705471, 0xf46b6530,
+ 0xbb2af3f7, 0xa231c2b6, 0x891c9175, 0x9007a034,
+ 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+ 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c,
+ 0xf0794f05, 0xe9627e44, 0xc24f2d87, 0xdb541cc6,
+ 0x94158a01, 0x8d0ebb40, 0xa623e883, 0xbf38d9c2,
+ 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, 0x138d96ce,
+ 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+ 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97,
+ 0xded79850, 0xc7cca911, 0xece1fad2, 0xf5facb93,
+ 0x7262d75c, 0x6b79e61d, 0x4054b5de, 0x594f849f,
+ 0x160e1258, 0x0f152319, 0x243870da, 0x3d23419b,
+ 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+ 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60,
+ 0xad24e1af, 0xb43fd0ee, 0x9f12832d, 0x8609b26c,
+ 0xc94824ab, 0xd05315ea, 0xfb7e4629, 0xe2657768,
+ 0x2f3f79f6, 0x362448b7, 0x1d091b74, 0x04122a35,
+ 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+ 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d,
+ 0x838a36fa, 0x9a9107bb, 0xb1bc5478, 0xa8a76539,
+ 0x3b83984b, 0x2298a90a, 0x09b5fac9, 0x10aecb88,
+ 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, 0x74c20e8c,
+ 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+ 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484,
+ 0x71418a1a, 0x685abb5b, 0x4377e898, 0x5a6cd9d9,
+ 0x152d4f1e, 0x0c367e5f, 0x271b2d9c, 0x3e001cdd,
+ 0xb9980012, 0xa0833153, 0x8bae6290, 0x92b553d1,
+ 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+ 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a,
+ 0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e,
+ 0x66de36e1, 0x7fc507a0, 0x54e85463, 0x4df36522,
+ 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, 0x299fa026,
+ 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+ 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f,
+ 0x2c1c24b0, 0x350715f1, 0x1e2a4632, 0x07317773,
+ 0x4870e1b4, 0x516bd0f5, 0x7a468336, 0x635db277,
+ 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d,
+ 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+ 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85,
+ 0x674f9842, 0x7e54a903, 0x5579fac0, 0x4c62cb81,
+ 0x8138c51f, 0x9823f45e, 0xb30ea79d, 0xaa1596dc,
+ 0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8,
+ 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+ 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0,
+ 0x5e7ef3ec, 0x4765c2ad, 0x6c48916e, 0x7553a02f,
+ 0x3a1236e8, 0x230907a9, 0x0824546a, 0x113f652b,
+ 0x96a779e4, 0x8fbc48a5, 0xa4911b66, 0xbd8a2a27,
+ 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+ 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e,
+ 0x70d024b9, 0x69cb15f8, 0x42e6463b, 0x5bfd777a,
+ 0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876,
+ 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, 0x9324fd72,
+ 0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59,
+ 0x0709a8dc, 0x06cbc2eb, 0x048d7cb2, 0x054f1685,
+ 0x0e1351b8, 0x0fd13b8f, 0x0d9785d6, 0x0c55efe1,
+ 0x091af964, 0x08d89353, 0x0a9e2d0a, 0x0b5c473d,
+ 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+ 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5,
+ 0x1235f2c8, 0x13f798ff, 0x11b126a6, 0x10734c91,
+ 0x153c5a14, 0x14fe3023, 0x16b88e7a, 0x177ae44d,
+ 0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9,
+ 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+ 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901,
+ 0x3157bf84, 0x3095d5b3, 0x32d36bea, 0x331101dd,
+ 0x246be590, 0x25a98fa7, 0x27ef31fe, 0x262d5bc9,
+ 0x23624d4c, 0x22a0277b, 0x20e69922, 0x2124f315,
+ 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+ 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad,
+ 0x709a8dc0, 0x7158e7f7, 0x731e59ae, 0x72dc3399,
+ 0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45,
+ 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, 0x7ccf6221,
+ 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+ 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9,
+ 0x6bb5866c, 0x6a77ec5b, 0x68315202, 0x69f33835,
+ 0x62af7f08, 0x636d153f, 0x612bab66, 0x60e9c151,
+ 0x65a6d7d4, 0x6464bde3, 0x662203ba, 0x67e0698d,
+ 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+ 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5,
+ 0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1,
+ 0x41cd3244, 0x400f5873, 0x4249e62a, 0x438b8c1d,
+ 0x54f16850, 0x55330267, 0x5775bc3e, 0x56b7d609,
+ 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+ 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1,
+ 0x5deb9134, 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d,
+ 0xe1351b80, 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9,
+ 0xe63cb35c, 0xe7fed96b, 0xe5b86732, 0xe47a0d05,
+ 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+ 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd,
+ 0xfd13b8f0, 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9,
+ 0xfa1a102c, 0xfbd87a1b, 0xf99ec442, 0xf85cae75,
+ 0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711,
+ 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+ 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339,
+ 0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5,
+ 0xd76b0cd8, 0xd6a966ef, 0xd4efd8b6, 0xd52db281,
+ 0xd062a404, 0xd1a0ce33, 0xd3e6706a, 0xd2241a5d,
+ 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+ 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895,
+ 0xcb4dafa8, 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1,
+ 0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d,
+ 0x91af9640, 0x906dfc77, 0x922b422e, 0x93e92819,
+ 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+ 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1,
+ 0x98b56f24, 0x99770513, 0x9b31bb4a, 0x9af3d17d,
+ 0x8d893530, 0x8c4b5f07, 0x8e0de15e, 0x8fcf8b69,
+ 0x8a809dec, 0x8b42f7db, 0x89044982, 0x88c623b5,
+ 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+ 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d,
+ 0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, 0xaba46ef9,
+ 0xaeeb787c, 0xaf29124b, 0xad6fac12, 0xacadc625,
+ 0xa7f18118, 0xa633eb2f, 0xa4755576, 0xa5b73f41,
+ 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+ 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89,
+ 0xb2cddb0c, 0xb30fb13b, 0xb1490f62, 0xb08b6555,
+ 0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31,
+ 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, 0xbe9834ed,
+ 0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee,
+ 0x8f629757, 0x37def032, 0x256b5fdc, 0x9dd738b9,
+ 0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701,
+ 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, 0x58631056,
+ 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+ 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26,
+ 0x95ad7f70, 0x2d111815, 0x3fa4b7fb, 0x8718d09e,
+ 0x1acfe827, 0xa2738f42, 0xb0c620ac, 0x087a47c9,
+ 0xa032af3e, 0x188ec85b, 0x0a3b67b5, 0xb28700d0,
+ 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+ 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f,
+ 0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68,
+ 0xf02bf8a1, 0x48979fc4, 0x5a22302a, 0xe29e574f,
+ 0x7f496ff6, 0xc7f50893, 0xd540a77d, 0x6dfcc018,
+ 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+ 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7,
+ 0x9b14583d, 0x23a83f58, 0x311d90b6, 0x89a1f7d3,
+ 0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, 0x06c36084,
+ 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, 0x4c15df3c,
+ 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+ 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c,
+ 0x446f98f5, 0xfcd3ff90, 0xee66507e, 0x56da371b,
+ 0x0eb9274d, 0xb6054028, 0xa4b0efc6, 0x1c0c88a3,
+ 0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4,
+ 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+ 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba,
+ 0xfe92dfec, 0x462eb889, 0x549b1767, 0xec277002,
+ 0x71f048bb, 0xc94c2fde, 0xdbf98030, 0x6345e755,
+ 0x6b3fa09c, 0xd383c7f9, 0xc1366817, 0x798a0f72,
+ 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+ 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d,
+ 0x21e91f24, 0x99557841, 0x8be0d7af, 0x335cb0ca,
+ 0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5,
+ 0x623b216c, 0xda874609, 0xc832e9e7, 0x708e8e82,
+ 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+ 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d,
+ 0xbd40e1a4, 0x05fc86c1, 0x1749292f, 0xaff54e4a,
+ 0x322276f3, 0x8a9e1196, 0x982bbe78, 0x2097d91d,
+ 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, 0x6a4166a5,
+ 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+ 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb,
+ 0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc,
+ 0x88df31ea, 0x3063568f, 0x22d6f961, 0x9a6a9e04,
+ 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, 0x15080953,
+ 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+ 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623,
+ 0xd8c66675, 0x607a0110, 0x72cfaefe, 0xca73c99b,
+ 0x57a4f122, 0xef189647, 0xfdad39a9, 0x45115ecc,
+ 0x764dee06, 0xcef18963, 0xdc44268d, 0x64f841e8,
+ 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+ 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907,
+ 0x3c9b51be, 0x842736db, 0x96929935, 0x2e2efe50,
+ 0x2654b999, 0x9ee8defc, 0x8c5d7112, 0x34e11677,
+ 0xa9362ece, 0x118a49ab, 0x033fe645, 0xbb838120,
+ 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+ 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf,
+ 0xd67f4138, 0x6ec3265d, 0x7c7689b3, 0xc4caeed6,
+ 0x591dd66f, 0xe1a1b10a, 0xf3141ee4, 0x4ba87981,
+ 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, 0x017ec639,
+ 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+ 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949,
+ 0x090481f0, 0xb1b8e695, 0xa30d497b, 0x1bb12e1e,
+ 0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6,
+ 0xccb0a91f, 0x740cce7a, 0x66b96194, 0xde0506f1,
+#endif /* CRC32_SLICE4 || CRC32_SLICE8 */
+#if defined(CRC32_SLICE8)
+ 0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0,
+ 0xf580a6c0, 0xc8e08f70, 0x8f40f5a0, 0xb220dc10,
+ 0x30704bc1, 0x0d106271, 0x4ab018a1, 0x77d03111,
+ 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, 0x825097d1,
+ 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
+ 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92,
+ 0x5090dc43, 0x6df0f5f3, 0x2a508f23, 0x1730a693,
+ 0xa5107a83, 0x98705333, 0xdfd029e3, 0xe2b00053,
+ 0xc1c12f04, 0xfca106b4, 0xbb017c64, 0x866155d4,
+ 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
+ 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15,
+ 0x0431c205, 0x3951ebb5, 0x7ef19165, 0x4391b8d5,
+ 0xa121b886, 0x9c419136, 0xdbe1ebe6, 0xe681c256,
+ 0x54a11e46, 0x69c137f6, 0x2e614d26, 0x13016496,
+ 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
+ 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57,
+ 0x58f35849, 0x659371f9, 0x22330b29, 0x1f532299,
+ 0xad73fe89, 0x9013d739, 0xd7b3ade9, 0xead38459,
+ 0x68831388, 0x55e33a38, 0x124340e8, 0x2f236958,
+ 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
+ 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b,
+ 0xcd93690b, 0xf0f340bb, 0xb7533a6b, 0x8a3313db,
+ 0x0863840a, 0x3503adba, 0x72a3d76a, 0x4fc3feda,
+ 0xfde322ca, 0xc0830b7a, 0x872371aa, 0xba43581a,
+ 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
+ 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d,
+ 0xa9423c8c, 0x9422153c, 0xd3826fec, 0xeee2465c,
+ 0x5cc29a4c, 0x61a2b3fc, 0x2602c92c, 0x1b62e09c,
+ 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, 0xbe729a1f,
+ 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
+ 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de,
+ 0x3c220dce, 0x0142247e, 0x46e25eae, 0x7b82771e,
+ 0xb1e6b092, 0x8c869922, 0xcb26e3f2, 0xf646ca42,
+ 0x44661652, 0x79063fe2, 0x3ea64532, 0x03c66c82,
+ 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
+ 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743,
+ 0xd1062710, 0xec660ea0, 0xabc67470, 0x96a65dc0,
+ 0x248681d0, 0x19e6a860, 0x5e46d2b0, 0x6326fb00,
+ 0xe1766cd1, 0xdc164561, 0x9bb63fb1, 0xa6d61601,
+ 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
+ 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546,
+ 0x85a73956, 0xb8c710e6, 0xff676a36, 0xc2074386,
+ 0x4057d457, 0x7d37fde7, 0x3a978737, 0x07f7ae87,
+ 0xb5d77297, 0x88b75b27, 0xcf1721f7, 0xf2770847,
+ 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
+ 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404,
+ 0x20b743d5, 0x1dd76a65, 0x5a7710b5, 0x67173905,
+ 0xd537e515, 0xe857cca5, 0xaff7b675, 0x92979fc5,
+ 0xe915e8db, 0xd475c16b, 0x93d5bbbb, 0xaeb5920b,
+ 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
+ 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca,
+ 0x2ce505da, 0x11852c6a, 0x562556ba, 0x6b457f0a,
+ 0x89f57f59, 0xb49556e9, 0xf3352c39, 0xce550589,
+ 0x7c75d999, 0x4115f029, 0x06b58af9, 0x3bd5a349,
+ 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
+ 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888,
+ 0x28d4c7df, 0x15b4ee6f, 0x521494bf, 0x6f74bd0f,
+ 0xdd54611f, 0xe03448af, 0xa794327f, 0x9af41bcf,
+ 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, 0x5f04f6ce,
+ 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
+ 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d,
+ 0xbdb4f69d, 0x80d4df2d, 0xc774a5fd, 0xfa148c4d,
+ 0x78441b9c, 0x4524322c, 0x028448fc, 0x3fe4614c,
+ 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, 0xca64c78c,
+ 0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae,
+ 0x9b914216, 0x50cd91b3, 0xd659e31d, 0x1d0530b8,
+ 0xec53826d, 0x270f51c8, 0xa19b2366, 0x6ac7f0c3,
+ 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, 0xf156b2d5,
+ 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
+ 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223,
+ 0xef8580f6, 0x24d95353, 0xa24d21fd, 0x6911f258,
+ 0x7414c2e0, 0xbf481145, 0x39dc63eb, 0xf280b04e,
+ 0x07ac0536, 0xccf0d693, 0x4a64a43d, 0x81387798,
+ 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
+ 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5,
+ 0x706ec54d, 0xbb3216e8, 0x3da66446, 0xf6fab7e3,
+ 0x047a07ad, 0xcf26d408, 0x49b2a6a6, 0x82ee7503,
+ 0x9feb45bb, 0x54b7961e, 0xd223e4b0, 0x197f3715,
+ 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
+ 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578,
+ 0x0f580a6c, 0xc404d9c9, 0x4290ab67, 0x89cc78c2,
+ 0x94c9487a, 0x5f959bdf, 0xd901e971, 0x125d3ad4,
+ 0xe30b8801, 0x28575ba4, 0xaec3290a, 0x659ffaaf,
+ 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
+ 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59,
+ 0x971f4ae1, 0x5c439944, 0xdad7ebea, 0x118b384f,
+ 0xe0dd8a9a, 0x2b81593f, 0xad152b91, 0x6649f834,
+ 0x7b4cc88c, 0xb0101b29, 0x36846987, 0xfdd8ba22,
+ 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
+ 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2,
+ 0xe4a78d37, 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99,
+ 0x7f36cf21, 0xb46a1c84, 0x32fe6e2a, 0xf9a2bd8f,
+ 0x0b220dc1, 0xc07ede64, 0x46eaacca, 0x8db67f6f,
+ 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
+ 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02,
+ 0x7ce0cdba, 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14,
+ 0x1eb014d8, 0xd5ecc77d, 0x5378b5d3, 0x98246676,
+ 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, 0x03b52460,
+ 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
+ 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d,
+ 0x1d661643, 0xd63ac5e6, 0x50aeb748, 0x9bf264ed,
+ 0x86f75455, 0x4dab87f0, 0xcb3ff55e, 0x006326fb,
+ 0xf135942e, 0x3a69478b, 0xbcfd3525, 0x77a1e680,
+ 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
+ 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340,
+ 0x828d53f8, 0x49d1805d, 0xcf45f2f3, 0x04192156,
+ 0xf54f9383, 0x3e134026, 0xb8873288, 0x73dbe12d,
+ 0x6eded195, 0xa5820230, 0x2316709e, 0xe84aa33b,
+ 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
+ 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd,
+ 0xf6999118, 0x3dc542bd, 0xbb513013, 0x700de3b6,
+ 0x6d08d30e, 0xa65400ab, 0x20c07205, 0xeb9ca1a0,
+ 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, 0x977c6c1a,
+ 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
+ 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77,
+ 0x662adecf, 0xad760d6a, 0x2be27fc4, 0xe0beac61,
+ 0x123e1c2f, 0xd962cf8a, 0x5ff6bd24, 0x94aa6e81,
+ 0x89af5e39, 0x42f38d9c, 0xc467ff32, 0x0f3b2c97,
+ 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
+ 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa,
+ 0x16441b82, 0xdd18c827, 0x5b8cba89, 0x90d0692c,
+ 0x8dd55994, 0x46898a31, 0xc01df89f, 0x0b412b3a,
+ 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, 0x7c83eb41,
+ 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
+ 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7,
+ 0x8e035b0f, 0x455f88aa, 0xc3cbfa04, 0x089729a1,
+ 0xf9c19b74, 0x329d48d1, 0xb4093a7f, 0x7f55e9da,
+ 0x6250d962, 0xa90c0ac7, 0x2f987869, 0xe4c4abcc,
+ 0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d,
+ 0xf44f2413, 0x52382fa7, 0x63d0353a, 0xc5a73e8e,
+ 0x33ef4e67, 0x959845d3, 0xa4705f4e, 0x020754fa,
+ 0xc7a06a74, 0x61d761c0, 0x503f7b5d, 0xf64870e9,
+ 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
+ 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240,
+ 0x5431d2a9, 0xf246d91d, 0xc3aec380, 0x65d9c834,
+ 0xa07ef6ba, 0x0609fd0e, 0x37e1e793, 0x9196ec27,
+ 0xcfbd399c, 0x69ca3228, 0x582228b5, 0xfe552301,
+ 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
+ 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66,
+ 0x081d53e8, 0xae6a585c, 0x9f8242c1, 0x39f54975,
+ 0xa863a552, 0x0e14aee6, 0x3ffcb47b, 0x998bbfcf,
+ 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, 0x6dc49bdc,
+ 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
+ 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb,
+ 0x440b7579, 0xe27c7ecd, 0xd3946450, 0x75e36fe4,
+ 0xb044516a, 0x16335ade, 0x27db4043, 0x81ac4bf7,
+ 0x77e43b1e, 0xd19330aa, 0xe07b2a37, 0x460c2183,
+ 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
+ 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a,
+ 0xd79acda4, 0x71edc610, 0x4005dc8d, 0xe672d739,
+ 0x103aa7d0, 0xb64dac64, 0x87a5b6f9, 0x21d2bd4d,
+ 0xe47583c3, 0x42028877, 0x73ea92ea, 0xd59d995e,
+ 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
+ 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b,
+ 0xb8590282, 0x1e2e0936, 0x2fc613ab, 0x89b1181f,
+ 0x4c162691, 0xea612d25, 0xdb8937b8, 0x7dfe3c0c,
+ 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, 0xdd80cab6,
+ 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
+ 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1,
+ 0x2bc8ba5f, 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2,
+ 0x8816eaf2, 0x2e61e146, 0x1f89fbdb, 0xb9fef06f,
+ 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, 0x4db1d47c,
+ 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
+ 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b,
+ 0xefc8763c, 0x49bf7d88, 0x78576715, 0xde206ca1,
+ 0x1b87522f, 0xbdf0599b, 0x8c184306, 0x2a6f48b2,
+ 0xdc27385b, 0x7a5033ef, 0x4bb82972, 0xedcf22c6,
+ 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
+ 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3,
+ 0xb3e4f77d, 0x1593fcc9, 0x247be654, 0x820cede0,
+ 0x74449d09, 0xd23396bd, 0xe3db8c20, 0x45ac8794,
+ 0x800bb91a, 0x267cb2ae, 0x1794a833, 0xb1e3a387,
+ 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
+ 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e,
+ 0x139a01c7, 0xb5ed0a73, 0x840510ee, 0x22721b5a,
+ 0xe7d525d4, 0x41a22e60, 0x704a34fd, 0xd63d3f49,
+ 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, 0xfdf58516,
+ 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
+ 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71,
+ 0x0bbdf5ff, 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62,
+ 0xabc30345, 0x0db408f1, 0x3c5c126c, 0x9a2b19d8,
+ 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, 0x6e643dcb,
+ 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
+ 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac,
+ 0x03a0a617, 0xa5d7ada3, 0x943fb73e, 0x3248bc8a,
+ 0xf7ef8204, 0x519889b0, 0x6070932d, 0xc6079899,
+ 0x304fe870, 0x9638e3c4, 0xa7d0f959, 0x01a7f2ed,
+ 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
+ 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044,
+ 0x90311eca, 0x3646157e, 0x07ae0fe3, 0xa1d90457,
+ 0x579174be, 0xf1e67f0a, 0xc00e6597, 0x66796e23,
+ 0xa3de50ad, 0x05a95b19, 0x34414184, 0x92364a30,
+ 0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3,
+ 0x844a0efa, 0x48e00e64, 0xc66f0987, 0x0ac50919,
+ 0xd3e51bb5, 0x1f4f1b2b, 0x91c01cc8, 0x5d6a1c56,
+ 0x57af154f, 0x9b0515d1, 0x158a1232, 0xd92012ac,
+ 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
+ 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832,
+ 0xaf5e2a9e, 0x63f42a00, 0xed7b2de3, 0x21d12d7d,
+ 0x2b142464, 0xe7be24fa, 0x69312319, 0xa59b2387,
+ 0xf9766256, 0x35dc62c8, 0xbb53652b, 0x77f965b5,
+ 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
+ 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00,
+ 0xaed97719, 0x62737787, 0xecfc7064, 0x205670fa,
+ 0x85cd537d, 0x496753e3, 0xc7e85400, 0x0b42549e,
+ 0x01875d87, 0xcd2d5d19, 0x43a25afa, 0x8f085a64,
+ 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
+ 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1,
+ 0x299dc2ed, 0xe537c273, 0x6bb8c590, 0xa712c50e,
+ 0xadd7cc17, 0x617dcc89, 0xeff2cb6a, 0x2358cbf4,
+ 0xfa78d958, 0x36d2d9c6, 0xb85dde25, 0x74f7debb,
+ 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
+ 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425,
+ 0xd16cfd3c, 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf,
+ 0x86c3e873, 0x4a69e8ed, 0xc4e6ef0e, 0x084cef90,
+ 0x0289e689, 0xce23e617, 0x40ace1f4, 0x8c06e16a,
+ 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
+ 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2,
+ 0x030ebb0e, 0xcfa4bb90, 0x412bbc73, 0x8d81bced,
+ 0x8744b5f4, 0x4beeb56a, 0xc561b289, 0x09cbb217,
+ 0xac509190, 0x60fa910e, 0xee7596ed, 0x22df9673,
+ 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
+ 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6,
+ 0xfbff84df, 0x37558441, 0xb9da83a2, 0x7570833c,
+ 0x533b85da, 0x9f918544, 0x111e82a7, 0xddb48239,
+ 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, 0x59fe8cc3,
+ 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
+ 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776,
+ 0x2f80b4f1, 0xe32ab46f, 0x6da5b38c, 0xa10fb312,
+ 0xabcaba0b, 0x6760ba95, 0xe9efbd76, 0x2545bde8,
+ 0xfc65af44, 0x30cfafda, 0xbe40a839, 0x72eaa8a7,
+ 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
+ 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f,
+ 0x2e07e976, 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95,
+ 0x79a8fc39, 0xb502fca7, 0x3b8dfb44, 0xf727fbda,
+ 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, 0x736df520,
+ 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
+ 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe,
+ 0x0513cd12, 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1,
+ 0x8159c3e8, 0x4df3c376, 0xc37cc495, 0x0fd6c40b,
+ 0x7aa64737, 0xb60c47a9, 0x3883404a, 0xf42940d4,
+ 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
+ 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61,
+ 0x2d095278, 0xe1a352e6, 0x6f2c5505, 0xa386559b,
+ 0x061d761c, 0xcab77682, 0x44387161, 0x889271ff,
+ 0x825778e6, 0x4efd7878, 0xc0727f9b, 0x0cd87f05,
+ 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
+ 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0,
+ 0x83d02561, 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282,
+ 0x079a2b9b, 0xcb302b05, 0x45bf2ce6, 0x89152c78,
+ 0x50353ed4, 0x9c9f3e4a, 0x121039a9, 0xdeba3937,
+ 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
+ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9,
+ 0x7b211ab0, 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53,
+ 0x2c8e0fff, 0xe0240f61, 0x6eab0882, 0xa201081c,
+ 0xa8c40105, 0x646e019b, 0xeae10678, 0x264b06e6,
+#endif /* CRC32_SLICE8 */
+};
diff --git a/util/compress/libdeflate/lib/crc32_vec_template.h b/util/compress/libdeflate/lib/crc32_vec_template.h
new file mode 100644
index 000000000..9a2ad5bde
--- /dev/null
+++ b/util/compress/libdeflate/lib/crc32_vec_template.h
@@ -0,0 +1,61 @@
+/*
+ * crc32_vec_template.h - template for vectorized CRC-32 implementations
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define CRC32_SLICE1 1
+static u32 crc32_slice1(u32, const u8 *, size_t);
+
+/*
+ * Template for vectorized CRC-32 implementations.
+ *
+ * Note: on unaligned ends of the buffer, we fall back to crc32_slice1() instead
+ * of crc32_slice8() because only a few bytes need to be processed, so a smaller
+ * table is preferable.
+ */
+static u32 ATTRIBUTES
+FUNCNAME(u32 remainder, const u8 *p, size_t size)
+{
+ if ((uintptr_t)p % IMPL_ALIGNMENT) {
+ size_t n = MIN(size, -(uintptr_t)p % IMPL_ALIGNMENT);
+
+ remainder = crc32_slice1(remainder, p, n);
+ p += n;
+ size -= n;
+ }
+ if (size >= IMPL_SEGMENT_SIZE) {
+ remainder = FUNCNAME_ALIGNED(remainder, (const void *)p,
+ size / IMPL_SEGMENT_SIZE);
+ p += size - (size % IMPL_SEGMENT_SIZE);
+ size %= IMPL_SEGMENT_SIZE;
+ }
+ return crc32_slice1(remainder, p, size);
+}
+
+#undef FUNCNAME
+#undef FUNCNAME_ALIGNED
+#undef ATTRIBUTES
+#undef IMPL_ALIGNMENT
+#undef IMPL_SEGMENT_SIZE
diff --git a/util/compress/libdeflate/lib/decompress_template.h b/util/compress/libdeflate/lib/decompress_template.h
new file mode 100644
index 000000000..c6bcf9f52
--- /dev/null
+++ b/util/compress/libdeflate/lib/decompress_template.h
@@ -0,0 +1,421 @@
+/*
+ * decompress_template.h
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This is the actual DEFLATE decompression routine, lifted out of
+ * deflate_decompress.c so that it can be compiled multiple times with different
+ * target instruction sets.
+ */
+
+static enum libdeflate_result ATTRIBUTES
+FUNCNAME(struct libdeflate_decompressor * restrict d,
+ const void * restrict in, size_t in_nbytes,
+ void * restrict out, size_t out_nbytes_avail,
+ size_t *actual_in_nbytes_ret, size_t *actual_out_nbytes_ret)
+{
+ u8 *out_next = out;
+ u8 * const out_end = out_next + out_nbytes_avail;
+ const u8 *in_next = in;
+ const u8 * const in_end = in_next + in_nbytes;
+ bitbuf_t bitbuf = 0;
+ unsigned bitsleft = 0;
+ size_t overrun_count = 0;
+ unsigned i;
+ unsigned is_final_block;
+ unsigned block_type;
+ u16 len;
+ u16 nlen;
+ unsigned num_litlen_syms;
+ unsigned num_offset_syms;
+ u16 tmp16;
+ u32 tmp32;
+
+next_block:
+ /* Starting to read the next block. */
+ ;
+
+ STATIC_ASSERT(CAN_ENSURE(1 + 2 + 5 + 5 + 4));
+ ENSURE_BITS(1 + 2 + 5 + 5 + 4);
+
+ /* BFINAL: 1 bit */
+ is_final_block = POP_BITS(1);
+
+ /* BTYPE: 2 bits */
+ block_type = POP_BITS(2);
+
+ if (block_type == DEFLATE_BLOCKTYPE_DYNAMIC_HUFFMAN) {
+
+ /* Dynamic Huffman block. */
+
+ /* The order in which precode lengths are stored. */
+ static const u8 deflate_precode_lens_permutation[DEFLATE_NUM_PRECODE_SYMS] = {
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+ unsigned num_explicit_precode_lens;
+
+ /* Read the codeword length counts. */
+
+ STATIC_ASSERT(DEFLATE_NUM_LITLEN_SYMS == ((1 << 5) - 1) + 257);
+ num_litlen_syms = POP_BITS(5) + 257;
+
+ STATIC_ASSERT(DEFLATE_NUM_OFFSET_SYMS == ((1 << 5) - 1) + 1);
+ num_offset_syms = POP_BITS(5) + 1;
+
+ STATIC_ASSERT(DEFLATE_NUM_PRECODE_SYMS == ((1 << 4) - 1) + 4);
+ num_explicit_precode_lens = POP_BITS(4) + 4;
+
+ d->static_codes_loaded = false;
+
+ /* Read the precode codeword lengths. */
+ STATIC_ASSERT(DEFLATE_MAX_PRE_CODEWORD_LEN == (1 << 3) - 1);
+ for (i = 0; i < num_explicit_precode_lens; i++) {
+ ENSURE_BITS(3);
+ d->u.precode_lens[deflate_precode_lens_permutation[i]] = POP_BITS(3);
+ }
+
+ for (; i < DEFLATE_NUM_PRECODE_SYMS; i++)
+ d->u.precode_lens[deflate_precode_lens_permutation[i]] = 0;
+
+ /* Build the decode table for the precode. */
+ SAFETY_CHECK(build_precode_decode_table(d));
+
+ /* Expand the literal/length and offset codeword lengths. */
+ for (i = 0; i < num_litlen_syms + num_offset_syms; ) {
+ u32 entry;
+ unsigned presym;
+ u8 rep_val;
+ unsigned rep_count;
+
+ ENSURE_BITS(DEFLATE_MAX_PRE_CODEWORD_LEN + 7);
+
+ /* (The code below assumes that the precode decode table
+ * does not have any subtables.) */
+ STATIC_ASSERT(PRECODE_TABLEBITS == DEFLATE_MAX_PRE_CODEWORD_LEN);
+
+ /* Read the next precode symbol. */
+ entry = d->u.l.precode_decode_table[BITS(DEFLATE_MAX_PRE_CODEWORD_LEN)];
+ REMOVE_BITS(entry & HUFFDEC_LENGTH_MASK);
+ presym = entry >> HUFFDEC_RESULT_SHIFT;
+
+ if (presym < 16) {
+ /* Explicit codeword length */
+ d->u.l.lens[i++] = presym;
+ continue;
+ }
+
+ /* Run-length encoded codeword lengths */
+
+ /* Note: we don't need verify that the repeat count
+ * doesn't overflow the number of elements, since we
+ * have enough extra spaces to allow for the worst-case
+ * overflow (138 zeroes when only 1 length was
+ * remaining).
+ *
+ * In the case of the small repeat counts (presyms 16
+ * and 17), it is fastest to always write the maximum
+ * number of entries. That gets rid of branches that
+ * would otherwise be required.
+ *
+ * It is not just because of the numerical order that
+ * our checks go in the order 'presym < 16', 'presym ==
+ * 16', and 'presym == 17'. For typical data this is
+ * ordered from most frequent to least frequent case.
+ */
+ STATIC_ASSERT(DEFLATE_MAX_LENS_OVERRUN == 138 - 1);
+
+ if (presym == 16) {
+ /* Repeat the previous length 3 - 6 times */
+ SAFETY_CHECK(i != 0);
+ rep_val = d->u.l.lens[i - 1];
+ STATIC_ASSERT(3 + ((1 << 2) - 1) == 6);
+ rep_count = 3 + POP_BITS(2);
+ d->u.l.lens[i + 0] = rep_val;
+ d->u.l.lens[i + 1] = rep_val;
+ d->u.l.lens[i + 2] = rep_val;
+ d->u.l.lens[i + 3] = rep_val;
+ d->u.l.lens[i + 4] = rep_val;
+ d->u.l.lens[i + 5] = rep_val;
+ i += rep_count;
+ } else if (presym == 17) {
+ /* Repeat zero 3 - 10 times */
+ STATIC_ASSERT(3 + ((1 << 3) - 1) == 10);
+ rep_count = 3 + POP_BITS(3);
+ d->u.l.lens[i + 0] = 0;
+ d->u.l.lens[i + 1] = 0;
+ d->u.l.lens[i + 2] = 0;
+ d->u.l.lens[i + 3] = 0;
+ d->u.l.lens[i + 4] = 0;
+ d->u.l.lens[i + 5] = 0;
+ d->u.l.lens[i + 6] = 0;
+ d->u.l.lens[i + 7] = 0;
+ d->u.l.lens[i + 8] = 0;
+ d->u.l.lens[i + 9] = 0;
+ i += rep_count;
+ } else {
+ /* Repeat zero 11 - 138 times */
+ STATIC_ASSERT(11 + ((1 << 7) - 1) == 138);
+ rep_count = 11 + POP_BITS(7);
+ memset(&d->u.l.lens[i], 0,
+ rep_count * sizeof(d->u.l.lens[i]));
+ i += rep_count;
+ }
+ }
+ } else if (block_type == DEFLATE_BLOCKTYPE_UNCOMPRESSED) {
+
+ /* Uncompressed block: copy 'len' bytes literally from the input
+ * buffer to the output buffer. */
+
+ ALIGN_INPUT();
+
+ SAFETY_CHECK(in_end - in_next >= 4);
+
+ len = READ_U16();
+ nlen = READ_U16();
+
+ SAFETY_CHECK(len == (u16)~nlen);
+ if (unlikely(len > out_end - out_next))
+ return LIBDEFLATE_INSUFFICIENT_SPACE;
+ SAFETY_CHECK(len <= in_end - in_next);
+
+ memcpy(out_next, in_next, len);
+ in_next += len;
+ out_next += len;
+
+ goto block_done;
+
+ } else {
+ SAFETY_CHECK(block_type == DEFLATE_BLOCKTYPE_STATIC_HUFFMAN);
+
+ /*
+ * Static Huffman block: build the decode tables for the static
+ * codes. Skip doing so if the tables are already set up from
+ * an earlier static block; this speeds up decompression of
+ * degenerate input of many empty or very short static blocks.
+ *
+ * Afterwards, the remainder is the same as decompressing a
+ * dynamic Huffman block.
+ */
+
+ if (d->static_codes_loaded)
+ goto have_decode_tables;
+
+ d->static_codes_loaded = true;
+
+ STATIC_ASSERT(DEFLATE_NUM_LITLEN_SYMS == 288);
+ STATIC_ASSERT(DEFLATE_NUM_OFFSET_SYMS == 32);
+
+ for (i = 0; i < 144; i++)
+ d->u.l.lens[i] = 8;
+ for (; i < 256; i++)
+ d->u.l.lens[i] = 9;
+ for (; i < 280; i++)
+ d->u.l.lens[i] = 7;
+ for (; i < 288; i++)
+ d->u.l.lens[i] = 8;
+
+ for (; i < 288 + 32; i++)
+ d->u.l.lens[i] = 5;
+
+ num_litlen_syms = 288;
+ num_offset_syms = 32;
+ }
+
+ /* Decompressing a Huffman block (either dynamic or static) */
+
+ SAFETY_CHECK(build_offset_decode_table(d, num_litlen_syms, num_offset_syms));
+ SAFETY_CHECK(build_litlen_decode_table(d, num_litlen_syms, num_offset_syms));
+have_decode_tables:
+
+ /* The main DEFLATE decode loop */
+ for (;;) {
+ u32 entry;
+ u32 length;
+ u32 offset;
+ const u8 *src;
+ u8 *dst;
+
+ /* Decode a litlen symbol. */
+ ENSURE_BITS(DEFLATE_MAX_LITLEN_CODEWORD_LEN);
+ entry = d->u.litlen_decode_table[BITS(LITLEN_TABLEBITS)];
+ if (entry & HUFFDEC_SUBTABLE_POINTER) {
+ /* Litlen subtable required (uncommon case) */
+ REMOVE_BITS(LITLEN_TABLEBITS);
+ entry = d->u.litlen_decode_table[
+ ((entry >> HUFFDEC_RESULT_SHIFT) & 0xFFFF) +
+ BITS(entry & HUFFDEC_LENGTH_MASK)];
+ }
+ REMOVE_BITS(entry & HUFFDEC_LENGTH_MASK);
+ if (entry & HUFFDEC_LITERAL) {
+ /* Literal */
+ if (unlikely(out_next == out_end))
+ return LIBDEFLATE_INSUFFICIENT_SPACE;
+ *out_next++ = (u8)(entry >> HUFFDEC_RESULT_SHIFT);
+ continue;
+ }
+
+ /* Match or end-of-block */
+
+ entry >>= HUFFDEC_RESULT_SHIFT;
+ ENSURE_BITS(MAX_ENSURE);
+
+ /* Pop the extra length bits and add them to the length base to
+ * produce the full length. */
+ length = (entry >> HUFFDEC_LENGTH_BASE_SHIFT) +
+ POP_BITS(entry & HUFFDEC_EXTRA_LENGTH_BITS_MASK);
+
+ /* The match destination must not end after the end of the
+ * output buffer. For efficiency, combine this check with the
+ * end-of-block check. We're using 0 for the special
+ * end-of-block length, so subtract 1 and it turn it into
+ * SIZE_MAX. */
+ STATIC_ASSERT(HUFFDEC_END_OF_BLOCK_LENGTH == 0);
+ if (unlikely((size_t)length - 1 >= out_end - out_next)) {
+ if (unlikely(length != HUFFDEC_END_OF_BLOCK_LENGTH))
+ return LIBDEFLATE_INSUFFICIENT_SPACE;
+ goto block_done;
+ }
+
+ /* Decode the match offset. */
+
+ entry = d->offset_decode_table[BITS(OFFSET_TABLEBITS)];
+ if (entry & HUFFDEC_SUBTABLE_POINTER) {
+ /* Offset subtable required (uncommon case) */
+ REMOVE_BITS(OFFSET_TABLEBITS);
+ entry = d->offset_decode_table[
+ ((entry >> HUFFDEC_RESULT_SHIFT) & 0xFFFF) +
+ BITS(entry & HUFFDEC_LENGTH_MASK)];
+ }
+ REMOVE_BITS(entry & HUFFDEC_LENGTH_MASK);
+ entry >>= HUFFDEC_RESULT_SHIFT;
+
+ STATIC_ASSERT(CAN_ENSURE(DEFLATE_MAX_EXTRA_LENGTH_BITS +
+ DEFLATE_MAX_OFFSET_CODEWORD_LEN) &&
+ CAN_ENSURE(DEFLATE_MAX_EXTRA_OFFSET_BITS));
+ if (!CAN_ENSURE(DEFLATE_MAX_EXTRA_LENGTH_BITS +
+ DEFLATE_MAX_OFFSET_CODEWORD_LEN +
+ DEFLATE_MAX_EXTRA_OFFSET_BITS))
+ ENSURE_BITS(DEFLATE_MAX_EXTRA_OFFSET_BITS);
+
+ /* Pop the extra offset bits and add them to the offset base to
+ * produce the full offset. */
+ offset = (entry & HUFFDEC_OFFSET_BASE_MASK) +
+ POP_BITS(entry >> HUFFDEC_EXTRA_OFFSET_BITS_SHIFT);
+
+ /* The match source must not begin before the beginning of the
+ * output buffer. */
+ SAFETY_CHECK(offset <= out_next - (const u8 *)out);
+
+ /*
+ * Copy the match: 'length' bytes at 'out_next - offset' to
+ * 'out_next', possibly overlapping. If the match doesn't end
+ * too close to the end of the buffer and offset >= WORDBYTES ||
+ * offset == 1, take a fast path which copies a word at a time
+ * -- potentially more than the length of the match, but that's
+ * fine as long as we check for enough extra space.
+ *
+ * The remaining cases are not performance-critical so are
+ * handled by a simple byte-by-byte copy.
+ */
+
+ src = out_next - offset;
+ dst = out_next;
+ out_next += length;
+
+ if (UNALIGNED_ACCESS_IS_FAST &&
+ /* max overrun is writing 3 words for a min length match */
+ likely(out_end - out_next >=
+ 3 * WORDBYTES - DEFLATE_MIN_MATCH_LEN)) {
+ if (offset >= WORDBYTES) { /* words don't overlap? */
+ copy_word_unaligned(src, dst);
+ src += WORDBYTES;
+ dst += WORDBYTES;
+ copy_word_unaligned(src, dst);
+ src += WORDBYTES;
+ dst += WORDBYTES;
+ do {
+ copy_word_unaligned(src, dst);
+ src += WORDBYTES;
+ dst += WORDBYTES;
+ } while (dst < out_next);
+ } else if (offset == 1) {
+ /* RLE encoding of previous byte, common if the
+ * data contains many repeated bytes */
+ machine_word_t v = repeat_byte(*src);
+
+ store_word_unaligned(v, dst);
+ dst += WORDBYTES;
+ store_word_unaligned(v, dst);
+ dst += WORDBYTES;
+ do {
+ store_word_unaligned(v, dst);
+ dst += WORDBYTES;
+ } while (dst < out_next);
+ } else {
+ *dst++ = *src++;
+ *dst++ = *src++;
+ do {
+ *dst++ = *src++;
+ } while (dst < out_next);
+ }
+ } else {
+ STATIC_ASSERT(DEFLATE_MIN_MATCH_LEN == 3);
+ *dst++ = *src++;
+ *dst++ = *src++;
+ do {
+ *dst++ = *src++;
+ } while (dst < out_next);
+ }
+ }
+
+block_done:
+ /* Finished decoding a block. */
+
+ if (!is_final_block)
+ goto next_block;
+
+ /* That was the last block. */
+
+ /* Discard any readahead bits and check for excessive overread */
+ ALIGN_INPUT();
+
+ /* Optionally return the actual number of bytes read */
+ if (actual_in_nbytes_ret)
+ *actual_in_nbytes_ret = in_next - (u8 *)in;
+
+ /* Optionally return the actual number of bytes written */
+ if (actual_out_nbytes_ret) {
+ *actual_out_nbytes_ret = out_next - (u8 *)out;
+ } else {
+ if (out_next != out_end)
+ return LIBDEFLATE_SHORT_OUTPUT;
+ }
+ return LIBDEFLATE_SUCCESS;
+}
+
+#undef FUNCNAME
+#undef ATTRIBUTES
diff --git a/util/compress/libdeflate/lib/deflate_compress.c b/util/compress/libdeflate/lib/deflate_compress.c
new file mode 100644
index 000000000..cf4379824
--- /dev/null
+++ b/util/compress/libdeflate/lib/deflate_compress.c
@@ -0,0 +1,2854 @@
+/*
+ * deflate_compress.c - a compressor for DEFLATE
+ *
+ * Originally public domain; changes after 2016-09-07 are copyrighted.
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "deflate_compress.h"
+#include "deflate_constants.h"
+#include "unaligned.h"
+
+#include "libdeflate.h"
+
+/*
+ * By default, the near-optimal parsing algorithm is enabled at compression
+ * level 8 and above. The near-optimal parsing algorithm produces a compression
+ * ratio significantly better than the greedy and lazy algorithms implemented
+ * here, and also the algorithm used by zlib at level 9. However, it is slow.
+ */
+#define SUPPORT_NEAR_OPTIMAL_PARSING 1
+
+/*
+ * Define to 1 to maintain the full map from match offsets to offset slots.
+ * This slightly speeds up translations of match offsets to offset slots, but it
+ * uses 32769 bytes of memory rather than the 512 bytes used by the condensed
+ * map. The speedup provided by the larger map is most helpful when the
+ * near-optimal parsing algorithm is being used.
+ */
+#define USE_FULL_OFFSET_SLOT_FAST SUPPORT_NEAR_OPTIMAL_PARSING
+
+/*
+ * DEFLATE uses a 32768 byte sliding window; set the matchfinder parameters
+ * appropriately.
+ */
+#define MATCHFINDER_WINDOW_ORDER 15
+
+#include "hc_matchfinder.h"
+#if SUPPORT_NEAR_OPTIMAL_PARSING
+# include "bt_matchfinder.h"
+#endif
+
+/*
+ * The compressor always chooses a block of at least MIN_BLOCK_LENGTH bytes,
+ * except if the last block has to be shorter.
+ */
+#define MIN_BLOCK_LENGTH 10000
+
+/*
+ * The compressor attempts to end blocks after SOFT_MAX_BLOCK_LENGTH bytes, but
+ * the final length might be slightly longer due to matches extending beyond
+ * this limit.
+ */
+#define SOFT_MAX_BLOCK_LENGTH 300000
+
+/*
+ * The number of observed matches or literals that represents sufficient data to
+ * decide whether the current block should be terminated or not.
+ */
+#define NUM_OBSERVATIONS_PER_BLOCK_CHECK 512
+
+
+#if SUPPORT_NEAR_OPTIMAL_PARSING
+/* Constants specific to the near-optimal parsing algorithm */
+
+/*
+ * The maximum number of matches the matchfinder can find at a single position.
+ * Since the matchfinder never finds more than one match for the same length,
+ * presuming one of each possible length is sufficient for an upper bound.
+ * (This says nothing about whether it is worthwhile to consider so many
+ * matches; this is just defining the worst case.)
+ */
+# define MAX_MATCHES_PER_POS (DEFLATE_MAX_MATCH_LEN - DEFLATE_MIN_MATCH_LEN + 1)
+
+/*
+ * The number of lz_match structures in the match cache, excluding the extra
+ * "overflow" entries. This value should be high enough so that nearly the
+ * time, all matches found in a given block can fit in the match cache.
+ * However, fallback behavior (immediately terminating the block) on cache
+ * overflow is still required.
+ */
+# define CACHE_LENGTH (SOFT_MAX_BLOCK_LENGTH * 5)
+
+#endif /* SUPPORT_NEAR_OPTIMAL_PARSING */
+
+/*
+ * These are the compressor-side limits on the codeword lengths for each Huffman
+ * code. To make outputting bits slightly faster, some of these limits are
+ * lower than the limits defined by the DEFLATE format. This does not
+ * significantly affect the compression ratio, at least for the block lengths we
+ * use.
+ */
+#define MAX_LITLEN_CODEWORD_LEN 14
+#define MAX_OFFSET_CODEWORD_LEN DEFLATE_MAX_OFFSET_CODEWORD_LEN
+#define MAX_PRE_CODEWORD_LEN DEFLATE_MAX_PRE_CODEWORD_LEN
+
+/* Table: length slot => length slot base value */
+static const unsigned deflate_length_slot_base[] = {
+ 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ,
+ 11 , 13 , 15 , 17 , 19 , 23 , 27 , 31 ,
+ 35 , 43 , 51 , 59 , 67 , 83 , 99 , 115 ,
+ 131 , 163 , 195 , 227 , 258 ,
+};
+
+/* Table: length slot => number of extra length bits */
+static const u8 deflate_extra_length_bits[] = {
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 1 , 1 , 1 , 1 , 2 , 2 , 2 , 2 ,
+ 3 , 3 , 3 , 3 , 4 , 4 , 4 , 4 ,
+ 5 , 5 , 5 , 5 , 0 ,
+};
+
+/* Table: offset slot => offset slot base value */
+static const unsigned deflate_offset_slot_base[] = {
+ 1 , 2 , 3 , 4 , 5 , 7 , 9 , 13 ,
+ 17 , 25 , 33 , 49 , 65 , 97 , 129 , 193 ,
+ 257 , 385 , 513 , 769 , 1025 , 1537 , 2049 , 3073 ,
+ 4097 , 6145 , 8193 , 12289 , 16385 , 24577 ,
+};
+
+/* Table: offset slot => number of extra offset bits */
+static const u8 deflate_extra_offset_bits[] = {
+ 0 , 0 , 0 , 0 , 1 , 1 , 2 , 2 ,
+ 3 , 3 , 4 , 4 , 5 , 5 , 6 , 6 ,
+ 7 , 7 , 8 , 8 , 9 , 9 , 10 , 10 ,
+ 11 , 11 , 12 , 12 , 13 , 13 ,
+};
+
+/* Table: length => length slot */
+static const u8 deflate_length_slot[DEFLATE_MAX_MATCH_LEN + 1] = {
+ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12,
+ 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16,
+ 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18,
+ 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 28,
+};
+
+/* The order in which precode codeword lengths are stored */
+static const u8 deflate_precode_lens_permutation[DEFLATE_NUM_PRECODE_SYMS] = {
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+};
+
+/* Codewords for the DEFLATE Huffman codes. */
+struct deflate_codewords {
+ u32 litlen[DEFLATE_NUM_LITLEN_SYMS];
+ u32 offset[DEFLATE_NUM_OFFSET_SYMS];
+};
+
+/* Codeword lengths (in bits) for the DEFLATE Huffman codes.
+ * A zero length means the corresponding symbol had zero frequency. */
+struct deflate_lens {
+ u8 litlen[DEFLATE_NUM_LITLEN_SYMS];
+ u8 offset[DEFLATE_NUM_OFFSET_SYMS];
+};
+
+/* Codewords and lengths for the DEFLATE Huffman codes. */
+struct deflate_codes {
+ struct deflate_codewords codewords;
+ struct deflate_lens lens;
+};
+
+/* Symbol frequency counters for the DEFLATE Huffman codes. */
+struct deflate_freqs {
+ u32 litlen[DEFLATE_NUM_LITLEN_SYMS];
+ u32 offset[DEFLATE_NUM_OFFSET_SYMS];
+};
+
+#if SUPPORT_NEAR_OPTIMAL_PARSING
+
+/* Costs for the near-optimal parsing algorithm. */
+struct deflate_costs {
+
+ /* The cost to output each possible literal. */
+ u32 literal[DEFLATE_NUM_LITERALS];
+
+ /* The cost to output each possible match length. */
+ u32 length[DEFLATE_MAX_MATCH_LEN + 1];
+
+ /* The cost to output a match offset of each possible offset slot. */
+ u32 offset_slot[DEFLATE_NUM_OFFSET_SYMS];
+};
+
+/*
+ * COST_SHIFT is a scaling factor that makes it possible to consider fractional
+ * bit costs. A token requiring 'n' bits to represent has cost n << COST_SHIFT.
+ *
+ * Note: this is only useful as a statistical trick for when the true costs are
+ * unknown. In reality, each token in DEFLATE requires a whole number of bits
+ * to output.
+ */
+#define COST_SHIFT 3
+
+/*
+ * The NOSTAT_BITS value for a given alphabet is the number of bits assumed to
+ * be needed to output a symbol that was unused in the previous optimization
+ * pass. Assigning a default cost allows the symbol to be used in the next
+ * optimization pass. However, the cost should be relatively high because the
+ * symbol probably won't be used very many times (if at all).
+ */
+#define LITERAL_NOSTAT_BITS 13
+#define LENGTH_NOSTAT_BITS 13
+#define OFFSET_NOSTAT_BITS 10
+
+#endif /* SUPPORT_NEAR_OPTIMAL_PARSING */
+
+/*
+ * Represents a run of literals followed by a match or end-of-block. This
+ * struct is needed to temporarily store items chosen by the parser, since items
+ * cannot be written until all items for the block have been chosen and the
+ * block's Huffman codes have been computed.
+ */
+struct deflate_sequence {
+
+ /* Bits 0..22: the number of literals in this run. This may be 0 and
+ * can be at most about SOFT_MAX_BLOCK_LENGTH. The literals are not
+ * stored explicitly in this structure; instead, they are read directly
+ * from the uncompressed data.
+ *
+ * Bits 23..31: the length of the match which follows the literals, or 0
+ * if this literal run was the last in the block, so there is no match
+ * which follows it. */
+ u32 litrunlen_and_length;
+
+ /* If 'length' doesn't indicate end-of-block, then this is the offset of
+ * the match which follows the literals. */
+ u16 offset;
+
+ /* If 'length' doesn't indicate end-of-block, then this is the offset
+ * symbol of the match which follows the literals. */
+ u8 offset_symbol;
+
+ /* If 'length' doesn't indicate end-of-block, then this is the length
+ * slot of the match which follows the literals. */
+ u8 length_slot;
+};
+
+#if SUPPORT_NEAR_OPTIMAL_PARSING
+
+/*
+ * This structure represents a byte position in the input data and a node in the
+ * graph of possible match/literal choices for the current block.
+ *
+ * Logically, each incoming edge to this node is labeled with a literal or a
+ * match that can be taken to reach this position from an earlier position; and
+ * each outgoing edge from this node is labeled with a literal or a match that
+ * can be taken to advance from this position to a later position.
+ *
+ * But these "edges" are actually stored elsewhere (in 'match_cache'). Here we
+ * associate with each node just two pieces of information:
+ *
+ * 'cost_to_end' is the minimum cost to reach the end of the block from
+ * this position.
+ *
+ * 'item' represents the literal or match that must be chosen from here to
+ * reach the end of the block with the minimum cost. Equivalently, this
+ * can be interpreted as the label of the outgoing edge on the minimum-cost
+ * path to the "end of block" node from this node.
+ */
+struct deflate_optimum_node {
+
+ u32 cost_to_end;
+
+ /*
+ * Notes on the match/literal representation used here:
+ *
+ * The low bits of 'item' are the length: 1 if this is a literal,
+ * or the match length if this is a match.
+ *
+ * The high bits of 'item' are the actual literal byte if this is a
+ * literal, or the match offset if this is a match.
+ */
+#define OPTIMUM_OFFSET_SHIFT 9
+#define OPTIMUM_LEN_MASK (((u32)1 << OPTIMUM_OFFSET_SHIFT) - 1)
+ u32 item;
+
+};
+
+#endif /* SUPPORT_NEAR_OPTIMAL_PARSING */
+
+/* Block split statistics. See "Block splitting algorithm" below. */
+#define NUM_LITERAL_OBSERVATION_TYPES 8
+#define NUM_MATCH_OBSERVATION_TYPES 2
+#define NUM_OBSERVATION_TYPES (NUM_LITERAL_OBSERVATION_TYPES + NUM_MATCH_OBSERVATION_TYPES)
+struct block_split_stats {
+ u32 new_observations[NUM_OBSERVATION_TYPES];
+ u32 observations[NUM_OBSERVATION_TYPES];
+ u32 num_new_observations;
+ u32 num_observations;
+};
+
+/* The main DEFLATE compressor structure */
+struct libdeflate_compressor {
+
+ /* Pointer to the compress() implementation chosen at allocation time */
+ size_t (*impl)(struct libdeflate_compressor *,
+ const u8 *, size_t, u8 *, size_t);
+
+ /* Frequency counters for the current block */
+ struct deflate_freqs freqs;
+
+ /* Dynamic Huffman codes for the current block */
+ struct deflate_codes codes;
+
+ /* Static Huffman codes */
+ struct deflate_codes static_codes;
+
+ /* Block split statistics for the currently pending block */
+ struct block_split_stats split_stats;
+
+ /* A table for fast lookups of offset slot by match offset.
+ *
+ * If the full table is being used, it is a direct mapping from offset
+ * to offset slot.
+ *
+ * If the condensed table is being used, the first 256 entries map
+ * directly to the offset slots of offsets 1 through 256. The next 256
+ * entries map to the offset slots for the remaining offsets, stepping
+ * through the offsets with a stride of 128. This relies on the fact
+ * that each of the remaining offset slots contains at least 128 offsets
+ * and has an offset base that is a multiple of 128. */
+#if USE_FULL_OFFSET_SLOT_FAST
+ u8 offset_slot_fast[DEFLATE_MAX_MATCH_OFFSET + 1];
+#else
+ u8 offset_slot_fast[512];
+#endif
+
+ /* The "nice" match length: if a match of this length is found, choose
+ * it immediately without further consideration. */
+ unsigned nice_match_length;
+
+ /* The maximum search depth: consider at most this many potential
+ * matches at each position. */
+ unsigned max_search_depth;
+
+ /* The compression level with which this compressor was created. */
+ unsigned compression_level;
+
+ /* Anything smaller than this we won't bother trying to compress. */
+ unsigned min_size_to_compress;
+
+ /* Temporary space for Huffman code output */
+ u32 precode_freqs[DEFLATE_NUM_PRECODE_SYMS];
+ u8 precode_lens[DEFLATE_NUM_PRECODE_SYMS];
+ u32 precode_codewords[DEFLATE_NUM_PRECODE_SYMS];
+ unsigned precode_items[DEFLATE_NUM_LITLEN_SYMS + DEFLATE_NUM_OFFSET_SYMS];
+ unsigned num_litlen_syms;
+ unsigned num_offset_syms;
+ unsigned num_explicit_lens;
+ unsigned num_precode_items;
+
+ union {
+ /* Data for greedy or lazy parsing */
+ struct {
+ /* Hash chain matchfinder */
+ struct hc_matchfinder hc_mf;
+
+ /* The matches and literals that the parser has chosen
+ * for the current block. The required length of this
+ * array is limited by the maximum number of matches
+ * that can ever be chosen for a single block, plus one
+ * for the special entry at the end. */
+ struct deflate_sequence sequences[
+ DIV_ROUND_UP(SOFT_MAX_BLOCK_LENGTH,
+ DEFLATE_MIN_MATCH_LEN) + 1];
+ } g; /* (g)reedy */
+
+ #if SUPPORT_NEAR_OPTIMAL_PARSING
+ /* Data for near-optimal parsing */
+ struct {
+
+ /* Binary tree matchfinder */
+ struct bt_matchfinder bt_mf;
+
+ /*
+ * Cached matches for the current block. This array
+ * contains the matches that were found at each position
+ * in the block. Specifically, for each position, there
+ * is a list of matches found at that position, if any,
+ * sorted by strictly increasing length. In addition,
+ * following the matches for each position, there is a
+ * special 'struct lz_match' whose 'length' member
+ * contains the number of matches found at that
+ * position, and whose 'offset' member contains the
+ * literal at that position.
+ *
+ * Note: in rare cases, there will be a very high number
+ * of matches in the block and this array will overflow.
+ * If this happens, we force the end of the current
+ * block. CACHE_LENGTH is the length at which we
+ * actually check for overflow. The extra slots beyond
+ * this are enough to absorb the worst case overflow,
+ * which occurs if starting at &match_cache[CACHE_LENGTH
+ * - 1], we write MAX_MATCHES_PER_POS matches and a
+ * match count header, then skip searching for matches
+ * at 'DEFLATE_MAX_MATCH_LEN - 1' positions and write
+ * the match count header for each.
+ */
+ struct lz_match match_cache[CACHE_LENGTH +
+ MAX_MATCHES_PER_POS +
+ DEFLATE_MAX_MATCH_LEN - 1];
+
+ /*
+ * Array of nodes, one per position, for running the
+ * minimum-cost path algorithm.
+ *
+ * This array must be large enough to accommodate the
+ * worst-case number of nodes, which occurs if we find a
+ * match of length DEFLATE_MAX_MATCH_LEN at position
+ * SOFT_MAX_BLOCK_LENGTH - 1, producing a block of
+ * length SOFT_MAX_BLOCK_LENGTH - 1 +
+ * DEFLATE_MAX_MATCH_LEN. Add one for the end-of-block
+ * node.
+ */
+ struct deflate_optimum_node optimum_nodes[SOFT_MAX_BLOCK_LENGTH - 1 +
+ DEFLATE_MAX_MATCH_LEN + 1];
+
+ /* The current cost model being used. */
+ struct deflate_costs costs;
+
+ unsigned num_optim_passes;
+ } n; /* (n)ear-optimal */
+ #endif /* SUPPORT_NEAR_OPTIMAL_PARSING */
+
+ } p; /* (p)arser */
+};
+
+/*
+ * The type for the bitbuffer variable, which temporarily holds bits that are
+ * being packed into bytes and written to the output buffer. For best
+ * performance, this should have size equal to a machine word.
+ */
+typedef machine_word_t bitbuf_t;
+#define BITBUF_NBITS (8 * sizeof(bitbuf_t))
+
+/* Can the specified number of bits always be added to 'bitbuf' after any
+ * pending bytes have been flushed? */
+#define CAN_BUFFER(n) ((n) <= BITBUF_NBITS - 7)
+
+/*
+ * Structure to keep track of the current state of sending bits to the
+ * compressed output buffer.
+ */
+struct deflate_output_bitstream {
+
+ /* Bits that haven't yet been written to the output buffer. */
+ bitbuf_t bitbuf;
+
+ /* Number of bits currently held in @bitbuf. */
+ unsigned bitcount;
+
+ /* Pointer to the beginning of the output buffer. */
+ u8 *begin;
+
+ /* Pointer to the position in the output buffer at which the next byte
+ * should be written. */
+ u8 *next;
+
+ /* Pointer just past the end of the output buffer. */
+ u8 *end;
+};
+
+/*
+ * OUTPUT_END_PADDING is the size, in bytes, of the extra space that must be
+ * present following os->end, in order to not overrun the buffer when generating
+ * output. When UNALIGNED_ACCESS_IS_FAST, we need at least sizeof(bitbuf_t)
+ * bytes for put_unaligned_leword(). Otherwise we need only 1 byte. However,
+ * to make the compression algorithm produce the same result on all CPU
+ * architectures (which is sometimes desirable), we have to unconditionally use
+ * the maximum for any CPU, which is sizeof(bitbuf_t) == 8.
+ */
+#define OUTPUT_END_PADDING 8
+
+/* Initialize the output bitstream. 'size' is assumed to be at least
+ * OUTPUT_END_PADDING. */
+static void
+deflate_init_output(struct deflate_output_bitstream *os,
+ void *buffer, size_t size)
+{
+ os->bitbuf = 0;
+ os->bitcount = 0;
+ os->begin = buffer;
+ os->next = os->begin;
+ os->end = os->begin + size - OUTPUT_END_PADDING;
+}
+
+/* Add some bits to the bitbuffer variable of the output bitstream. The caller
+ * must make sure there is enough room. */
+static forceinline void
+deflate_add_bits(struct deflate_output_bitstream *os,
+ const bitbuf_t bits, const unsigned num_bits)
+{
+ os->bitbuf |= bits << os->bitcount;
+ os->bitcount += num_bits;
+}
+
+/* Flush bits from the bitbuffer variable to the output buffer. */
+static forceinline void
+deflate_flush_bits(struct deflate_output_bitstream *os)
+{
+ if (UNALIGNED_ACCESS_IS_FAST) {
+ /* Flush a whole word (branchlessly). */
+ put_unaligned_leword(os->bitbuf, os->next);
+ os->bitbuf >>= os->bitcount & ~7;
+ os->next += MIN(os->end - os->next, os->bitcount >> 3);
+ os->bitcount &= 7;
+ } else {
+ /* Flush a byte at a time. */
+ while (os->bitcount >= 8) {
+ *os->next = os->bitbuf;
+ if (os->next != os->end)
+ os->next++;
+ os->bitcount -= 8;
+ os->bitbuf >>= 8;
+ }
+ }
+}
+
+/* Align the bitstream on a byte boundary. */
+static forceinline void
+deflate_align_bitstream(struct deflate_output_bitstream *os)
+{
+ os->bitcount += -os->bitcount & 7;
+ deflate_flush_bits(os);
+}
+
+/*
+ * Flush any remaining bits to the output buffer if needed. Return the total
+ * number of bytes written to the output buffer, or 0 if an overflow occurred.
+ */
+static size_t
+deflate_flush_output(struct deflate_output_bitstream *os)
+{
+ if (os->next == os->end) /* overflow? */
+ return 0;
+
+ while ((int)os->bitcount > 0) {
+ *os->next++ = os->bitbuf;
+ os->bitcount -= 8;
+ os->bitbuf >>= 8;
+ }
+
+ return os->next - os->begin;
+}
+
+/* Given the binary tree node A[subtree_idx] whose children already
+ * satisfy the maxheap property, swap the node with its greater child
+ * until it is greater than both its children, so that the maxheap
+ * property is satisfied in the subtree rooted at A[subtree_idx]. */
+static void
+heapify_subtree(u32 A[], unsigned length, unsigned subtree_idx)
+{
+ unsigned parent_idx;
+ unsigned child_idx;
+ u32 v;
+
+ v = A[subtree_idx];
+ parent_idx = subtree_idx;
+ while ((child_idx = parent_idx * 2) <= length) {
+ if (child_idx < length && A[child_idx + 1] > A[child_idx])
+ child_idx++;
+ if (v >= A[child_idx])
+ break;
+ A[parent_idx] = A[child_idx];
+ parent_idx = child_idx;
+ }
+ A[parent_idx] = v;
+}
+
+/* Rearrange the array 'A' so that it satisfies the maxheap property.
+ * 'A' uses 1-based indices, so the children of A[i] are A[i*2] and A[i*2 + 1].
+ */
+static void
+heapify_array(u32 A[], unsigned length)
+{
+ unsigned subtree_idx;
+
+ for (subtree_idx = length / 2; subtree_idx >= 1; subtree_idx--)
+ heapify_subtree(A, length, subtree_idx);
+}
+
+/*
+ * Sort the array 'A', which contains 'length' unsigned 32-bit integers.
+ *
+ * Note: name this function heap_sort() instead of heapsort() to avoid colliding
+ * with heapsort() from stdlib.h on BSD-derived systems --- though this isn't
+ * necessary when compiling with -D_ANSI_SOURCE, which is the better solution.
+ */
+static void
+heap_sort(u32 A[], unsigned length)
+{
+ A--; /* Use 1-based indices */
+
+ heapify_array(A, length);
+
+ while (length >= 2) {
+ u32 tmp = A[length];
+ A[length] = A[1];
+ A[1] = tmp;
+ length--;
+ heapify_subtree(A, length, 1);
+ }
+}
+
+#define NUM_SYMBOL_BITS 10
+#define SYMBOL_MASK ((1 << NUM_SYMBOL_BITS) - 1)
+
+#define GET_NUM_COUNTERS(num_syms) ((((num_syms) + 3 / 4) + 3) & ~3)
+/*
+ * Sort the symbols primarily by frequency and secondarily by symbol
+ * value. Discard symbols with zero frequency and fill in an array with
+ * the remaining symbols, along with their frequencies. The low
+ * NUM_SYMBOL_BITS bits of each array entry will contain the symbol
+ * value, and the remaining bits will contain the frequency.
+ *
+ * @num_syms
+ * Number of symbols in the alphabet.
+ * Can't be greater than (1 << NUM_SYMBOL_BITS).
+ *
+ * @freqs[num_syms]
+ * The frequency of each symbol.
+ *
+ * @lens[num_syms]
+ * An array that eventually will hold the length of each codeword.
+ * This function only fills in the codeword lengths for symbols that
+ * have zero frequency, which are not well defined per se but will
+ * be set to 0.
+ *
+ * @symout[num_syms]
+ * The output array, described above.
+ *
+ * Returns the number of entries in 'symout' that were filled. This is
+ * the number of symbols that have nonzero frequency.
+ */
+static unsigned
+sort_symbols(unsigned num_syms, const u32 freqs[restrict],
+ u8 lens[restrict], u32 symout[restrict])
+{
+ unsigned sym;
+ unsigned i;
+ unsigned num_used_syms;
+ unsigned num_counters;
+ unsigned counters[GET_NUM_COUNTERS(DEFLATE_MAX_NUM_SYMS)];
+
+ /* We rely on heapsort, but with an added optimization. Since
+ * it's common for most symbol frequencies to be low, we first do
+ * a count sort using a limited number of counters. High
+ * frequencies will be counted in the last counter, and only they
+ * will be sorted with heapsort.
+ *
+ * Note: with more symbols, it is generally beneficial to have more
+ * counters. About 1 counter per 4 symbols seems fast.
+ *
+ * Note: I also tested radix sort, but even for large symbol
+ * counts (> 255) and frequencies bounded at 16 bits (enabling
+ * radix sort by just two base-256 digits), it didn't seem any
+ * faster than the method implemented here.
+ *
+ * Note: I tested the optimized quicksort implementation from
+ * glibc (with indirection overhead removed), but it was only
+ * marginally faster than the simple heapsort implemented here.
+ *
+ * Tests were done with building the codes for LZX. Results may
+ * vary for different compression algorithms...! */
+
+ num_counters = GET_NUM_COUNTERS(num_syms);
+
+ memset(counters, 0, num_counters * sizeof(counters[0]));
+
+ /* Count the frequencies. */
+ for (sym = 0; sym < num_syms; sym++)
+ counters[MIN(freqs[sym], num_counters - 1)]++;
+
+ /* Make the counters cumulative, ignoring the zero-th, which
+ * counted symbols with zero frequency. As a side effect, this
+ * calculates the number of symbols with nonzero frequency. */
+ num_used_syms = 0;
+ for (i = 1; i < num_counters; i++) {
+ unsigned count = counters[i];
+ counters[i] = num_used_syms;
+ num_used_syms += count;
+ }
+
+ /* Sort nonzero-frequency symbols using the counters. At the
+ * same time, set the codeword lengths of zero-frequency symbols
+ * to 0. */
+ for (sym = 0; sym < num_syms; sym++) {
+ u32 freq = freqs[sym];
+ if (freq != 0) {
+ symout[counters[MIN(freq, num_counters - 1)]++] =
+ sym | (freq << NUM_SYMBOL_BITS);
+ } else {
+ lens[sym] = 0;
+ }
+ }
+
+ /* Sort the symbols counted in the last counter. */
+ heap_sort(symout + counters[num_counters - 2],
+ counters[num_counters - 1] - counters[num_counters - 2]);
+
+ return num_used_syms;
+}
+
+/*
+ * Build the Huffman tree.
+ *
+ * This is an optimized implementation that
+ * (a) takes advantage of the frequencies being already sorted;
+ * (b) only generates non-leaf nodes, since the non-leaf nodes of a
+ * Huffman tree are sufficient to generate a canonical code;
+ * (c) Only stores parent pointers, not child pointers;
+ * (d) Produces the nodes in the same memory used for input
+ * frequency information.
+ *
+ * Array 'A', which contains 'sym_count' entries, is used for both input
+ * and output. For this function, 'sym_count' must be at least 2.
+ *
+ * For input, the array must contain the frequencies of the symbols,
+ * sorted in increasing order. Specifically, each entry must contain a
+ * frequency left shifted by NUM_SYMBOL_BITS bits. Any data in the low
+ * NUM_SYMBOL_BITS bits of the entries will be ignored by this function.
+ * Although these bits will, in fact, contain the symbols that correspond
+ * to the frequencies, this function is concerned with frequencies only
+ * and keeps the symbols as-is.
+ *
+ * For output, this function will produce the non-leaf nodes of the
+ * Huffman tree. These nodes will be stored in the first (sym_count - 1)
+ * entries of the array. Entry A[sym_count - 2] will represent the root
+ * node. Each other node will contain the zero-based index of its parent
+ * node in 'A', left shifted by NUM_SYMBOL_BITS bits. The low
+ * NUM_SYMBOL_BITS bits of each entry in A will be kept as-is. Again,
+ * note that although these low bits will, in fact, contain a symbol
+ * value, this symbol will have *no relationship* with the Huffman tree
+ * node that happens to occupy the same slot. This is because this
+ * implementation only generates the non-leaf nodes of the tree.
+ */
+static void
+build_tree(u32 A[], unsigned sym_count)
+{
+ /* Index, in 'A', of next lowest frequency symbol that has not
+ * yet been processed. */
+ unsigned i = 0;
+
+ /* Index, in 'A', of next lowest frequency parentless non-leaf
+ * node; or, if equal to 'e', then no such node exists yet. */
+ unsigned b = 0;
+
+ /* Index, in 'A', of next node to allocate as a non-leaf. */
+ unsigned e = 0;
+
+ do {
+ unsigned m, n;
+ u32 freq_shifted;
+
+ /* Choose the two next lowest frequency entries. */
+
+ if (i != sym_count &&
+ (b == e || (A[i] >> NUM_SYMBOL_BITS) <= (A[b] >> NUM_SYMBOL_BITS)))
+ m = i++;
+ else
+ m = b++;
+
+ if (i != sym_count &&
+ (b == e || (A[i] >> NUM_SYMBOL_BITS) <= (A[b] >> NUM_SYMBOL_BITS)))
+ n = i++;
+ else
+ n = b++;
+
+ /* Allocate a non-leaf node and link the entries to it.
+ *
+ * If we link an entry that we're visiting for the first
+ * time (via index 'i'), then we're actually linking a
+ * leaf node and it will have no effect, since the leaf
+ * will be overwritten with a non-leaf when index 'e'
+ * catches up to it. But it's not any slower to
+ * unconditionally set the parent index.
+ *
+ * We also compute the frequency of the non-leaf node as
+ * the sum of its two children's frequencies. */
+
+ freq_shifted = (A[m] & ~SYMBOL_MASK) + (A[n] & ~SYMBOL_MASK);
+
+ A[m] = (A[m] & SYMBOL_MASK) | (e << NUM_SYMBOL_BITS);
+ A[n] = (A[n] & SYMBOL_MASK) | (e << NUM_SYMBOL_BITS);
+ A[e] = (A[e] & SYMBOL_MASK) | freq_shifted;
+ e++;
+ } while (sym_count - e > 1);
+ /* When just one entry remains, it is a "leaf" that was
+ * linked to some other node. We ignore it, since the
+ * rest of the array contains the non-leaves which we
+ * need. (Note that we're assuming the cases with 0 or 1
+ * symbols were handled separately.) */
+}
+
+/*
+ * Given the stripped-down Huffman tree constructed by build_tree(),
+ * determine the number of codewords that should be assigned each
+ * possible length, taking into account the length-limited constraint.
+ *
+ * @A
+ * The array produced by build_tree(), containing parent index
+ * information for the non-leaf nodes of the Huffman tree. Each
+ * entry in this array is a node; a node's parent always has a
+ * greater index than that node itself. This function will
+ * overwrite the parent index information in this array, so
+ * essentially it will destroy the tree. However, the data in the
+ * low NUM_SYMBOL_BITS of each entry will be preserved.
+ *
+ * @root_idx
+ * The 0-based index of the root node in 'A', and consequently one
+ * less than the number of tree node entries in 'A'. (Or, really 2
+ * less than the actual length of 'A'.)
+ *
+ * @len_counts
+ * An array of length ('max_codeword_len' + 1) in which the number of
+ * codewords having each length <= max_codeword_len will be
+ * returned.
+ *
+ * @max_codeword_len
+ * The maximum permissible codeword length.
+ */
+static void
+compute_length_counts(u32 A[restrict], unsigned root_idx,
+ unsigned len_counts[restrict], unsigned max_codeword_len)
+{
+ unsigned len;
+ int node;
+
+ /* The key observations are:
+ *
+ * (1) We can traverse the non-leaf nodes of the tree, always
+ * visiting a parent before its children, by simply iterating
+ * through the array in reverse order. Consequently, we can
+ * compute the depth of each node in one pass, overwriting the
+ * parent indices with depths.
+ *
+ * (2) We can initially assume that in the real Huffman tree,
+ * both children of the root are leaves. This corresponds to two
+ * codewords of length 1. Then, whenever we visit a (non-leaf)
+ * node during the traversal, we modify this assumption to
+ * account for the current node *not* being a leaf, but rather
+ * its two children being leaves. This causes the loss of one
+ * codeword for the current depth and the addition of two
+ * codewords for the current depth plus one.
+ *
+ * (3) We can handle the length-limited constraint fairly easily
+ * by simply using the largest length available when a depth
+ * exceeds max_codeword_len.
+ */
+
+ for (len = 0; len <= max_codeword_len; len++)
+ len_counts[len] = 0;
+ len_counts[1] = 2;
+
+ /* Set the root node's depth to 0. */
+ A[root_idx] &= SYMBOL_MASK;
+
+ for (node = root_idx - 1; node >= 0; node--) {
+
+ /* Calculate the depth of this node. */
+
+ unsigned parent = A[node] >> NUM_SYMBOL_BITS;
+ unsigned parent_depth = A[parent] >> NUM_SYMBOL_BITS;
+ unsigned depth = parent_depth + 1;
+ unsigned len = depth;
+
+ /* Set the depth of this node so that it is available
+ * when its children (if any) are processed. */
+
+ A[node] = (A[node] & SYMBOL_MASK) | (depth << NUM_SYMBOL_BITS);
+
+ /* If needed, decrease the length to meet the
+ * length-limited constraint. This is not the optimal
+ * method for generating length-limited Huffman codes!
+ * But it should be good enough. */
+ if (len >= max_codeword_len) {
+ len = max_codeword_len;
+ do {
+ len--;
+ } while (len_counts[len] == 0);
+ }
+
+ /* Account for the fact that we have a non-leaf node at
+ * the current depth. */
+ len_counts[len]--;
+ len_counts[len + 1] += 2;
+ }
+}
+
+/*
+ * Generate the codewords for a canonical Huffman code.
+ *
+ * @A
+ * The output array for codewords. In addition, initially this
+ * array must contain the symbols, sorted primarily by frequency and
+ * secondarily by symbol value, in the low NUM_SYMBOL_BITS bits of
+ * each entry.
+ *
+ * @len
+ * Output array for codeword lengths.
+ *
+ * @len_counts
+ * An array that provides the number of codewords that will have
+ * each possible length <= max_codeword_len.
+ *
+ * @max_codeword_len
+ * Maximum length, in bits, of each codeword.
+ *
+ * @num_syms
+ * Number of symbols in the alphabet, including symbols with zero
+ * frequency. This is the length of the 'A' and 'len' arrays.
+ */
+static void
+gen_codewords(u32 A[restrict], u8 lens[restrict],
+ const unsigned len_counts[restrict],
+ unsigned max_codeword_len, unsigned num_syms)
+{
+ u32 next_codewords[DEFLATE_MAX_CODEWORD_LEN + 1];
+ unsigned i;
+ unsigned len;
+ unsigned sym;
+
+ /* Given the number of codewords that will have each length,
+ * assign codeword lengths to symbols. We do this by assigning
+ * the lengths in decreasing order to the symbols sorted
+ * primarily by increasing frequency and secondarily by
+ * increasing symbol value. */
+ for (i = 0, len = max_codeword_len; len >= 1; len--) {
+ unsigned count = len_counts[len];
+ while (count--)
+ lens[A[i++] & SYMBOL_MASK] = len;
+ }
+
+ /* Generate the codewords themselves. We initialize the
+ * 'next_codewords' array to provide the lexicographically first
+ * codeword of each length, then assign codewords in symbol
+ * order. This produces a canonical code. */
+ next_codewords[0] = 0;
+ next_codewords[1] = 0;
+ for (len = 2; len <= max_codeword_len; len++)
+ next_codewords[len] =
+ (next_codewords[len - 1] + len_counts[len - 1]) << 1;
+
+ for (sym = 0; sym < num_syms; sym++)
+ A[sym] = next_codewords[lens[sym]]++;
+}
+
+/*
+ * ---------------------------------------------------------------------
+ * make_canonical_huffman_code()
+ * ---------------------------------------------------------------------
+ *
+ * Given an alphabet and the frequency of each symbol in it, construct a
+ * length-limited canonical Huffman code.
+ *
+ * @num_syms
+ * The number of symbols in the alphabet. The symbols are the
+ * integers in the range [0, num_syms - 1]. This parameter must be
+ * at least 2 and can't be greater than (1 << NUM_SYMBOL_BITS).
+ *
+ * @max_codeword_len
+ * The maximum permissible codeword length.
+ *
+ * @freqs
+ * An array of @num_syms entries, each of which specifies the
+ * frequency of the corresponding symbol. It is valid for some,
+ * none, or all of the frequencies to be 0.
+ *
+ * @lens
+ * An array of @num_syms entries in which this function will return
+ * the length, in bits, of the codeword assigned to each symbol.
+ * Symbols with 0 frequency will not have codewords per se, but
+ * their entries in this array will be set to 0. No lengths greater
+ * than @max_codeword_len will be assigned.
+ *
+ * @codewords
+ * An array of @num_syms entries in which this function will return
+ * the codeword for each symbol, right-justified and padded on the
+ * left with zeroes. Codewords for symbols with 0 frequency will be
+ * undefined.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * This function builds a length-limited canonical Huffman code.
+ *
+ * A length-limited Huffman code contains no codewords longer than some
+ * specified length, and has exactly (with some algorithms) or
+ * approximately (with the algorithm used here) the minimum weighted path
+ * length from the root, given this constraint.
+ *
+ * A canonical Huffman code satisfies the properties that a longer
+ * codeword never lexicographically precedes a shorter codeword, and the
+ * lexicographic ordering of codewords of the same length is the same as
+ * the lexicographic ordering of the corresponding symbols. A canonical
+ * Huffman code, or more generally a canonical prefix code, can be
+ * reconstructed from only a list containing the codeword length of each
+ * symbol.
+ *
+ * The classic algorithm to generate a Huffman code creates a node for
+ * each symbol, then inserts these nodes into a min-heap keyed by symbol
+ * frequency. Then, repeatedly, the two lowest-frequency nodes are
+ * removed from the min-heap and added as the children of a new node
+ * having frequency equal to the sum of its two children, which is then
+ * inserted into the min-heap. When only a single node remains in the
+ * min-heap, it is the root of the Huffman tree. The codeword for each
+ * symbol is determined by the path needed to reach the corresponding
+ * node from the root. Descending to the left child appends a 0 bit,
+ * whereas descending to the right child appends a 1 bit.
+ *
+ * The classic algorithm is relatively easy to understand, but it is
+ * subject to a number of inefficiencies. In practice, it is fastest to
+ * first sort the symbols by frequency. (This itself can be subject to
+ * an optimization based on the fact that most frequencies tend to be
+ * low.) At the same time, we sort secondarily by symbol value, which
+ * aids the process of generating a canonical code. Then, during tree
+ * construction, no heap is necessary because both the leaf nodes and the
+ * unparented non-leaf nodes can be easily maintained in sorted order.
+ * Consequently, there can never be more than two possibilities for the
+ * next-lowest-frequency node.
+ *
+ * In addition, because we're generating a canonical code, we actually
+ * don't need the leaf nodes of the tree at all, only the non-leaf nodes.
+ * This is because for canonical code generation we don't need to know
+ * where the symbols are in the tree. Rather, we only need to know how
+ * many leaf nodes have each depth (codeword length). And this
+ * information can, in fact, be quickly generated from the tree of
+ * non-leaves only.
+ *
+ * Furthermore, we can build this stripped-down Huffman tree directly in
+ * the array in which the codewords are to be generated, provided that
+ * these array slots are large enough to hold a symbol and frequency
+ * value.
+ *
+ * Still furthermore, we don't even need to maintain explicit child
+ * pointers. We only need the parent pointers, and even those can be
+ * overwritten in-place with depth information as part of the process of
+ * extracting codeword lengths from the tree. So in summary, we do NOT
+ * need a big structure like:
+ *
+ * struct huffman_tree_node {
+ * unsigned int symbol;
+ * unsigned int frequency;
+ * unsigned int depth;
+ * struct huffman_tree_node *left_child;
+ * struct huffman_tree_node *right_child;
+ * };
+ *
+ *
+ * ... which often gets used in "naive" implementations of Huffman code
+ * generation.
+ *
+ * Many of these optimizations are based on the implementation in 7-Zip
+ * (source file: C/HuffEnc.c), which has been placed in the public domain
+ * by Igor Pavlov.
+ */
+static void
+make_canonical_huffman_code(unsigned num_syms, unsigned max_codeword_len,
+ const u32 freqs[restrict],
+ u8 lens[restrict], u32 codewords[restrict])
+{
+ u32 *A = codewords;
+ unsigned num_used_syms;
+
+ STATIC_ASSERT(DEFLATE_MAX_NUM_SYMS <= 1 << NUM_SYMBOL_BITS);
+
+ /* We begin by sorting the symbols primarily by frequency and
+ * secondarily by symbol value. As an optimization, the array
+ * used for this purpose ('A') shares storage with the space in
+ * which we will eventually return the codewords. */
+
+ num_used_syms = sort_symbols(num_syms, freqs, lens, A);
+
+ /* 'num_used_syms' is the number of symbols with nonzero
+ * frequency. This may be less than @num_syms. 'num_used_syms'
+ * is also the number of entries in 'A' that are valid. Each
+ * entry consists of a distinct symbol and a nonzero frequency
+ * packed into a 32-bit integer. */
+
+ /* Handle special cases where only 0 or 1 symbols were used (had
+ * nonzero frequency). */
+
+ if (unlikely(num_used_syms == 0)) {
+ /* Code is empty. sort_symbols() already set all lengths
+ * to 0, so there is nothing more to do. */
+ return;
+ }
+
+ if (unlikely(num_used_syms == 1)) {
+ /* Only one symbol was used, so we only need one
+ * codeword. But two codewords are needed to form the
+ * smallest complete Huffman code, which uses codewords 0
+ * and 1. Therefore, we choose another symbol to which
+ * to assign a codeword. We use 0 (if the used symbol is
+ * not 0) or 1 (if the used symbol is 0). In either
+ * case, the lesser-valued symbol must be assigned
+ * codeword 0 so that the resulting code is canonical. */
+
+ unsigned sym = A[0] & SYMBOL_MASK;
+ unsigned nonzero_idx = sym ? sym : 1;
+
+ codewords[0] = 0;
+ lens[0] = 1;
+ codewords[nonzero_idx] = 1;
+ lens[nonzero_idx] = 1;
+ return;
+ }
+
+ /* Build a stripped-down version of the Huffman tree, sharing the
+ * array 'A' with the symbol values. Then extract length counts
+ * from the tree and use them to generate the final codewords. */
+
+ build_tree(A, num_used_syms);
+
+ {
+ unsigned len_counts[DEFLATE_MAX_CODEWORD_LEN + 1];
+
+ compute_length_counts(A, num_used_syms - 2,
+ len_counts, max_codeword_len);
+
+ gen_codewords(A, lens, len_counts, max_codeword_len, num_syms);
+ }
+}
+
+/*
+ * Clear the Huffman symbol frequency counters.
+ * This must be called when starting a new DEFLATE block.
+ */
+static void
+deflate_reset_symbol_frequencies(struct libdeflate_compressor *c)
+{
+ memset(&c->freqs, 0, sizeof(c->freqs));
+}
+
+/* Reverse the Huffman codeword 'codeword', which is 'len' bits in length. */
+static u32
+deflate_reverse_codeword(u32 codeword, u8 len)
+{
+ /* The following branchless algorithm is faster than going bit by bit.
+ * Note: since no codewords are longer than 16 bits, we only need to
+ * reverse the low 16 bits of the 'u32'. */
+ STATIC_ASSERT(DEFLATE_MAX_CODEWORD_LEN <= 16);
+
+ /* Flip adjacent 1-bit fields */
+ codeword = ((codeword & 0x5555) << 1) | ((codeword & 0xAAAA) >> 1);
+
+ /* Flip adjacent 2-bit fields */
+ codeword = ((codeword & 0x3333) << 2) | ((codeword & 0xCCCC) >> 2);
+
+ /* Flip adjacent 4-bit fields */
+ codeword = ((codeword & 0x0F0F) << 4) | ((codeword & 0xF0F0) >> 4);
+
+ /* Flip adjacent 8-bit fields */
+ codeword = ((codeword & 0x00FF) << 8) | ((codeword & 0xFF00) >> 8);
+
+ /* Return the high 'len' bits of the bit-reversed 16 bit value. */
+ return codeword >> (16 - len);
+}
+
+/* Make a canonical Huffman code with bit-reversed codewords. */
+static void
+deflate_make_huffman_code(unsigned num_syms, unsigned max_codeword_len,
+ const u32 freqs[], u8 lens[], u32 codewords[])
+{
+ unsigned sym;
+
+ make_canonical_huffman_code(num_syms, max_codeword_len,
+ freqs, lens, codewords);
+
+ for (sym = 0; sym < num_syms; sym++)
+ codewords[sym] = deflate_reverse_codeword(codewords[sym], lens[sym]);
+}
+
+/*
+ * Build the literal/length and offset Huffman codes for a DEFLATE block.
+ *
+ * This takes as input the frequency tables for each code and produces as output
+ * a set of tables that map symbols to codewords and codeword lengths.
+ */
+static void
+deflate_make_huffman_codes(const struct deflate_freqs *freqs,
+ struct deflate_codes *codes)
+{
+ STATIC_ASSERT(MAX_LITLEN_CODEWORD_LEN <= DEFLATE_MAX_LITLEN_CODEWORD_LEN);
+ STATIC_ASSERT(MAX_OFFSET_CODEWORD_LEN <= DEFLATE_MAX_OFFSET_CODEWORD_LEN);
+
+ deflate_make_huffman_code(DEFLATE_NUM_LITLEN_SYMS,
+ MAX_LITLEN_CODEWORD_LEN,
+ freqs->litlen,
+ codes->lens.litlen,
+ codes->codewords.litlen);
+
+ deflate_make_huffman_code(DEFLATE_NUM_OFFSET_SYMS,
+ MAX_OFFSET_CODEWORD_LEN,
+ freqs->offset,
+ codes->lens.offset,
+ codes->codewords.offset);
+}
+
+/* Initialize c->static_codes. */
+static void
+deflate_init_static_codes(struct libdeflate_compressor *c)
+{
+ unsigned i;
+
+ for (i = 0; i < 144; i++)
+ c->freqs.litlen[i] = 1 << (9 - 8);
+ for (; i < 256; i++)
+ c->freqs.litlen[i] = 1 << (9 - 9);
+ for (; i < 280; i++)
+ c->freqs.litlen[i] = 1 << (9 - 7);
+ for (; i < 288; i++)
+ c->freqs.litlen[i] = 1 << (9 - 8);
+
+ for (i = 0; i < 32; i++)
+ c->freqs.offset[i] = 1 << (5 - 5);
+
+ deflate_make_huffman_codes(&c->freqs, &c->static_codes);
+}
+
+/* Return the offset slot for the specified match offset. */
+static forceinline unsigned
+deflate_get_offset_slot(struct libdeflate_compressor *c, unsigned offset)
+{
+#if USE_FULL_OFFSET_SLOT_FAST
+ return c->offset_slot_fast[offset];
+#else
+ if (offset <= 256)
+ return c->offset_slot_fast[offset - 1];
+ else
+ return c->offset_slot_fast[256 + ((offset - 1) >> 7)];
+#endif
+}
+
+/* Write the header fields common to all DEFLATE block types. */
+static void
+deflate_write_block_header(struct deflate_output_bitstream *os,
+ bool is_final_block, unsigned block_type)
+{
+ deflate_add_bits(os, is_final_block, 1);
+ deflate_add_bits(os, block_type, 2);
+ deflate_flush_bits(os);
+}
+
+static unsigned
+deflate_compute_precode_items(const u8 lens[restrict],
+ const unsigned num_lens,
+ u32 precode_freqs[restrict],
+ unsigned precode_items[restrict])
+{
+ unsigned *itemptr;
+ unsigned run_start;
+ unsigned run_end;
+ unsigned extra_bits;
+ u8 len;
+
+ memset(precode_freqs, 0,
+ DEFLATE_NUM_PRECODE_SYMS * sizeof(precode_freqs[0]));
+
+ itemptr = precode_items;
+ run_start = 0;
+ do {
+ /* Find the next run of codeword lengths. */
+
+ /* len = the length being repeated */
+ len = lens[run_start];
+
+ /* Extend the run. */
+ run_end = run_start;
+ do {
+ run_end++;
+ } while (run_end != num_lens && len == lens[run_end]);
+
+ if (len == 0) {
+ /* Run of zeroes. */
+
+ /* Symbol 18: RLE 11 to 138 zeroes at a time. */
+ while ((run_end - run_start) >= 11) {
+ extra_bits = MIN((run_end - run_start) - 11, 0x7F);
+ precode_freqs[18]++;
+ *itemptr++ = 18 | (extra_bits << 5);
+ run_start += 11 + extra_bits;
+ }
+
+ /* Symbol 17: RLE 3 to 10 zeroes at a time. */
+ if ((run_end - run_start) >= 3) {
+ extra_bits = MIN((run_end - run_start) - 3, 0x7);
+ precode_freqs[17]++;
+ *itemptr++ = 17 | (extra_bits << 5);
+ run_start += 3 + extra_bits;
+ }
+ } else {
+
+ /* A run of nonzero lengths. */
+
+ /* Symbol 16: RLE 3 to 6 of the previous length. */
+ if ((run_end - run_start) >= 4) {
+ precode_freqs[len]++;
+ *itemptr++ = len;
+ run_start++;
+ do {
+ extra_bits = MIN((run_end - run_start) - 3, 0x3);
+ precode_freqs[16]++;
+ *itemptr++ = 16 | (extra_bits << 5);
+ run_start += 3 + extra_bits;
+ } while ((run_end - run_start) >= 3);
+ }
+ }
+
+ /* Output any remaining lengths without RLE. */
+ while (run_start != run_end) {
+ precode_freqs[len]++;
+ *itemptr++ = len;
+ run_start++;
+ }
+ } while (run_start != num_lens);
+
+ return itemptr - precode_items;
+}
+
+/*
+ * Huffman codeword lengths for dynamic Huffman blocks are compressed using a
+ * separate Huffman code, the "precode", which contains a symbol for each
+ * possible codeword length in the larger code as well as several special
+ * symbols to represent repeated codeword lengths (a form of run-length
+ * encoding). The precode is itself constructed in canonical form, and its
+ * codeword lengths are represented literally in 19 3-bit fields that
+ * immediately precede the compressed codeword lengths of the larger code.
+ */
+
+/* Precompute the information needed to output Huffman codes. */
+static void
+deflate_precompute_huffman_header(struct libdeflate_compressor *c)
+{
+ /* Compute how many litlen and offset symbols are needed. */
+
+ for (c->num_litlen_syms = DEFLATE_NUM_LITLEN_SYMS;
+ c->num_litlen_syms > 257;
+ c->num_litlen_syms--)
+ if (c->codes.lens.litlen[c->num_litlen_syms - 1] != 0)
+ break;
+
+ for (c->num_offset_syms = DEFLATE_NUM_OFFSET_SYMS;
+ c->num_offset_syms > 1;
+ c->num_offset_syms--)
+ if (c->codes.lens.offset[c->num_offset_syms - 1] != 0)
+ break;
+
+ /* If we're not using the full set of literal/length codeword lengths,
+ * then temporarily move the offset codeword lengths over so that the
+ * literal/length and offset codeword lengths are contiguous. */
+
+ STATIC_ASSERT(offsetof(struct deflate_lens, offset) ==
+ DEFLATE_NUM_LITLEN_SYMS);
+
+ if (c->num_litlen_syms != DEFLATE_NUM_LITLEN_SYMS) {
+ memmove((u8 *)&c->codes.lens + c->num_litlen_syms,
+ (u8 *)&c->codes.lens + DEFLATE_NUM_LITLEN_SYMS,
+ c->num_offset_syms);
+ }
+
+ /* Compute the "items" (RLE / literal tokens and extra bits) with which
+ * the codeword lengths in the larger code will be output. */
+ c->num_precode_items =
+ deflate_compute_precode_items((u8 *)&c->codes.lens,
+ c->num_litlen_syms +
+ c->num_offset_syms,
+ c->precode_freqs,
+ c->precode_items);
+
+ /* Build the precode. */
+ STATIC_ASSERT(MAX_PRE_CODEWORD_LEN <= DEFLATE_MAX_PRE_CODEWORD_LEN);
+ deflate_make_huffman_code(DEFLATE_NUM_PRECODE_SYMS,
+ MAX_PRE_CODEWORD_LEN,
+ c->precode_freqs, c->precode_lens,
+ c->precode_codewords);
+
+ /* Count how many precode lengths we actually need to output. */
+ for (c->num_explicit_lens = DEFLATE_NUM_PRECODE_SYMS;
+ c->num_explicit_lens > 4;
+ c->num_explicit_lens--)
+ if (c->precode_lens[deflate_precode_lens_permutation[
+ c->num_explicit_lens - 1]] != 0)
+ break;
+
+ /* Restore the offset codeword lengths if needed. */
+ if (c->num_litlen_syms != DEFLATE_NUM_LITLEN_SYMS) {
+ memmove((u8 *)&c->codes.lens + DEFLATE_NUM_LITLEN_SYMS,
+ (u8 *)&c->codes.lens + c->num_litlen_syms,
+ c->num_offset_syms);
+ }
+}
+
+/* Output the Huffman codes. */
+static void
+deflate_write_huffman_header(struct libdeflate_compressor *c,
+ struct deflate_output_bitstream *os)
+{
+ unsigned i;
+
+ deflate_add_bits(os, c->num_litlen_syms - 257, 5);
+ deflate_add_bits(os, c->num_offset_syms - 1, 5);
+ deflate_add_bits(os, c->num_explicit_lens - 4, 4);
+ deflate_flush_bits(os);
+
+ /* Output the lengths of the codewords in the precode. */
+ for (i = 0; i < c->num_explicit_lens; i++) {
+ deflate_add_bits(os, c->precode_lens[
+ deflate_precode_lens_permutation[i]], 3);
+ deflate_flush_bits(os);
+ }
+
+ /* Output the encoded lengths of the codewords in the larger code. */
+ for (i = 0; i < c->num_precode_items; i++) {
+ unsigned precode_item = c->precode_items[i];
+ unsigned precode_sym = precode_item & 0x1F;
+ deflate_add_bits(os, c->precode_codewords[precode_sym],
+ c->precode_lens[precode_sym]);
+ if (precode_sym >= 16) {
+ if (precode_sym == 16)
+ deflate_add_bits(os, precode_item >> 5, 2);
+ else if (precode_sym == 17)
+ deflate_add_bits(os, precode_item >> 5, 3);
+ else
+ deflate_add_bits(os, precode_item >> 5, 7);
+ }
+ STATIC_ASSERT(CAN_BUFFER(DEFLATE_MAX_PRE_CODEWORD_LEN + 7));
+ deflate_flush_bits(os);
+ }
+}
+
+static void
+deflate_write_sequences(struct deflate_output_bitstream * restrict os,
+ const struct deflate_codes * restrict codes,
+ const struct deflate_sequence sequences[restrict],
+ const u8 * restrict in_next)
+{
+ const struct deflate_sequence *seq = sequences;
+
+ for (;;) {
+ u32 litrunlen = seq->litrunlen_and_length & 0x7FFFFF;
+ unsigned length = seq->litrunlen_and_length >> 23;
+ unsigned length_slot;
+ unsigned litlen_symbol;
+ unsigned offset_symbol;
+
+ if (litrunlen) {
+ #if 1
+ while (litrunlen >= 4) {
+ unsigned lit0 = in_next[0];
+ unsigned lit1 = in_next[1];
+ unsigned lit2 = in_next[2];
+ unsigned lit3 = in_next[3];
+
+ deflate_add_bits(os, codes->codewords.litlen[lit0],
+ codes->lens.litlen[lit0]);
+ if (!CAN_BUFFER(2 * MAX_LITLEN_CODEWORD_LEN))
+ deflate_flush_bits(os);
+
+ deflate_add_bits(os, codes->codewords.litlen[lit1],
+ codes->lens.litlen[lit1]);
+ if (!CAN_BUFFER(4 * MAX_LITLEN_CODEWORD_LEN))
+ deflate_flush_bits(os);
+
+ deflate_add_bits(os, codes->codewords.litlen[lit2],
+ codes->lens.litlen[lit2]);
+ if (!CAN_BUFFER(2 * MAX_LITLEN_CODEWORD_LEN))
+ deflate_flush_bits(os);
+
+ deflate_add_bits(os, codes->codewords.litlen[lit3],
+ codes->lens.litlen[lit3]);
+ deflate_flush_bits(os);
+ in_next += 4;
+ litrunlen -= 4;
+ }
+ if (litrunlen-- != 0) {
+ deflate_add_bits(os, codes->codewords.litlen[*in_next],
+ codes->lens.litlen[*in_next]);
+ if (!CAN_BUFFER(3 * MAX_LITLEN_CODEWORD_LEN))
+ deflate_flush_bits(os);
+ in_next++;
+ if (litrunlen-- != 0) {
+ deflate_add_bits(os, codes->codewords.litlen[*in_next],
+ codes->lens.litlen[*in_next]);
+ if (!CAN_BUFFER(3 * MAX_LITLEN_CODEWORD_LEN))
+ deflate_flush_bits(os);
+ in_next++;
+ if (litrunlen-- != 0) {
+ deflate_add_bits(os, codes->codewords.litlen[*in_next],
+ codes->lens.litlen[*in_next]);
+ if (!CAN_BUFFER(3 * MAX_LITLEN_CODEWORD_LEN))
+ deflate_flush_bits(os);
+ in_next++;
+ }
+ }
+ if (CAN_BUFFER(3 * MAX_LITLEN_CODEWORD_LEN))
+ deflate_flush_bits(os);
+ }
+ #else
+ do {
+ unsigned lit = *in_next++;
+ deflate_add_bits(os, codes->codewords.litlen[lit],
+ codes->lens.litlen[lit]);
+ deflate_flush_bits(os);
+ } while (--litrunlen);
+ #endif
+ }
+
+ if (length == 0)
+ return;
+
+ in_next += length;
+
+ length_slot = seq->length_slot;
+ litlen_symbol = 257 + length_slot;
+
+ /* Litlen symbol */
+ deflate_add_bits(os, codes->codewords.litlen[litlen_symbol],
+ codes->lens.litlen[litlen_symbol]);
+
+ /* Extra length bits */
+ STATIC_ASSERT(CAN_BUFFER(MAX_LITLEN_CODEWORD_LEN +
+ DEFLATE_MAX_EXTRA_LENGTH_BITS));
+ deflate_add_bits(os, length - deflate_length_slot_base[length_slot],
+ deflate_extra_length_bits[length_slot]);
+
+ if (!CAN_BUFFER(MAX_LITLEN_CODEWORD_LEN +
+ DEFLATE_MAX_EXTRA_LENGTH_BITS +
+ MAX_OFFSET_CODEWORD_LEN +
+ DEFLATE_MAX_EXTRA_OFFSET_BITS))
+ deflate_flush_bits(os);
+
+ /* Offset symbol */
+ offset_symbol = seq->offset_symbol;
+ deflate_add_bits(os, codes->codewords.offset[offset_symbol],
+ codes->lens.offset[offset_symbol]);
+
+ if (!CAN_BUFFER(MAX_OFFSET_CODEWORD_LEN +
+ DEFLATE_MAX_EXTRA_OFFSET_BITS))
+ deflate_flush_bits(os);
+
+ /* Extra offset bits */
+ deflate_add_bits(os, seq->offset - deflate_offset_slot_base[offset_symbol],
+ deflate_extra_offset_bits[offset_symbol]);
+
+ deflate_flush_bits(os);
+
+ seq++;
+ }
+}
+
+#if SUPPORT_NEAR_OPTIMAL_PARSING
+/*
+ * Follow the minimum-cost path in the graph of possible match/literal choices
+ * for the current block and write out the matches/literals using the specified
+ * Huffman codes.
+ *
+ * Note: this is slightly duplicated with deflate_write_sequences(), the reason
+ * being that we don't want to waste time translating between intermediate
+ * match/literal representations.
+ */
+static void
+deflate_write_item_list(struct deflate_output_bitstream *os,
+ const struct deflate_codes *codes,
+ struct libdeflate_compressor *c,
+ u32 block_length)
+{
+ struct deflate_optimum_node *cur_node = &c->p.n.optimum_nodes[0];
+ struct deflate_optimum_node * const end_node = &c->p.n.optimum_nodes[block_length];
+ do {
+ unsigned length = cur_node->item & OPTIMUM_LEN_MASK;
+ unsigned offset = cur_node->item >> OPTIMUM_OFFSET_SHIFT;
+ unsigned litlen_symbol;
+ unsigned length_slot;
+ unsigned offset_slot;
+
+ if (length == 1) {
+ /* Literal */
+ litlen_symbol = offset;
+ deflate_add_bits(os, codes->codewords.litlen[litlen_symbol],
+ codes->lens.litlen[litlen_symbol]);
+ deflate_flush_bits(os);
+ } else {
+ /* Match length */
+ length_slot = deflate_length_slot[length];
+ litlen_symbol = 257 + length_slot;
+ deflate_add_bits(os, codes->codewords.litlen[litlen_symbol],
+ codes->lens.litlen[litlen_symbol]);
+
+ deflate_add_bits(os, length - deflate_length_slot_base[length_slot],
+ deflate_extra_length_bits[length_slot]);
+
+ if (!CAN_BUFFER(MAX_LITLEN_CODEWORD_LEN +
+ DEFLATE_MAX_EXTRA_LENGTH_BITS +
+ MAX_OFFSET_CODEWORD_LEN +
+ DEFLATE_MAX_EXTRA_OFFSET_BITS))
+ deflate_flush_bits(os);
+
+
+ /* Match offset */
+ offset_slot = deflate_get_offset_slot(c, offset);
+ deflate_add_bits(os, codes->codewords.offset[offset_slot],
+ codes->lens.offset[offset_slot]);
+
+ if (!CAN_BUFFER(MAX_OFFSET_CODEWORD_LEN +
+ DEFLATE_MAX_EXTRA_OFFSET_BITS))
+ deflate_flush_bits(os);
+
+ deflate_add_bits(os, offset - deflate_offset_slot_base[offset_slot],
+ deflate_extra_offset_bits[offset_slot]);
+
+ deflate_flush_bits(os);
+ }
+ cur_node += length;
+ } while (cur_node != end_node);
+}
+#endif /* SUPPORT_NEAR_OPTIMAL_PARSING */
+
+/* Output the end-of-block symbol. */
+static void
+deflate_write_end_of_block(struct deflate_output_bitstream *os,
+ const struct deflate_codes *codes)
+{
+ deflate_add_bits(os, codes->codewords.litlen[DEFLATE_END_OF_BLOCK],
+ codes->lens.litlen[DEFLATE_END_OF_BLOCK]);
+ deflate_flush_bits(os);
+}
+
+static void
+deflate_write_uncompressed_block(struct deflate_output_bitstream *os,
+ const u8 *data, u16 len,
+ bool is_final_block)
+{
+ deflate_write_block_header(os, is_final_block,
+ DEFLATE_BLOCKTYPE_UNCOMPRESSED);
+ deflate_align_bitstream(os);
+
+ if (4 + (u32)len >= os->end - os->next) {
+ os->next = os->end;
+ return;
+ }
+
+ put_unaligned_le16(len, os->next);
+ os->next += 2;
+ put_unaligned_le16(~len, os->next);
+ os->next += 2;
+ memcpy(os->next, data, len);
+ os->next += len;
+}
+
+static void
+deflate_write_uncompressed_blocks(struct deflate_output_bitstream *os,
+ const u8 *data, size_t data_length,
+ bool is_final_block)
+{
+ do {
+ u16 len = MIN(data_length, UINT16_MAX);
+
+ deflate_write_uncompressed_block(os, data, len,
+ is_final_block && len == data_length);
+ data += len;
+ data_length -= len;
+ } while (data_length != 0);
+}
+
+/*
+ * Choose the best type of block to use (dynamic Huffman, static Huffman, or
+ * uncompressed), then output it.
+ */
+static void
+deflate_flush_block(struct libdeflate_compressor * restrict c,
+ struct deflate_output_bitstream * restrict os,
+ const u8 * restrict block_begin, u32 block_length,
+ bool is_final_block, bool use_item_list)
+{
+ static const u8 deflate_extra_precode_bits[DEFLATE_NUM_PRECODE_SYMS] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7,
+ };
+
+ /* Costs are measured in bits */
+ u32 dynamic_cost = 0;
+ u32 static_cost = 0;
+ u32 uncompressed_cost = 0;
+ struct deflate_codes *codes;
+ int block_type;
+ unsigned sym;
+
+ /* Tally the end-of-block symbol. */
+ c->freqs.litlen[DEFLATE_END_OF_BLOCK]++;
+
+ /* Build dynamic Huffman codes. */
+ deflate_make_huffman_codes(&c->freqs, &c->codes);
+
+ /* Account for the cost of sending dynamic Huffman codes. */
+ deflate_precompute_huffman_header(c);
+ dynamic_cost += 5 + 5 + 4 + (3 * c->num_explicit_lens);
+ for (sym = 0; sym < DEFLATE_NUM_PRECODE_SYMS; sym++) {
+ u32 extra = deflate_extra_precode_bits[sym];
+ dynamic_cost += c->precode_freqs[sym] *
+ (extra + c->precode_lens[sym]);
+ }
+
+ /* Account for the cost of encoding literals. */
+ for (sym = 0; sym < 256; sym++) {
+ dynamic_cost += c->freqs.litlen[sym] *
+ c->codes.lens.litlen[sym];
+ }
+ for (sym = 0; sym < 144; sym++)
+ static_cost += c->freqs.litlen[sym] * 8;
+ for (; sym < 256; sym++)
+ static_cost += c->freqs.litlen[sym] * 9;
+
+ /* Account for the cost of encoding the end-of-block symbol. */
+ dynamic_cost += c->codes.lens.litlen[256];
+ static_cost += 7;
+
+ /* Account for the cost of encoding lengths. */
+ for (sym = 257; sym < 257 + ARRAY_LEN(deflate_extra_length_bits); sym++) {
+ u32 extra = deflate_extra_length_bits[sym - 257];
+ dynamic_cost += c->freqs.litlen[sym] *
+ (extra + c->codes.lens.litlen[sym]);
+ static_cost += c->freqs.litlen[sym] *
+ (extra + c->static_codes.lens.litlen[sym]);
+ }
+
+ /* Account for the cost of encoding offsets. */
+ for (sym = 0; sym < ARRAY_LEN(deflate_extra_offset_bits); sym++) {
+ u32 extra = deflate_extra_offset_bits[sym];
+ dynamic_cost += c->freqs.offset[sym] *
+ (extra + c->codes.lens.offset[sym]);
+ static_cost += c->freqs.offset[sym] * (extra + 5);
+ }
+
+ /* Compute the cost of using uncompressed blocks. */
+ uncompressed_cost += (-(os->bitcount + 3) & 7) + 32 +
+ (40 * (DIV_ROUND_UP(block_length,
+ UINT16_MAX) - 1)) +
+ (8 * block_length);
+
+ /* Choose the cheapest block type. */
+ if (dynamic_cost < MIN(static_cost, uncompressed_cost)) {
+ block_type = DEFLATE_BLOCKTYPE_DYNAMIC_HUFFMAN;
+ codes = &c->codes;
+ } else if (static_cost < uncompressed_cost) {
+ block_type = DEFLATE_BLOCKTYPE_STATIC_HUFFMAN;
+ codes = &c->static_codes;
+ } else {
+ block_type = DEFLATE_BLOCKTYPE_UNCOMPRESSED;
+ }
+
+ /* Now actually output the block. */
+
+ if (block_type == DEFLATE_BLOCKTYPE_UNCOMPRESSED) {
+ /* Note: the length being flushed may exceed the maximum length
+ * of an uncompressed block (65535 bytes). Therefore, more than
+ * one uncompressed block might be needed. */
+ deflate_write_uncompressed_blocks(os, block_begin, block_length,
+ is_final_block);
+ } else {
+ /* Output the block header. */
+ deflate_write_block_header(os, is_final_block, block_type);
+
+ /* Output the Huffman codes (dynamic Huffman blocks only). */
+ if (block_type == DEFLATE_BLOCKTYPE_DYNAMIC_HUFFMAN)
+ deflate_write_huffman_header(c, os);
+
+ /* Output the literals, matches, and end-of-block symbol. */
+ #if SUPPORT_NEAR_OPTIMAL_PARSING
+ if (use_item_list)
+ deflate_write_item_list(os, codes, c, block_length);
+ else
+ #endif
+ deflate_write_sequences(os, codes, c->p.g.sequences,
+ block_begin);
+ deflate_write_end_of_block(os, codes);
+ }
+}
+
+static forceinline void
+deflate_choose_literal(struct libdeflate_compressor *c, unsigned literal,
+ u32 *litrunlen_p)
+{
+ c->freqs.litlen[literal]++;
+ ++*litrunlen_p;
+}
+
+static forceinline void
+deflate_choose_match(struct libdeflate_compressor *c,
+ unsigned length, unsigned offset,
+ u32 *litrunlen_p, struct deflate_sequence **next_seq_p)
+{
+ struct deflate_sequence *seq = *next_seq_p;
+ unsigned length_slot = deflate_length_slot[length];
+ unsigned offset_slot = deflate_get_offset_slot(c, offset);
+
+ c->freqs.litlen[257 + length_slot]++;
+ c->freqs.offset[offset_slot]++;
+
+ seq->litrunlen_and_length = ((u32)length << 23) | *litrunlen_p;
+ seq->offset = offset;
+ seq->length_slot = length_slot;
+ seq->offset_symbol = offset_slot;
+
+ *litrunlen_p = 0;
+ *next_seq_p = seq + 1;
+}
+
+static forceinline void
+deflate_finish_sequence(struct deflate_sequence *seq, u32 litrunlen)
+{
+ seq->litrunlen_and_length = litrunlen; /* length = 0 */
+}
+
+/******************************************************************************/
+
+/*
+ * Block splitting algorithm. The problem is to decide when it is worthwhile to
+ * start a new block with new Huffman codes. There is a theoretically optimal
+ * solution: recursively consider every possible block split, considering the
+ * exact cost of each block, and choose the minimum cost approach. But this is
+ * far too slow. Instead, as an approximation, we can count symbols and after
+ * every N symbols, compare the expected distribution of symbols based on the
+ * previous data with the actual distribution. If they differ "by enough", then
+ * start a new block.
+ *
+ * As an optimization and heuristic, we don't distinguish between every symbol
+ * but rather we combine many symbols into a single "observation type". For
+ * literals we only look at the high bits and low bits, and for matches we only
+ * look at whether the match is long or not. The assumption is that for typical
+ * "real" data, places that are good block boundaries will tend to be noticeable
+ * based only on changes in these aggregate frequencies, without looking for
+ * subtle differences in individual symbols. For example, a change from ASCII
+ * bytes to non-ASCII bytes, or from few matches (generally less compressible)
+ * to many matches (generally more compressible), would be easily noticed based
+ * on the aggregates.
+ *
+ * For determining whether the frequency distributions are "different enough" to
+ * start a new block, the simply heuristic of splitting when the sum of absolute
+ * differences exceeds a constant seems to be good enough. We also add a number
+ * proportional to the block length so that the algorithm is more likely to end
+ * long blocks than short blocks. This reflects the general expectation that it
+ * will become increasingly beneficial to start a new block as the current
+ * block grows longer.
+ *
+ * Finally, for an approximation, it is not strictly necessary that the exact
+ * symbols being used are considered. With "near-optimal parsing", for example,
+ * the actual symbols that will be used are unknown until after the block
+ * boundary is chosen and the block has been optimized. Since the final choices
+ * cannot be used, we can use preliminary "greedy" choices instead.
+ */
+
+/* Initialize the block split statistics when starting a new block. */
+static void
+init_block_split_stats(struct block_split_stats *stats)
+{
+ int i;
+
+ for (i = 0; i < NUM_OBSERVATION_TYPES; i++) {
+ stats->new_observations[i] = 0;
+ stats->observations[i] = 0;
+ }
+ stats->num_new_observations = 0;
+ stats->num_observations = 0;
+}
+
+/* Literal observation. Heuristic: use the top 2 bits and low 1 bits of the
+ * literal, for 8 possible literal observation types. */
+static forceinline void
+observe_literal(struct block_split_stats *stats, u8 lit)
+{
+ stats->new_observations[((lit >> 5) & 0x6) | (lit & 1)]++;
+ stats->num_new_observations++;
+}
+
+/* Match observation. Heuristic: use one observation type for "short match" and
+ * one observation type for "long match". */
+static forceinline void
+observe_match(struct block_split_stats *stats, unsigned length)
+{
+ stats->new_observations[NUM_LITERAL_OBSERVATION_TYPES + (length >= 9)]++;
+ stats->num_new_observations++;
+}
+
+static bool
+do_end_block_check(struct block_split_stats *stats, u32 block_length)
+{
+ int i;
+
+ if (stats->num_observations > 0) {
+
+ /* Note: to avoid slow divisions, we do not divide by
+ * 'num_observations', but rather do all math with the numbers
+ * multiplied by 'num_observations'. */
+ u32 total_delta = 0;
+ for (i = 0; i < NUM_OBSERVATION_TYPES; i++) {
+ u32 expected = stats->observations[i] * stats->num_new_observations;
+ u32 actual = stats->new_observations[i] * stats->num_observations;
+ u32 delta = (actual > expected) ? actual - expected :
+ expected - actual;
+ total_delta += delta;
+ }
+
+ /* Ready to end the block? */
+ if (total_delta + (block_length / 4096) * stats->num_observations >=
+ NUM_OBSERVATIONS_PER_BLOCK_CHECK * 200 / 512 * stats->num_observations)
+ return true;
+ }
+
+ for (i = 0; i < NUM_OBSERVATION_TYPES; i++) {
+ stats->num_observations += stats->new_observations[i];
+ stats->observations[i] += stats->new_observations[i];
+ stats->new_observations[i] = 0;
+ }
+ stats->num_new_observations = 0;
+ return false;
+}
+
+static forceinline bool
+should_end_block(struct block_split_stats *stats,
+ const u8 *in_block_begin, const u8 *in_next, const u8 *in_end)
+{
+ /* Ready to check block split statistics? */
+ if (stats->num_new_observations < NUM_OBSERVATIONS_PER_BLOCK_CHECK ||
+ in_next - in_block_begin < MIN_BLOCK_LENGTH ||
+ in_end - in_next < MIN_BLOCK_LENGTH)
+ return false;
+
+ return do_end_block_check(stats, in_next - in_block_begin);
+}
+
+/******************************************************************************/
+
+/*
+ * This is the level 0 "compressor". It always outputs uncompressed blocks.
+ */
+static size_t
+deflate_compress_none(struct libdeflate_compressor * restrict c,
+ const u8 * restrict in, size_t in_nbytes,
+ u8 * restrict out, size_t out_nbytes_avail)
+{
+ struct deflate_output_bitstream os;
+
+ deflate_init_output(&os, out, out_nbytes_avail);
+
+ deflate_write_uncompressed_blocks(&os, in, in_nbytes, true);
+
+ return deflate_flush_output(&os);
+}
+
+/*
+ * This is the "greedy" DEFLATE compressor. It always chooses the longest match.
+ */
+static size_t
+deflate_compress_greedy(struct libdeflate_compressor * restrict c,
+ const u8 * restrict in, size_t in_nbytes,
+ u8 * restrict out, size_t out_nbytes_avail)
+{
+ const u8 *in_next = in;
+ const u8 *in_end = in_next + in_nbytes;
+ struct deflate_output_bitstream os;
+ const u8 *in_cur_base = in_next;
+ unsigned max_len = DEFLATE_MAX_MATCH_LEN;
+ unsigned nice_len = MIN(c->nice_match_length, max_len);
+ u32 next_hashes[2] = {0, 0};
+
+ deflate_init_output(&os, out, out_nbytes_avail);
+ hc_matchfinder_init(&c->p.g.hc_mf);
+
+ do {
+ /* Starting a new DEFLATE block. */
+
+ const u8 * const in_block_begin = in_next;
+ const u8 * const in_max_block_end =
+ in_next + MIN(in_end - in_next, SOFT_MAX_BLOCK_LENGTH);
+ u32 litrunlen = 0;
+ struct deflate_sequence *next_seq = c->p.g.sequences;
+
+ init_block_split_stats(&c->split_stats);
+ deflate_reset_symbol_frequencies(c);
+
+ do {
+ u32 length;
+ u32 offset;
+
+ /* Decrease the maximum and nice match lengths if we're
+ * approaching the end of the input buffer. */
+ if (unlikely(max_len > in_end - in_next)) {
+ max_len = in_end - in_next;
+ nice_len = MIN(nice_len, max_len);
+ }
+
+ length = hc_matchfinder_longest_match(&c->p.g.hc_mf,
+ &in_cur_base,
+ in_next,
+ DEFLATE_MIN_MATCH_LEN - 1,
+ max_len,
+ nice_len,
+ c->max_search_depth,
+ next_hashes,
+ &offset);
+
+ if (length >= DEFLATE_MIN_MATCH_LEN) {
+ /* Match found. */
+ deflate_choose_match(c, length, offset,
+ &litrunlen, &next_seq);
+ observe_match(&c->split_stats, length);
+ in_next = hc_matchfinder_skip_positions(&c->p.g.hc_mf,
+ &in_cur_base,
+ in_next + 1,
+ in_end,
+ length - 1,
+ next_hashes);
+ } else {
+ /* No match found. */
+ deflate_choose_literal(c, *in_next, &litrunlen);
+ observe_literal(&c->split_stats, *in_next);
+ in_next++;
+ }
+
+ /* Check if it's time to output another block. */
+ } while (in_next < in_max_block_end &&
+ !should_end_block(&c->split_stats, in_block_begin, in_next, in_end));
+
+ deflate_finish_sequence(next_seq, litrunlen);
+ deflate_flush_block(c, &os, in_block_begin,
+ in_next - in_block_begin,
+ in_next == in_end, false);
+ } while (in_next != in_end);
+
+ return deflate_flush_output(&os);
+}
+
+/*
+ * This is the "lazy" DEFLATE compressor. Before choosing a match, it checks to
+ * see if there's a longer match at the next position. If yes, it outputs a
+ * literal and continues to the next position. If no, it outputs the match.
+ */
+static size_t
+deflate_compress_lazy(struct libdeflate_compressor * restrict c,
+ const u8 * restrict in, size_t in_nbytes,
+ u8 * restrict out, size_t out_nbytes_avail)
+{
+ const u8 *in_next = in;
+ const u8 *in_end = in_next + in_nbytes;
+ struct deflate_output_bitstream os;
+ const u8 *in_cur_base = in_next;
+ unsigned max_len = DEFLATE_MAX_MATCH_LEN;
+ unsigned nice_len = MIN(c->nice_match_length, max_len);
+ u32 next_hashes[2] = {0, 0};
+
+ deflate_init_output(&os, out, out_nbytes_avail);
+ hc_matchfinder_init(&c->p.g.hc_mf);
+
+ do {
+ /* Starting a new DEFLATE block. */
+
+ const u8 * const in_block_begin = in_next;
+ const u8 * const in_max_block_end =
+ in_next + MIN(in_end - in_next, SOFT_MAX_BLOCK_LENGTH);
+ u32 litrunlen = 0;
+ struct deflate_sequence *next_seq = c->p.g.sequences;
+
+ init_block_split_stats(&c->split_stats);
+ deflate_reset_symbol_frequencies(c);
+
+ do {
+ unsigned cur_len;
+ unsigned cur_offset;
+ unsigned next_len;
+ unsigned next_offset;
+
+ if (unlikely(in_end - in_next < DEFLATE_MAX_MATCH_LEN)) {
+ max_len = in_end - in_next;
+ nice_len = MIN(nice_len, max_len);
+ }
+
+ /* Find the longest match at the current position. */
+ cur_len = hc_matchfinder_longest_match(&c->p.g.hc_mf,
+ &in_cur_base,
+ in_next,
+ DEFLATE_MIN_MATCH_LEN - 1,
+ max_len,
+ nice_len,
+ c->max_search_depth,
+ next_hashes,
+ &cur_offset);
+ in_next += 1;
+
+ if (cur_len < DEFLATE_MIN_MATCH_LEN) {
+ /* No match found. Choose a literal. */
+ deflate_choose_literal(c, *(in_next - 1), &litrunlen);
+ observe_literal(&c->split_stats, *(in_next - 1));
+ continue;
+ }
+
+ have_cur_match:
+ observe_match(&c->split_stats, cur_len);
+
+ /* We have a match at the current position. */
+
+ /* If the current match is very long, choose it
+ * immediately. */
+ if (cur_len >= nice_len) {
+ deflate_choose_match(c, cur_len, cur_offset,
+ &litrunlen, &next_seq);
+ in_next = hc_matchfinder_skip_positions(&c->p.g.hc_mf,
+ &in_cur_base,
+ in_next,
+ in_end,
+ cur_len - 1,
+ next_hashes);
+ continue;
+ }
+
+ /*
+ * Try to find a match at the next position.
+ *
+ * Note: since we already have a match at the *current*
+ * position, we use only half the 'max_search_depth'
+ * when checking the *next* position. This is a useful
+ * trade-off because it's more worthwhile to use a
+ * greater search depth on the initial match.
+ *
+ * Note: it's possible to structure the code such that
+ * there's only one call to longest_match(), which
+ * handles both the "find the initial match" and "try to
+ * find a longer match" cases. However, it is faster to
+ * have two call sites, with longest_match() inlined at
+ * each.
+ */
+ if (unlikely(in_end - in_next < DEFLATE_MAX_MATCH_LEN)) {
+ max_len = in_end - in_next;
+ nice_len = MIN(nice_len, max_len);
+ }
+ next_len = hc_matchfinder_longest_match(&c->p.g.hc_mf,
+ &in_cur_base,
+ in_next,
+ cur_len,
+ max_len,
+ nice_len,
+ c->max_search_depth / 2,
+ next_hashes,
+ &next_offset);
+ in_next += 1;
+
+ if (next_len > cur_len) {
+ /* Found a longer match at the next position.
+ * Output a literal. Then the next match
+ * becomes the current match. */
+ deflate_choose_literal(c, *(in_next - 2), &litrunlen);
+ cur_len = next_len;
+ cur_offset = next_offset;
+ goto have_cur_match;
+ }
+
+ /* No longer match at the next position.
+ * Output the current match. */
+ deflate_choose_match(c, cur_len, cur_offset,
+ &litrunlen, &next_seq);
+ in_next = hc_matchfinder_skip_positions(&c->p.g.hc_mf,
+ &in_cur_base,
+ in_next,
+ in_end,
+ cur_len - 2,
+ next_hashes);
+
+ /* Check if it's time to output another block. */
+ } while (in_next < in_max_block_end &&
+ !should_end_block(&c->split_stats, in_block_begin, in_next, in_end));
+
+ deflate_finish_sequence(next_seq, litrunlen);
+ deflate_flush_block(c, &os, in_block_begin,
+ in_next - in_block_begin,
+ in_next == in_end, false);
+ } while (in_next != in_end);
+
+ return deflate_flush_output(&os);
+}
+
+#if SUPPORT_NEAR_OPTIMAL_PARSING
+
+/*
+ * Follow the minimum-cost path in the graph of possible match/literal choices
+ * for the current block and compute the frequencies of the Huffman symbols that
+ * would be needed to output those matches and literals.
+ */
+static void
+deflate_tally_item_list(struct libdeflate_compressor *c, u32 block_length)
+{
+ struct deflate_optimum_node *cur_node = &c->p.n.optimum_nodes[0];
+ struct deflate_optimum_node *end_node = &c->p.n.optimum_nodes[block_length];
+ do {
+ unsigned length = cur_node->item & OPTIMUM_LEN_MASK;
+ unsigned offset = cur_node->item >> OPTIMUM_OFFSET_SHIFT;
+
+ if (length == 1) {
+ /* Literal */
+ c->freqs.litlen[offset]++;
+ } else {
+ /* Match */
+ c->freqs.litlen[257 + deflate_length_slot[length]]++;
+ c->freqs.offset[deflate_get_offset_slot(c, offset)]++;
+ }
+ cur_node += length;
+ } while (cur_node != end_node);
+}
+
+/* Set the current cost model from the codeword lengths specified in @lens. */
+static void
+deflate_set_costs_from_codes(struct libdeflate_compressor *c,
+ const struct deflate_lens *lens)
+{
+ unsigned i;
+
+ /* Literals */
+ for (i = 0; i < DEFLATE_NUM_LITERALS; i++) {
+ u32 bits = (lens->litlen[i] ? lens->litlen[i] : LITERAL_NOSTAT_BITS);
+ c->p.n.costs.literal[i] = bits << COST_SHIFT;
+ }
+
+ /* Lengths */
+ for (i = DEFLATE_MIN_MATCH_LEN; i <= DEFLATE_MAX_MATCH_LEN; i++) {
+ unsigned length_slot = deflate_length_slot[i];
+ unsigned litlen_sym = 257 + length_slot;
+ u32 bits = (lens->litlen[litlen_sym] ? lens->litlen[litlen_sym] : LENGTH_NOSTAT_BITS);
+ bits += deflate_extra_length_bits[length_slot];
+ c->p.n.costs.length[i] = bits << COST_SHIFT;
+ }
+
+ /* Offset slots */
+ for (i = 0; i < ARRAY_LEN(deflate_offset_slot_base); i++) {
+ u32 bits = (lens->offset[i] ? lens->offset[i] : OFFSET_NOSTAT_BITS);
+ bits += deflate_extra_offset_bits[i];
+ c->p.n.costs.offset_slot[i] = bits << COST_SHIFT;
+ }
+}
+
+static forceinline u32
+deflate_default_literal_cost(unsigned literal)
+{
+ STATIC_ASSERT(COST_SHIFT == 3);
+ /* 66 is 8.25 bits/symbol */
+ return 66;
+}
+
+static forceinline u32
+deflate_default_length_slot_cost(unsigned length_slot)
+{
+ STATIC_ASSERT(COST_SHIFT == 3);
+ /* 60 is 7.5 bits/symbol */
+ return 60 + ((u32)deflate_extra_length_bits[length_slot] << COST_SHIFT);
+}
+
+static forceinline u32
+deflate_default_offset_slot_cost(unsigned offset_slot)
+{
+ STATIC_ASSERT(COST_SHIFT == 3);
+ /* 39 is 4.875 bits/symbol */
+ return 39 + ((u32)deflate_extra_offset_bits[offset_slot] << COST_SHIFT);
+}
+
+/*
+ * Set default symbol costs for the first block's first optimization pass.
+ *
+ * It works well to assume that each symbol is equally probable. This results
+ * in each symbol being assigned a cost of (-log2(1.0/num_syms) * (1 <<
+ * COST_SHIFT)) where 'num_syms' is the number of symbols in the corresponding
+ * alphabet. However, we intentionally bias the parse towards matches rather
+ * than literals by using a slightly lower default cost for length symbols than
+ * for literals. This often improves the compression ratio slightly.
+ */
+static void
+deflate_set_default_costs(struct libdeflate_compressor *c)
+{
+ unsigned i;
+
+ /* Literals */
+ for (i = 0; i < DEFLATE_NUM_LITERALS; i++)
+ c->p.n.costs.literal[i] = deflate_default_literal_cost(i);
+
+ /* Lengths */
+ for (i = DEFLATE_MIN_MATCH_LEN; i <= DEFLATE_MAX_MATCH_LEN; i++)
+ c->p.n.costs.length[i] = deflate_default_length_slot_cost(
+ deflate_length_slot[i]);
+
+ /* Offset slots */
+ for (i = 0; i < ARRAY_LEN(deflate_offset_slot_base); i++)
+ c->p.n.costs.offset_slot[i] = deflate_default_offset_slot_cost(i);
+}
+
+static forceinline void
+deflate_adjust_cost(u32 *cost_p, u32 default_cost)
+{
+ *cost_p += ((s32)default_cost - (s32)*cost_p) >> 1;
+}
+
+/*
+ * Adjust the costs when beginning a new block.
+ *
+ * Since the current costs have been optimized for the data, it's undesirable to
+ * throw them away and start over with the default costs. At the same time, we
+ * don't want to bias the parse by assuming that the next block will be similar
+ * to the current block. As a compromise, make the costs closer to the
+ * defaults, but don't simply set them to the defaults.
+ */
+static void
+deflate_adjust_costs(struct libdeflate_compressor *c)
+{
+ unsigned i;
+
+ /* Literals */
+ for (i = 0; i < DEFLATE_NUM_LITERALS; i++)
+ deflate_adjust_cost(&c->p.n.costs.literal[i],
+ deflate_default_literal_cost(i));
+
+ /* Lengths */
+ for (i = DEFLATE_MIN_MATCH_LEN; i <= DEFLATE_MAX_MATCH_LEN; i++)
+ deflate_adjust_cost(&c->p.n.costs.length[i],
+ deflate_default_length_slot_cost(
+ deflate_length_slot[i]));
+
+ /* Offset slots */
+ for (i = 0; i < ARRAY_LEN(deflate_offset_slot_base); i++)
+ deflate_adjust_cost(&c->p.n.costs.offset_slot[i],
+ deflate_default_offset_slot_cost(i));
+}
+
+/*
+ * Find the minimum-cost path through the graph of possible match/literal
+ * choices for this block.
+ *
+ * We find the minimum cost path from 'c->p.n.optimum_nodes[0]', which
+ * represents the node at the beginning of the block, to
+ * 'c->p.n.optimum_nodes[block_length]', which represents the node at the end of
+ * the block. Edge costs are evaluated using the cost model 'c->p.n.costs'.
+ *
+ * The algorithm works backwards, starting at the end node and proceeding
+ * backwards one node at a time. At each node, the minimum cost to reach the
+ * end node is computed and the match/literal choice that begins that path is
+ * saved.
+ */
+static void
+deflate_find_min_cost_path(struct libdeflate_compressor *c,
+ const u32 block_length,
+ const struct lz_match *cache_ptr)
+{
+ struct deflate_optimum_node *end_node = &c->p.n.optimum_nodes[block_length];
+ struct deflate_optimum_node *cur_node = end_node;
+
+ cur_node->cost_to_end = 0;
+ do {
+ unsigned num_matches;
+ unsigned literal;
+ u32 best_cost_to_end;
+
+ cur_node--;
+ cache_ptr--;
+
+ num_matches = cache_ptr->length;
+ literal = cache_ptr->offset;
+
+ /* It's always possible to choose a literal. */
+ best_cost_to_end = c->p.n.costs.literal[literal] +
+ (cur_node + 1)->cost_to_end;
+ cur_node->item = ((u32)literal << OPTIMUM_OFFSET_SHIFT) | 1;
+
+ /* Also consider matches if there are any. */
+ if (num_matches) {
+ const struct lz_match *match;
+ unsigned len;
+ unsigned offset;
+ unsigned offset_slot;
+ u32 offset_cost;
+ u32 cost_to_end;
+
+ /*
+ * Consider each length from the minimum
+ * (DEFLATE_MIN_MATCH_LEN) to the length of the longest
+ * match found at this position. For each length, we
+ * consider only the smallest offset for which that
+ * length is available. Although this is not guaranteed
+ * to be optimal due to the possibility of a larger
+ * offset costing less than a smaller offset to code,
+ * this is a very useful heuristic.
+ */
+ match = cache_ptr - num_matches;
+ len = DEFLATE_MIN_MATCH_LEN;
+ do {
+ offset = match->offset;
+ offset_slot = deflate_get_offset_slot(c, offset);
+ offset_cost = c->p.n.costs.offset_slot[offset_slot];
+ do {
+ cost_to_end = offset_cost +
+ c->p.n.costs.length[len] +
+ (cur_node + len)->cost_to_end;
+ if (cost_to_end < best_cost_to_end) {
+ best_cost_to_end = cost_to_end;
+ cur_node->item = ((u32)offset << OPTIMUM_OFFSET_SHIFT) | len;
+ }
+ } while (++len <= match->length);
+ } while (++match != cache_ptr);
+ cache_ptr -= num_matches;
+ }
+ cur_node->cost_to_end = best_cost_to_end;
+ } while (cur_node != &c->p.n.optimum_nodes[0]);
+}
+
+/*
+ * Choose the literal/match sequence to use for the current block. The basic
+ * algorithm finds a minimum-cost path through the block's graph of
+ * literal/match choices, given a cost model. However, the cost of each symbol
+ * is unknown until the Huffman codes have been built, but at the same time the
+ * Huffman codes depend on the frequencies of chosen symbols. Consequently,
+ * multiple passes must be used to try to approximate an optimal solution. The
+ * first pass uses default costs, mixed with the costs from the previous block
+ * if any. Later passes use the Huffman codeword lengths from the previous pass
+ * as the costs.
+ */
+static void
+deflate_optimize_block(struct libdeflate_compressor *c, u32 block_length,
+ const struct lz_match *cache_ptr, bool is_first_block)
+{
+ unsigned num_passes_remaining = c->p.n.num_optim_passes;
+ u32 i;
+
+ /* Force the block to really end at the desired length, even if some
+ * matches extend beyond it. */
+ for (i = block_length; i <= MIN(block_length - 1 + DEFLATE_MAX_MATCH_LEN,
+ ARRAY_LEN(c->p.n.optimum_nodes) - 1); i++)
+ c->p.n.optimum_nodes[i].cost_to_end = 0x80000000;
+
+ /* Set the initial costs. */
+ if (is_first_block)
+ deflate_set_default_costs(c);
+ else
+ deflate_adjust_costs(c);
+
+ for (;;) {
+ /* Find the minimum cost path for this pass. */
+ deflate_find_min_cost_path(c, block_length, cache_ptr);
+
+ /* Compute frequencies of the chosen symbols. */
+ deflate_reset_symbol_frequencies(c);
+ deflate_tally_item_list(c, block_length);
+
+ if (--num_passes_remaining == 0)
+ break;
+
+ /* At least one optimization pass remains; update the costs. */
+ deflate_make_huffman_codes(&c->freqs, &c->codes);
+ deflate_set_costs_from_codes(c, &c->codes.lens);
+ }
+}
+
+/*
+ * This is the "near-optimal" DEFLATE compressor. It computes the optimal
+ * representation of each DEFLATE block using a minimum-cost path search over
+ * the graph of possible match/literal choices for that block, assuming a
+ * certain cost for each Huffman symbol.
+ *
+ * For several reasons, the end result is not guaranteed to be optimal:
+ *
+ * - Nonoptimal choice of blocks
+ * - Heuristic limitations on which matches are actually considered
+ * - Symbol costs are unknown until the symbols have already been chosen
+ * (so iterative optimization must be used)
+ */
+static size_t
+deflate_compress_near_optimal(struct libdeflate_compressor * restrict c,
+ const u8 * restrict in, size_t in_nbytes,
+ u8 * restrict out, size_t out_nbytes_avail)
+{
+ const u8 *in_next = in;
+ const u8 *in_end = in_next + in_nbytes;
+ struct deflate_output_bitstream os;
+ const u8 *in_cur_base = in_next;
+ const u8 *in_next_slide = in_next + MIN(in_end - in_next, MATCHFINDER_WINDOW_SIZE);
+ unsigned max_len = DEFLATE_MAX_MATCH_LEN;
+ unsigned nice_len = MIN(c->nice_match_length, max_len);
+ u32 next_hashes[2] = {0, 0};
+
+ deflate_init_output(&os, out, out_nbytes_avail);
+ bt_matchfinder_init(&c->p.n.bt_mf);
+
+ do {
+ /* Starting a new DEFLATE block. */
+
+ struct lz_match *cache_ptr = c->p.n.match_cache;
+ const u8 * const in_block_begin = in_next;
+ const u8 * const in_max_block_end =
+ in_next + MIN(in_end - in_next, SOFT_MAX_BLOCK_LENGTH);
+ const u8 *next_observation = in_next;
+
+ init_block_split_stats(&c->split_stats);
+
+ /*
+ * Find matches until we decide to end the block. We end the
+ * block if any of the following is true:
+ *
+ * (1) Maximum block length has been reached
+ * (2) Match catch may overflow.
+ * (3) Block split heuristic says to split now.
+ */
+ do {
+ struct lz_match *matches;
+ unsigned best_len;
+
+ /* Slide the window forward if needed. */
+ if (in_next == in_next_slide) {
+ bt_matchfinder_slide_window(&c->p.n.bt_mf);
+ in_cur_base = in_next;
+ in_next_slide = in_next + MIN(in_end - in_next,
+ MATCHFINDER_WINDOW_SIZE);
+ }
+
+ /* Decrease the maximum and nice match lengths if we're
+ * approaching the end of the input buffer. */
+ if (unlikely(max_len > in_end - in_next)) {
+ max_len = in_end - in_next;
+ nice_len = MIN(nice_len, max_len);
+ }
+
+ /*
+ * Find matches with the current position using the
+ * binary tree matchfinder and save them in
+ * 'match_cache'.
+ *
+ * Note: the binary tree matchfinder is more suited for
+ * optimal parsing than the hash chain matchfinder. The
+ * reasons for this include:
+ *
+ * - The binary tree matchfinder can find more matches
+ * in the same number of steps.
+ * - One of the major advantages of hash chains is that
+ * skipping positions (not searching for matches at
+ * them) is faster; however, with optimal parsing we
+ * search for matches at almost all positions, so this
+ * advantage of hash chains is negated.
+ */
+ matches = cache_ptr;
+ best_len = 0;
+ if (likely(max_len >= BT_MATCHFINDER_REQUIRED_NBYTES)) {
+ cache_ptr = bt_matchfinder_get_matches(&c->p.n.bt_mf,
+ in_cur_base,
+ in_next - in_cur_base,
+ max_len,
+ nice_len,
+ c->max_search_depth,
+ next_hashes,
+ &best_len,
+ matches);
+ }
+
+ if (in_next >= next_observation) {
+ if (best_len >= 4) {
+ observe_match(&c->split_stats, best_len);
+ next_observation = in_next + best_len;
+ } else {
+ observe_literal(&c->split_stats, *in_next);
+ next_observation = in_next + 1;
+ }
+ }
+
+ cache_ptr->length = cache_ptr - matches;
+ cache_ptr->offset = *in_next;
+ in_next++;
+ cache_ptr++;
+
+ /*
+ * If there was a very long match found, don't cache any
+ * matches for the bytes covered by that match. This
+ * avoids degenerate behavior when compressing highly
+ * redundant data, where the number of matches can be
+ * very large.
+ *
+ * This heuristic doesn't actually hurt the compression
+ * ratio very much. If there's a long match, then the
+ * data must be highly compressible, so it doesn't
+ * matter much what we do.
+ */
+ if (best_len >= DEFLATE_MIN_MATCH_LEN && best_len >= nice_len) {
+ --best_len;
+ do {
+ if (in_next == in_next_slide) {
+ bt_matchfinder_slide_window(&c->p.n.bt_mf);
+ in_cur_base = in_next;
+ in_next_slide = in_next + MIN(in_end - in_next,
+ MATCHFINDER_WINDOW_SIZE);
+ }
+ if (unlikely(max_len > in_end - in_next)) {
+ max_len = in_end - in_next;
+ nice_len = MIN(nice_len, max_len);
+ }
+ if (max_len >= BT_MATCHFINDER_REQUIRED_NBYTES) {
+ bt_matchfinder_skip_position(&c->p.n.bt_mf,
+ in_cur_base,
+ in_next - in_cur_base,
+ nice_len,
+ c->max_search_depth,
+ next_hashes);
+ }
+ cache_ptr->length = 0;
+ cache_ptr->offset = *in_next;
+ in_next++;
+ cache_ptr++;
+ } while (--best_len);
+ }
+ } while (in_next < in_max_block_end &&
+ cache_ptr < &c->p.n.match_cache[CACHE_LENGTH] &&
+ !should_end_block(&c->split_stats, in_block_begin, in_next, in_end));
+
+ /* All the matches for this block have been cached. Now choose
+ * the sequence of items to output and flush the block. */
+ deflate_optimize_block(c, in_next - in_block_begin, cache_ptr,
+ in_block_begin == in);
+ deflate_flush_block(c, &os, in_block_begin, in_next - in_block_begin,
+ in_next == in_end, true);
+ } while (in_next != in_end);
+
+ return deflate_flush_output(&os);
+}
+
+#endif /* SUPPORT_NEAR_OPTIMAL_PARSING */
+
+/* Initialize c->offset_slot_fast. */
+static void
+deflate_init_offset_slot_fast(struct libdeflate_compressor *c)
+{
+ unsigned offset_slot;
+ unsigned offset;
+ unsigned offset_end;
+
+ for (offset_slot = 0;
+ offset_slot < ARRAY_LEN(deflate_offset_slot_base);
+ offset_slot++)
+ {
+ offset = deflate_offset_slot_base[offset_slot];
+ #if USE_FULL_OFFSET_SLOT_FAST
+ offset_end = offset + (1 << deflate_extra_offset_bits[offset_slot]);
+ do {
+ c->offset_slot_fast[offset] = offset_slot;
+ } while (++offset != offset_end);
+ #else
+ if (offset <= 256) {
+ offset_end = offset + (1 << deflate_extra_offset_bits[offset_slot]);
+ do {
+ c->offset_slot_fast[offset - 1] = offset_slot;
+ } while (++offset != offset_end);
+ } else {
+ offset_end = offset + (1 << deflate_extra_offset_bits[offset_slot]);
+ do {
+ c->offset_slot_fast[256 + ((offset - 1) >> 7)] = offset_slot;
+ } while ((offset += (1 << 7)) != offset_end);
+ }
+ #endif
+ }
+}
+
+LIBDEFLATEEXPORT struct libdeflate_compressor * LIBDEFLATEAPI
+libdeflate_alloc_compressor(int compression_level)
+{
+ struct libdeflate_compressor *c;
+ size_t size = offsetof(struct libdeflate_compressor, p);
+
+ if (compression_level < 0 || compression_level > 12)
+ return NULL;
+
+#if SUPPORT_NEAR_OPTIMAL_PARSING
+ if (compression_level >= 8)
+ size += sizeof(c->p.n);
+ else if (compression_level >= 1)
+ size += sizeof(c->p.g);
+#else
+ if (compression_level >= 1)
+ size += sizeof(c->p.g);
+#endif
+
+ c = libdeflate_aligned_malloc(MATCHFINDER_MEM_ALIGNMENT, size);
+ if (!c)
+ return NULL;
+
+ c->compression_level = compression_level;
+
+ /*
+ * The higher the compression level, the more we should bother trying to
+ * compress very small inputs.
+ */
+ c->min_size_to_compress = 56 - (compression_level * 4);
+
+ switch (compression_level) {
+ case 0:
+ c->impl = deflate_compress_none;
+ break;
+ case 1:
+ c->impl = deflate_compress_greedy;
+ c->max_search_depth = 2;
+ c->nice_match_length = 8;
+ break;
+ case 2:
+ c->impl = deflate_compress_greedy;
+ c->max_search_depth = 6;
+ c->nice_match_length = 10;
+ break;
+ case 3:
+ c->impl = deflate_compress_greedy;
+ c->max_search_depth = 12;
+ c->nice_match_length = 14;
+ break;
+ case 4:
+ c->impl = deflate_compress_greedy;
+ c->max_search_depth = 24;
+ c->nice_match_length = 24;
+ break;
+ case 5:
+ c->impl = deflate_compress_lazy;
+ c->max_search_depth = 20;
+ c->nice_match_length = 30;
+ break;
+ case 6:
+ c->impl = deflate_compress_lazy;
+ c->max_search_depth = 40;
+ c->nice_match_length = 65;
+ break;
+ case 7:
+ c->impl = deflate_compress_lazy;
+ c->max_search_depth = 100;
+ c->nice_match_length = 130;
+ break;
+#if SUPPORT_NEAR_OPTIMAL_PARSING
+ case 8:
+ c->impl = deflate_compress_near_optimal;
+ c->max_search_depth = 12;
+ c->nice_match_length = 20;
+ c->p.n.num_optim_passes = 1;
+ break;
+ case 9:
+ c->impl = deflate_compress_near_optimal;
+ c->max_search_depth = 16;
+ c->nice_match_length = 26;
+ c->p.n.num_optim_passes = 2;
+ break;
+ case 10:
+ c->impl = deflate_compress_near_optimal;
+ c->max_search_depth = 30;
+ c->nice_match_length = 50;
+ c->p.n.num_optim_passes = 2;
+ break;
+ case 11:
+ c->impl = deflate_compress_near_optimal;
+ c->max_search_depth = 60;
+ c->nice_match_length = 80;
+ c->p.n.num_optim_passes = 3;
+ break;
+ default:
+ c->impl = deflate_compress_near_optimal;
+ c->max_search_depth = 100;
+ c->nice_match_length = 133;
+ c->p.n.num_optim_passes = 4;
+ break;
+#else
+ case 8:
+ c->impl = deflate_compress_lazy;
+ c->max_search_depth = 150;
+ c->nice_match_length = 200;
+ break;
+ default:
+ c->impl = deflate_compress_lazy;
+ c->max_search_depth = 200;
+ c->nice_match_length = DEFLATE_MAX_MATCH_LEN;
+ break;
+#endif
+ }
+
+ deflate_init_offset_slot_fast(c);
+ deflate_init_static_codes(c);
+
+ return c;
+}
+
+LIBDEFLATEEXPORT size_t LIBDEFLATEAPI
+libdeflate_deflate_compress(struct libdeflate_compressor *c,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail)
+{
+ if (unlikely(out_nbytes_avail < OUTPUT_END_PADDING))
+ return 0;
+
+ /* For extremely small inputs just use a single uncompressed block. */
+ if (unlikely(in_nbytes < c->min_size_to_compress)) {
+ struct deflate_output_bitstream os;
+ deflate_init_output(&os, out, out_nbytes_avail);
+ if (in_nbytes == 0)
+ in = &os; /* Avoid passing NULL to memcpy() */
+ deflate_write_uncompressed_block(&os, in, in_nbytes, true);
+ return deflate_flush_output(&os);
+ }
+
+ return (*c->impl)(c, in, in_nbytes, out, out_nbytes_avail);
+}
+
+LIBDEFLATEEXPORT void LIBDEFLATEAPI
+libdeflate_free_compressor(struct libdeflate_compressor *c)
+{
+ libdeflate_aligned_free(c);
+}
+
+unsigned int
+deflate_get_compression_level(struct libdeflate_compressor *c)
+{
+ return c->compression_level;
+}
+
+LIBDEFLATEEXPORT size_t LIBDEFLATEAPI
+libdeflate_deflate_compress_bound(struct libdeflate_compressor *c,
+ size_t in_nbytes)
+{
+ /*
+ * The worst case is all uncompressed blocks where one block has length
+ * <= MIN_BLOCK_LENGTH and the others have length MIN_BLOCK_LENGTH.
+ * Each uncompressed block has 5 bytes of overhead: 1 for BFINAL, BTYPE,
+ * and alignment to a byte boundary; 2 for LEN; and 2 for NLEN.
+ */
+ size_t max_num_blocks = MAX(DIV_ROUND_UP(in_nbytes, MIN_BLOCK_LENGTH), 1);
+ return (5 * max_num_blocks) + in_nbytes + 1 + OUTPUT_END_PADDING;
+}
diff --git a/util/compress/libdeflate/lib/deflate_compress.h b/util/compress/libdeflate/lib/deflate_compress.h
new file mode 100644
index 000000000..d97d019ae
--- /dev/null
+++ b/util/compress/libdeflate/lib/deflate_compress.h
@@ -0,0 +1,13 @@
+#ifndef LIB_DEFLATE_COMPRESS_H
+#define LIB_DEFLATE_COMPRESS_H
+
+#include "lib_common.h"
+
+/* DEFLATE compression is private to deflate_compress.c, but we do need to be
+ * able to query the compression level for zlib and gzip header generation. */
+
+struct libdeflate_compressor;
+
+unsigned int deflate_get_compression_level(struct libdeflate_compressor *c);
+
+#endif /* LIB_DEFLATE_COMPRESS_H */
diff --git a/util/compress/libdeflate/lib/deflate_constants.h b/util/compress/libdeflate/lib/deflate_constants.h
new file mode 100644
index 000000000..a10b57dec
--- /dev/null
+++ b/util/compress/libdeflate/lib/deflate_constants.h
@@ -0,0 +1,66 @@
+/*
+ * deflate_constants.h - constants for the DEFLATE compression format
+ */
+
+#ifndef LIB_DEFLATE_CONSTANTS_H
+#define LIB_DEFLATE_CONSTANTS_H
+
+/* Valid block types */
+#define DEFLATE_BLOCKTYPE_UNCOMPRESSED 0
+#define DEFLATE_BLOCKTYPE_STATIC_HUFFMAN 1
+#define DEFLATE_BLOCKTYPE_DYNAMIC_HUFFMAN 2
+
+/* Minimum and maximum supported match lengths (in bytes) */
+#define DEFLATE_MIN_MATCH_LEN 3
+#define DEFLATE_MAX_MATCH_LEN 258
+
+/* Minimum and maximum supported match offsets (in bytes) */
+#define DEFLATE_MIN_MATCH_OFFSET 1
+#define DEFLATE_MAX_MATCH_OFFSET 32768
+
+#define DEFLATE_MAX_WINDOW_SIZE 32768
+
+/* Number of symbols in each Huffman code. Note: for the literal/length
+ * and offset codes, these are actually the maximum values; a given block
+ * might use fewer symbols. */
+#define DEFLATE_NUM_PRECODE_SYMS 19
+#define DEFLATE_NUM_LITLEN_SYMS 288
+#define DEFLATE_NUM_OFFSET_SYMS 32
+
+/* The maximum number of symbols across all codes */
+#define DEFLATE_MAX_NUM_SYMS 288
+
+/* Division of symbols in the literal/length code */
+#define DEFLATE_NUM_LITERALS 256
+#define DEFLATE_END_OF_BLOCK 256
+#define DEFLATE_NUM_LEN_SYMS 31
+
+/* Maximum codeword length, in bits, within each Huffman code */
+#define DEFLATE_MAX_PRE_CODEWORD_LEN 7
+#define DEFLATE_MAX_LITLEN_CODEWORD_LEN 15
+#define DEFLATE_MAX_OFFSET_CODEWORD_LEN 15
+
+/* The maximum codeword length across all codes */
+#define DEFLATE_MAX_CODEWORD_LEN 15
+
+/* Maximum possible overrun when decoding codeword lengths */
+#define DEFLATE_MAX_LENS_OVERRUN 137
+
+/*
+ * Maximum number of extra bits that may be required to represent a match
+ * length or offset.
+ *
+ * TODO: are we going to have full DEFLATE64 support? If so, up to 16
+ * length bits must be supported.
+ */
+#define DEFLATE_MAX_EXTRA_LENGTH_BITS 5
+#define DEFLATE_MAX_EXTRA_OFFSET_BITS 14
+
+/* The maximum number of bits in which a match can be represented. This
+ * is the absolute worst case, which assumes the longest possible Huffman
+ * codewords and the maximum numbers of extra bits. */
+#define DEFLATE_MAX_MATCH_BITS \
+ (DEFLATE_MAX_LITLEN_CODEWORD_LEN + DEFLATE_MAX_EXTRA_LENGTH_BITS + \
+ DEFLATE_MAX_OFFSET_CODEWORD_LEN + DEFLATE_MAX_EXTRA_OFFSET_BITS)
+
+#endif /* LIB_DEFLATE_CONSTANTS_H */
diff --git a/util/compress/libdeflate/lib/deflate_decompress.c b/util/compress/libdeflate/lib/deflate_decompress.c
new file mode 100644
index 000000000..1990e74d6
--- /dev/null
+++ b/util/compress/libdeflate/lib/deflate_decompress.c
@@ -0,0 +1,1000 @@
+/*
+ * deflate_decompress.c - a decompressor for DEFLATE
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * This is a highly optimized DEFLATE decompressor. When compiled with gcc on
+ * x86_64, it decompresses data in about 52% of the time of zlib (48% if BMI2
+ * instructions are available). On other architectures it should still be
+ * significantly faster than zlib, but the difference may be smaller.
+ *
+ * Why this is faster than zlib's implementation:
+ *
+ * - Word accesses rather than byte accesses when reading input
+ * - Word accesses rather than byte accesses when copying matches
+ * - Faster Huffman decoding combined with various DEFLATE-specific tricks
+ * - Larger bitbuffer variable that doesn't need to be filled as often
+ * - Other optimizations to remove unnecessary branches
+ * - Only full-buffer decompression is supported, so the code doesn't need to
+ * support stopping and resuming decompression.
+ * - On x86_64, compile a version of the decompression routine using BMI2
+ * instructions and use it automatically at runtime when supported.
+ */
+
+#include <limits.h>
+
+#include "deflate_constants.h"
+#include "unaligned.h"
+
+#include "libdeflate.h"
+
+/*
+ * If the expression passed to SAFETY_CHECK() evaluates to false, then the
+ * decompression routine immediately returns LIBDEFLATE_BAD_DATA, indicating the
+ * compressed data is invalid.
+ *
+ * Theoretically, these checks could be disabled for specialized applications
+ * where all input to the decompressor will be trusted.
+ */
+#if 0
+# pragma message("UNSAFE DECOMPRESSION IS ENABLED. THIS MUST ONLY BE USED IF THE DECOMPRESSOR INPUT WILL ALWAYS BE TRUSTED!")
+# define SAFETY_CHECK(expr) (void)(expr)
+#else
+# define SAFETY_CHECK(expr) if (unlikely(!(expr))) return LIBDEFLATE_BAD_DATA
+#endif
+
+/*
+ * Each TABLEBITS number is the base-2 logarithm of the number of entries in the
+ * main portion of the corresponding decode table. Each number should be large
+ * enough to ensure that for typical data, the vast majority of symbols can be
+ * decoded by a direct lookup of the next TABLEBITS bits of compressed data.
+ * However, this must be balanced against the fact that a larger table requires
+ * more memory and requires more time to fill.
+ *
+ * Note: you cannot change a TABLEBITS number without also changing the
+ * corresponding ENOUGH number!
+ */
+#define PRECODE_TABLEBITS 7
+#define LITLEN_TABLEBITS 10
+#define OFFSET_TABLEBITS 8
+
+/*
+ * Each ENOUGH number is the maximum number of decode table entries that may be
+ * required for the corresponding Huffman code, including the main table and all
+ * subtables. Each number depends on three parameters:
+ *
+ * (1) the maximum number of symbols in the code (DEFLATE_NUM_*_SYMS)
+ * (2) the number of main table bits (the TABLEBITS numbers defined above)
+ * (3) the maximum allowed codeword length (DEFLATE_MAX_*_CODEWORD_LEN)
+ *
+ * The ENOUGH numbers were computed using the utility program 'enough' from
+ * zlib. This program enumerates all possible relevant Huffman codes to find
+ * the worst-case usage of decode table entries.
+ */
+#define PRECODE_ENOUGH 128 /* enough 19 7 7 */
+#define LITLEN_ENOUGH 1334 /* enough 288 10 15 */
+#define OFFSET_ENOUGH 402 /* enough 32 8 15 */
+
+/*
+ * Type for codeword lengths.
+ */
+typedef u8 len_t;
+
+/*
+ * The main DEFLATE decompressor structure. Since this implementation only
+ * supports full buffer decompression, this structure does not store the entire
+ * decompression state, but rather only some arrays that are too large to
+ * comfortably allocate on the stack.
+ */
+struct libdeflate_decompressor {
+
+ /*
+ * The arrays aren't all needed at the same time. 'precode_lens' and
+ * 'precode_decode_table' are unneeded after 'lens' has been filled.
+ * Furthermore, 'lens' need not be retained after building the litlen
+ * and offset decode tables. In fact, 'lens' can be in union with
+ * 'litlen_decode_table' provided that 'offset_decode_table' is separate
+ * and is built first.
+ */
+
+ union {
+ len_t precode_lens[DEFLATE_NUM_PRECODE_SYMS];
+
+ struct {
+ len_t lens[DEFLATE_NUM_LITLEN_SYMS +
+ DEFLATE_NUM_OFFSET_SYMS +
+ DEFLATE_MAX_LENS_OVERRUN];
+
+ u32 precode_decode_table[PRECODE_ENOUGH];
+ } l;
+
+ u32 litlen_decode_table[LITLEN_ENOUGH];
+ } u;
+
+ u32 offset_decode_table[OFFSET_ENOUGH];
+
+ /* used only during build_decode_table() */
+ u16 sorted_syms[DEFLATE_MAX_NUM_SYMS];
+
+ bool static_codes_loaded;
+};
+
+/*****************************************************************************
+ * Input bitstream *
+ *****************************************************************************/
+
+/*
+ * The state of the "input bitstream" consists of the following variables:
+ *
+ * - in_next: pointer to the next unread byte in the input buffer
+ *
+ * - in_end: pointer just past the end of the input buffer
+ *
+ * - bitbuf: a word-sized variable containing bits that have been read from
+ * the input buffer. The buffered bits are right-aligned
+ * (they're the low-order bits).
+ *
+ * - bitsleft: number of bits in 'bitbuf' that are valid.
+ *
+ * To make it easier for the compiler to optimize the code by keeping variables
+ * in registers, these are declared as normal variables and manipulated using
+ * macros.
+ */
+
+/*
+ * The type for the bitbuffer variable ('bitbuf' described above). For best
+ * performance, this should have size equal to a machine word.
+ *
+ * 64-bit platforms have a significant advantage: they get a bigger bitbuffer
+ * which they have to fill less often.
+ */
+typedef machine_word_t bitbuf_t;
+
+/*
+ * Number of bits the bitbuffer variable can hold.
+ *
+ * This is one less than the obvious value because of the optimized arithmetic
+ * in FILL_BITS_WORDWISE() that leaves 'bitsleft' in the range
+ * [WORDBITS - 8, WORDBITS - 1] rather than [WORDBITS - 7, WORDBITS].
+ */
+#define BITBUF_NBITS (8 * sizeof(bitbuf_t) - 1)
+
+/*
+ * The maximum number of bits that can be ensured in the bitbuffer variable,
+ * i.e. the maximum value of 'n' that can be passed ENSURE_BITS(n). The decoder
+ * only reads whole bytes from memory, so this is the lowest value of 'bitsleft'
+ * at which another byte cannot be read without first consuming some bits.
+ */
+#define MAX_ENSURE (BITBUF_NBITS - 7)
+
+/*
+ * Evaluates to true if 'n' is a valid argument to ENSURE_BITS(n), or false if
+ * 'n' is too large to be passed to ENSURE_BITS(n). Note: if 'n' is a compile
+ * time constant, then this expression will be a compile-type constant.
+ * Therefore, CAN_ENSURE() can be used choose between alternative
+ * implementations at compile time.
+ */
+#define CAN_ENSURE(n) ((n) <= MAX_ENSURE)
+
+/*
+ * Fill the bitbuffer variable, reading one byte at a time.
+ *
+ * If we would overread the input buffer, we just don't read anything, leaving
+ * the bits zeroed but marking them filled. This simplifies the decompressor
+ * because it removes the need to distinguish between real overreads and
+ * overreads that occur only because of the decompressor's own lookahead.
+ *
+ * The disadvantage is that real overreads are not detected immediately.
+ * However, this is safe because the decompressor is still guaranteed to make
+ * forward progress when presented never-ending 0 bits. In an existing block
+ * output will be getting generated, whereas new blocks can only be uncompressed
+ * (since the type code for uncompressed blocks is 0), for which we check for
+ * previous overread. But even if we didn't check, uncompressed blocks would
+ * fail to validate because LEN would not equal ~NLEN. So the decompressor will
+ * eventually either detect that the output buffer is full, or detect invalid
+ * input, or finish the final block.
+ */
+#define FILL_BITS_BYTEWISE() \
+do { \
+ if (likely(in_next != in_end)) \
+ bitbuf |= (bitbuf_t)*in_next++ << bitsleft; \
+ else \
+ overrun_count++; \
+ bitsleft += 8; \
+} while (bitsleft <= BITBUF_NBITS - 8)
+
+/*
+ * Fill the bitbuffer variable by reading the next word from the input buffer
+ * and branchlessly updating 'in_next' and 'bitsleft' based on how many bits
+ * were filled. This can be significantly faster than FILL_BITS_BYTEWISE().
+ * However, for this to work correctly, the word must be interpreted in
+ * little-endian format. In addition, the memory access may be unaligned.
+ * Therefore, this method is most efficient on little-endian architectures that
+ * support fast unaligned access, such as x86 and x86_64.
+ *
+ * For faster updating of 'bitsleft', we consider the bitbuffer size in bits to
+ * be 1 less than the word size and therefore be all 1 bits. Then the number of
+ * bits filled is the value of the 0 bits in position >= 3 when changed to 1.
+ * E.g. if words are 64 bits and bitsleft = 16 = b010000 then we refill b101000
+ * = 40 bits = 5 bytes. This uses only 4 operations to update 'in_next' and
+ * 'bitsleft': one each of +, ^, >>, and |. (Not counting operations the
+ * compiler optimizes out.) In contrast, the alternative of:
+ *
+ * in_next += (BITBUF_NBITS - bitsleft) >> 3;
+ * bitsleft += (BITBUF_NBITS - bitsleft) & ~7;
+ *
+ * (where BITBUF_NBITS would be WORDBITS rather than WORDBITS - 1) would on
+ * average refill an extra bit, but uses 5 operations: two +, and one each of
+ * -, >>, and &. Also the - and & must be completed before 'bitsleft' can be
+ * updated, while the current solution updates 'bitsleft' with no dependencies.
+ */
+#define FILL_BITS_WORDWISE() \
+do { \
+ /* BITBUF_NBITS must be all 1's in binary, see above */ \
+ STATIC_ASSERT((BITBUF_NBITS & (BITBUF_NBITS + 1)) == 0);\
+ \
+ bitbuf |= get_unaligned_leword(in_next) << bitsleft; \
+ in_next += (bitsleft ^ BITBUF_NBITS) >> 3; \
+ bitsleft |= BITBUF_NBITS & ~7; \
+} while (0)
+
+/*
+ * Does the bitbuffer variable currently contain at least 'n' bits?
+ */
+#define HAVE_BITS(n) (bitsleft >= (n))
+
+/*
+ * Load more bits from the input buffer until the specified number of bits is
+ * present in the bitbuffer variable. 'n' cannot be too large; see MAX_ENSURE
+ * and CAN_ENSURE().
+ */
+#define ENSURE_BITS(n) \
+if (!HAVE_BITS(n)) { \
+ if (CPU_IS_LITTLE_ENDIAN() && \
+ UNALIGNED_ACCESS_IS_FAST && \
+ likely(in_end - in_next >= sizeof(bitbuf_t))) \
+ FILL_BITS_WORDWISE(); \
+ else \
+ FILL_BITS_BYTEWISE(); \
+}
+
+/*
+ * Return the next 'n' bits from the bitbuffer variable without removing them.
+ */
+#define BITS(n) ((u32)bitbuf & (((u32)1 << (n)) - 1))
+
+/*
+ * Remove the next 'n' bits from the bitbuffer variable.
+ */
+#define REMOVE_BITS(n) (bitbuf >>= (n), bitsleft -= (n))
+
+/*
+ * Remove and return the next 'n' bits from the bitbuffer variable.
+ */
+#define POP_BITS(n) (tmp32 = BITS(n), REMOVE_BITS(n), tmp32)
+
+/*
+ * Verify that the input buffer hasn't been overread, then align the input to
+ * the next byte boundary, discarding any remaining bits in the current byte.
+ *
+ * Note that if the bitbuffer variable currently contains more than 7 bits, then
+ * we must rewind 'in_next', effectively putting those bits back. Only the bits
+ * in what would be the "current" byte if we were reading one byte at a time can
+ * be actually discarded.
+ */
+#define ALIGN_INPUT() \
+do { \
+ SAFETY_CHECK(overrun_count <= (bitsleft >> 3)); \
+ in_next -= (bitsleft >> 3) - overrun_count; \
+ overrun_count = 0; \
+ bitbuf = 0; \
+ bitsleft = 0; \
+} while(0)
+
+/*
+ * Read a 16-bit value from the input. This must have been preceded by a call
+ * to ALIGN_INPUT(), and the caller must have already checked for overrun.
+ */
+#define READ_U16() (tmp16 = get_unaligned_le16(in_next), in_next += 2, tmp16)
+
+/*****************************************************************************
+ * Huffman decoding *
+ *****************************************************************************/
+
+/*
+ * A decode table for order TABLEBITS consists of a main table of (1 <<
+ * TABLEBITS) entries followed by a variable number of subtables.
+ *
+ * The decoding algorithm takes the next TABLEBITS bits of compressed data and
+ * uses them as an index into the decode table. The resulting entry is either a
+ * "direct entry", meaning that it contains the value desired, or a "subtable
+ * pointer", meaning that the entry references a subtable that must be indexed
+ * using more bits of the compressed data to decode the symbol.
+ *
+ * Each decode table (a main table along with its subtables, if any) is
+ * associated with a Huffman code. Logically, the result of a decode table
+ * lookup is a symbol from the alphabet from which the corresponding Huffman
+ * code was constructed. A symbol with codeword length n <= TABLEBITS is
+ * associated with 2**(TABLEBITS - n) direct entries in the table, whereas a
+ * symbol with codeword length n > TABLEBITS is associated with one or more
+ * subtable entries.
+ *
+ * On top of this basic design, we implement several optimizations:
+ *
+ * - We store the length of each codeword directly in each of its decode table
+ * entries. This allows the codeword length to be produced without indexing
+ * an additional table.
+ *
+ * - When beneficial, we don't store the Huffman symbol itself, but instead data
+ * generated from it. For example, when decoding an offset symbol in DEFLATE,
+ * it's more efficient if we can decode the offset base and number of extra
+ * offset bits directly rather than decoding the offset symbol and then
+ * looking up both of those values in an additional table or tables.
+ *
+ * The size of each decode table entry is 32 bits, which provides slightly
+ * better performance than 16-bit entries on 32 and 64 bit processers, provided
+ * that the table doesn't get so large that it takes up too much memory and
+ * starts generating cache misses. The bits of each decode table entry are
+ * defined as follows:
+ *
+ * - Bits 30 -- 31: flags (see below)
+ * - Bits 8 -- 29: decode result: a Huffman symbol or related data
+ * - Bits 0 -- 7: codeword length
+ */
+
+/*
+ * This flag is set in all main decode table entries that represent subtable
+ * pointers.
+ */
+#define HUFFDEC_SUBTABLE_POINTER 0x80000000
+
+/*
+ * This flag is set in all entries in the litlen decode table that represent
+ * literals.
+ */
+#define HUFFDEC_LITERAL 0x40000000
+
+/* Mask for extracting the codeword length from a decode table entry. */
+#define HUFFDEC_LENGTH_MASK 0xFF
+
+/* Shift to extract the decode result from a decode table entry. */
+#define HUFFDEC_RESULT_SHIFT 8
+
+/* Shift a decode result into its position in the decode table entry. */
+#define HUFFDEC_RESULT_ENTRY(result) ((u32)(result) << HUFFDEC_RESULT_SHIFT)
+
+/* The decode result for each precode symbol. There is no special optimization
+ * for the precode; the decode result is simply the symbol value. */
+static const u32 precode_decode_results[DEFLATE_NUM_PRECODE_SYMS] = {
+#define ENTRY(presym) HUFFDEC_RESULT_ENTRY(presym)
+ ENTRY(0) , ENTRY(1) , ENTRY(2) , ENTRY(3) ,
+ ENTRY(4) , ENTRY(5) , ENTRY(6) , ENTRY(7) ,
+ ENTRY(8) , ENTRY(9) , ENTRY(10) , ENTRY(11) ,
+ ENTRY(12) , ENTRY(13) , ENTRY(14) , ENTRY(15) ,
+ ENTRY(16) , ENTRY(17) , ENTRY(18) ,
+#undef ENTRY
+};
+
+/* The decode result for each litlen symbol. For literals, this is the literal
+ * value itself and the HUFFDEC_LITERAL flag. For lengths, this is the length
+ * base and the number of extra length bits. */
+static const u32 litlen_decode_results[DEFLATE_NUM_LITLEN_SYMS] = {
+
+ /* Literals */
+#define ENTRY(literal) (HUFFDEC_LITERAL | HUFFDEC_RESULT_ENTRY(literal))
+ ENTRY(0) , ENTRY(1) , ENTRY(2) , ENTRY(3) ,
+ ENTRY(4) , ENTRY(5) , ENTRY(6) , ENTRY(7) ,
+ ENTRY(8) , ENTRY(9) , ENTRY(10) , ENTRY(11) ,
+ ENTRY(12) , ENTRY(13) , ENTRY(14) , ENTRY(15) ,
+ ENTRY(16) , ENTRY(17) , ENTRY(18) , ENTRY(19) ,
+ ENTRY(20) , ENTRY(21) , ENTRY(22) , ENTRY(23) ,
+ ENTRY(24) , ENTRY(25) , ENTRY(26) , ENTRY(27) ,
+ ENTRY(28) , ENTRY(29) , ENTRY(30) , ENTRY(31) ,
+ ENTRY(32) , ENTRY(33) , ENTRY(34) , ENTRY(35) ,
+ ENTRY(36) , ENTRY(37) , ENTRY(38) , ENTRY(39) ,
+ ENTRY(40) , ENTRY(41) , ENTRY(42) , ENTRY(43) ,
+ ENTRY(44) , ENTRY(45) , ENTRY(46) , ENTRY(47) ,
+ ENTRY(48) , ENTRY(49) , ENTRY(50) , ENTRY(51) ,
+ ENTRY(52) , ENTRY(53) , ENTRY(54) , ENTRY(55) ,
+ ENTRY(56) , ENTRY(57) , ENTRY(58) , ENTRY(59) ,
+ ENTRY(60) , ENTRY(61) , ENTRY(62) , ENTRY(63) ,
+ ENTRY(64) , ENTRY(65) , ENTRY(66) , ENTRY(67) ,
+ ENTRY(68) , ENTRY(69) , ENTRY(70) , ENTRY(71) ,
+ ENTRY(72) , ENTRY(73) , ENTRY(74) , ENTRY(75) ,
+ ENTRY(76) , ENTRY(77) , ENTRY(78) , ENTRY(79) ,
+ ENTRY(80) , ENTRY(81) , ENTRY(82) , ENTRY(83) ,
+ ENTRY(84) , ENTRY(85) , ENTRY(86) , ENTRY(87) ,
+ ENTRY(88) , ENTRY(89) , ENTRY(90) , ENTRY(91) ,
+ ENTRY(92) , ENTRY(93) , ENTRY(94) , ENTRY(95) ,
+ ENTRY(96) , ENTRY(97) , ENTRY(98) , ENTRY(99) ,
+ ENTRY(100) , ENTRY(101) , ENTRY(102) , ENTRY(103) ,
+ ENTRY(104) , ENTRY(105) , ENTRY(106) , ENTRY(107) ,
+ ENTRY(108) , ENTRY(109) , ENTRY(110) , ENTRY(111) ,
+ ENTRY(112) , ENTRY(113) , ENTRY(114) , ENTRY(115) ,
+ ENTRY(116) , ENTRY(117) , ENTRY(118) , ENTRY(119) ,
+ ENTRY(120) , ENTRY(121) , ENTRY(122) , ENTRY(123) ,
+ ENTRY(124) , ENTRY(125) , ENTRY(126) , ENTRY(127) ,
+ ENTRY(128) , ENTRY(129) , ENTRY(130) , ENTRY(131) ,
+ ENTRY(132) , ENTRY(133) , ENTRY(134) , ENTRY(135) ,
+ ENTRY(136) , ENTRY(137) , ENTRY(138) , ENTRY(139) ,
+ ENTRY(140) , ENTRY(141) , ENTRY(142) , ENTRY(143) ,
+ ENTRY(144) , ENTRY(145) , ENTRY(146) , ENTRY(147) ,
+ ENTRY(148) , ENTRY(149) , ENTRY(150) , ENTRY(151) ,
+ ENTRY(152) , ENTRY(153) , ENTRY(154) , ENTRY(155) ,
+ ENTRY(156) , ENTRY(157) , ENTRY(158) , ENTRY(159) ,
+ ENTRY(160) , ENTRY(161) , ENTRY(162) , ENTRY(163) ,
+ ENTRY(164) , ENTRY(165) , ENTRY(166) , ENTRY(167) ,
+ ENTRY(168) , ENTRY(169) , ENTRY(170) , ENTRY(171) ,
+ ENTRY(172) , ENTRY(173) , ENTRY(174) , ENTRY(175) ,
+ ENTRY(176) , ENTRY(177) , ENTRY(178) , ENTRY(179) ,
+ ENTRY(180) , ENTRY(181) , ENTRY(182) , ENTRY(183) ,
+ ENTRY(184) , ENTRY(185) , ENTRY(186) , ENTRY(187) ,
+ ENTRY(188) , ENTRY(189) , ENTRY(190) , ENTRY(191) ,
+ ENTRY(192) , ENTRY(193) , ENTRY(194) , ENTRY(195) ,
+ ENTRY(196) , ENTRY(197) , ENTRY(198) , ENTRY(199) ,
+ ENTRY(200) , ENTRY(201) , ENTRY(202) , ENTRY(203) ,
+ ENTRY(204) , ENTRY(205) , ENTRY(206) , ENTRY(207) ,
+ ENTRY(208) , ENTRY(209) , ENTRY(210) , ENTRY(211) ,
+ ENTRY(212) , ENTRY(213) , ENTRY(214) , ENTRY(215) ,
+ ENTRY(216) , ENTRY(217) , ENTRY(218) , ENTRY(219) ,
+ ENTRY(220) , ENTRY(221) , ENTRY(222) , ENTRY(223) ,
+ ENTRY(224) , ENTRY(225) , ENTRY(226) , ENTRY(227) ,
+ ENTRY(228) , ENTRY(229) , ENTRY(230) , ENTRY(231) ,
+ ENTRY(232) , ENTRY(233) , ENTRY(234) , ENTRY(235) ,
+ ENTRY(236) , ENTRY(237) , ENTRY(238) , ENTRY(239) ,
+ ENTRY(240) , ENTRY(241) , ENTRY(242) , ENTRY(243) ,
+ ENTRY(244) , ENTRY(245) , ENTRY(246) , ENTRY(247) ,
+ ENTRY(248) , ENTRY(249) , ENTRY(250) , ENTRY(251) ,
+ ENTRY(252) , ENTRY(253) , ENTRY(254) , ENTRY(255) ,
+#undef ENTRY
+
+#define HUFFDEC_EXTRA_LENGTH_BITS_MASK 0xFF
+#define HUFFDEC_LENGTH_BASE_SHIFT 8
+#define HUFFDEC_END_OF_BLOCK_LENGTH 0
+
+#define ENTRY(length_base, num_extra_bits) HUFFDEC_RESULT_ENTRY( \
+ ((u32)(length_base) << HUFFDEC_LENGTH_BASE_SHIFT) | (num_extra_bits))
+
+ /* End of block */
+ ENTRY(HUFFDEC_END_OF_BLOCK_LENGTH, 0),
+
+ /* Lengths */
+ ENTRY(3 , 0) , ENTRY(4 , 0) , ENTRY(5 , 0) , ENTRY(6 , 0),
+ ENTRY(7 , 0) , ENTRY(8 , 0) , ENTRY(9 , 0) , ENTRY(10 , 0),
+ ENTRY(11 , 1) , ENTRY(13 , 1) , ENTRY(15 , 1) , ENTRY(17 , 1),
+ ENTRY(19 , 2) , ENTRY(23 , 2) , ENTRY(27 , 2) , ENTRY(31 , 2),
+ ENTRY(35 , 3) , ENTRY(43 , 3) , ENTRY(51 , 3) , ENTRY(59 , 3),
+ ENTRY(67 , 4) , ENTRY(83 , 4) , ENTRY(99 , 4) , ENTRY(115, 4),
+ ENTRY(131, 5) , ENTRY(163, 5) , ENTRY(195, 5) , ENTRY(227, 5),
+ ENTRY(258, 0) , ENTRY(258, 0) , ENTRY(258, 0) ,
+#undef ENTRY
+};
+
+/* The decode result for each offset symbol. This is the offset base and the
+ * number of extra offset bits. */
+static const u32 offset_decode_results[DEFLATE_NUM_OFFSET_SYMS] = {
+
+#define HUFFDEC_EXTRA_OFFSET_BITS_SHIFT 16
+#define HUFFDEC_OFFSET_BASE_MASK (((u32)1 << HUFFDEC_EXTRA_OFFSET_BITS_SHIFT) - 1)
+
+#define ENTRY(offset_base, num_extra_bits) HUFFDEC_RESULT_ENTRY( \
+ ((u32)(num_extra_bits) << HUFFDEC_EXTRA_OFFSET_BITS_SHIFT) | \
+ (offset_base))
+ ENTRY(1 , 0) , ENTRY(2 , 0) , ENTRY(3 , 0) , ENTRY(4 , 0) ,
+ ENTRY(5 , 1) , ENTRY(7 , 1) , ENTRY(9 , 2) , ENTRY(13 , 2) ,
+ ENTRY(17 , 3) , ENTRY(25 , 3) , ENTRY(33 , 4) , ENTRY(49 , 4) ,
+ ENTRY(65 , 5) , ENTRY(97 , 5) , ENTRY(129 , 6) , ENTRY(193 , 6) ,
+ ENTRY(257 , 7) , ENTRY(385 , 7) , ENTRY(513 , 8) , ENTRY(769 , 8) ,
+ ENTRY(1025 , 9) , ENTRY(1537 , 9) , ENTRY(2049 , 10) , ENTRY(3073 , 10) ,
+ ENTRY(4097 , 11) , ENTRY(6145 , 11) , ENTRY(8193 , 12) , ENTRY(12289 , 12) ,
+ ENTRY(16385 , 13) , ENTRY(24577 , 13) , ENTRY(32769 , 14) , ENTRY(49153 , 14) ,
+#undef ENTRY
+};
+
+/*
+ * Build a table for fast decoding of symbols from a Huffman code. As input,
+ * this function takes the codeword length of each symbol which may be used in
+ * the code. As output, it produces a decode table for the canonical Huffman
+ * code described by the codeword lengths. The decode table is built with the
+ * assumption that it will be indexed with "bit-reversed" codewords, where the
+ * low-order bit is the first bit of the codeword. This format is used for all
+ * Huffman codes in DEFLATE.
+ *
+ * @decode_table
+ * The array in which the decode table will be generated. This array must
+ * have sufficient length; see the definition of the ENOUGH numbers.
+ * @lens
+ * An array which provides, for each symbol, the length of the
+ * corresponding codeword in bits, or 0 if the symbol is unused. This may
+ * alias @decode_table, since nothing is written to @decode_table until all
+ * @lens have been consumed. All codeword lengths are assumed to be <=
+ * @max_codeword_len but are otherwise considered untrusted. If they do
+ * not form a valid Huffman code, then the decode table is not built and
+ * %false is returned.
+ * @num_syms
+ * The number of symbols in the code, including all unused symbols.
+ * @decode_results
+ * An array which provides, for each symbol, the actual value to store into
+ * the decode table. This value will be directly produced as the result of
+ * decoding that symbol, thereby moving the indirection out of the decode
+ * loop and into the table initialization.
+ * @table_bits
+ * The log base-2 of the number of main table entries to use.
+ * @max_codeword_len
+ * The maximum allowed codeword length for this Huffman code.
+ * Must be <= DEFLATE_MAX_CODEWORD_LEN.
+ * @sorted_syms
+ * A temporary array of length @num_syms.
+ *
+ * Returns %true if successful; %false if the codeword lengths do not form a
+ * valid Huffman code.
+ */
+static bool
+build_decode_table(u32 decode_table[],
+ const len_t lens[],
+ const unsigned num_syms,
+ const u32 decode_results[],
+ const unsigned table_bits,
+ const unsigned max_codeword_len,
+ u16 *sorted_syms)
+{
+ unsigned len_counts[DEFLATE_MAX_CODEWORD_LEN + 1];
+ unsigned offsets[DEFLATE_MAX_CODEWORD_LEN + 1];
+ unsigned sym; /* current symbol */
+ unsigned codeword; /* current codeword, bit-reversed */
+ unsigned len; /* current codeword length in bits */
+ unsigned count; /* num codewords remaining with this length */
+ u32 codespace_used; /* codespace used out of '2^max_codeword_len' */
+ unsigned cur_table_end; /* end index of current table */
+ unsigned subtable_prefix; /* codeword prefix of current subtable */
+ unsigned subtable_start; /* start index of current subtable */
+ unsigned subtable_bits; /* log2 of current subtable length */
+
+ /* Count how many codewords have each length, including 0. */
+ for (len = 0; len <= max_codeword_len; len++)
+ len_counts[len] = 0;
+ for (sym = 0; sym < num_syms; sym++)
+ len_counts[lens[sym]]++;
+
+ /*
+ * Sort the symbols primarily by increasing codeword length and
+ * secondarily by increasing symbol value; or equivalently by their
+ * codewords in lexicographic order, since a canonical code is assumed.
+ *
+ * For efficiency, also compute 'codespace_used' in the same pass over
+ * 'len_counts[]' used to build 'offsets[]' for sorting.
+ */
+
+ /* Ensure that 'codespace_used' cannot overflow. */
+ STATIC_ASSERT(sizeof(codespace_used) == 4);
+ STATIC_ASSERT(UINT32_MAX / (1U << (DEFLATE_MAX_CODEWORD_LEN - 1)) >=
+ DEFLATE_MAX_NUM_SYMS);
+
+ offsets[0] = 0;
+ offsets[1] = len_counts[0];
+ codespace_used = 0;
+ for (len = 1; len < max_codeword_len; len++) {
+ offsets[len + 1] = offsets[len] + len_counts[len];
+ codespace_used = (codespace_used << 1) + len_counts[len];
+ }
+ codespace_used = (codespace_used << 1) + len_counts[len];
+
+ for (sym = 0; sym < num_syms; sym++)
+ sorted_syms[offsets[lens[sym]]++] = sym;
+
+ sorted_syms += offsets[0]; /* Skip unused symbols */
+
+ /* lens[] is done being used, so we can write to decode_table[] now. */
+
+ /*
+ * Check whether the lengths form a complete code (exactly fills the
+ * codespace), an incomplete code (doesn't fill the codespace), or an
+ * overfull code (overflows the codespace). A codeword of length 'n'
+ * uses proportion '1/(2^n)' of the codespace. An overfull code is
+ * nonsensical, so is considered invalid. An incomplete code is
+ * considered valid only in two specific cases; see below.
+ */
+
+ /* overfull code? */
+ if (unlikely(codespace_used > (1U << max_codeword_len)))
+ return false;
+
+ /* incomplete code? */
+ if (unlikely(codespace_used < (1U << max_codeword_len))) {
+ u32 entry;
+ unsigned i;
+
+ if (codespace_used == 0) {
+ /*
+ * An empty code is allowed. This can happen for the
+ * offset code in DEFLATE, since a dynamic Huffman block
+ * need not contain any matches.
+ */
+
+ /* sym=0, len=1 (arbitrary) */
+ entry = decode_results[0] | 1;
+ } else {
+ /*
+ * Allow codes with a single used symbol, with codeword
+ * length 1. The DEFLATE RFC is unclear regarding this
+ * case. What zlib's decompressor does is permit this
+ * for the litlen and offset codes and assume the
+ * codeword is '0' rather than '1'. We do the same
+ * except we allow this for precodes too, since there's
+ * no convincing reason to treat the codes differently.
+ * We also assign both codewords '0' and '1' to the
+ * symbol to avoid having to handle '1' specially.
+ */
+ if (codespace_used != (1U << (max_codeword_len - 1)) ||
+ len_counts[1] != 1)
+ return false;
+ entry = decode_results[*sorted_syms] | 1;
+ }
+ /*
+ * Note: the decode table still must be fully initialized, in
+ * case the stream is malformed and contains bits from the part
+ * of the codespace the incomplete code doesn't use.
+ */
+ for (i = 0; i < (1U << table_bits); i++)
+ decode_table[i] = entry;
+ return true;
+ }
+
+ /*
+ * The lengths form a complete code. Now, enumerate the codewords in
+ * lexicographic order and fill the decode table entries for each one.
+ *
+ * First, process all codewords with len <= table_bits. Each one gets
+ * '2^(table_bits-len)' direct entries in the table.
+ *
+ * Since DEFLATE uses bit-reversed codewords, these entries aren't
+ * consecutive but rather are spaced '2^len' entries apart. This makes
+ * filling them naively somewhat awkward and inefficient, since strided
+ * stores are less cache-friendly and preclude the use of word or
+ * vector-at-a-time stores to fill multiple entries per instruction.
+ *
+ * To optimize this, we incrementally double the table size. When
+ * processing codewords with length 'len', the table is treated as
+ * having only '2^len' entries, so each codeword uses just one entry.
+ * Then, each time 'len' is incremented, the table size is doubled and
+ * the first half is copied to the second half. This significantly
+ * improves performance over naively doing strided stores.
+ *
+ * Note that some entries copied for each table doubling may not have
+ * been initialized yet, but it doesn't matter since they're guaranteed
+ * to be initialized later (because the Huffman code is complete).
+ */
+ codeword = 0;
+ len = 1;
+ while ((count = len_counts[len]) == 0)
+ len++;
+ cur_table_end = 1U << len;
+ while (len <= table_bits) {
+ /* Process all 'count' codewords with length 'len' bits. */
+ do {
+ unsigned bit;
+
+ /* Fill the first entry for the current codeword. */
+ decode_table[codeword] =
+ decode_results[*sorted_syms++] | len;
+
+ if (codeword == cur_table_end - 1) {
+ /* Last codeword (all 1's) */
+ for (; len < table_bits; len++) {
+ memcpy(&decode_table[cur_table_end],
+ decode_table,
+ cur_table_end *
+ sizeof(decode_table[0]));
+ cur_table_end <<= 1;
+ }
+ return true;
+ }
+ /*
+ * To advance to the lexicographically next codeword in
+ * the canonical code, the codeword must be incremented,
+ * then 0's must be appended to the codeword as needed
+ * to match the next codeword's length.
+ *
+ * Since the codeword is bit-reversed, appending 0's is
+ * a no-op. However, incrementing it is nontrivial. To
+ * do so efficiently, use the 'bsr' instruction to find
+ * the last (highest order) 0 bit in the codeword, set
+ * it, and clear any later (higher order) 1 bits. But
+ * 'bsr' actually finds the highest order 1 bit, so to
+ * use it first flip all bits in the codeword by XOR'ing
+ * it with (1U << len) - 1 == cur_table_end - 1.
+ */
+ bit = 1U << bsr32(codeword ^ (cur_table_end - 1));
+ codeword &= bit - 1;
+ codeword |= bit;
+ } while (--count);
+
+ /* Advance to the next codeword length. */
+ do {
+ if (++len <= table_bits) {
+ memcpy(&decode_table[cur_table_end],
+ decode_table,
+ cur_table_end * sizeof(decode_table[0]));
+ cur_table_end <<= 1;
+ }
+ } while ((count = len_counts[len]) == 0);
+ }
+
+ /* Process codewords with len > table_bits. These require subtables. */
+ cur_table_end = 1U << table_bits;
+ subtable_prefix = -1;
+ subtable_start = 0;
+ for (;;) {
+ u32 entry;
+ unsigned i;
+ unsigned stride;
+ unsigned bit;
+
+ /*
+ * Start a new subtable if the first 'table_bits' bits of the
+ * codeword don't match the prefix of the current subtable.
+ */
+ if ((codeword & ((1U << table_bits) - 1)) != subtable_prefix) {
+ subtable_prefix = (codeword & ((1U << table_bits) - 1));
+ subtable_start = cur_table_end;
+ /*
+ * Calculate the subtable length. If the codeword has
+ * length 'table_bits + n', then the subtable needs
+ * '2^n' entries. But it may need more; if fewer than
+ * '2^n' codewords of length 'table_bits + n' remain,
+ * then the length will need to be incremented to bring
+ * in longer codewords until the subtable can be
+ * completely filled. Note that because the Huffman
+ * code is complete, it will always be possible to fill
+ * the subtable eventually.
+ */
+ subtable_bits = len - table_bits;
+ codespace_used = count;
+ while (codespace_used < (1U << subtable_bits)) {
+ subtable_bits++;
+ codespace_used = (codespace_used << 1) +
+ len_counts[table_bits + subtable_bits];
+ }
+ cur_table_end = subtable_start + (1U << subtable_bits);
+
+ /*
+ * Create the entry that points from the main table to
+ * the subtable. This entry contains the index of the
+ * start of the subtable and the number of bits with
+ * which the subtable is indexed (the log base 2 of the
+ * number of entries it contains).
+ */
+ decode_table[subtable_prefix] =
+ HUFFDEC_SUBTABLE_POINTER |
+ HUFFDEC_RESULT_ENTRY(subtable_start) |
+ subtable_bits;
+ }
+
+ /* Fill the subtable entries for the current codeword. */
+ entry = decode_results[*sorted_syms++] | (len - table_bits);
+ i = subtable_start + (codeword >> table_bits);
+ stride = 1U << (len - table_bits);
+ do {
+ decode_table[i] = entry;
+ i += stride;
+ } while (i < cur_table_end);
+
+ /* Advance to the next codeword. */
+ if (codeword == (1U << len) - 1) /* last codeword (all 1's)? */
+ return true;
+ bit = 1U << bsr32(codeword ^ ((1U << len) - 1));
+ codeword &= bit - 1;
+ codeword |= bit;
+ count--;
+ while (count == 0)
+ count = len_counts[++len];
+ }
+}
+
+/* Build the decode table for the precode. */
+static bool
+build_precode_decode_table(struct libdeflate_decompressor *d)
+{
+ /* When you change TABLEBITS, you must change ENOUGH, and vice versa! */
+ STATIC_ASSERT(PRECODE_TABLEBITS == 7 && PRECODE_ENOUGH == 128);
+
+ return build_decode_table(d->u.l.precode_decode_table,
+ d->u.precode_lens,
+ DEFLATE_NUM_PRECODE_SYMS,
+ precode_decode_results,
+ PRECODE_TABLEBITS,
+ DEFLATE_MAX_PRE_CODEWORD_LEN,
+ d->sorted_syms);
+}
+
+/* Build the decode table for the literal/length code. */
+static bool
+build_litlen_decode_table(struct libdeflate_decompressor *d,
+ unsigned num_litlen_syms, unsigned num_offset_syms)
+{
+ /* When you change TABLEBITS, you must change ENOUGH, and vice versa! */
+ STATIC_ASSERT(LITLEN_TABLEBITS == 10 && LITLEN_ENOUGH == 1334);
+
+ return build_decode_table(d->u.litlen_decode_table,
+ d->u.l.lens,
+ num_litlen_syms,
+ litlen_decode_results,
+ LITLEN_TABLEBITS,
+ DEFLATE_MAX_LITLEN_CODEWORD_LEN,
+ d->sorted_syms);
+}
+
+/* Build the decode table for the offset code. */
+static bool
+build_offset_decode_table(struct libdeflate_decompressor *d,
+ unsigned num_litlen_syms, unsigned num_offset_syms)
+{
+ /* When you change TABLEBITS, you must change ENOUGH, and vice versa! */
+ STATIC_ASSERT(OFFSET_TABLEBITS == 8 && OFFSET_ENOUGH == 402);
+
+ return build_decode_table(d->offset_decode_table,
+ d->u.l.lens + num_litlen_syms,
+ num_offset_syms,
+ offset_decode_results,
+ OFFSET_TABLEBITS,
+ DEFLATE_MAX_OFFSET_CODEWORD_LEN,
+ d->sorted_syms);
+}
+
+static forceinline machine_word_t
+repeat_byte(u8 b)
+{
+ machine_word_t v;
+
+ STATIC_ASSERT(WORDBITS == 32 || WORDBITS == 64);
+
+ v = b;
+ v |= v << 8;
+ v |= v << 16;
+ v |= v << ((WORDBITS == 64) ? 32 : 0);
+ return v;
+}
+
+static forceinline void
+copy_word_unaligned(const void *src, void *dst)
+{
+ store_word_unaligned(load_word_unaligned(src), dst);
+}
+
+/*****************************************************************************
+ * Main decompression routine
+ *****************************************************************************/
+
+typedef enum libdeflate_result (*decompress_func_t)
+ (struct libdeflate_decompressor * restrict d,
+ const void * restrict in, size_t in_nbytes,
+ void * restrict out, size_t out_nbytes_avail,
+ size_t *actual_in_nbytes_ret, size_t *actual_out_nbytes_ret);
+
+#undef DEFAULT_IMPL
+#undef DISPATCH
+#if defined(__i386__) || defined(__x86_64__)
+# include "x86/decompress_impl.h"
+#endif
+
+#ifndef DEFAULT_IMPL
+# define FUNCNAME deflate_decompress_default
+# define ATTRIBUTES
+# include "decompress_template.h"
+# define DEFAULT_IMPL deflate_decompress_default
+#endif
+
+#ifdef DISPATCH
+static enum libdeflate_result
+dispatch(struct libdeflate_decompressor * restrict d,
+ const void * restrict in, size_t in_nbytes,
+ void * restrict out, size_t out_nbytes_avail,
+ size_t *actual_in_nbytes_ret, size_t *actual_out_nbytes_ret);
+
+static volatile decompress_func_t decompress_impl = dispatch;
+
+/* Choose the fastest implementation at runtime */
+static enum libdeflate_result
+dispatch(struct libdeflate_decompressor * restrict d,
+ const void * restrict in, size_t in_nbytes,
+ void * restrict out, size_t out_nbytes_avail,
+ size_t *actual_in_nbytes_ret, size_t *actual_out_nbytes_ret)
+{
+ decompress_func_t f = arch_select_decompress_func();
+
+ if (f == NULL)
+ f = DEFAULT_IMPL;
+
+ decompress_impl = f;
+ return (*f)(d, in, in_nbytes, out, out_nbytes_avail,
+ actual_in_nbytes_ret, actual_out_nbytes_ret);
+}
+#else
+# define decompress_impl DEFAULT_IMPL /* only one implementation, use it */
+#endif
+
+
+/*
+ * This is the main DEFLATE decompression routine. See libdeflate.h for the
+ * documentation.
+ *
+ * Note that the real code is in decompress_template.h. The part here just
+ * handles calling the appropriate implementation depending on the CPU features
+ * at runtime.
+ */
+LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
+libdeflate_deflate_decompress_ex(struct libdeflate_decompressor * restrict d,
+ const void * restrict in, size_t in_nbytes,
+ void * restrict out, size_t out_nbytes_avail,
+ size_t *actual_in_nbytes_ret,
+ size_t *actual_out_nbytes_ret)
+{
+ return decompress_impl(d, in, in_nbytes, out, out_nbytes_avail,
+ actual_in_nbytes_ret, actual_out_nbytes_ret);
+}
+
+LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
+libdeflate_deflate_decompress(struct libdeflate_decompressor * restrict d,
+ const void * restrict in, size_t in_nbytes,
+ void * restrict out, size_t out_nbytes_avail,
+ size_t *actual_out_nbytes_ret)
+{
+ return libdeflate_deflate_decompress_ex(d, in, in_nbytes,
+ out, out_nbytes_avail,
+ NULL, actual_out_nbytes_ret);
+}
+
+LIBDEFLATEEXPORT struct libdeflate_decompressor * LIBDEFLATEAPI
+libdeflate_alloc_decompressor(void)
+{
+ /*
+ * Note that only certain parts of the decompressor actually must be
+ * initialized here:
+ *
+ * - 'static_codes_loaded' must be initialized to false.
+ *
+ * - The first half of the main portion of each decode table must be
+ * initialized to any value, to avoid reading from uninitialized
+ * memory during table expansion in build_decode_table(). (Although,
+ * this is really just to avoid warnings with dynamic tools like
+ * valgrind, since build_decode_table() is guaranteed to initialize
+ * all entries eventually anyway.)
+ *
+ * But for simplicity, we currently just zero the whole decompressor.
+ */
+ struct libdeflate_decompressor *d = libdeflate_malloc(sizeof(*d));
+
+ if (d == NULL)
+ return NULL;
+ memset(d, 0, sizeof(*d));
+ return d;
+}
+
+LIBDEFLATEEXPORT void LIBDEFLATEAPI
+libdeflate_free_decompressor(struct libdeflate_decompressor *d)
+{
+ libdeflate_free(d);
+}
diff --git a/util/compress/libdeflate/lib/gzip_compress.c b/util/compress/libdeflate/lib/gzip_compress.c
new file mode 100644
index 000000000..3cb8803cf
--- /dev/null
+++ b/util/compress/libdeflate/lib/gzip_compress.c
@@ -0,0 +1,95 @@
+/*
+ * gzip_compress.c - compress with a gzip wrapper
+ *
+ * Originally public domain; changes after 2016-09-07 are copyrighted.
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "deflate_compress.h"
+#include "gzip_constants.h"
+#include "unaligned.h"
+
+#include "libdeflate.h"
+
+LIBDEFLATEEXPORT size_t LIBDEFLATEAPI
+libdeflate_gzip_compress(struct libdeflate_compressor *c,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail)
+{
+ u8 *out_next = out;
+ unsigned compression_level;
+ u8 xfl;
+ size_t deflate_size;
+
+ if (out_nbytes_avail <= GZIP_MIN_OVERHEAD)
+ return 0;
+
+ /* ID1 */
+ *out_next++ = GZIP_ID1;
+ /* ID2 */
+ *out_next++ = GZIP_ID2;
+ /* CM */
+ *out_next++ = GZIP_CM_DEFLATE;
+ /* FLG */
+ *out_next++ = 0;
+ /* MTIME */
+ put_unaligned_le32(GZIP_MTIME_UNAVAILABLE, out_next);
+ out_next += 4;
+ /* XFL */
+ xfl = 0;
+ compression_level = deflate_get_compression_level(c);
+ if (compression_level < 2)
+ xfl |= GZIP_XFL_FASTEST_COMPRESSION;
+ else if (compression_level >= 8)
+ xfl |= GZIP_XFL_SLOWEST_COMPRESSION;
+ *out_next++ = xfl;
+ /* OS */
+ *out_next++ = GZIP_OS_UNKNOWN; /* OS */
+
+ /* Compressed data */
+ deflate_size = libdeflate_deflate_compress(c, in, in_nbytes, out_next,
+ out_nbytes_avail - GZIP_MIN_OVERHEAD);
+ if (deflate_size == 0)
+ return 0;
+ out_next += deflate_size;
+
+ /* CRC32 */
+ put_unaligned_le32(libdeflate_crc32(0, in, in_nbytes), out_next);
+ out_next += 4;
+
+ /* ISIZE */
+ put_unaligned_le32((u32)in_nbytes, out_next);
+ out_next += 4;
+
+ return out_next - (u8 *)out;
+}
+
+LIBDEFLATEEXPORT size_t LIBDEFLATEAPI
+libdeflate_gzip_compress_bound(struct libdeflate_compressor *c,
+ size_t in_nbytes)
+{
+ return GZIP_MIN_OVERHEAD +
+ libdeflate_deflate_compress_bound(c, in_nbytes);
+}
diff --git a/util/compress/libdeflate/lib/gzip_constants.h b/util/compress/libdeflate/lib/gzip_constants.h
new file mode 100644
index 000000000..35e4728d8
--- /dev/null
+++ b/util/compress/libdeflate/lib/gzip_constants.h
@@ -0,0 +1,45 @@
+/*
+ * gzip_constants.h - constants for the gzip wrapper format
+ */
+
+#ifndef LIB_GZIP_CONSTANTS_H
+#define LIB_GZIP_CONSTANTS_H
+
+#define GZIP_MIN_HEADER_SIZE 10
+#define GZIP_FOOTER_SIZE 8
+#define GZIP_MIN_OVERHEAD (GZIP_MIN_HEADER_SIZE + GZIP_FOOTER_SIZE)
+
+#define GZIP_ID1 0x1F
+#define GZIP_ID2 0x8B
+
+#define GZIP_CM_DEFLATE 8
+
+#define GZIP_FTEXT 0x01
+#define GZIP_FHCRC 0x02
+#define GZIP_FEXTRA 0x04
+#define GZIP_FNAME 0x08
+#define GZIP_FCOMMENT 0x10
+#define GZIP_FRESERVED 0xE0
+
+#define GZIP_MTIME_UNAVAILABLE 0
+
+#define GZIP_XFL_SLOWEST_COMPRESSION 0x02
+#define GZIP_XFL_FASTEST_COMPRESSION 0x04
+
+#define GZIP_OS_FAT 0
+#define GZIP_OS_AMIGA 1
+#define GZIP_OS_VMS 2
+#define GZIP_OS_UNIX 3
+#define GZIP_OS_VM_CMS 4
+#define GZIP_OS_ATARI_TOS 5
+#define GZIP_OS_HPFS 6
+#define GZIP_OS_MACINTOSH 7
+#define GZIP_OS_Z_SYSTEM 8
+#define GZIP_OS_CP_M 9
+#define GZIP_OS_TOPS_20 10
+#define GZIP_OS_NTFS 11
+#define GZIP_OS_QDOS 12
+#define GZIP_OS_RISCOS 13
+#define GZIP_OS_UNKNOWN 255
+
+#endif /* LIB_GZIP_CONSTANTS_H */
diff --git a/util/compress/libdeflate/lib/gzip_decompress.c b/util/compress/libdeflate/lib/gzip_decompress.c
new file mode 100644
index 000000000..1b31d8a8e
--- /dev/null
+++ b/util/compress/libdeflate/lib/gzip_decompress.c
@@ -0,0 +1,148 @@
+/*
+ * gzip_decompress.c - decompress with a gzip wrapper
+ *
+ * Originally public domain; changes after 2016-09-07 are copyrighted.
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "gzip_constants.h"
+#include "unaligned.h"
+
+#include "libdeflate.h"
+
+LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
+libdeflate_gzip_decompress_ex(struct libdeflate_decompressor *d,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail,
+ size_t *actual_in_nbytes_ret,
+ size_t *actual_out_nbytes_ret)
+{
+ const u8 *in_next = in;
+ const u8 * const in_end = in_next + in_nbytes;
+ u8 flg;
+ size_t actual_in_nbytes;
+ size_t actual_out_nbytes;
+ enum libdeflate_result result;
+
+ if (in_nbytes < GZIP_MIN_OVERHEAD)
+ return LIBDEFLATE_BAD_DATA;
+
+ /* ID1 */
+ if (*in_next++ != GZIP_ID1)
+ return LIBDEFLATE_BAD_DATA;
+ /* ID2 */
+ if (*in_next++ != GZIP_ID2)
+ return LIBDEFLATE_BAD_DATA;
+ /* CM */
+ if (*in_next++ != GZIP_CM_DEFLATE)
+ return LIBDEFLATE_BAD_DATA;
+ flg = *in_next++;
+ /* MTIME */
+ in_next += 4;
+ /* XFL */
+ in_next += 1;
+ /* OS */
+ in_next += 1;
+
+ if (flg & GZIP_FRESERVED)
+ return LIBDEFLATE_BAD_DATA;
+
+ /* Extra field */
+ if (flg & GZIP_FEXTRA) {
+ u16 xlen = get_unaligned_le16(in_next);
+ in_next += 2;
+
+ if (in_end - in_next < (u32)xlen + GZIP_FOOTER_SIZE)
+ return LIBDEFLATE_BAD_DATA;
+
+ in_next += xlen;
+ }
+
+ /* Original file name (zero terminated) */
+ if (flg & GZIP_FNAME) {
+ while (*in_next++ != 0 && in_next != in_end)
+ ;
+ if (in_end - in_next < GZIP_FOOTER_SIZE)
+ return LIBDEFLATE_BAD_DATA;
+ }
+
+ /* File comment (zero terminated) */
+ if (flg & GZIP_FCOMMENT) {
+ while (*in_next++ != 0 && in_next != in_end)
+ ;
+ if (in_end - in_next < GZIP_FOOTER_SIZE)
+ return LIBDEFLATE_BAD_DATA;
+ }
+
+ /* CRC16 for gzip header */
+ if (flg & GZIP_FHCRC) {
+ in_next += 2;
+ if (in_end - in_next < GZIP_FOOTER_SIZE)
+ return LIBDEFLATE_BAD_DATA;
+ }
+
+ /* Compressed data */
+ result = libdeflate_deflate_decompress_ex(d, in_next,
+ in_end - GZIP_FOOTER_SIZE - in_next,
+ out, out_nbytes_avail,
+ &actual_in_nbytes,
+ actual_out_nbytes_ret);
+ if (result != LIBDEFLATE_SUCCESS)
+ return result;
+
+ if (actual_out_nbytes_ret)
+ actual_out_nbytes = *actual_out_nbytes_ret;
+ else
+ actual_out_nbytes = out_nbytes_avail;
+
+ in_next += actual_in_nbytes;
+
+ /* CRC32 */
+ if (libdeflate_crc32(0, out, actual_out_nbytes) !=
+ get_unaligned_le32(in_next))
+ return LIBDEFLATE_BAD_DATA;
+ in_next += 4;
+
+ /* ISIZE */
+ if ((u32)actual_out_nbytes != get_unaligned_le32(in_next))
+ return LIBDEFLATE_BAD_DATA;
+ in_next += 4;
+
+ if (actual_in_nbytes_ret)
+ *actual_in_nbytes_ret = in_next - (u8 *)in;
+
+ return LIBDEFLATE_SUCCESS;
+}
+
+LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
+libdeflate_gzip_decompress(struct libdeflate_decompressor *d,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail,
+ size_t *actual_out_nbytes_ret)
+{
+ return libdeflate_gzip_decompress_ex(d, in, in_nbytes,
+ out, out_nbytes_avail,
+ NULL, actual_out_nbytes_ret);
+}
diff --git a/util/compress/libdeflate/lib/hc_matchfinder.h b/util/compress/libdeflate/lib/hc_matchfinder.h
new file mode 100644
index 000000000..b81d32c6c
--- /dev/null
+++ b/util/compress/libdeflate/lib/hc_matchfinder.h
@@ -0,0 +1,412 @@
+/*
+ * hc_matchfinder.h - Lempel-Ziv matchfinding with a hash table of linked lists
+ *
+ * Originally public domain; changes after 2016-09-07 are copyrighted.
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * Algorithm
+ *
+ * This is a Hash Chains (hc) based matchfinder.
+ *
+ * The main data structure is a hash table where each hash bucket contains a
+ * linked list (or "chain") of sequences whose first 4 bytes share the same hash
+ * code. Each sequence is identified by its starting position in the input
+ * buffer.
+ *
+ * The algorithm processes the input buffer sequentially. At each byte
+ * position, the hash code of the first 4 bytes of the sequence beginning at
+ * that position (the sequence being matched against) is computed. This
+ * identifies the hash bucket to use for that position. Then, this hash
+ * bucket's linked list is searched for matches. Then, a new linked list node
+ * is created to represent the current sequence and is prepended to the list.
+ *
+ * This algorithm has several useful properties:
+ *
+ * - It only finds true Lempel-Ziv matches; i.e., those where the matching
+ * sequence occurs prior to the sequence being matched against.
+ *
+ * - The sequences in each linked list are always sorted by decreasing starting
+ * position. Therefore, the closest (smallest offset) matches are found
+ * first, which in many compression formats tend to be the cheapest to encode.
+ *
+ * - Although fast running time is not guaranteed due to the possibility of the
+ * lists getting very long, the worst degenerate behavior can be easily
+ * prevented by capping the number of nodes searched at each position.
+ *
+ * - If the compressor decides not to search for matches at a certain position,
+ * then that position can be quickly inserted without searching the list.
+ *
+ * - The algorithm is adaptable to sliding windows: just store the positions
+ * relative to a "base" value that is updated from time to time, and stop
+ * searching each list when the sequences get too far away.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * Optimizations
+ *
+ * The main hash table and chains handle length 4+ matches. Length 3 matches
+ * are handled by a separate hash table with no chains. This works well for
+ * typical "greedy" or "lazy"-style compressors, where length 3 matches are
+ * often only helpful if they have small offsets. Instead of searching a full
+ * chain for length 3+ matches, the algorithm just checks for one close length 3
+ * match, then focuses on finding length 4+ matches.
+ *
+ * The longest_match() and skip_positions() functions are inlined into the
+ * compressors that use them. This isn't just about saving the overhead of a
+ * function call. These functions are intended to be called from the inner
+ * loops of compressors, where giving the compiler more control over register
+ * allocation is very helpful. There is also significant benefit to be gained
+ * from allowing the CPU to predict branches independently at each call site.
+ * For example, "lazy"-style compressors can be written with two calls to
+ * longest_match(), each of which starts with a different 'best_len' and
+ * therefore has significantly different performance characteristics.
+ *
+ * Although any hash function can be used, a multiplicative hash is fast and
+ * works well.
+ *
+ * On some processors, it is significantly faster to extend matches by whole
+ * words (32 or 64 bits) instead of by individual bytes. For this to be the
+ * case, the processor must implement unaligned memory accesses efficiently and
+ * must have either a fast "find first set bit" instruction or a fast "find last
+ * set bit" instruction, depending on the processor's endianness.
+ *
+ * The code uses one loop for finding the first match and one loop for finding a
+ * longer match. Each of these loops is tuned for its respective task and in
+ * combination are faster than a single generalized loop that handles both
+ * tasks.
+ *
+ * The code also uses a tight inner loop that only compares the last and first
+ * bytes of a potential match. It is only when these bytes match that a full
+ * match extension is attempted.
+ *
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef LIB_HC_MATCHFINDER_H
+#define LIB_HC_MATCHFINDER_H
+
+#include "matchfinder_common.h"
+
+#define HC_MATCHFINDER_HASH3_ORDER 15
+#define HC_MATCHFINDER_HASH4_ORDER 16
+
+#define HC_MATCHFINDER_TOTAL_HASH_SIZE \
+ (((1UL << HC_MATCHFINDER_HASH3_ORDER) + \
+ (1UL << HC_MATCHFINDER_HASH4_ORDER)) * sizeof(mf_pos_t))
+
+struct hc_matchfinder {
+
+ /* The hash table for finding length 3 matches */
+ mf_pos_t hash3_tab[1UL << HC_MATCHFINDER_HASH3_ORDER];
+
+ /* The hash table which contains the first nodes of the linked lists for
+ * finding length 4+ matches */
+ mf_pos_t hash4_tab[1UL << HC_MATCHFINDER_HASH4_ORDER];
+
+ /* The "next node" references for the linked lists. The "next node" of
+ * the node for the sequence with position 'pos' is 'next_tab[pos]'. */
+ mf_pos_t next_tab[MATCHFINDER_WINDOW_SIZE];
+
+}
+#ifdef _aligned_attribute
+ _aligned_attribute(MATCHFINDER_MEM_ALIGNMENT)
+#endif
+;
+
+/* Prepare the matchfinder for a new input buffer. */
+static forceinline void
+hc_matchfinder_init(struct hc_matchfinder *mf)
+{
+ STATIC_ASSERT(HC_MATCHFINDER_TOTAL_HASH_SIZE %
+ MATCHFINDER_SIZE_ALIGNMENT == 0);
+
+ matchfinder_init((mf_pos_t *)mf, HC_MATCHFINDER_TOTAL_HASH_SIZE);
+}
+
+static forceinline void
+hc_matchfinder_slide_window(struct hc_matchfinder *mf)
+{
+ STATIC_ASSERT(sizeof(*mf) % MATCHFINDER_SIZE_ALIGNMENT == 0);
+
+ matchfinder_rebase((mf_pos_t *)mf, sizeof(*mf));
+}
+
+/*
+ * Find the longest match longer than 'best_len' bytes.
+ *
+ * @mf
+ * The matchfinder structure.
+ * @in_base_p
+ * Location of a pointer which points to the place in the input data the
+ * matchfinder currently stores positions relative to. This may be updated
+ * by this function.
+ * @cur_pos
+ * The current position in the input buffer relative to @in_base (the
+ * position of the sequence being matched against).
+ * @best_len
+ * Require a match longer than this length.
+ * @max_len
+ * The maximum permissible match length at this position.
+ * @nice_len
+ * Stop searching if a match of at least this length is found.
+ * Must be <= @max_len.
+ * @max_search_depth
+ * Limit on the number of potential matches to consider. Must be >= 1.
+ * @next_hashes
+ * The precomputed hash codes for the sequence beginning at @in_next.
+ * These will be used and then updated with the precomputed hashcodes for
+ * the sequence beginning at @in_next + 1.
+ * @offset_ret
+ * If a match is found, its offset is returned in this location.
+ *
+ * Return the length of the match found, or 'best_len' if no match longer than
+ * 'best_len' was found.
+ */
+static forceinline u32
+hc_matchfinder_longest_match(struct hc_matchfinder * const restrict mf,
+ const u8 ** const restrict in_base_p,
+ const u8 * const restrict in_next,
+ u32 best_len,
+ const u32 max_len,
+ const u32 nice_len,
+ const u32 max_search_depth,
+ u32 * const restrict next_hashes,
+ u32 * const restrict offset_ret)
+{
+ u32 depth_remaining = max_search_depth;
+ const u8 *best_matchptr = in_next;
+ mf_pos_t cur_node3, cur_node4;
+ u32 hash3, hash4;
+ u32 next_hashseq;
+ u32 seq4;
+ const u8 *matchptr;
+ u32 len;
+ u32 cur_pos = in_next - *in_base_p;
+ const u8 *in_base;
+ mf_pos_t cutoff;
+
+ if (cur_pos == MATCHFINDER_WINDOW_SIZE) {
+ hc_matchfinder_slide_window(mf);
+ *in_base_p += MATCHFINDER_WINDOW_SIZE;
+ cur_pos = 0;
+ }
+
+ in_base = *in_base_p;
+ cutoff = cur_pos - MATCHFINDER_WINDOW_SIZE;
+
+ if (unlikely(max_len < 5)) /* can we read 4 bytes from 'in_next + 1'? */
+ goto out;
+
+ /* Get the precomputed hash codes. */
+ hash3 = next_hashes[0];
+ hash4 = next_hashes[1];
+
+ /* From the hash buckets, get the first node of each linked list. */
+ cur_node3 = mf->hash3_tab[hash3];
+ cur_node4 = mf->hash4_tab[hash4];
+
+ /* Update for length 3 matches. This replaces the singleton node in the
+ * 'hash3' bucket with the node for the current sequence. */
+ mf->hash3_tab[hash3] = cur_pos;
+
+ /* Update for length 4 matches. This prepends the node for the current
+ * sequence to the linked list in the 'hash4' bucket. */
+ mf->hash4_tab[hash4] = cur_pos;
+ mf->next_tab[cur_pos] = cur_node4;
+
+ /* Compute the next hash codes. */
+ next_hashseq = get_unaligned_le32(in_next + 1);
+ next_hashes[0] = lz_hash(next_hashseq & 0xFFFFFF, HC_MATCHFINDER_HASH3_ORDER);
+ next_hashes[1] = lz_hash(next_hashseq, HC_MATCHFINDER_HASH4_ORDER);
+ prefetchw(&mf->hash3_tab[next_hashes[0]]);
+ prefetchw(&mf->hash4_tab[next_hashes[1]]);
+
+ if (best_len < 4) { /* No match of length >= 4 found yet? */
+
+ /* Check for a length 3 match if needed. */
+
+ if (cur_node3 <= cutoff)
+ goto out;
+
+ seq4 = load_u32_unaligned(in_next);
+
+ if (best_len < 3) {
+ matchptr = &in_base[cur_node3];
+ if (load_u24_unaligned(matchptr) == loaded_u32_to_u24(seq4)) {
+ best_len = 3;
+ best_matchptr = matchptr;
+ }
+ }
+
+ /* Check for a length 4 match. */
+
+ if (cur_node4 <= cutoff)
+ goto out;
+
+ for (;;) {
+ /* No length 4 match found yet. Check the first 4 bytes. */
+ matchptr = &in_base[cur_node4];
+
+ if (load_u32_unaligned(matchptr) == seq4)
+ break;
+
+ /* The first 4 bytes did not match. Keep trying. */
+ cur_node4 = mf->next_tab[cur_node4 & (MATCHFINDER_WINDOW_SIZE - 1)];
+ if (cur_node4 <= cutoff || !--depth_remaining)
+ goto out;
+ }
+
+ /* Found a match of length >= 4. Extend it to its full length. */
+ best_matchptr = matchptr;
+ best_len = lz_extend(in_next, best_matchptr, 4, max_len);
+ if (best_len >= nice_len)
+ goto out;
+ cur_node4 = mf->next_tab[cur_node4 & (MATCHFINDER_WINDOW_SIZE - 1)];
+ if (cur_node4 <= cutoff || !--depth_remaining)
+ goto out;
+ } else {
+ if (cur_node4 <= cutoff || best_len >= nice_len)
+ goto out;
+ }
+
+ /* Check for matches of length >= 5. */
+
+ for (;;) {
+ for (;;) {
+ matchptr = &in_base[cur_node4];
+
+ /* Already found a length 4 match. Try for a longer
+ * match; start by checking either the last 4 bytes and
+ * the first 4 bytes, or the last byte. (The last byte,
+ * the one which would extend the match length by 1, is
+ * the most important.) */
+ #if UNALIGNED_ACCESS_IS_FAST
+ if ((load_u32_unaligned(matchptr + best_len - 3) ==
+ load_u32_unaligned(in_next + best_len - 3)) &&
+ (load_u32_unaligned(matchptr) ==
+ load_u32_unaligned(in_next)))
+ #else
+ if (matchptr[best_len] == in_next[best_len])
+ #endif
+ break;
+
+ /* Continue to the next node in the list. */
+ cur_node4 = mf->next_tab[cur_node4 & (MATCHFINDER_WINDOW_SIZE - 1)];
+ if (cur_node4 <= cutoff || !--depth_remaining)
+ goto out;
+ }
+
+ #if UNALIGNED_ACCESS_IS_FAST
+ len = 4;
+ #else
+ len = 0;
+ #endif
+ len = lz_extend(in_next, matchptr, len, max_len);
+ if (len > best_len) {
+ /* This is the new longest match. */
+ best_len = len;
+ best_matchptr = matchptr;
+ if (best_len >= nice_len)
+ goto out;
+ }
+
+ /* Continue to the next node in the list. */
+ cur_node4 = mf->next_tab[cur_node4 & (MATCHFINDER_WINDOW_SIZE - 1)];
+ if (cur_node4 <= cutoff || !--depth_remaining)
+ goto out;
+ }
+out:
+ *offset_ret = in_next - best_matchptr;
+ return best_len;
+}
+
+/*
+ * Advance the matchfinder, but don't search for matches.
+ *
+ * @mf
+ * The matchfinder structure.
+ * @in_base_p
+ * Location of a pointer which points to the place in the input data the
+ * matchfinder currently stores positions relative to. This may be updated
+ * by this function.
+ * @cur_pos
+ * The current position in the input buffer relative to @in_base.
+ * @end_pos
+ * The end position of the input buffer, relative to @in_base.
+ * @next_hashes
+ * The precomputed hash codes for the sequence beginning at @in_next.
+ * These will be used and then updated with the precomputed hashcodes for
+ * the sequence beginning at @in_next + @count.
+ * @count
+ * The number of bytes to advance. Must be > 0.
+ *
+ * Returns @in_next + @count.
+ */
+static forceinline const u8 *
+hc_matchfinder_skip_positions(struct hc_matchfinder * const restrict mf,
+ const u8 ** const restrict in_base_p,
+ const u8 *in_next,
+ const u8 * const in_end,
+ const u32 count,
+ u32 * const restrict next_hashes)
+{
+ u32 cur_pos;
+ u32 hash3, hash4;
+ u32 next_hashseq;
+ u32 remaining = count;
+
+ if (unlikely(count + 5 > in_end - in_next))
+ return &in_next[count];
+
+ cur_pos = in_next - *in_base_p;
+ hash3 = next_hashes[0];
+ hash4 = next_hashes[1];
+ do {
+ if (cur_pos == MATCHFINDER_WINDOW_SIZE) {
+ hc_matchfinder_slide_window(mf);
+ *in_base_p += MATCHFINDER_WINDOW_SIZE;
+ cur_pos = 0;
+ }
+ mf->hash3_tab[hash3] = cur_pos;
+ mf->next_tab[cur_pos] = mf->hash4_tab[hash4];
+ mf->hash4_tab[hash4] = cur_pos;
+
+ next_hashseq = get_unaligned_le32(++in_next);
+ hash3 = lz_hash(next_hashseq & 0xFFFFFF, HC_MATCHFINDER_HASH3_ORDER);
+ hash4 = lz_hash(next_hashseq, HC_MATCHFINDER_HASH4_ORDER);
+ cur_pos++;
+ } while (--remaining);
+
+ prefetchw(&mf->hash3_tab[hash3]);
+ prefetchw(&mf->hash4_tab[hash4]);
+ next_hashes[0] = hash3;
+ next_hashes[1] = hash4;
+
+ return in_next;
+}
+
+#endif /* LIB_HC_MATCHFINDER_H */
diff --git a/util/compress/libdeflate/lib/lib_common.h b/util/compress/libdeflate/lib/lib_common.h
new file mode 100644
index 000000000..2eea56c72
--- /dev/null
+++ b/util/compress/libdeflate/lib/lib_common.h
@@ -0,0 +1,67 @@
+/*
+ * lib_common.h - internal header included by all library code
+ */
+
+#ifndef LIB_LIB_COMMON_H
+#define LIB_LIB_COMMON_H
+
+#ifdef LIBDEFLATE_H
+# error "lib_common.h must always be included before libdeflate.h"
+ /* because BUILDING_LIBDEFLATE must be set first */
+#endif
+
+#define BUILDING_LIBDEFLATE
+
+#include "../common/common_defs.h"
+
+/*
+ * Prefix with "_libdeflate_" all global symbols which are not part of the API
+ * and don't already have a "libdeflate" prefix. This avoids exposing overly
+ * generic names when libdeflate is built as a static library.
+ *
+ * Note that the chosen prefix is not really important and can be changed
+ * without breaking library users. It was just chosen so that the resulting
+ * symbol names are unlikely to conflict with those from any other software.
+ * Also note that this fixup has no useful effect when libdeflate is built as a
+ * shared library, since these symbols are not exported.
+ */
+#define SYM_FIXUP(sym) _libdeflate_##sym
+#define deflate_get_compression_level SYM_FIXUP(deflate_get_compression_level)
+#define _cpu_features SYM_FIXUP(_cpu_features)
+#define setup_cpu_features SYM_FIXUP(setup_cpu_features)
+
+void *libdeflate_malloc(size_t size);
+void libdeflate_free(void *ptr);
+
+void *libdeflate_aligned_malloc(size_t alignment, size_t size);
+void libdeflate_aligned_free(void *ptr);
+
+#ifdef FREESTANDING
+/*
+ * With -ffreestanding, <string.h> may be missing, and we must provide
+ * implementations of memset(), memcpy(), memmove(), and memcmp().
+ * See https://gcc.gnu.org/onlinedocs/gcc/Standards.html
+ *
+ * Also, -ffreestanding disables interpreting calls to these functions as
+ * built-ins. E.g., calling memcpy(&v, p, WORDBYTES) will make a function call,
+ * not be optimized to a single load instruction. For performance reasons we
+ * don't want that. So, declare these functions as macros that expand to the
+ * corresponding built-ins. This approach is recommended in the gcc man page.
+ * We still need the actual function definitions in case gcc calls them.
+ */
+void *memset(void *s, int c, size_t n);
+#define memset(s, c, n) __builtin_memset((s), (c), (n))
+
+void *memcpy(void *dest, const void *src, size_t n);
+#define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n))
+
+void *memmove(void *dest, const void *src, size_t n);
+#define memmove(dest, src, n) __builtin_memmove((dest), (src), (n))
+
+int memcmp(const void *s1, const void *s2, size_t n);
+#define memcmp(s1, s2, n) __builtin_memcmp((s1), (s2), (n))
+#else
+#include <string.h>
+#endif
+
+#endif /* LIB_LIB_COMMON_H */
diff --git a/util/compress/libdeflate/lib/matchfinder_common.h b/util/compress/libdeflate/lib/matchfinder_common.h
new file mode 100644
index 000000000..49ff3343e
--- /dev/null
+++ b/util/compress/libdeflate/lib/matchfinder_common.h
@@ -0,0 +1,176 @@
+/*
+ * matchfinder_common.h - common code for Lempel-Ziv matchfinding
+ */
+
+#ifndef LIB_MATCHFINDER_COMMON_H
+#define LIB_MATCHFINDER_COMMON_H
+
+#include "lib_common.h"
+#include "unaligned.h"
+
+#ifndef MATCHFINDER_WINDOW_ORDER
+# error "MATCHFINDER_WINDOW_ORDER must be defined!"
+#endif
+
+#define MATCHFINDER_WINDOW_SIZE (1UL << MATCHFINDER_WINDOW_ORDER)
+
+typedef s16 mf_pos_t;
+
+#define MATCHFINDER_INITVAL ((mf_pos_t)-MATCHFINDER_WINDOW_SIZE)
+
+/*
+ * Required alignment of the matchfinder buffer pointer and size. The values
+ * here come from the AVX-2 implementation, which is the worst case.
+ */
+#define MATCHFINDER_MEM_ALIGNMENT 32
+#define MATCHFINDER_SIZE_ALIGNMENT 128
+
+#undef matchfinder_init
+#undef matchfinder_rebase
+#ifdef _aligned_attribute
+# if defined(__arm__) || defined(__aarch64__)
+# include "arm/matchfinder_impl.h"
+# elif defined(__i386__) || defined(__x86_64__)
+# include "x86/matchfinder_impl.h"
+# endif
+#endif
+
+/*
+ * Initialize the hash table portion of the matchfinder.
+ *
+ * Essentially, this is an optimized memset().
+ *
+ * 'data' must be aligned to a MATCHFINDER_MEM_ALIGNMENT boundary, and
+ * 'size' must be a multiple of MATCHFINDER_SIZE_ALIGNMENT.
+ */
+#ifndef matchfinder_init
+static forceinline void
+matchfinder_init(mf_pos_t *data, size_t size)
+{
+ size_t num_entries = size / sizeof(*data);
+ size_t i;
+
+ for (i = 0; i < num_entries; i++)
+ data[i] = MATCHFINDER_INITVAL;
+}
+#endif
+
+/*
+ * Slide the matchfinder by WINDOW_SIZE bytes.
+ *
+ * This must be called just after each WINDOW_SIZE bytes have been run through
+ * the matchfinder.
+ *
+ * This will subtract WINDOW_SIZE bytes from each entry in the array specified.
+ * The effect is that all entries are updated to be relative to the current
+ * position, rather than the position WINDOW_SIZE bytes prior.
+ *
+ * Underflow is detected and replaced with signed saturation. This ensures that
+ * once the sliding window has passed over a position, that position forever
+ * remains out of bounds.
+ *
+ * The array passed in must contain all matchfinder data that is
+ * position-relative. Concretely, this will include the hash table as well as
+ * the table of positions that is used to link together the sequences in each
+ * hash bucket. Note that in the latter table, the links are 1-ary in the case
+ * of "hash chains", and 2-ary in the case of "binary trees". In either case,
+ * the links need to be rebased in the same way.
+ *
+ * 'data' must be aligned to a MATCHFINDER_MEM_ALIGNMENT boundary, and
+ * 'size' must be a multiple of MATCHFINDER_SIZE_ALIGNMENT.
+ */
+#ifndef matchfinder_rebase
+static forceinline void
+matchfinder_rebase(mf_pos_t *data, size_t size)
+{
+ size_t num_entries = size / sizeof(*data);
+ size_t i;
+
+ if (MATCHFINDER_WINDOW_SIZE == 32768) {
+ /* Branchless version for 32768 byte windows. If the value was
+ * already negative, clear all bits except the sign bit; this
+ * changes the value to -32768. Otherwise, set the sign bit;
+ * this is equivalent to subtracting 32768. */
+ for (i = 0; i < num_entries; i++) {
+ u16 v = data[i];
+ u16 sign_bit = v & 0x8000;
+ v &= sign_bit - ((sign_bit >> 15) ^ 1);
+ v |= 0x8000;
+ data[i] = v;
+ }
+ return;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ if (data[i] >= 0)
+ data[i] -= (mf_pos_t)-MATCHFINDER_WINDOW_SIZE;
+ else
+ data[i] = (mf_pos_t)-MATCHFINDER_WINDOW_SIZE;
+ }
+}
+#endif
+
+/*
+ * The hash function: given a sequence prefix held in the low-order bits of a
+ * 32-bit value, multiply by a carefully-chosen large constant. Discard any
+ * bits of the product that don't fit in a 32-bit value, but take the
+ * next-highest @num_bits bits of the product as the hash value, as those have
+ * the most randomness.
+ */
+static forceinline u32
+lz_hash(u32 seq, unsigned num_bits)
+{
+ return (u32)(seq * 0x1E35A7BD) >> (32 - num_bits);
+}
+
+/*
+ * Return the number of bytes at @matchptr that match the bytes at @strptr, up
+ * to a maximum of @max_len. Initially, @start_len bytes are matched.
+ */
+static forceinline unsigned
+lz_extend(const u8 * const strptr, const u8 * const matchptr,
+ const unsigned start_len, const unsigned max_len)
+{
+ unsigned len = start_len;
+ machine_word_t v_word;
+
+ if (UNALIGNED_ACCESS_IS_FAST) {
+
+ if (likely(max_len - len >= 4 * WORDBYTES)) {
+
+ #define COMPARE_WORD_STEP \
+ v_word = load_word_unaligned(&matchptr[len]) ^ \
+ load_word_unaligned(&strptr[len]); \
+ if (v_word != 0) \
+ goto word_differs; \
+ len += WORDBYTES; \
+
+ COMPARE_WORD_STEP
+ COMPARE_WORD_STEP
+ COMPARE_WORD_STEP
+ COMPARE_WORD_STEP
+ #undef COMPARE_WORD_STEP
+ }
+
+ while (len + WORDBYTES <= max_len) {
+ v_word = load_word_unaligned(&matchptr[len]) ^
+ load_word_unaligned(&strptr[len]);
+ if (v_word != 0)
+ goto word_differs;
+ len += WORDBYTES;
+ }
+ }
+
+ while (len < max_len && matchptr[len] == strptr[len])
+ len++;
+ return len;
+
+word_differs:
+ if (CPU_IS_LITTLE_ENDIAN())
+ len += (bsfw(v_word) >> 3);
+ else
+ len += (WORDBITS - 1 - bsrw(v_word)) >> 3;
+ return len;
+}
+
+#endif /* LIB_MATCHFINDER_COMMON_H */
diff --git a/util/compress/libdeflate/lib/unaligned.h b/util/compress/libdeflate/lib/unaligned.h
new file mode 100644
index 000000000..bb48bf828
--- /dev/null
+++ b/util/compress/libdeflate/lib/unaligned.h
@@ -0,0 +1,228 @@
+/*
+ * unaligned.h - inline functions for unaligned memory accesses
+ */
+
+#ifndef LIB_UNALIGNED_H
+#define LIB_UNALIGNED_H
+
+#include "lib_common.h"
+
+/***** Unaligned loads and stores without endianness conversion *****/
+
+/*
+ * memcpy() is portable, and it usually gets optimized appropriately by modern
+ * compilers. I.e., each memcpy() of 1, 2, 4, or WORDBYTES bytes gets compiled
+ * to a load or store instruction, not to an actual function call.
+ *
+ * We no longer use the "packed struct" approach, as that is nonstandard, has
+ * unclear semantics, and doesn't receive enough testing
+ * (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94994).
+ *
+ * arm32 with __ARM_FEATURE_UNALIGNED in gcc 5 and earlier is a known exception
+ * where memcpy() generates inefficient code
+ * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67366). However, we no longer
+ * consider that one case important enough to maintain different code for.
+ * If you run into it, please just use a newer version of gcc (or use clang).
+ */
+
+#define DEFINE_UNALIGNED_TYPE(type) \
+static forceinline type \
+load_##type##_unaligned(const void *p) \
+{ \
+ type v; \
+ memcpy(&v, p, sizeof(v)); \
+ return v; \
+} \
+ \
+static forceinline void \
+store_##type##_unaligned(type v, void *p) \
+{ \
+ memcpy(p, &v, sizeof(v)); \
+}
+
+DEFINE_UNALIGNED_TYPE(u16)
+DEFINE_UNALIGNED_TYPE(u32)
+DEFINE_UNALIGNED_TYPE(u64)
+DEFINE_UNALIGNED_TYPE(machine_word_t)
+
+#define load_word_unaligned load_machine_word_t_unaligned
+#define store_word_unaligned store_machine_word_t_unaligned
+
+/***** Unaligned loads with endianness conversion *****/
+
+static forceinline u16
+get_unaligned_le16(const u8 *p)
+{
+ if (UNALIGNED_ACCESS_IS_FAST)
+ return le16_bswap(load_u16_unaligned(p));
+ else
+ return ((u16)p[1] << 8) | p[0];
+}
+
+static forceinline u16
+get_unaligned_be16(const u8 *p)
+{
+ if (UNALIGNED_ACCESS_IS_FAST)
+ return be16_bswap(load_u16_unaligned(p));
+ else
+ return ((u16)p[0] << 8) | p[1];
+}
+
+static forceinline u32
+get_unaligned_le32(const u8 *p)
+{
+ if (UNALIGNED_ACCESS_IS_FAST)
+ return le32_bswap(load_u32_unaligned(p));
+ else
+ return ((u32)p[3] << 24) | ((u32)p[2] << 16) |
+ ((u32)p[1] << 8) | p[0];
+}
+
+static forceinline u32
+get_unaligned_be32(const u8 *p)
+{
+ if (UNALIGNED_ACCESS_IS_FAST)
+ return be32_bswap(load_u32_unaligned(p));
+ else
+ return ((u32)p[0] << 24) | ((u32)p[1] << 16) |
+ ((u32)p[2] << 8) | p[3];
+}
+
+static forceinline u64
+get_unaligned_le64(const u8 *p)
+{
+ if (UNALIGNED_ACCESS_IS_FAST)
+ return le64_bswap(load_u64_unaligned(p));
+ else
+ return ((u64)p[7] << 56) | ((u64)p[6] << 48) |
+ ((u64)p[5] << 40) | ((u64)p[4] << 32) |
+ ((u64)p[3] << 24) | ((u64)p[2] << 16) |
+ ((u64)p[1] << 8) | p[0];
+}
+
+static forceinline machine_word_t
+get_unaligned_leword(const u8 *p)
+{
+ STATIC_ASSERT(WORDBITS == 32 || WORDBITS == 64);
+ if (WORDBITS == 32)
+ return get_unaligned_le32(p);
+ else
+ return get_unaligned_le64(p);
+}
+
+/***** Unaligned stores with endianness conversion *****/
+
+static forceinline void
+put_unaligned_le16(u16 v, u8 *p)
+{
+ if (UNALIGNED_ACCESS_IS_FAST) {
+ store_u16_unaligned(le16_bswap(v), p);
+ } else {
+ p[0] = (u8)(v >> 0);
+ p[1] = (u8)(v >> 8);
+ }
+}
+
+static forceinline void
+put_unaligned_be16(u16 v, u8 *p)
+{
+ if (UNALIGNED_ACCESS_IS_FAST) {
+ store_u16_unaligned(be16_bswap(v), p);
+ } else {
+ p[0] = (u8)(v >> 8);
+ p[1] = (u8)(v >> 0);
+ }
+}
+
+static forceinline void
+put_unaligned_le32(u32 v, u8 *p)
+{
+ if (UNALIGNED_ACCESS_IS_FAST) {
+ store_u32_unaligned(le32_bswap(v), p);
+ } else {
+ p[0] = (u8)(v >> 0);
+ p[1] = (u8)(v >> 8);
+ p[2] = (u8)(v >> 16);
+ p[3] = (u8)(v >> 24);
+ }
+}
+
+static forceinline void
+put_unaligned_be32(u32 v, u8 *p)
+{
+ if (UNALIGNED_ACCESS_IS_FAST) {
+ store_u32_unaligned(be32_bswap(v), p);
+ } else {
+ p[0] = (u8)(v >> 24);
+ p[1] = (u8)(v >> 16);
+ p[2] = (u8)(v >> 8);
+ p[3] = (u8)(v >> 0);
+ }
+}
+
+static forceinline void
+put_unaligned_le64(u64 v, u8 *p)
+{
+ if (UNALIGNED_ACCESS_IS_FAST) {
+ store_u64_unaligned(le64_bswap(v), p);
+ } else {
+ p[0] = (u8)(v >> 0);
+ p[1] = (u8)(v >> 8);
+ p[2] = (u8)(v >> 16);
+ p[3] = (u8)(v >> 24);
+ p[4] = (u8)(v >> 32);
+ p[5] = (u8)(v >> 40);
+ p[6] = (u8)(v >> 48);
+ p[7] = (u8)(v >> 56);
+ }
+}
+
+static forceinline void
+put_unaligned_leword(machine_word_t v, u8 *p)
+{
+ STATIC_ASSERT(WORDBITS == 32 || WORDBITS == 64);
+ if (WORDBITS == 32)
+ put_unaligned_le32(v, p);
+ else
+ put_unaligned_le64(v, p);
+}
+
+/***** 24-bit loads *****/
+
+/*
+ * Given a 32-bit value that was loaded with the platform's native endianness,
+ * return a 32-bit value whose high-order 8 bits are 0 and whose low-order 24
+ * bits contain the first 3 bytes, arranged in octets in a platform-dependent
+ * order, at the memory location from which the input 32-bit value was loaded.
+ */
+static forceinline u32
+loaded_u32_to_u24(u32 v)
+{
+ if (CPU_IS_LITTLE_ENDIAN())
+ return v & 0xFFFFFF;
+ else
+ return v >> 8;
+}
+
+/*
+ * Load the next 3 bytes from the memory location @p into the 24 low-order bits
+ * of a 32-bit value. The order in which the 3 bytes will be arranged as octets
+ * in the 24 bits is platform-dependent. At least LOAD_U24_REQUIRED_NBYTES
+ * bytes must be available at @p; note that this may be more than 3.
+ */
+static forceinline u32
+load_u24_unaligned(const u8 *p)
+{
+#if UNALIGNED_ACCESS_IS_FAST
+# define LOAD_U24_REQUIRED_NBYTES 4
+ return loaded_u32_to_u24(load_u32_unaligned(p));
+#else
+# define LOAD_U24_REQUIRED_NBYTES 3
+ if (CPU_IS_LITTLE_ENDIAN())
+ return ((u32)p[0] << 0) | ((u32)p[1] << 8) | ((u32)p[2] << 16);
+ else
+ return ((u32)p[2] << 0) | ((u32)p[1] << 8) | ((u32)p[0] << 16);
+#endif
+}
+
+#endif /* LIB_UNALIGNED_H */
diff --git a/util/compress/libdeflate/lib/utils.c b/util/compress/libdeflate/lib/utils.c
new file mode 100644
index 000000000..c626af1f2
--- /dev/null
+++ b/util/compress/libdeflate/lib/utils.c
@@ -0,0 +1,142 @@
+/*
+ * utils.c - utility functions for libdeflate
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "lib_common.h"
+
+#include "libdeflate.h"
+
+#ifdef FREESTANDING
+# define malloc NULL
+# define free NULL
+#else
+# include <stdlib.h>
+#endif
+
+static void *(*libdeflate_malloc_func)(size_t) = malloc;
+static void (*libdeflate_free_func)(void *) = free;
+
+void *
+libdeflate_malloc(size_t size)
+{
+ return (*libdeflate_malloc_func)(size);
+}
+
+void
+libdeflate_free(void *ptr)
+{
+ (*libdeflate_free_func)(ptr);
+}
+
+void *
+libdeflate_aligned_malloc(size_t alignment, size_t size)
+{
+ void *ptr = libdeflate_malloc(sizeof(void *) + alignment - 1 + size);
+ if (ptr) {
+ void *orig_ptr = ptr;
+ ptr = (void *)ALIGN((uintptr_t)ptr + sizeof(void *), alignment);
+ ((void **)ptr)[-1] = orig_ptr;
+ }
+ return ptr;
+}
+
+void
+libdeflate_aligned_free(void *ptr)
+{
+ if (ptr)
+ libdeflate_free(((void **)ptr)[-1]);
+}
+
+LIBDEFLATEEXPORT void LIBDEFLATEAPI
+libdeflate_set_memory_allocator(void *(*malloc_func)(size_t),
+ void (*free_func)(void *))
+{
+ libdeflate_malloc_func = malloc_func;
+ libdeflate_free_func = free_func;
+}
+
+/*
+ * Implementations of libc functions for freestanding library builds.
+ * Normal library builds don't use these. Not optimized yet; usually the
+ * compiler expands these functions and doesn't actually call them anyway.
+ */
+#ifdef FREESTANDING
+#undef memset
+void * __attribute__((weak))
+memset(void *s, int c, size_t n)
+{
+ u8 *p = s;
+ size_t i;
+
+ for (i = 0; i < n; i++)
+ p[i] = c;
+ return s;
+}
+
+#undef memcpy
+void * __attribute__((weak))
+memcpy(void *dest, const void *src, size_t n)
+{
+ u8 *d = dest;
+ const u8 *s = src;
+ size_t i;
+
+ for (i = 0; i < n; i++)
+ d[i] = s[i];
+ return dest;
+}
+
+#undef memmove
+void * __attribute__((weak))
+memmove(void *dest, const void *src, size_t n)
+{
+ u8 *d = dest;
+ const u8 *s = src;
+ size_t i;
+
+ if (d <= s)
+ return memcpy(d, s, n);
+
+ for (i = n; i > 0; i--)
+ d[i - 1] = s[i - 1];
+ return dest;
+}
+
+#undef memcmp
+int __attribute__((weak))
+memcmp(const void *s1, const void *s2, size_t n)
+{
+ const u8 *p1 = s1;
+ const u8 *p2 = s2;
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ if (p1[i] != p2[i])
+ return (int)p1[i] - (int)p2[i];
+ }
+ return 0;
+}
+#endif /* FREESTANDING */
diff --git a/util/compress/libdeflate/lib/x86/adler32_impl.h b/util/compress/libdeflate/lib/x86/adler32_impl.h
new file mode 100644
index 000000000..f89bde585
--- /dev/null
+++ b/util/compress/libdeflate/lib/x86/adler32_impl.h
@@ -0,0 +1,337 @@
+/*
+ * x86/adler32_impl.h - x86 implementations of Adler-32 checksum algorithm
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef LIB_X86_ADLER32_IMPL_H
+#define LIB_X86_ADLER32_IMPL_H
+
+#include "cpu_features.h"
+
+/*
+ * The following macros horizontally sum the s1 counters and add them to the
+ * real s1, and likewise for s2. They do this via a series of reductions, each
+ * of which halves the vector length, until just one counter remains.
+ *
+ * The s1 reductions don't depend on the s2 reductions and vice versa, so for
+ * efficiency they are interleaved. Also, every other s1 counter is 0 due to
+ * the 'psadbw' instruction (_mm_sad_epu8) summing groups of 8 bytes rather than
+ * 4; hence, one of the s1 reductions is skipped when going from 128 => 32 bits.
+ */
+
+#define ADLER32_FINISH_VEC_CHUNK_128(s1, s2, v_s1, v_s2) \
+{ \
+ __v4su s1_last = (v_s1), s2_last = (v_s2); \
+ \
+ /* 128 => 32 bits */ \
+ s2_last += (__v4su)_mm_shuffle_epi32((__m128i)s2_last, 0x31); \
+ s1_last += (__v4su)_mm_shuffle_epi32((__m128i)s1_last, 0x02); \
+ s2_last += (__v4su)_mm_shuffle_epi32((__m128i)s2_last, 0x02); \
+ \
+ *(s1) += (u32)_mm_cvtsi128_si32((__m128i)s1_last); \
+ *(s2) += (u32)_mm_cvtsi128_si32((__m128i)s2_last); \
+}
+
+#define ADLER32_FINISH_VEC_CHUNK_256(s1, s2, v_s1, v_s2) \
+{ \
+ __v4su s1_128bit, s2_128bit; \
+ \
+ /* 256 => 128 bits */ \
+ s1_128bit = (__v4su)_mm256_extracti128_si256((__m256i)(v_s1), 0) + \
+ (__v4su)_mm256_extracti128_si256((__m256i)(v_s1), 1); \
+ s2_128bit = (__v4su)_mm256_extracti128_si256((__m256i)(v_s2), 0) + \
+ (__v4su)_mm256_extracti128_si256((__m256i)(v_s2), 1); \
+ \
+ ADLER32_FINISH_VEC_CHUNK_128((s1), (s2), s1_128bit, s2_128bit); \
+}
+
+#define ADLER32_FINISH_VEC_CHUNK_512(s1, s2, v_s1, v_s2) \
+{ \
+ __v8su s1_256bit, s2_256bit; \
+ \
+ /* 512 => 256 bits */ \
+ s1_256bit = (__v8su)_mm512_extracti64x4_epi64((__m512i)(v_s1), 0) + \
+ (__v8su)_mm512_extracti64x4_epi64((__m512i)(v_s1), 1); \
+ s2_256bit = (__v8su)_mm512_extracti64x4_epi64((__m512i)(v_s2), 0) + \
+ (__v8su)_mm512_extracti64x4_epi64((__m512i)(v_s2), 1); \
+ \
+ ADLER32_FINISH_VEC_CHUNK_256((s1), (s2), s1_256bit, s2_256bit); \
+}
+
+/* AVX-512BW implementation: like the AVX2 one, but does 64 bytes at a time */
+#undef DISPATCH_AVX512BW
+#if !defined(DEFAULT_IMPL) && \
+ /*
+ * clang before v3.9 is missing some AVX-512BW intrinsics including
+ * _mm512_sad_epu8(), a.k.a. __builtin_ia32_psadbw512. So just make using
+ * AVX-512BW, even when __AVX512BW__ is defined, conditional on
+ * COMPILER_SUPPORTS_AVX512BW_TARGET where we check for that builtin.
+ */ \
+ COMPILER_SUPPORTS_AVX512BW_TARGET && \
+ (defined(__AVX512BW__) || (X86_CPU_FEATURES_ENABLED && \
+ COMPILER_SUPPORTS_AVX512BW_TARGET_INTRINSICS))
+# define FUNCNAME adler32_avx512bw
+# define FUNCNAME_CHUNK adler32_avx512bw_chunk
+# define IMPL_ALIGNMENT 64
+# define IMPL_SEGMENT_SIZE 64
+# define IMPL_MAX_CHUNK_SIZE MAX_CHUNK_SIZE
+# ifdef __AVX512BW__
+# define ATTRIBUTES
+# define DEFAULT_IMPL adler32_avx512bw
+# else
+# define ATTRIBUTES __attribute__((target("avx512bw")))
+# define DISPATCH 1
+# define DISPATCH_AVX512BW 1
+# endif
+# include <immintrin.h>
+static forceinline ATTRIBUTES void
+adler32_avx512bw_chunk(const __m512i *p, const __m512i *const end,
+ u32 *s1, u32 *s2)
+{
+ const __m512i zeroes = _mm512_setzero_si512();
+ const __v64qi multipliers = (__v64qi){
+ 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49,
+ 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33,
+ 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
+ 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
+ };
+ const __v32hi ones = (__v32hi)_mm512_set1_epi16(1);
+ __v16si v_s1 = (__v16si)zeroes;
+ __v16si v_s1_sums = (__v16si)zeroes;
+ __v16si v_s2 = (__v16si)zeroes;
+
+ do {
+ /* Load the next 64-byte segment */
+ __m512i bytes = *p++;
+
+ /* Multiply the bytes by 64...1 (the number of times they need
+ * to be added to s2) and add adjacent products */
+ __v32hi sums = (__v32hi)_mm512_maddubs_epi16(
+ bytes, (__m512i)multipliers);
+
+ /* Keep sum of all previous s1 counters, for adding to s2 later.
+ * This allows delaying the multiplication by 64 to the end. */
+ v_s1_sums += v_s1;
+
+ /* Add the sum of each group of 8 bytes to the corresponding s1
+ * counter */
+ v_s1 += (__v16si)_mm512_sad_epu8(bytes, zeroes);
+
+ /* Add the sum of each group of 4 products of the bytes by
+ * 64...1 to the corresponding s2 counter */
+ v_s2 += (__v16si)_mm512_madd_epi16((__m512i)sums,
+ (__m512i)ones);
+ } while (p != end);
+
+ /* Finish the s2 counters by adding the sum of the s1 values at the
+ * beginning of each segment, multiplied by the segment size (64) */
+ v_s2 += (__v16si)_mm512_slli_epi32((__m512i)v_s1_sums, 6);
+
+ /* Add the counters to the real s1 and s2 */
+ ADLER32_FINISH_VEC_CHUNK_512(s1, s2, v_s1, v_s2);
+}
+# include "../adler32_vec_template.h"
+#endif /* AVX-512BW implementation */
+
+/* AVX2 implementation: like the AVX-512BW one, but does 32 bytes at a time */
+#undef DISPATCH_AVX2
+#if !defined(DEFAULT_IMPL) && \
+ (defined(__AVX2__) || (X86_CPU_FEATURES_ENABLED && \
+ COMPILER_SUPPORTS_AVX2_TARGET_INTRINSICS))
+# define FUNCNAME adler32_avx2
+# define FUNCNAME_CHUNK adler32_avx2_chunk
+# define IMPL_ALIGNMENT 32
+# define IMPL_SEGMENT_SIZE 32
+# define IMPL_MAX_CHUNK_SIZE MAX_CHUNK_SIZE
+# ifdef __AVX2__
+# define ATTRIBUTES
+# define DEFAULT_IMPL adler32_avx2
+# else
+# define ATTRIBUTES __attribute__((target("avx2")))
+# define DISPATCH 1
+# define DISPATCH_AVX2 1
+# endif
+# include <immintrin.h>
+static forceinline ATTRIBUTES void
+adler32_avx2_chunk(const __m256i *p, const __m256i *const end, u32 *s1, u32 *s2)
+{
+ const __m256i zeroes = _mm256_setzero_si256();
+ const __v32qu multipliers = (__v32qu){
+ 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
+ 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
+ };
+ const __v16hu ones = (__v16hu)_mm256_set1_epi16(1);
+ __v8su v_s1 = (__v8su)zeroes;
+ __v8su v_s1_sums = (__v8su)zeroes;
+ __v8su v_s2 = (__v8su)zeroes;
+
+ do {
+ /* Load the next 32-byte segment */
+ __m256i bytes = *p++;
+
+ /* Multiply the bytes by 32...1 (the number of times they need
+ * to be added to s2) and add adjacent products */
+ __v16hu sums = (__v16hu)_mm256_maddubs_epi16(
+ bytes, (__m256i)multipliers);
+
+ /* Keep sum of all previous s1 counters, for adding to s2 later.
+ * This allows delaying the multiplication by 32 to the end. */
+ v_s1_sums += v_s1;
+
+ /* Add the sum of each group of 8 bytes to the corresponding s1
+ * counter */
+ v_s1 += (__v8su)_mm256_sad_epu8(bytes, zeroes);
+
+ /* Add the sum of each group of 4 products of the bytes by
+ * 32...1 to the corresponding s2 counter */
+ v_s2 += (__v8su)_mm256_madd_epi16((__m256i)sums, (__m256i)ones);
+ } while (p != end);
+
+ /* Finish the s2 counters by adding the sum of the s1 values at the
+ * beginning of each segment, multiplied by the segment size (32) */
+ v_s2 += (__v8su)_mm256_slli_epi32((__m256i)v_s1_sums, 5);
+
+ /* Add the counters to the real s1 and s2 */
+ ADLER32_FINISH_VEC_CHUNK_256(s1, s2, v_s1, v_s2);
+}
+# include "../adler32_vec_template.h"
+#endif /* AVX2 implementation */
+
+/* SSE2 implementation */
+#undef DISPATCH_SSE2
+#if !defined(DEFAULT_IMPL) && \
+ (defined(__SSE2__) || (X86_CPU_FEATURES_ENABLED && \
+ COMPILER_SUPPORTS_SSE2_TARGET_INTRINSICS))
+# define FUNCNAME adler32_sse2
+# define FUNCNAME_CHUNK adler32_sse2_chunk
+# define IMPL_ALIGNMENT 16
+# define IMPL_SEGMENT_SIZE 32
+/*
+ * The 16-bit precision byte counters must not be allowed to undergo *signed*
+ * overflow, otherwise the signed multiplications at the end (_mm_madd_epi16)
+ * would behave incorrectly.
+ */
+# define IMPL_MAX_CHUNK_SIZE (32 * (0x7FFF / 0xFF))
+# ifdef __SSE2__
+# define ATTRIBUTES
+# define DEFAULT_IMPL adler32_sse2
+# else
+# define ATTRIBUTES __attribute__((target("sse2")))
+# define DISPATCH 1
+# define DISPATCH_SSE2 1
+# endif
+# include <emmintrin.h>
+static forceinline ATTRIBUTES void
+adler32_sse2_chunk(const __m128i *p, const __m128i *const end, u32 *s1, u32 *s2)
+{
+ const __m128i zeroes = _mm_setzero_si128();
+
+ /* s1 counters: 32-bit, sum of bytes */
+ __v4su v_s1 = (__v4su)zeroes;
+
+ /* s2 counters: 32-bit, sum of s1 values */
+ __v4su v_s2 = (__v4su)zeroes;
+
+ /*
+ * Thirty-two 16-bit counters for byte sums. Each accumulates the bytes
+ * that eventually need to be multiplied by a number 32...1 for addition
+ * into s2.
+ */
+ __v8hu v_byte_sums_a = (__v8hu)zeroes;
+ __v8hu v_byte_sums_b = (__v8hu)zeroes;
+ __v8hu v_byte_sums_c = (__v8hu)zeroes;
+ __v8hu v_byte_sums_d = (__v8hu)zeroes;
+
+ do {
+ /* Load the next 32 bytes */
+ const __m128i bytes1 = *p++;
+ const __m128i bytes2 = *p++;
+
+ /*
+ * Accumulate the previous s1 counters into the s2 counters.
+ * Logically, this really should be v_s2 += v_s1 * 32, but we
+ * can do the multiplication (or left shift) later.
+ */
+ v_s2 += v_s1;
+
+ /*
+ * s1 update: use "Packed Sum of Absolute Differences" to add
+ * the bytes horizontally with 8 bytes per sum. Then add the
+ * sums to the s1 counters.
+ */
+ v_s1 += (__v4su)_mm_sad_epu8(bytes1, zeroes);
+ v_s1 += (__v4su)_mm_sad_epu8(bytes2, zeroes);
+
+ /*
+ * Also accumulate the bytes into 32 separate counters that have
+ * 16-bit precision.
+ */
+ v_byte_sums_a += (__v8hu)_mm_unpacklo_epi8(bytes1, zeroes);
+ v_byte_sums_b += (__v8hu)_mm_unpackhi_epi8(bytes1, zeroes);
+ v_byte_sums_c += (__v8hu)_mm_unpacklo_epi8(bytes2, zeroes);
+ v_byte_sums_d += (__v8hu)_mm_unpackhi_epi8(bytes2, zeroes);
+
+ } while (p != end);
+
+ /* Finish calculating the s2 counters */
+ v_s2 = (__v4su)_mm_slli_epi32((__m128i)v_s2, 5);
+ v_s2 += (__v4su)_mm_madd_epi16((__m128i)v_byte_sums_a,
+ (__m128i)(__v8hu){ 32, 31, 30, 29, 28, 27, 26, 25 });
+ v_s2 += (__v4su)_mm_madd_epi16((__m128i)v_byte_sums_b,
+ (__m128i)(__v8hu){ 24, 23, 22, 21, 20, 19, 18, 17 });
+ v_s2 += (__v4su)_mm_madd_epi16((__m128i)v_byte_sums_c,
+ (__m128i)(__v8hu){ 16, 15, 14, 13, 12, 11, 10, 9 });
+ v_s2 += (__v4su)_mm_madd_epi16((__m128i)v_byte_sums_d,
+ (__m128i)(__v8hu){ 8, 7, 6, 5, 4, 3, 2, 1 });
+
+ /* Add the counters to the real s1 and s2 */
+ ADLER32_FINISH_VEC_CHUNK_128(s1, s2, v_s1, v_s2);
+}
+# include "../adler32_vec_template.h"
+#endif /* SSE2 implementation */
+
+#ifdef DISPATCH
+static inline adler32_func_t
+arch_select_adler32_func(void)
+{
+ u32 features = get_cpu_features();
+
+#ifdef DISPATCH_AVX512BW
+ if (features & X86_CPU_FEATURE_AVX512BW)
+ return adler32_avx512bw;
+#endif
+#ifdef DISPATCH_AVX2
+ if (features & X86_CPU_FEATURE_AVX2)
+ return adler32_avx2;
+#endif
+#ifdef DISPATCH_SSE2
+ if (features & X86_CPU_FEATURE_SSE2)
+ return adler32_sse2;
+#endif
+ return NULL;
+}
+#endif /* DISPATCH */
+
+#endif /* LIB_X86_ADLER32_IMPL_H */
diff --git a/util/compress/libdeflate/lib/x86/cpu_features.c b/util/compress/libdeflate/lib/x86/cpu_features.c
new file mode 100644
index 000000000..e3471d468
--- /dev/null
+++ b/util/compress/libdeflate/lib/x86/cpu_features.c
@@ -0,0 +1,152 @@
+/*
+ * x86/cpu_features.c - feature detection for x86 processors
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "../cpu_features_common.h" /* must be included first */
+#include "cpu_features.h"
+
+#if X86_CPU_FEATURES_ENABLED
+
+volatile u32 _cpu_features = 0;
+
+/* With old GCC versions we have to manually save and restore the x86_32 PIC
+ * register (ebx). See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47602 */
+#if defined(__i386__) && defined(__PIC__)
+# define EBX_CONSTRAINT "=&r"
+#else
+# define EBX_CONSTRAINT "=b"
+#endif
+
+/* Execute the CPUID instruction. */
+static inline void
+cpuid(u32 leaf, u32 subleaf, u32 *a, u32 *b, u32 *c, u32 *d)
+{
+ __asm__(".ifnc %%ebx, %1; mov %%ebx, %1; .endif\n"
+ "cpuid \n"
+ ".ifnc %%ebx, %1; xchg %%ebx, %1; .endif\n"
+ : "=a" (*a), EBX_CONSTRAINT (*b), "=c" (*c), "=d" (*d)
+ : "a" (leaf), "c" (subleaf));
+}
+
+/* Read an extended control register. */
+static inline u64
+read_xcr(u32 index)
+{
+ u32 edx, eax;
+
+ /* Execute the "xgetbv" instruction. Old versions of binutils do not
+ * recognize this instruction, so list the raw bytes instead. */
+ __asm__ (".byte 0x0f, 0x01, 0xd0" : "=d" (edx), "=a" (eax) : "c" (index));
+
+ return ((u64)edx << 32) | eax;
+}
+
+#undef BIT
+#define BIT(nr) (1UL << (nr))
+
+#define XCR0_BIT_SSE BIT(1)
+#define XCR0_BIT_AVX BIT(2)
+#define XCR0_BIT_OPMASK BIT(5)
+#define XCR0_BIT_ZMM_HI256 BIT(6)
+#define XCR0_BIT_HI16_ZMM BIT(7)
+
+#define IS_SET(reg, nr) ((reg) & BIT(nr))
+#define IS_ALL_SET(reg, mask) (((reg) & (mask)) == (mask))
+
+static const struct cpu_feature x86_cpu_feature_table[] = {
+ {X86_CPU_FEATURE_SSE2, "sse2"},
+ {X86_CPU_FEATURE_PCLMUL, "pclmul"},
+ {X86_CPU_FEATURE_AVX, "avx"},
+ {X86_CPU_FEATURE_AVX2, "avx2"},
+ {X86_CPU_FEATURE_BMI2, "bmi2"},
+ {X86_CPU_FEATURE_AVX512BW, "avx512bw"},
+};
+
+/* Initialize _cpu_features with bits for interesting processor features. */
+void setup_cpu_features(void)
+{
+ u32 features = 0;
+ u32 dummy1, dummy2, dummy3, dummy4;
+ u32 max_function;
+ u32 features_1, features_2, features_3, features_4;
+ bool os_avx_support = false;
+ bool os_avx512_support = false;
+
+ /* Get maximum supported function */
+ cpuid(0, 0, &max_function, &dummy2, &dummy3, &dummy4);
+ if (max_function < 1)
+ goto out;
+
+ /* Standard feature flags */
+ cpuid(1, 0, &dummy1, &dummy2, &features_2, &features_1);
+
+ if (IS_SET(features_1, 26))
+ features |= X86_CPU_FEATURE_SSE2;
+
+ if (IS_SET(features_2, 1))
+ features |= X86_CPU_FEATURE_PCLMUL;
+
+ if (IS_SET(features_2, 27)) { /* OSXSAVE set? */
+ u64 xcr0 = read_xcr(0);
+
+ os_avx_support = IS_ALL_SET(xcr0,
+ XCR0_BIT_SSE |
+ XCR0_BIT_AVX);
+
+ os_avx512_support = IS_ALL_SET(xcr0,
+ XCR0_BIT_SSE |
+ XCR0_BIT_AVX |
+ XCR0_BIT_OPMASK |
+ XCR0_BIT_ZMM_HI256 |
+ XCR0_BIT_HI16_ZMM);
+ }
+
+ if (os_avx_support && IS_SET(features_2, 28))
+ features |= X86_CPU_FEATURE_AVX;
+
+ if (max_function < 7)
+ goto out;
+
+ /* Extended feature flags */
+ cpuid(7, 0, &dummy1, &features_3, &features_4, &dummy4);
+
+ if (os_avx_support && IS_SET(features_3, 5))
+ features |= X86_CPU_FEATURE_AVX2;
+
+ if (IS_SET(features_3, 8))
+ features |= X86_CPU_FEATURE_BMI2;
+
+ if (os_avx512_support && IS_SET(features_3, 30))
+ features |= X86_CPU_FEATURE_AVX512BW;
+
+out:
+ disable_cpu_features_for_testing(&features, x86_cpu_feature_table,
+ ARRAY_LEN(x86_cpu_feature_table));
+
+ _cpu_features = features | X86_CPU_FEATURES_KNOWN;
+}
+
+#endif /* X86_CPU_FEATURES_ENABLED */
diff --git a/util/compress/libdeflate/lib/x86/cpu_features.h b/util/compress/libdeflate/lib/x86/cpu_features.h
new file mode 100644
index 000000000..4c023539e
--- /dev/null
+++ b/util/compress/libdeflate/lib/x86/cpu_features.h
@@ -0,0 +1,41 @@
+/*
+ * x86/cpu_features.h - feature detection for x86 processors
+ */
+
+#ifndef LIB_X86_CPU_FEATURES_H
+#define LIB_X86_CPU_FEATURES_H
+
+#include "../lib_common.h"
+
+#if (defined(__i386__) || defined(__x86_64__)) && \
+ COMPILER_SUPPORTS_TARGET_FUNCTION_ATTRIBUTE
+# define X86_CPU_FEATURES_ENABLED 1
+#else
+# define X86_CPU_FEATURES_ENABLED 0
+#endif
+
+#if X86_CPU_FEATURES_ENABLED
+
+#define X86_CPU_FEATURE_SSE2 0x00000001
+#define X86_CPU_FEATURE_PCLMUL 0x00000002
+#define X86_CPU_FEATURE_AVX 0x00000004
+#define X86_CPU_FEATURE_AVX2 0x00000008
+#define X86_CPU_FEATURE_BMI2 0x00000010
+#define X86_CPU_FEATURE_AVX512BW 0x00000020
+
+#define X86_CPU_FEATURES_KNOWN 0x80000000
+
+extern volatile u32 _cpu_features;
+
+void setup_cpu_features(void);
+
+static inline u32 get_cpu_features(void)
+{
+ if (_cpu_features == 0)
+ setup_cpu_features();
+ return _cpu_features;
+}
+
+#endif /* X86_CPU_FEATURES_ENABLED */
+
+#endif /* LIB_X86_CPU_FEATURES_H */
diff --git a/util/compress/libdeflate/lib/x86/crc32_impl.h b/util/compress/libdeflate/lib/x86/crc32_impl.h
new file mode 100644
index 000000000..14a686792
--- /dev/null
+++ b/util/compress/libdeflate/lib/x86/crc32_impl.h
@@ -0,0 +1,92 @@
+/*
+ * x86/crc32_impl.h - x86 implementations of CRC-32 checksum algorithm
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef LIB_X86_CRC32_IMPL_H
+#define LIB_X86_CRC32_IMPL_H
+
+#include "cpu_features.h"
+
+/*
+ * Include the PCLMUL/AVX implementation? Although our PCLMUL-optimized CRC-32
+ * function doesn't use any AVX intrinsics specifically, it can benefit a lot
+ * from being compiled for an AVX target: on Skylake, ~16700 MB/s vs. ~10100
+ * MB/s. I expect this is related to the PCLMULQDQ instructions being assembled
+ * in the newer three-operand form rather than the older two-operand form.
+ *
+ * Note: this is only needed if __AVX__ is *not* defined, since otherwise the
+ * "regular" PCLMUL implementation would already be AVX enabled.
+ */
+#undef DISPATCH_PCLMUL_AVX
+#if !defined(DEFAULT_IMPL) && !defined(__AVX__) && \
+ X86_CPU_FEATURES_ENABLED && COMPILER_SUPPORTS_AVX_TARGET && \
+ (defined(__PCLMUL__) || COMPILER_SUPPORTS_PCLMUL_TARGET_INTRINSICS)
+# define FUNCNAME crc32_pclmul_avx
+# define FUNCNAME_ALIGNED crc32_pclmul_avx_aligned
+# define ATTRIBUTES __attribute__((target("pclmul,avx")))
+# define DISPATCH 1
+# define DISPATCH_PCLMUL_AVX 1
+# include "crc32_pclmul_template.h"
+#endif
+
+/* PCLMUL implementation */
+#undef DISPATCH_PCLMUL
+#if !defined(DEFAULT_IMPL) && \
+ (defined(__PCLMUL__) || (X86_CPU_FEATURES_ENABLED && \
+ COMPILER_SUPPORTS_PCLMUL_TARGET_INTRINSICS))
+# define FUNCNAME crc32_pclmul
+# define FUNCNAME_ALIGNED crc32_pclmul_aligned
+# ifdef __PCLMUL__
+# define ATTRIBUTES
+# define DEFAULT_IMPL crc32_pclmul
+# else
+# define ATTRIBUTES __attribute__((target("pclmul")))
+# define DISPATCH 1
+# define DISPATCH_PCLMUL 1
+# endif
+# include "crc32_pclmul_template.h"
+#endif
+
+#ifdef DISPATCH
+static inline crc32_func_t
+arch_select_crc32_func(void)
+{
+ u32 features = get_cpu_features();
+
+#ifdef DISPATCH_PCLMUL_AVX
+ if ((features & X86_CPU_FEATURE_PCLMUL) &&
+ (features & X86_CPU_FEATURE_AVX))
+ return crc32_pclmul_avx;
+#endif
+#ifdef DISPATCH_PCLMUL
+ if (features & X86_CPU_FEATURE_PCLMUL)
+ return crc32_pclmul;
+#endif
+ return NULL;
+}
+#endif /* DISPATCH */
+
+#endif /* LIB_X86_CRC32_IMPL_H */
diff --git a/util/compress/libdeflate/lib/x86/crc32_pclmul_template.h b/util/compress/libdeflate/lib/x86/crc32_pclmul_template.h
new file mode 100644
index 000000000..a5eda9b87
--- /dev/null
+++ b/util/compress/libdeflate/lib/x86/crc32_pclmul_template.h
@@ -0,0 +1,262 @@
+/*
+ * x86/crc32_pclmul_template.h
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <immintrin.h>
+
+/*
+ * CRC-32 folding with PCLMULQDQ.
+ *
+ * The basic idea is to repeatedly "fold" each 512 bits into the next 512 bits,
+ * producing an abbreviated message which is congruent the original message
+ * modulo the generator polynomial G(x).
+ *
+ * Folding each 512 bits is implemented as eight 64-bit folds, each of which
+ * uses one carryless multiplication instruction. It's expected that CPUs may
+ * be able to execute some of these multiplications in parallel.
+ *
+ * Explanation of "folding": let A(x) be 64 bits from the message, and let B(x)
+ * be 95 bits from a constant distance D later in the message. The relevant
+ * portion of the message can be written as:
+ *
+ * M(x) = A(x)*x^D + B(x)
+ *
+ * ... where + and * represent addition and multiplication, respectively, of
+ * polynomials over GF(2). Note that when implemented on a computer, these
+ * operations are equivalent to XOR and carryless multiplication, respectively.
+ *
+ * For the purpose of CRC calculation, only the remainder modulo the generator
+ * polynomial G(x) matters:
+ *
+ * M(x) mod G(x) = (A(x)*x^D + B(x)) mod G(x)
+ *
+ * Since the modulo operation can be applied anywhere in a sequence of additions
+ * and multiplications without affecting the result, this is equivalent to:
+ *
+ * M(x) mod G(x) = (A(x)*(x^D mod G(x)) + B(x)) mod G(x)
+ *
+ * For any D, 'x^D mod G(x)' will be a polynomial with maximum degree 31, i.e.
+ * a 32-bit quantity. So 'A(x) * (x^D mod G(x))' is equivalent to a carryless
+ * multiplication of a 64-bit quantity by a 32-bit quantity, producing a 95-bit
+ * product. Then, adding (XOR-ing) the product to B(x) produces a polynomial
+ * with the same length as B(x) but with the same remainder as 'A(x)*x^D +
+ * B(x)'. This is the basic fold operation with 64 bits.
+ *
+ * Note that the carryless multiplication instruction PCLMULQDQ actually takes
+ * two 64-bit inputs and produces a 127-bit product in the low-order bits of a
+ * 128-bit XMM register. This works fine, but care must be taken to account for
+ * "bit endianness". With the CRC version implemented here, bits are always
+ * ordered such that the lowest-order bit represents the coefficient of highest
+ * power of x and the highest-order bit represents the coefficient of the lowest
+ * power of x. This is backwards from the more intuitive order. Still,
+ * carryless multiplication works essentially the same either way. It just must
+ * be accounted for that when we XOR the 95-bit product in the low-order 95 bits
+ * of a 128-bit XMM register into 128-bits of later data held in another XMM
+ * register, we'll really be XOR-ing the product into the mathematically higher
+ * degree end of those later bits, not the lower degree end as may be expected.
+ *
+ * So given that caveat and the fact that we process 512 bits per iteration, the
+ * 'D' values we need for the two 64-bit halves of each 128 bits of data are:
+ *
+ * D = (512 + 95) - 64 for the higher-degree half of each 128 bits,
+ * i.e. the lower order bits in the XMM register
+ *
+ * D = (512 + 95) - 128 for the lower-degree half of each 128 bits,
+ * i.e. the higher order bits in the XMM register
+ *
+ * The required 'x^D mod G(x)' values were precomputed.
+ *
+ * When <= 512 bits remain in the message, we finish up by folding across
+ * smaller distances. This works similarly; the distance D is just different,
+ * so different constant multipliers must be used. Finally, once the remaining
+ * message is just 64 bits, it is reduced to the CRC-32 using Barrett reduction
+ * (explained later).
+ *
+ * For more information see the original paper from Intel:
+ * "Fast CRC Computation for Generic Polynomials Using PCLMULQDQ Instruction"
+ * December 2009
+ * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
+ */
+static u32 ATTRIBUTES
+FUNCNAME_ALIGNED(u32 remainder, const __m128i *p, size_t nr_segs)
+{
+ /* Constants precomputed by gen_crc32_multipliers.c. Do not edit! */
+ const __v2di multipliers_4 = (__v2di){ 0x8F352D95, 0x1D9513D7 };
+ const __v2di multipliers_2 = (__v2di){ 0xF1DA05AA, 0x81256527 };
+ const __v2di multipliers_1 = (__v2di){ 0xAE689191, 0xCCAA009E };
+ const __v2di final_multiplier = (__v2di){ 0xB8BC6765 };
+ const __m128i mask32 = (__m128i)(__v4si){ 0xFFFFFFFF };
+ const __v2di barrett_reduction_constants =
+ (__v2di){ 0x00000001F7011641, 0x00000001DB710641 };
+
+ const __m128i * const end = p + nr_segs;
+ const __m128i * const end512 = p + (nr_segs & ~3);
+ __m128i x0, x1, x2, x3;
+
+ /*
+ * Account for the current 'remainder', i.e. the CRC of the part of the
+ * message already processed. Explanation: rewrite the message
+ * polynomial M(x) in terms of the first part A(x), the second part
+ * B(x), and the length of the second part in bits |B(x)| >= 32:
+ *
+ * M(x) = A(x)*x^|B(x)| + B(x)
+ *
+ * Then the CRC of M(x) is:
+ *
+ * CRC(M(x)) = CRC(A(x)*x^|B(x)| + B(x))
+ * = CRC(A(x)*x^32*x^(|B(x)| - 32) + B(x))
+ * = CRC(CRC(A(x))*x^(|B(x)| - 32) + B(x))
+ *
+ * Note: all arithmetic is modulo G(x), the generator polynomial; that's
+ * why A(x)*x^32 can be replaced with CRC(A(x)) = A(x)*x^32 mod G(x).
+ *
+ * So the CRC of the full message is the CRC of the second part of the
+ * message where the first 32 bits of the second part of the message
+ * have been XOR'ed with the CRC of the first part of the message.
+ */
+ x0 = *p++;
+ x0 ^= (__m128i)(__v4si){ remainder };
+
+ if (p > end512) /* only 128, 256, or 384 bits of input? */
+ goto _128_bits_at_a_time;
+ x1 = *p++;
+ x2 = *p++;
+ x3 = *p++;
+
+ /* Fold 512 bits at a time */
+ for (; p != end512; p += 4) {
+ __m128i y0, y1, y2, y3;
+
+ y0 = p[0];
+ y1 = p[1];
+ y2 = p[2];
+ y3 = p[3];
+
+ /*
+ * Note: the immediate constant for PCLMULQDQ specifies which
+ * 64-bit halves of the 128-bit vectors to multiply:
+ *
+ * 0x00 means low halves (higher degree polynomial terms for us)
+ * 0x11 means high halves (lower degree polynomial terms for us)
+ */
+ y0 ^= _mm_clmulepi64_si128(x0, multipliers_4, 0x00);
+ y1 ^= _mm_clmulepi64_si128(x1, multipliers_4, 0x00);
+ y2 ^= _mm_clmulepi64_si128(x2, multipliers_4, 0x00);
+ y3 ^= _mm_clmulepi64_si128(x3, multipliers_4, 0x00);
+ y0 ^= _mm_clmulepi64_si128(x0, multipliers_4, 0x11);
+ y1 ^= _mm_clmulepi64_si128(x1, multipliers_4, 0x11);
+ y2 ^= _mm_clmulepi64_si128(x2, multipliers_4, 0x11);
+ y3 ^= _mm_clmulepi64_si128(x3, multipliers_4, 0x11);
+
+ x0 = y0;
+ x1 = y1;
+ x2 = y2;
+ x3 = y3;
+ }
+
+ /* Fold 512 bits => 128 bits */
+ x2 ^= _mm_clmulepi64_si128(x0, multipliers_2, 0x00);
+ x3 ^= _mm_clmulepi64_si128(x1, multipliers_2, 0x00);
+ x2 ^= _mm_clmulepi64_si128(x0, multipliers_2, 0x11);
+ x3 ^= _mm_clmulepi64_si128(x1, multipliers_2, 0x11);
+ x3 ^= _mm_clmulepi64_si128(x2, multipliers_1, 0x00);
+ x3 ^= _mm_clmulepi64_si128(x2, multipliers_1, 0x11);
+ x0 = x3;
+
+_128_bits_at_a_time:
+ while (p != end) {
+ /* Fold 128 bits into next 128 bits */
+ x1 = *p++;
+ x1 ^= _mm_clmulepi64_si128(x0, multipliers_1, 0x00);
+ x1 ^= _mm_clmulepi64_si128(x0, multipliers_1, 0x11);
+ x0 = x1;
+ }
+
+ /* Now there are just 128 bits left, stored in 'x0'. */
+
+ /*
+ * Fold 128 => 96 bits. This also implicitly appends 32 zero bits,
+ * which is equivalent to multiplying by x^32. This is needed because
+ * the CRC is defined as M(x)*x^32 mod G(x), not just M(x) mod G(x).
+ */
+ x0 = _mm_srli_si128(x0, 8) ^
+ _mm_clmulepi64_si128(x0, multipliers_1, 0x10);
+
+ /* Fold 96 => 64 bits */
+ x0 = _mm_srli_si128(x0, 4) ^
+ _mm_clmulepi64_si128(x0 & mask32, final_multiplier, 0x00);
+
+ /*
+ * Finally, reduce 64 => 32 bits using Barrett reduction.
+ *
+ * Let M(x) = A(x)*x^32 + B(x) be the remaining message. The goal is to
+ * compute R(x) = M(x) mod G(x). Since degree(B(x)) < degree(G(x)):
+ *
+ * R(x) = (A(x)*x^32 + B(x)) mod G(x)
+ * = (A(x)*x^32) mod G(x) + B(x)
+ *
+ * Then, by the Division Algorithm there exists a unique q(x) such that:
+ *
+ * A(x)*x^32 mod G(x) = A(x)*x^32 - q(x)*G(x)
+ *
+ * Since the left-hand side is of maximum degree 31, the right-hand side
+ * must be too. This implies that we can apply 'mod x^32' to the
+ * right-hand side without changing its value:
+ *
+ * (A(x)*x^32 - q(x)*G(x)) mod x^32 = q(x)*G(x) mod x^32
+ *
+ * Note that '+' is equivalent to '-' in polynomials over GF(2).
+ *
+ * We also know that:
+ *
+ * / A(x)*x^32 \
+ * q(x) = floor ( --------- )
+ * \ G(x) /
+ *
+ * To compute this efficiently, we can multiply the top and bottom by
+ * x^32 and move the division by G(x) to the top:
+ *
+ * / A(x) * floor(x^64 / G(x)) \
+ * q(x) = floor ( ------------------------- )
+ * \ x^32 /
+ *
+ * Note that floor(x^64 / G(x)) is a constant.
+ *
+ * So finally we have:
+ *
+ * / A(x) * floor(x^64 / G(x)) \
+ * R(x) = B(x) + G(x)*floor ( ------------------------- )
+ * \ x^32 /
+ */
+ x1 = x0;
+ x0 = _mm_clmulepi64_si128(x0 & mask32, barrett_reduction_constants, 0x00);
+ x0 = _mm_clmulepi64_si128(x0 & mask32, barrett_reduction_constants, 0x10);
+ return _mm_cvtsi128_si32(_mm_srli_si128(x0 ^ x1, 4));
+}
+
+#define IMPL_ALIGNMENT 16
+#define IMPL_SEGMENT_SIZE 16
+#include "../crc32_vec_template.h"
diff --git a/util/compress/libdeflate/lib/x86/decompress_impl.h b/util/compress/libdeflate/lib/x86/decompress_impl.h
new file mode 100644
index 000000000..de6d23631
--- /dev/null
+++ b/util/compress/libdeflate/lib/x86/decompress_impl.h
@@ -0,0 +1,31 @@
+#ifndef LIB_X86_DECOMPRESS_IMPL_H
+#define LIB_X86_DECOMPRESS_IMPL_H
+
+#include "cpu_features.h"
+
+/* Include the BMI2-optimized version? */
+#undef DISPATCH_BMI2
+#if !defined(__BMI2__) && X86_CPU_FEATURES_ENABLED && \
+ COMPILER_SUPPORTS_BMI2_TARGET
+# define FUNCNAME deflate_decompress_bmi2
+# define ATTRIBUTES __attribute__((target("bmi2")))
+# define DISPATCH 1
+# define DISPATCH_BMI2 1
+# include "../decompress_template.h"
+#endif
+
+#ifdef DISPATCH
+static inline decompress_func_t
+arch_select_decompress_func(void)
+{
+ u32 features = get_cpu_features();
+
+#ifdef DISPATCH_BMI2
+ if (features & X86_CPU_FEATURE_BMI2)
+ return deflate_decompress_bmi2;
+#endif
+ return NULL;
+}
+#endif /* DISPATCH */
+
+#endif /* LIB_X86_DECOMPRESS_IMPL_H */
diff --git a/util/compress/libdeflate/lib/x86/matchfinder_impl.h b/util/compress/libdeflate/lib/x86/matchfinder_impl.h
new file mode 100644
index 000000000..99fbebe8d
--- /dev/null
+++ b/util/compress/libdeflate/lib/x86/matchfinder_impl.h
@@ -0,0 +1,122 @@
+/*
+ * x86/matchfinder_impl.h - x86 implementations of matchfinder functions
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef LIB_X86_MATCHFINDER_IMPL_H
+#define LIB_X86_MATCHFINDER_IMPL_H
+
+#ifdef __AVX2__
+# include <immintrin.h>
+static forceinline void
+matchfinder_init_avx2(mf_pos_t *data, size_t size)
+{
+ __m256i *p = (__m256i *)data;
+ __m256i v = _mm256_set1_epi16(MATCHFINDER_INITVAL);
+
+ STATIC_ASSERT(MATCHFINDER_MEM_ALIGNMENT % sizeof(*p) == 0);
+ STATIC_ASSERT(MATCHFINDER_SIZE_ALIGNMENT % (4 * sizeof(*p)) == 0);
+ STATIC_ASSERT(sizeof(mf_pos_t) == 2);
+
+ do {
+ p[0] = v;
+ p[1] = v;
+ p[2] = v;
+ p[3] = v;
+ p += 4;
+ size -= 4 * sizeof(*p);
+ } while (size != 0);
+}
+#define matchfinder_init matchfinder_init_avx2
+
+static forceinline void
+matchfinder_rebase_avx2(mf_pos_t *data, size_t size)
+{
+ __m256i *p = (__m256i *)data;
+ __m256i v = _mm256_set1_epi16((u16)-MATCHFINDER_WINDOW_SIZE);
+
+ STATIC_ASSERT(MATCHFINDER_MEM_ALIGNMENT % sizeof(*p) == 0);
+ STATIC_ASSERT(MATCHFINDER_SIZE_ALIGNMENT % (4 * sizeof(*p)) == 0);
+ STATIC_ASSERT(sizeof(mf_pos_t) == 2);
+
+ do {
+ /* PADDSW: Add Packed Signed Integers With Signed Saturation */
+ p[0] = _mm256_adds_epi16(p[0], v);
+ p[1] = _mm256_adds_epi16(p[1], v);
+ p[2] = _mm256_adds_epi16(p[2], v);
+ p[3] = _mm256_adds_epi16(p[3], v);
+ p += 4;
+ size -= 4 * sizeof(*p);
+ } while (size != 0);
+}
+#define matchfinder_rebase matchfinder_rebase_avx2
+
+#elif defined(__SSE2__)
+# include <emmintrin.h>
+static forceinline void
+matchfinder_init_sse2(mf_pos_t *data, size_t size)
+{
+ __m128i *p = (__m128i *)data;
+ __m128i v = _mm_set1_epi16(MATCHFINDER_INITVAL);
+
+ STATIC_ASSERT(MATCHFINDER_MEM_ALIGNMENT % sizeof(*p) == 0);
+ STATIC_ASSERT(MATCHFINDER_SIZE_ALIGNMENT % (4 * sizeof(*p)) == 0);
+ STATIC_ASSERT(sizeof(mf_pos_t) == 2);
+
+ do {
+ p[0] = v;
+ p[1] = v;
+ p[2] = v;
+ p[3] = v;
+ p += 4;
+ size -= 4 * sizeof(*p);
+ } while (size != 0);
+}
+#define matchfinder_init matchfinder_init_sse2
+
+static forceinline void
+matchfinder_rebase_sse2(mf_pos_t *data, size_t size)
+{
+ __m128i *p = (__m128i *)data;
+ __m128i v = _mm_set1_epi16((u16)-MATCHFINDER_WINDOW_SIZE);
+
+ STATIC_ASSERT(MATCHFINDER_MEM_ALIGNMENT % sizeof(*p) == 0);
+ STATIC_ASSERT(MATCHFINDER_SIZE_ALIGNMENT % (4 * sizeof(*p)) == 0);
+ STATIC_ASSERT(sizeof(mf_pos_t) == 2);
+
+ do {
+ /* PADDSW: Add Packed Signed Integers With Signed Saturation */
+ p[0] = _mm_adds_epi16(p[0], v);
+ p[1] = _mm_adds_epi16(p[1], v);
+ p[2] = _mm_adds_epi16(p[2], v);
+ p[3] = _mm_adds_epi16(p[3], v);
+ p += 4;
+ size -= 4 * sizeof(*p);
+ } while (size != 0);
+}
+#define matchfinder_rebase matchfinder_rebase_sse2
+#endif /* __SSE2__ */
+
+#endif /* LIB_X86_MATCHFINDER_IMPL_H */
diff --git a/util/compress/libdeflate/lib/zlib_compress.c b/util/compress/libdeflate/lib/zlib_compress.c
new file mode 100644
index 000000000..ab0075136
--- /dev/null
+++ b/util/compress/libdeflate/lib/zlib_compress.c
@@ -0,0 +1,87 @@
+/*
+ * zlib_compress.c - compress with a zlib wrapper
+ *
+ * Originally public domain; changes after 2016-09-07 are copyrighted.
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "deflate_compress.h"
+#include "unaligned.h"
+#include "zlib_constants.h"
+
+#include "libdeflate.h"
+
+LIBDEFLATEEXPORT size_t LIBDEFLATEAPI
+libdeflate_zlib_compress(struct libdeflate_compressor *c,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail)
+{
+ u8 *out_next = out;
+ u16 hdr;
+ unsigned compression_level;
+ unsigned level_hint;
+ size_t deflate_size;
+
+ if (out_nbytes_avail <= ZLIB_MIN_OVERHEAD)
+ return 0;
+
+ /* 2 byte header: CMF and FLG */
+ hdr = (ZLIB_CM_DEFLATE << 8) | (ZLIB_CINFO_32K_WINDOW << 12);
+ compression_level = deflate_get_compression_level(c);
+ if (compression_level < 2)
+ level_hint = ZLIB_FASTEST_COMPRESSION;
+ else if (compression_level < 6)
+ level_hint = ZLIB_FAST_COMPRESSION;
+ else if (compression_level < 8)
+ level_hint = ZLIB_DEFAULT_COMPRESSION;
+ else
+ level_hint = ZLIB_SLOWEST_COMPRESSION;
+ hdr |= level_hint << 6;
+ hdr |= 31 - (hdr % 31);
+
+ put_unaligned_be16(hdr, out_next);
+ out_next += 2;
+
+ /* Compressed data */
+ deflate_size = libdeflate_deflate_compress(c, in, in_nbytes, out_next,
+ out_nbytes_avail - ZLIB_MIN_OVERHEAD);
+ if (deflate_size == 0)
+ return 0;
+ out_next += deflate_size;
+
+ /* ADLER32 */
+ put_unaligned_be32(libdeflate_adler32(1, in, in_nbytes), out_next);
+ out_next += 4;
+
+ return out_next - (u8 *)out;
+}
+
+LIBDEFLATEEXPORT size_t LIBDEFLATEAPI
+libdeflate_zlib_compress_bound(struct libdeflate_compressor *c,
+ size_t in_nbytes)
+{
+ return ZLIB_MIN_OVERHEAD +
+ libdeflate_deflate_compress_bound(c, in_nbytes);
+}
diff --git a/util/compress/libdeflate/lib/zlib_constants.h b/util/compress/libdeflate/lib/zlib_constants.h
new file mode 100644
index 000000000..f304310c7
--- /dev/null
+++ b/util/compress/libdeflate/lib/zlib_constants.h
@@ -0,0 +1,21 @@
+/*
+ * zlib_constants.h - constants for the zlib wrapper format
+ */
+
+#ifndef LIB_ZLIB_CONSTANTS_H
+#define LIB_ZLIB_CONSTANTS_H
+
+#define ZLIB_MIN_HEADER_SIZE 2
+#define ZLIB_FOOTER_SIZE 4
+#define ZLIB_MIN_OVERHEAD (ZLIB_MIN_HEADER_SIZE + ZLIB_FOOTER_SIZE)
+
+#define ZLIB_CM_DEFLATE 8
+
+#define ZLIB_CINFO_32K_WINDOW 7
+
+#define ZLIB_FASTEST_COMPRESSION 0
+#define ZLIB_FAST_COMPRESSION 1
+#define ZLIB_DEFAULT_COMPRESSION 2
+#define ZLIB_SLOWEST_COMPRESSION 3
+
+#endif /* LIB_ZLIB_CONSTANTS_H */
diff --git a/util/compress/libdeflate/lib/zlib_decompress.c b/util/compress/libdeflate/lib/zlib_decompress.c
new file mode 100644
index 000000000..0f6c71489
--- /dev/null
+++ b/util/compress/libdeflate/lib/zlib_decompress.c
@@ -0,0 +1,108 @@
+/*
+ * zlib_decompress.c - decompress with a zlib wrapper
+ *
+ * Originally public domain; changes after 2016-09-07 are copyrighted.
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "unaligned.h"
+#include "zlib_constants.h"
+
+#include "libdeflate.h"
+
+LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
+libdeflate_zlib_decompress_ex(struct libdeflate_decompressor *d,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail,
+ size_t *actual_in_nbytes_ret,
+ size_t *actual_out_nbytes_ret)
+{
+ const u8 *in_next = in;
+ const u8 * const in_end = in_next + in_nbytes;
+ u16 hdr;
+ size_t actual_in_nbytes;
+ size_t actual_out_nbytes;
+ enum libdeflate_result result;
+
+ if (in_nbytes < ZLIB_MIN_OVERHEAD)
+ return LIBDEFLATE_BAD_DATA;
+
+ /* 2 byte header: CMF and FLG */
+ hdr = get_unaligned_be16(in_next);
+ in_next += 2;
+
+ /* FCHECK */
+ if ((hdr % 31) != 0)
+ return LIBDEFLATE_BAD_DATA;
+
+ /* CM */
+ if (((hdr >> 8) & 0xF) != ZLIB_CM_DEFLATE)
+ return LIBDEFLATE_BAD_DATA;
+
+ /* CINFO */
+ if ((hdr >> 12) > ZLIB_CINFO_32K_WINDOW)
+ return LIBDEFLATE_BAD_DATA;
+
+ /* FDICT */
+ if ((hdr >> 5) & 1)
+ return LIBDEFLATE_BAD_DATA;
+
+ /* Compressed data */
+ result = libdeflate_deflate_decompress_ex(d, in_next,
+ in_end - ZLIB_FOOTER_SIZE - in_next,
+ out, out_nbytes_avail,
+ &actual_in_nbytes, actual_out_nbytes_ret);
+ if (result != LIBDEFLATE_SUCCESS)
+ return result;
+
+ if (actual_out_nbytes_ret)
+ actual_out_nbytes = *actual_out_nbytes_ret;
+ else
+ actual_out_nbytes = out_nbytes_avail;
+
+ in_next += actual_in_nbytes;
+
+ /* ADLER32 */
+ if (libdeflate_adler32(1, out, actual_out_nbytes) !=
+ get_unaligned_be32(in_next))
+ return LIBDEFLATE_BAD_DATA;
+ in_next += 4;
+
+ if (actual_in_nbytes_ret)
+ *actual_in_nbytes_ret = in_next - (u8 *)in;
+
+ return LIBDEFLATE_SUCCESS;
+}
+
+LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
+libdeflate_zlib_decompress(struct libdeflate_decompressor *d,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail,
+ size_t *actual_out_nbytes_ret)
+{
+ return libdeflate_zlib_decompress_ex(d, in, in_nbytes,
+ out, out_nbytes_avail,
+ NULL, actual_out_nbytes_ret);
+}
diff --git a/util/compress/libdeflate/libdeflate.h b/util/compress/libdeflate/libdeflate.h
new file mode 100644
index 000000000..cbcda0420
--- /dev/null
+++ b/util/compress/libdeflate/libdeflate.h
@@ -0,0 +1,366 @@
+/*
+ * libdeflate.h - public header for libdeflate
+ */
+
+#ifndef LIBDEFLATE_H
+#define LIBDEFLATE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIBDEFLATE_VERSION_MAJOR 1
+#define LIBDEFLATE_VERSION_MINOR 7
+#define LIBDEFLATE_VERSION_STRING "1.7"
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * On Windows, if you want to link to the DLL version of libdeflate, then
+ * #define LIBDEFLATE_DLL. Note that the calling convention is "stdcall".
+ */
+#ifdef LIBDEFLATE_DLL
+# ifdef BUILDING_LIBDEFLATE
+# define LIBDEFLATEEXPORT LIBEXPORT
+# elif defined(_WIN32) || defined(__CYGWIN__)
+# define LIBDEFLATEEXPORT __declspec(dllimport)
+# endif
+#endif
+#ifndef LIBDEFLATEEXPORT
+# define LIBDEFLATEEXPORT
+#endif
+
+#if defined(_WIN32) && !defined(_WIN64)
+# define LIBDEFLATEAPI_ABI __stdcall
+#else
+# define LIBDEFLATEAPI_ABI
+#endif
+
+#if defined(BUILDING_LIBDEFLATE) && defined(__GNUC__) && \
+ defined(_WIN32) && !defined(_WIN64)
+ /*
+ * On 32-bit Windows, gcc assumes 16-byte stack alignment but MSVC only 4.
+ * Realign the stack when entering libdeflate to avoid crashing in SSE/AVX
+ * code when called from an MSVC-compiled application.
+ */
+# define LIBDEFLATEAPI_STACKALIGN __attribute__((force_align_arg_pointer))
+#else
+# define LIBDEFLATEAPI_STACKALIGN
+#endif
+
+#define LIBDEFLATEAPI LIBDEFLATEAPI_ABI LIBDEFLATEAPI_STACKALIGN
+
+/* ========================================================================== */
+/* Compression */
+/* ========================================================================== */
+
+struct libdeflate_compressor;
+
+/*
+ * libdeflate_alloc_compressor() allocates a new compressor that supports
+ * DEFLATE, zlib, and gzip compression. 'compression_level' is the compression
+ * level on a zlib-like scale but with a higher maximum value (1 = fastest, 6 =
+ * medium/default, 9 = slow, 12 = slowest). Level 0 is also supported and means
+ * "no compression", specifically "create a valid stream, but only emit
+ * uncompressed blocks" (this will expand the data slightly).
+ *
+ * The return value is a pointer to the new compressor, or NULL if out of memory
+ * or if the compression level is invalid (i.e. outside the range [0, 12]).
+ *
+ * Note: for compression, the sliding window size is defined at compilation time
+ * to 32768, the largest size permissible in the DEFLATE format. It cannot be
+ * changed at runtime.
+ *
+ * A single compressor is not safe to use by multiple threads concurrently.
+ * However, different threads may use different compressors concurrently.
+ */
+LIBDEFLATEEXPORT struct libdeflate_compressor * LIBDEFLATEAPI
+libdeflate_alloc_compressor(int compression_level);
+
+/*
+ * libdeflate_deflate_compress() performs raw DEFLATE compression on a buffer of
+ * data. The function attempts to compress 'in_nbytes' bytes of data located at
+ * 'in' and write the results to 'out', which has space for 'out_nbytes_avail'
+ * bytes. The return value is the compressed size in bytes, or 0 if the data
+ * could not be compressed to 'out_nbytes_avail' bytes or fewer.
+ */
+LIBDEFLATEEXPORT size_t LIBDEFLATEAPI
+libdeflate_deflate_compress(struct libdeflate_compressor *compressor,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail);
+
+/*
+ * libdeflate_deflate_compress_bound() returns a worst-case upper bound on the
+ * number of bytes of compressed data that may be produced by compressing any
+ * buffer of length less than or equal to 'in_nbytes' using
+ * libdeflate_deflate_compress() with the specified compressor. Mathematically,
+ * this bound will necessarily be a number greater than or equal to 'in_nbytes'.
+ * It may be an overestimate of the true upper bound. The return value is
+ * guaranteed to be the same for all invocations with the same compressor and
+ * same 'in_nbytes'.
+ *
+ * As a special case, 'compressor' may be NULL. This causes the bound to be
+ * taken across *any* libdeflate_compressor that could ever be allocated with
+ * this build of the library, with any options.
+ *
+ * Note that this function is not necessary in many applications. With
+ * block-based compression, it is usually preferable to separately store the
+ * uncompressed size of each block and to store any blocks that did not compress
+ * to less than their original size uncompressed. In that scenario, there is no
+ * need to know the worst-case compressed size, since the maximum number of
+ * bytes of compressed data that may be used would always be one less than the
+ * input length. You can just pass a buffer of that size to
+ * libdeflate_deflate_compress() and store the data uncompressed if
+ * libdeflate_deflate_compress() returns 0, indicating that the compressed data
+ * did not fit into the provided output buffer.
+ */
+LIBDEFLATEEXPORT size_t LIBDEFLATEAPI
+libdeflate_deflate_compress_bound(struct libdeflate_compressor *compressor,
+ size_t in_nbytes);
+
+/*
+ * Like libdeflate_deflate_compress(), but stores the data in the zlib wrapper
+ * format.
+ */
+LIBDEFLATEEXPORT size_t LIBDEFLATEAPI
+libdeflate_zlib_compress(struct libdeflate_compressor *compressor,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail);
+
+/*
+ * Like libdeflate_deflate_compress_bound(), but assumes the data will be
+ * compressed with libdeflate_zlib_compress() rather than with
+ * libdeflate_deflate_compress().
+ */
+LIBDEFLATEEXPORT size_t LIBDEFLATEAPI
+libdeflate_zlib_compress_bound(struct libdeflate_compressor *compressor,
+ size_t in_nbytes);
+
+/*
+ * Like libdeflate_deflate_compress(), but stores the data in the gzip wrapper
+ * format.
+ */
+LIBDEFLATEEXPORT size_t LIBDEFLATEAPI
+libdeflate_gzip_compress(struct libdeflate_compressor *compressor,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail);
+
+/*
+ * Like libdeflate_deflate_compress_bound(), but assumes the data will be
+ * compressed with libdeflate_gzip_compress() rather than with
+ * libdeflate_deflate_compress().
+ */
+LIBDEFLATEEXPORT size_t LIBDEFLATEAPI
+libdeflate_gzip_compress_bound(struct libdeflate_compressor *compressor,
+ size_t in_nbytes);
+
+/*
+ * libdeflate_free_compressor() frees a compressor that was allocated with
+ * libdeflate_alloc_compressor(). If a NULL pointer is passed in, no action is
+ * taken.
+ */
+LIBDEFLATEEXPORT void LIBDEFLATEAPI
+libdeflate_free_compressor(struct libdeflate_compressor *compressor);
+
+/* ========================================================================== */
+/* Decompression */
+/* ========================================================================== */
+
+struct libdeflate_decompressor;
+
+/*
+ * libdeflate_alloc_decompressor() allocates a new decompressor that can be used
+ * for DEFLATE, zlib, and gzip decompression. The return value is a pointer to
+ * the new decompressor, or NULL if out of memory.
+ *
+ * This function takes no parameters, and the returned decompressor is valid for
+ * decompressing data that was compressed at any compression level and with any
+ * sliding window size.
+ *
+ * A single decompressor is not safe to use by multiple threads concurrently.
+ * However, different threads may use different decompressors concurrently.
+ */
+LIBDEFLATEEXPORT struct libdeflate_decompressor * LIBDEFLATEAPI
+libdeflate_alloc_decompressor(void);
+
+/*
+ * Result of a call to libdeflate_deflate_decompress(),
+ * libdeflate_zlib_decompress(), or libdeflate_gzip_decompress().
+ */
+enum libdeflate_result {
+ /* Decompression was successful. */
+ LIBDEFLATE_SUCCESS = 0,
+
+ /* Decompressed failed because the compressed data was invalid, corrupt,
+ * or otherwise unsupported. */
+ LIBDEFLATE_BAD_DATA = 1,
+
+ /* A NULL 'actual_out_nbytes_ret' was provided, but the data would have
+ * decompressed to fewer than 'out_nbytes_avail' bytes. */
+ LIBDEFLATE_SHORT_OUTPUT = 2,
+
+ /* The data would have decompressed to more than 'out_nbytes_avail'
+ * bytes. */
+ LIBDEFLATE_INSUFFICIENT_SPACE = 3,
+};
+
+/*
+ * libdeflate_deflate_decompress() decompresses the DEFLATE-compressed stream
+ * from the buffer 'in' with compressed size up to 'in_nbytes' bytes. The
+ * uncompressed data is written to 'out', a buffer with size 'out_nbytes_avail'
+ * bytes. If decompression succeeds, then 0 (LIBDEFLATE_SUCCESS) is returned.
+ * Otherwise, a nonzero result code such as LIBDEFLATE_BAD_DATA is returned. If
+ * a nonzero result code is returned, then the contents of the output buffer are
+ * undefined.
+ *
+ * Decompression stops at the end of the DEFLATE stream (as indicated by the
+ * BFINAL flag), even if it is actually shorter than 'in_nbytes' bytes.
+ *
+ * libdeflate_deflate_decompress() can be used in cases where the actual
+ * uncompressed size is known (recommended) or unknown (not recommended):
+ *
+ * - If the actual uncompressed size is known, then pass the actual
+ * uncompressed size as 'out_nbytes_avail' and pass NULL for
+ * 'actual_out_nbytes_ret'. This makes libdeflate_deflate_decompress() fail
+ * with LIBDEFLATE_SHORT_OUTPUT if the data decompressed to fewer than the
+ * specified number of bytes.
+ *
+ * - If the actual uncompressed size is unknown, then provide a non-NULL
+ * 'actual_out_nbytes_ret' and provide a buffer with some size
+ * 'out_nbytes_avail' that you think is large enough to hold all the
+ * uncompressed data. In this case, if the data decompresses to less than
+ * or equal to 'out_nbytes_avail' bytes, then
+ * libdeflate_deflate_decompress() will write the actual uncompressed size
+ * to *actual_out_nbytes_ret and return 0 (LIBDEFLATE_SUCCESS). Otherwise,
+ * it will return LIBDEFLATE_INSUFFICIENT_SPACE if the provided buffer was
+ * not large enough but no other problems were encountered, or another
+ * nonzero result code if decompression failed for another reason.
+ */
+LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
+libdeflate_deflate_decompress(struct libdeflate_decompressor *decompressor,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail,
+ size_t *actual_out_nbytes_ret);
+
+/*
+ * Like libdeflate_deflate_decompress(), but adds the 'actual_in_nbytes_ret'
+ * argument. If decompression succeeds and 'actual_in_nbytes_ret' is not NULL,
+ * then the actual compressed size of the DEFLATE stream (aligned to the next
+ * byte boundary) is written to *actual_in_nbytes_ret.
+ */
+LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
+libdeflate_deflate_decompress_ex(struct libdeflate_decompressor *decompressor,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail,
+ size_t *actual_in_nbytes_ret,
+ size_t *actual_out_nbytes_ret);
+
+/*
+ * Like libdeflate_deflate_decompress(), but assumes the zlib wrapper format
+ * instead of raw DEFLATE.
+ *
+ * Decompression will stop at the end of the zlib stream, even if it is shorter
+ * than 'in_nbytes'. If you need to know exactly where the zlib stream ended,
+ * use libdeflate_zlib_decompress_ex().
+ */
+LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
+libdeflate_zlib_decompress(struct libdeflate_decompressor *decompressor,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail,
+ size_t *actual_out_nbytes_ret);
+
+/*
+ * Like libdeflate_zlib_decompress(), but adds the 'actual_in_nbytes_ret'
+ * argument. If 'actual_in_nbytes_ret' is not NULL and the decompression
+ * succeeds (indicating that the first zlib-compressed stream in the input
+ * buffer was decompressed), then the actual number of input bytes consumed is
+ * written to *actual_in_nbytes_ret.
+ */
+LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
+libdeflate_zlib_decompress_ex(struct libdeflate_decompressor *decompressor,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail,
+ size_t *actual_in_nbytes_ret,
+ size_t *actual_out_nbytes_ret);
+
+/*
+ * Like libdeflate_deflate_decompress(), but assumes the gzip wrapper format
+ * instead of raw DEFLATE.
+ *
+ * If multiple gzip-compressed members are concatenated, then only the first
+ * will be decompressed. Use libdeflate_gzip_decompress_ex() if you need
+ * multi-member support.
+ */
+LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
+libdeflate_gzip_decompress(struct libdeflate_decompressor *decompressor,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail,
+ size_t *actual_out_nbytes_ret);
+
+/*
+ * Like libdeflate_gzip_decompress(), but adds the 'actual_in_nbytes_ret'
+ * argument. If 'actual_in_nbytes_ret' is not NULL and the decompression
+ * succeeds (indicating that the first gzip-compressed member in the input
+ * buffer was decompressed), then the actual number of input bytes consumed is
+ * written to *actual_in_nbytes_ret.
+ */
+LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
+libdeflate_gzip_decompress_ex(struct libdeflate_decompressor *decompressor,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail,
+ size_t *actual_in_nbytes_ret,
+ size_t *actual_out_nbytes_ret);
+
+/*
+ * libdeflate_free_decompressor() frees a decompressor that was allocated with
+ * libdeflate_alloc_decompressor(). If a NULL pointer is passed in, no action
+ * is taken.
+ */
+LIBDEFLATEEXPORT void LIBDEFLATEAPI
+libdeflate_free_decompressor(struct libdeflate_decompressor *decompressor);
+
+/* ========================================================================== */
+/* Checksums */
+/* ========================================================================== */
+
+/*
+ * libdeflate_adler32() updates a running Adler-32 checksum with 'len' bytes of
+ * data and returns the updated checksum. When starting a new checksum, the
+ * required initial value for 'adler' is 1. This value is also returned when
+ * 'buffer' is specified as NULL.
+ */
+LIBDEFLATEEXPORT uint32_t LIBDEFLATEAPI
+libdeflate_adler32(uint32_t adler, const void *buffer, size_t len);
+
+
+/*
+ * libdeflate_crc32() updates a running CRC-32 checksum with 'len' bytes of data
+ * and returns the updated checksum. When starting a new checksum, the required
+ * initial value for 'crc' is 0. This value is also returned when 'buffer' is
+ * specified as NULL.
+ */
+LIBDEFLATEEXPORT uint32_t LIBDEFLATEAPI
+libdeflate_crc32(uint32_t crc, const void *buffer, size_t len);
+
+/* ========================================================================== */
+/* Custom memory allocator */
+/* ========================================================================== */
+
+/*
+ * Install a custom memory allocator which libdeflate will use for all memory
+ * allocations. 'malloc_func' is a function that must behave like malloc(), and
+ * 'free_func' is a function that must behave like free().
+ *
+ * There must not be any libdeflate_compressor or libdeflate_decompressor
+ * structures in existence when calling this function.
+ */
+LIBDEFLATEEXPORT void LIBDEFLATEAPI
+libdeflate_set_memory_allocator(void *(*malloc_func)(size_t),
+ void (*free_func)(void *));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBDEFLATE_H */
diff --git a/util/compress/libdeflate/programs/benchmark.c b/util/compress/libdeflate/programs/benchmark.c
new file mode 100644
index 000000000..52af8dafc
--- /dev/null
+++ b/util/compress/libdeflate/programs/benchmark.c
@@ -0,0 +1,696 @@
+/*
+ * benchmark.c - a compression testing and benchmark program
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "test_util.h"
+
+static const tchar *const optstring = T("0::1::2::3::4::5::6::7::8::9::C:D:eghs:VYZz");
+
+enum format {
+ DEFLATE_FORMAT,
+ ZLIB_FORMAT,
+ GZIP_FORMAT,
+};
+
+struct compressor {
+ int level;
+ enum format format;
+ const struct engine *engine;
+ void *private;
+};
+
+struct decompressor {
+ enum format format;
+ const struct engine *engine;
+ void *private;
+};
+
+struct engine {
+ const tchar *name;
+
+ bool (*init_compressor)(struct compressor *);
+ size_t (*compress_bound)(struct compressor *, size_t);
+ size_t (*compress)(struct compressor *, const void *, size_t,
+ void *, size_t);
+ void (*destroy_compressor)(struct compressor *);
+
+ bool (*init_decompressor)(struct decompressor *);
+ bool (*decompress)(struct decompressor *, const void *, size_t,
+ void *, size_t);
+ void (*destroy_decompressor)(struct decompressor *);
+};
+
+/******************************************************************************/
+
+static bool
+libdeflate_engine_init_compressor(struct compressor *c)
+{
+ c->private = alloc_compressor(c->level);
+ return c->private != NULL;
+}
+
+static size_t
+libdeflate_engine_compress_bound(struct compressor *c, size_t in_nbytes)
+{
+ switch (c->format) {
+ case ZLIB_FORMAT:
+ return libdeflate_zlib_compress_bound(c->private, in_nbytes);
+ case GZIP_FORMAT:
+ return libdeflate_gzip_compress_bound(c->private, in_nbytes);
+ default:
+ return libdeflate_deflate_compress_bound(c->private, in_nbytes);
+ }
+}
+
+static size_t
+libdeflate_engine_compress(struct compressor *c, const void *in,
+ size_t in_nbytes, void *out, size_t out_nbytes_avail)
+{
+ switch (c->format) {
+ case ZLIB_FORMAT:
+ return libdeflate_zlib_compress(c->private, in, in_nbytes,
+ out, out_nbytes_avail);
+ case GZIP_FORMAT:
+ return libdeflate_gzip_compress(c->private, in, in_nbytes,
+ out, out_nbytes_avail);
+ default:
+ return libdeflate_deflate_compress(c->private, in, in_nbytes,
+ out, out_nbytes_avail);
+ }
+}
+
+static void
+libdeflate_engine_destroy_compressor(struct compressor *c)
+{
+ libdeflate_free_compressor(c->private);
+}
+
+static bool
+libdeflate_engine_init_decompressor(struct decompressor *d)
+{
+ d->private = alloc_decompressor();
+ return d->private != NULL;
+}
+
+static bool
+libdeflate_engine_decompress(struct decompressor *d, const void *in,
+ size_t in_nbytes, void *out, size_t out_nbytes)
+{
+ switch (d->format) {
+ case ZLIB_FORMAT:
+ return !libdeflate_zlib_decompress(d->private, in, in_nbytes,
+ out, out_nbytes, NULL);
+ case GZIP_FORMAT:
+ return !libdeflate_gzip_decompress(d->private, in, in_nbytes,
+ out, out_nbytes, NULL);
+ default:
+ return !libdeflate_deflate_decompress(d->private, in, in_nbytes,
+ out, out_nbytes, NULL);
+ }
+}
+
+static void
+libdeflate_engine_destroy_decompressor(struct decompressor *d)
+{
+ libdeflate_free_decompressor(d->private);
+}
+
+static const struct engine libdeflate_engine = {
+ .name = T("libdeflate"),
+
+ .init_compressor = libdeflate_engine_init_compressor,
+ .compress_bound = libdeflate_engine_compress_bound,
+ .compress = libdeflate_engine_compress,
+ .destroy_compressor = libdeflate_engine_destroy_compressor,
+
+ .init_decompressor = libdeflate_engine_init_decompressor,
+ .decompress = libdeflate_engine_decompress,
+ .destroy_decompressor = libdeflate_engine_destroy_decompressor,
+};
+
+/******************************************************************************/
+
+static int
+get_libz_window_bits(enum format format)
+{
+ const int windowBits = 15;
+ switch (format) {
+ case ZLIB_FORMAT:
+ return windowBits;
+ case GZIP_FORMAT:
+ return windowBits + 16;
+ default:
+ return -windowBits;
+ }
+}
+
+static bool
+libz_engine_init_compressor(struct compressor *c)
+{
+ z_stream *z;
+
+ if (c->level > 9) {
+ msg("libz only supports up to compression level 9");
+ return false;
+ }
+
+ z = xmalloc(sizeof(*z));
+ if (z == NULL)
+ return false;
+
+ z->next_in = NULL;
+ z->avail_in = 0;
+ z->zalloc = NULL;
+ z->zfree = NULL;
+ z->opaque = NULL;
+ if (deflateInit2(z, c->level, Z_DEFLATED,
+ get_libz_window_bits(c->format),
+ 8, Z_DEFAULT_STRATEGY) != Z_OK)
+ {
+ msg("unable to initialize deflater");
+ free(z);
+ return false;
+ }
+
+ c->private = z;
+ return true;
+}
+
+static size_t
+libz_engine_compress_bound(struct compressor *c, size_t in_nbytes)
+{
+ return deflateBound(c->private, in_nbytes);
+}
+
+static size_t
+libz_engine_compress(struct compressor *c, const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail)
+{
+ z_stream *z = c->private;
+
+ deflateReset(z);
+
+ z->next_in = (void *)in;
+ z->avail_in = in_nbytes;
+ z->next_out = out;
+ z->avail_out = out_nbytes_avail;
+
+ if (deflate(z, Z_FINISH) != Z_STREAM_END)
+ return 0;
+
+ return out_nbytes_avail - z->avail_out;
+}
+
+static void
+libz_engine_destroy_compressor(struct compressor *c)
+{
+ z_stream *z = c->private;
+
+ deflateEnd(z);
+ free(z);
+}
+
+static bool
+libz_engine_init_decompressor(struct decompressor *d)
+{
+ z_stream *z;
+
+ z = xmalloc(sizeof(*z));
+ if (z == NULL)
+ return false;
+
+ z->next_in = NULL;
+ z->avail_in = 0;
+ z->zalloc = NULL;
+ z->zfree = NULL;
+ z->opaque = NULL;
+ if (inflateInit2(z, get_libz_window_bits(d->format)) != Z_OK) {
+ msg("unable to initialize inflater");
+ free(z);
+ return false;
+ }
+
+ d->private = z;
+ return true;
+}
+
+static bool
+libz_engine_decompress(struct decompressor *d, const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes)
+{
+ z_stream *z = d->private;
+
+ inflateReset(z);
+
+ z->next_in = (void *)in;
+ z->avail_in = in_nbytes;
+ z->next_out = out;
+ z->avail_out = out_nbytes;
+
+ return inflate(z, Z_FINISH) == Z_STREAM_END && z->avail_out == 0;
+}
+
+static void
+libz_engine_destroy_decompressor(struct decompressor *d)
+{
+ z_stream *z = d->private;
+
+ inflateEnd(z);
+ free(z);
+}
+
+static const struct engine libz_engine = {
+ .name = T("libz"),
+
+ .init_compressor = libz_engine_init_compressor,
+ .compress_bound = libz_engine_compress_bound,
+ .compress = libz_engine_compress,
+ .destroy_compressor = libz_engine_destroy_compressor,
+
+ .init_decompressor = libz_engine_init_decompressor,
+ .decompress = libz_engine_decompress,
+ .destroy_decompressor = libz_engine_destroy_decompressor,
+};
+
+/******************************************************************************/
+
+static const struct engine * const all_engines[] = {
+ &libdeflate_engine,
+ &libz_engine,
+};
+
+#define DEFAULT_ENGINE libdeflate_engine
+
+static const struct engine *
+name_to_engine(const tchar *name)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_LEN(all_engines); i++)
+ if (tstrcmp(all_engines[i]->name, name) == 0)
+ return all_engines[i];
+ return NULL;
+}
+
+/******************************************************************************/
+
+static bool
+compressor_init(struct compressor *c, int level, enum format format,
+ const struct engine *engine)
+{
+ c->level = level;
+ c->format = format;
+ c->engine = engine;
+ return engine->init_compressor(c);
+}
+
+static size_t
+compress_bound(struct compressor *c, size_t in_nbytes)
+{
+ return c->engine->compress_bound(c, in_nbytes);
+}
+
+static size_t
+do_compress(struct compressor *c, const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail)
+{
+ return c->engine->compress(c, in, in_nbytes, out, out_nbytes_avail);
+}
+
+static void
+compressor_destroy(struct compressor *c)
+{
+ if (c->engine != NULL)
+ c->engine->destroy_compressor(c);
+}
+
+static bool
+decompressor_init(struct decompressor *d, enum format format,
+ const struct engine *engine)
+{
+ d->format = format;
+ d->engine = engine;
+ return engine->init_decompressor(d);
+}
+
+static bool
+do_decompress(struct decompressor *d, const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes)
+{
+ return d->engine->decompress(d, in, in_nbytes, out, out_nbytes);
+}
+
+static void
+decompressor_destroy(struct decompressor *d)
+{
+ if (d->engine != NULL)
+ d->engine->destroy_decompressor(d);
+}
+
+/******************************************************************************/
+
+static void
+show_available_engines(FILE *fp)
+{
+ size_t i;
+
+ fprintf(fp, "Available ENGINEs are: ");
+ for (i = 0; i < ARRAY_LEN(all_engines); i++) {
+ fprintf(fp, "%"TS, all_engines[i]->name);
+ if (i < ARRAY_LEN(all_engines) - 1)
+ fprintf(fp, ", ");
+ }
+ fprintf(fp, ". Default is %"TS"\n", DEFAULT_ENGINE.name);
+}
+
+static void
+show_usage(FILE *fp)
+{
+ fprintf(fp,
+"Usage: %"TS" [-LVL] [-C ENGINE] [-D ENGINE] [-ghVz] [-s SIZE] [FILE]...\n"
+"Benchmark DEFLATE compression and decompression on the specified FILEs.\n"
+"\n"
+"Options:\n"
+" -0 no compression\n"
+" -1 fastest (worst) compression\n"
+" -6 medium compression (default)\n"
+" -12 slowest (best) compression\n"
+" -C ENGINE compression engine\n"
+" -D ENGINE decompression engine\n"
+" -e allow chunks to be expanded (implied by -0)\n"
+" -g use gzip format instead of raw DEFLATE\n"
+" -h print this help\n"
+" -s SIZE chunk size\n"
+" -V show version and legal information\n"
+" -z use zlib format instead of raw DEFLATE\n"
+"\n", prog_invocation_name);
+
+ show_available_engines(fp);
+}
+
+static void
+show_version(void)
+{
+ printf(
+"libdeflate compression benchmark program v" LIBDEFLATE_VERSION_STRING "\n"
+"Copyright 2016 Eric Biggers\n"
+"\n"
+"This program is free software which may be modified and/or redistributed\n"
+"under the terms of the MIT license. There is NO WARRANTY, to the extent\n"
+"permitted by law. See the COPYING file for details.\n"
+ );
+}
+
+
+/******************************************************************************/
+
+static int
+do_benchmark(struct file_stream *in, void *original_buf, void *compressed_buf,
+ void *decompressed_buf, u32 chunk_size,
+ bool allow_expansion, size_t compressed_buf_size,
+ struct compressor *compressor,
+ struct decompressor *decompressor)
+{
+ u64 total_uncompressed_size = 0;
+ u64 total_compressed_size = 0;
+ u64 total_compress_time = 0;
+ u64 total_decompress_time = 0;
+ ssize_t ret;
+
+ while ((ret = xread(in, original_buf, chunk_size)) > 0) {
+ u32 original_size = ret;
+ size_t out_nbytes_avail;
+ u32 compressed_size;
+ u64 start_time;
+ bool ok;
+
+ total_uncompressed_size += original_size;
+
+ if (allow_expansion) {
+ out_nbytes_avail = compress_bound(compressor,
+ original_size);
+ if (out_nbytes_avail > compressed_buf_size) {
+ msg("%"TS": bug in compress_bound()", in->name);
+ return -1;
+ }
+ } else {
+ out_nbytes_avail = original_size - 1;
+ }
+
+ /* Compress the chunk of data. */
+ start_time = timer_ticks();
+ compressed_size = do_compress(compressor,
+ original_buf,
+ original_size,
+ compressed_buf,
+ out_nbytes_avail);
+ total_compress_time += timer_ticks() - start_time;
+
+ if (compressed_size) {
+ /* Successfully compressed the chunk of data. */
+
+ /* Decompress the data we just compressed and compare
+ * the result with the original. */
+ start_time = timer_ticks();
+ ok = do_decompress(decompressor,
+ compressed_buf, compressed_size,
+ decompressed_buf, original_size);
+ total_decompress_time += timer_ticks() - start_time;
+
+ if (!ok) {
+ msg("%"TS": failed to decompress data",
+ in->name);
+ return -1;
+ }
+
+ if (memcmp(original_buf, decompressed_buf,
+ original_size) != 0)
+ {
+ msg("%"TS": data did not decompress to "
+ "original", in->name);
+ return -1;
+ }
+
+ total_compressed_size += compressed_size;
+ } else {
+ /*
+ * The chunk would have compressed to more than
+ * out_nbytes_avail bytes.
+ */
+ if (allow_expansion) {
+ msg("%"TS": bug in compress_bound()", in->name);
+ return -1;
+ }
+ total_compressed_size += original_size;
+ }
+ }
+
+ if (ret < 0)
+ return ret;
+
+ if (total_uncompressed_size == 0) {
+ printf("\tFile was empty.\n");
+ return 0;
+ }
+
+ if (total_compress_time == 0)
+ total_compress_time = 1;
+ if (total_decompress_time == 0)
+ total_decompress_time = 1;
+
+ printf("\tCompressed %"PRIu64 " => %"PRIu64" bytes (%u.%03u%%)\n",
+ total_uncompressed_size, total_compressed_size,
+ (unsigned int)(total_compressed_size * 100 /
+ total_uncompressed_size),
+ (unsigned int)(total_compressed_size * 100000 /
+ total_uncompressed_size % 1000));
+ printf("\tCompression time: %"PRIu64" ms (%"PRIu64" MB/s)\n",
+ timer_ticks_to_ms(total_compress_time),
+ timer_MB_per_s(total_uncompressed_size, total_compress_time));
+ printf("\tDecompression time: %"PRIu64" ms (%"PRIu64" MB/s)\n",
+ timer_ticks_to_ms(total_decompress_time),
+ timer_MB_per_s(total_uncompressed_size, total_decompress_time));
+
+ return 0;
+}
+
+int
+tmain(int argc, tchar *argv[])
+{
+ u32 chunk_size = 1048576;
+ int level = 6;
+ enum format format = DEFLATE_FORMAT;
+ const struct engine *compress_engine = &DEFAULT_ENGINE;
+ const struct engine *decompress_engine = &DEFAULT_ENGINE;
+ bool allow_expansion = false;
+ struct compressor compressor = { 0 };
+ struct decompressor decompressor = { 0 };
+ size_t compressed_buf_size;
+ void *original_buf = NULL;
+ void *compressed_buf = NULL;
+ void *decompressed_buf = NULL;
+ tchar *default_file_list[] = { NULL };
+ int opt_char;
+ int i;
+ int ret;
+
+ begin_program(argv);
+
+ while ((opt_char = tgetopt(argc, argv, optstring)) != -1) {
+ switch (opt_char) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ level = parse_compression_level(opt_char, toptarg);
+ if (level < 0)
+ return 1;
+ break;
+ case 'C':
+ compress_engine = name_to_engine(toptarg);
+ if (compress_engine == NULL) {
+ msg("invalid compression engine: \"%"TS"\"", toptarg);
+ show_available_engines(stderr);
+ return 1;
+ }
+ break;
+ case 'D':
+ decompress_engine = name_to_engine(toptarg);
+ if (decompress_engine == NULL) {
+ msg("invalid decompression engine: \"%"TS"\"", toptarg);
+ show_available_engines(stderr);
+ return 1;
+ }
+ break;
+ case 'e':
+ allow_expansion = true;
+ break;
+ case 'g':
+ format = GZIP_FORMAT;
+ break;
+ case 'h':
+ show_usage(stdout);
+ return 0;
+ case 's':
+ chunk_size = tstrtoul(toptarg, NULL, 10);
+ if (chunk_size == 0) {
+ msg("invalid chunk size: \"%"TS"\"", toptarg);
+ return 1;
+ }
+ break;
+ case 'V':
+ show_version();
+ return 0;
+ case 'Y': /* deprecated, use '-C libz' instead */
+ compress_engine = &libz_engine;
+ break;
+ case 'Z': /* deprecated, use '-D libz' instead */
+ decompress_engine = &libz_engine;
+ break;
+ case 'z':
+ format = ZLIB_FORMAT;
+ break;
+ default:
+ show_usage(stderr);
+ return 1;
+ }
+ }
+
+ argc -= toptind;
+ argv += toptind;
+
+ if (level == 0)
+ allow_expansion = true;
+
+ ret = -1;
+ if (!compressor_init(&compressor, level, format, compress_engine))
+ goto out;
+ if (!decompressor_init(&decompressor, format, decompress_engine))
+ goto out;
+
+ if (allow_expansion)
+ compressed_buf_size = compress_bound(&compressor, chunk_size);
+ else
+ compressed_buf_size = chunk_size - 1;
+
+ original_buf = xmalloc(chunk_size);
+ compressed_buf = xmalloc(compressed_buf_size);
+ decompressed_buf = xmalloc(chunk_size);
+
+ ret = -1;
+ if (original_buf == NULL || compressed_buf == NULL ||
+ decompressed_buf == NULL)
+ goto out;
+
+ if (argc == 0) {
+ argv = default_file_list;
+ argc = ARRAY_LEN(default_file_list);
+ } else {
+ for (i = 0; i < argc; i++)
+ if (argv[i][0] == '-' && argv[i][1] == '\0')
+ argv[i] = NULL;
+ }
+
+ printf("Benchmarking %s compression:\n",
+ format == DEFLATE_FORMAT ? "DEFLATE" :
+ format == ZLIB_FORMAT ? "zlib" : "gzip");
+ printf("\tCompression level: %d\n", level);
+ printf("\tChunk size: %"PRIu32"\n", chunk_size);
+ printf("\tCompression engine: %"TS"\n", compress_engine->name);
+ printf("\tDecompression engine: %"TS"\n", decompress_engine->name);
+
+ for (i = 0; i < argc; i++) {
+ struct file_stream in;
+
+ ret = xopen_for_read(argv[i], true, &in);
+ if (ret != 0)
+ goto out;
+
+ printf("Processing %"TS"...\n", in.name);
+
+ ret = do_benchmark(&in, original_buf, compressed_buf,
+ decompressed_buf, chunk_size,
+ allow_expansion, compressed_buf_size,
+ &compressor, &decompressor);
+ xclose(&in);
+ if (ret != 0)
+ goto out;
+ }
+ ret = 0;
+out:
+ free(decompressed_buf);
+ free(compressed_buf);
+ free(original_buf);
+ decompressor_destroy(&decompressor);
+ compressor_destroy(&compressor);
+ return -ret;
+}
diff --git a/util/compress/libdeflate/programs/checksum.c b/util/compress/libdeflate/programs/checksum.c
new file mode 100644
index 000000000..0d394723b
--- /dev/null
+++ b/util/compress/libdeflate/programs/checksum.c
@@ -0,0 +1,207 @@
+/*
+ * checksum.c - Adler-32 and CRC-32 checksumming program
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "test_util.h"
+
+static const tchar *const optstring = T("Ahs:tZ");
+
+static void
+show_usage(FILE *fp)
+{
+ fprintf(fp,
+"Usage: %"TS" [-A] [-h] [-s SIZE] [-t] [-Z] [FILE]...\n"
+"Calculate Adler-32 or CRC-32 checksums of the specified FILEs.\n"
+"\n"
+"Options:\n"
+" -A use Adler-32 (default is CRC-32)\n"
+" -h print this help\n"
+" -s SIZE chunk size\n"
+" -t show checksum speed, excluding I/O\n"
+" -Z use zlib implementation instead of libdeflate\n",
+ prog_invocation_name);
+}
+
+typedef u32 (*cksum_fn_t)(u32, const void *, size_t);
+
+static u32
+adler32_libdeflate(u32 adler, const void *buf, size_t len)
+{
+ return libdeflate_adler32(adler, buf, len);
+}
+
+static u32
+crc32_libdeflate(u32 crc, const void *buf, size_t len)
+{
+ return libdeflate_crc32(crc, buf, len);
+}
+
+static u32
+adler32_zlib(u32 adler, const void *buf, size_t len)
+{
+ return adler32(adler, buf, len);
+}
+
+static u32
+crc32_zlib(u32 crc, const void *buf, size_t len)
+{
+ return crc32(crc, buf, len);
+}
+
+static int
+checksum_stream(struct file_stream *in, cksum_fn_t cksum, u32 *sum,
+ void *buf, size_t bufsize, u64 *size_ret, u64 *elapsed_ret)
+{
+ u64 size = 0;
+ u64 elapsed = 0;
+
+ for (;;) {
+ ssize_t ret;
+ u64 start_time;
+
+ ret = xread(in, buf, bufsize);
+ if (ret < 0)
+ return ret;
+ if (ret == 0)
+ break;
+
+ size += ret;
+ start_time = timer_ticks();
+ *sum = cksum(*sum, buf, ret);
+ elapsed += timer_ticks() - start_time;
+ }
+
+ if (elapsed == 0)
+ elapsed = 1;
+ *size_ret = size;
+ *elapsed_ret = elapsed;
+ return 0;
+}
+
+int
+tmain(int argc, tchar *argv[])
+{
+ bool use_adler32 = false;
+ bool use_zlib_impl = false;
+ bool do_timing = false;
+ void *buf;
+ size_t bufsize = 131072;
+ tchar *default_file_list[] = { NULL };
+ cksum_fn_t cksum;
+ int opt_char;
+ int i;
+ int ret;
+
+ begin_program(argv);
+
+ while ((opt_char = tgetopt(argc, argv, optstring)) != -1) {
+ switch (opt_char) {
+ case 'A':
+ use_adler32 = true;
+ break;
+ case 'h':
+ show_usage(stdout);
+ return 0;
+ case 's':
+ bufsize = tstrtoul(toptarg, NULL, 10);
+ if (bufsize == 0) {
+ msg("invalid chunk size: \"%"TS"\"", toptarg);
+ return 1;
+ }
+ break;
+ case 't':
+ do_timing = true;
+ break;
+ case 'Z':
+ use_zlib_impl = true;
+ break;
+ default:
+ show_usage(stderr);
+ return 1;
+ }
+ }
+
+ argc -= toptind;
+ argv += toptind;
+
+ if (use_adler32) {
+ if (use_zlib_impl)
+ cksum = adler32_zlib;
+ else
+ cksum = adler32_libdeflate;
+ } else {
+ if (use_zlib_impl)
+ cksum = crc32_zlib;
+ else
+ cksum = crc32_libdeflate;
+ }
+
+ buf = xmalloc(bufsize);
+ if (buf == NULL)
+ return 1;
+
+ if (argc == 0) {
+ argv = default_file_list;
+ argc = ARRAY_LEN(default_file_list);
+ } else {
+ for (i = 0; i < argc; i++)
+ if (argv[i][0] == '-' && argv[i][1] == '\0')
+ argv[i] = NULL;
+ }
+
+ for (i = 0; i < argc; i++) {
+ struct file_stream in;
+ u32 sum = cksum(0, NULL, 0);
+ u64 size = 0;
+ u64 elapsed = 0;
+
+ ret = xopen_for_read(argv[i], true, &in);
+ if (ret != 0)
+ goto out;
+
+ ret = checksum_stream(&in, cksum, &sum, buf, bufsize,
+ &size, &elapsed);
+ if (ret == 0) {
+ if (do_timing) {
+ printf("%08"PRIx32"\t%"TS"\t"
+ "%"PRIu64" ms\t%"PRIu64" MB/s\n",
+ sum, in.name, timer_ticks_to_ms(elapsed),
+ timer_MB_per_s(size, elapsed));
+ } else {
+ printf("%08"PRIx32"\t%"TS"\t\n", sum, in.name);
+ }
+ }
+
+ xclose(&in);
+
+ if (ret != 0)
+ goto out;
+ }
+ ret = 0;
+out:
+ free(buf);
+ return -ret;
+}
diff --git a/util/compress/libdeflate/programs/gzip.c b/util/compress/libdeflate/programs/gzip.c
new file mode 100644
index 000000000..a1d6d2a0d
--- /dev/null
+++ b/util/compress/libdeflate/programs/gzip.c
@@ -0,0 +1,658 @@
+/*
+ * gzip.c - a file compression and decompression program
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "prog_util.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef _WIN32
+# include <sys/utime.h>
+#else
+# include <sys/time.h>
+# include <unistd.h>
+# include <utime.h>
+#endif
+
+struct options {
+ bool to_stdout;
+ bool decompress;
+ bool force;
+ bool keep;
+ bool test;
+ int compression_level;
+ const tchar *suffix;
+};
+
+static const tchar *const optstring = T("1::2::3::4::5::6::7::8::9::cdfhknS:tV");
+
+static void
+show_usage(FILE *fp)
+{
+ fprintf(fp,
+"Usage: %"TS" [-LEVEL] [-cdfhkV] [-S SUF] FILE...\n"
+"Compress or decompress the specified FILEs.\n"
+"\n"
+"Options:\n"
+" -1 fastest (worst) compression\n"
+" -6 medium compression (default)\n"
+" -12 slowest (best) compression\n"
+" -c write to standard output\n"
+" -d decompress\n"
+" -f overwrite existing output files\n"
+" -h print this help\n"
+" -k don't delete input files\n"
+" -S SUF use suffix SUF instead of .gz\n"
+" -t test file integrity\n"
+" -V show version and legal information\n",
+ prog_invocation_name);
+}
+
+static void
+show_version(void)
+{
+ printf(
+"gzip compression program v" LIBDEFLATE_VERSION_STRING "\n"
+"Copyright 2016 Eric Biggers\n"
+"\n"
+"This program is free software which may be modified and/or redistributed\n"
+"under the terms of the MIT license. There is NO WARRANTY, to the extent\n"
+"permitted by law. See the COPYING file for details.\n"
+ );
+}
+
+/* Was the program invoked in decompression mode? */
+static bool
+is_gunzip(void)
+{
+ if (tstrxcmp(prog_invocation_name, T("gunzip")) == 0)
+ return true;
+ if (tstrxcmp(prog_invocation_name, T("libdeflate-gunzip")) == 0)
+ return true;
+#ifdef _WIN32
+ if (tstrxcmp(prog_invocation_name, T("gunzip.exe")) == 0)
+ return true;
+ if (tstrxcmp(prog_invocation_name, T("libdeflate-gunzip.exe")) == 0)
+ return true;
+#endif
+ return false;
+}
+
+static const tchar *
+get_suffix(const tchar *path, const tchar *suffix)
+{
+ size_t path_len = tstrlen(path);
+ size_t suffix_len = tstrlen(suffix);
+ const tchar *p;
+
+ if (path_len <= suffix_len)
+ return NULL;
+ p = &path[path_len - suffix_len];
+ if (tstrxcmp(p, suffix) == 0)
+ return p;
+ return NULL;
+}
+
+static bool
+has_suffix(const tchar *path, const tchar *suffix)
+{
+ return get_suffix(path, suffix) != NULL;
+}
+
+static tchar *
+append_suffix(const tchar *path, const tchar *suffix)
+{
+ size_t path_len = tstrlen(path);
+ size_t suffix_len = tstrlen(suffix);
+ tchar *suffixed_path;
+
+ suffixed_path = xmalloc((path_len + suffix_len + 1) * sizeof(tchar));
+ if (suffixed_path == NULL)
+ return NULL;
+ tmemcpy(suffixed_path, path, path_len);
+ tmemcpy(&suffixed_path[path_len], suffix, suffix_len + 1);
+ return suffixed_path;
+}
+
+static int
+do_compress(struct libdeflate_compressor *compressor,
+ struct file_stream *in, struct file_stream *out)
+{
+ const void *uncompressed_data = in->mmap_mem;
+ size_t uncompressed_size = in->mmap_size;
+ void *compressed_data;
+ size_t actual_compressed_size;
+ size_t max_compressed_size;
+ int ret;
+
+ max_compressed_size = libdeflate_gzip_compress_bound(compressor,
+ uncompressed_size);
+ compressed_data = xmalloc(max_compressed_size);
+ if (compressed_data == NULL) {
+ msg("%"TS": file is probably too large to be processed by this "
+ "program", in->name);
+ ret = -1;
+ goto out;
+ }
+
+ actual_compressed_size = libdeflate_gzip_compress(compressor,
+ uncompressed_data,
+ uncompressed_size,
+ compressed_data,
+ max_compressed_size);
+ if (actual_compressed_size == 0) {
+ msg("Bug in libdeflate_gzip_compress_bound()!");
+ ret = -1;
+ goto out;
+ }
+
+ ret = full_write(out, compressed_data, actual_compressed_size);
+out:
+ free(compressed_data);
+ return ret;
+}
+
+static u32
+load_u32_gzip(const u8 *p)
+{
+ return ((u32)p[0] << 0) | ((u32)p[1] << 8) |
+ ((u32)p[2] << 16) | ((u32)p[3] << 24);
+}
+
+static int
+do_decompress(struct libdeflate_decompressor *decompressor,
+ struct file_stream *in, struct file_stream *out,
+ const struct options *options)
+{
+ const u8 *compressed_data = in->mmap_mem;
+ size_t compressed_size = in->mmap_size;
+ void *uncompressed_data = NULL;
+ size_t uncompressed_size;
+ size_t actual_in_nbytes;
+ size_t actual_out_nbytes;
+ enum libdeflate_result result;
+ int ret = 0;
+
+ if (compressed_size < sizeof(u32)) {
+ msg("%"TS": not in gzip format", in->name);
+ ret = -1;
+ goto out;
+ }
+
+ /*
+ * Use the ISIZE field as a hint for the decompressed data size. It may
+ * need to be increased later, however, because the file may contain
+ * multiple gzip members and the particular ISIZE we happen to use may
+ * not be the largest; or the real size may be >= 4 GiB, causing ISIZE
+ * to overflow. In any case, make sure to allocate at least one byte.
+ */
+ uncompressed_size = load_u32_gzip(&compressed_data[compressed_size - 4]);
+ if (uncompressed_size == 0)
+ uncompressed_size = 1;
+
+ do {
+ if (uncompressed_data == NULL) {
+ uncompressed_data = xmalloc(uncompressed_size);
+ if (uncompressed_data == NULL) {
+ msg("%"TS": file is probably too large to be "
+ "processed by this program", in->name);
+ ret = -1;
+ goto out;
+ }
+ }
+
+ result = libdeflate_gzip_decompress_ex(decompressor,
+ compressed_data,
+ compressed_size,
+ uncompressed_data,
+ uncompressed_size,
+ &actual_in_nbytes,
+ &actual_out_nbytes);
+
+ if (result == LIBDEFLATE_INSUFFICIENT_SPACE) {
+ if (uncompressed_size * 2 <= uncompressed_size) {
+ msg("%"TS": file corrupt or too large to be "
+ "processed by this program", in->name);
+ ret = -1;
+ goto out;
+ }
+ uncompressed_size *= 2;
+ free(uncompressed_data);
+ uncompressed_data = NULL;
+ continue;
+ }
+
+ if (result != LIBDEFLATE_SUCCESS) {
+ msg("%"TS": file corrupt or not in gzip format",
+ in->name);
+ ret = -1;
+ goto out;
+ }
+
+ if (actual_in_nbytes == 0 ||
+ actual_in_nbytes > compressed_size ||
+ actual_out_nbytes > uncompressed_size) {
+ msg("Bug in libdeflate_gzip_decompress_ex()!");
+ ret = -1;
+ goto out;
+ }
+
+ if (!options->test) {
+ ret = full_write(out, uncompressed_data, actual_out_nbytes);
+ if (ret != 0)
+ goto out;
+ }
+
+ compressed_data += actual_in_nbytes;
+ compressed_size -= actual_in_nbytes;
+
+ } while (compressed_size != 0);
+out:
+ free(uncompressed_data);
+ return ret;
+}
+
+static int
+stat_file(struct file_stream *in, stat_t *stbuf, bool allow_hard_links)
+{
+ if (tfstat(in->fd, stbuf) != 0) {
+ msg("%"TS": unable to stat file", in->name);
+ return -1;
+ }
+
+ if (!S_ISREG(stbuf->st_mode) && !in->is_standard_stream) {
+ msg("%"TS" is %s -- skipping",
+ in->name, S_ISDIR(stbuf->st_mode) ? "a directory" :
+ "not a regular file");
+ return -2;
+ }
+
+ if (stbuf->st_nlink > 1 && !allow_hard_links) {
+ msg("%"TS" has multiple hard links -- skipping "
+ "(use -f to process anyway)", in->name);
+ return -2;
+ }
+
+ return 0;
+}
+
+static void
+restore_mode(struct file_stream *out, const stat_t *stbuf)
+{
+#ifndef _WIN32
+ if (fchmod(out->fd, stbuf->st_mode) != 0)
+ msg_errno("%"TS": unable to preserve mode", out->name);
+#endif
+}
+
+static void
+restore_owner_and_group(struct file_stream *out, const stat_t *stbuf)
+{
+#ifndef _WIN32
+ if (fchown(out->fd, stbuf->st_uid, stbuf->st_gid) != 0) {
+ msg_errno("%"TS": unable to preserve owner and group",
+ out->name);
+ }
+#endif
+}
+
+static void
+restore_timestamps(struct file_stream *out, const tchar *newpath,
+ const stat_t *stbuf)
+{
+ int ret;
+#if defined(HAVE_FUTIMENS) && defined(HAVE_STAT_NANOSECOND_PRECISION)
+ struct timespec times[2] = {
+ stbuf->st_atim, stbuf->st_mtim,
+ };
+ ret = futimens(out->fd, times);
+#elif defined(HAVE_FUTIMES) && defined(HAVE_STAT_NANOSECOND_PRECISION)
+ struct timeval times[2] = {
+ { stbuf->st_atim.tv_sec, stbuf->st_atim.tv_nsec / 1000, },
+ { stbuf->st_mtim.tv_sec, stbuf->st_mtim.tv_nsec / 1000, },
+ };
+ ret = futimes(out->fd, times);
+#else
+ struct tutimbuf times = {
+ stbuf->st_atime, stbuf->st_mtime,
+ };
+ ret = tutime(newpath, &times);
+#endif
+ if (ret != 0)
+ msg_errno("%"TS": unable to preserve timestamps", out->name);
+}
+
+static void
+restore_metadata(struct file_stream *out, const tchar *newpath,
+ const stat_t *stbuf)
+{
+ restore_mode(out, stbuf);
+ restore_owner_and_group(out, stbuf);
+ restore_timestamps(out, newpath, stbuf);
+}
+
+static int
+decompress_file(struct libdeflate_decompressor *decompressor, const tchar *path,
+ const struct options *options)
+{
+ tchar *oldpath = (tchar *)path;
+ tchar *newpath = NULL;
+ struct file_stream in;
+ struct file_stream out;
+ stat_t stbuf;
+ int ret;
+ int ret2;
+
+ if (path != NULL) {
+ const tchar *suffix = get_suffix(path, options->suffix);
+ if (suffix == NULL) {
+ /*
+ * Input file is unsuffixed. If the file doesn't exist,
+ * then try it suffixed. Otherwise, if we're not
+ * writing to stdout, skip the file with warning status.
+ * Otherwise, go ahead and try to open the file anyway
+ * (which will very likely fail).
+ */
+ if (tstat(path, &stbuf) != 0 && errno == ENOENT) {
+ oldpath = append_suffix(path, options->suffix);
+ if (oldpath == NULL)
+ return -1;
+ if (!options->to_stdout)
+ newpath = (tchar *)path;
+ } else if (!options->to_stdout) {
+ msg("\"%"TS"\" does not end with the %"TS" "
+ "suffix -- skipping",
+ path, options->suffix);
+ return -2;
+ }
+ } else if (!options->to_stdout) {
+ /*
+ * Input file is suffixed, and we're not writing to
+ * stdout. Strip the suffix to get the path to the
+ * output file.
+ */
+ newpath = xmalloc((suffix - oldpath + 1) *
+ sizeof(tchar));
+ if (newpath == NULL)
+ return -1;
+ tmemcpy(newpath, oldpath, suffix - oldpath);
+ newpath[suffix - oldpath] = '\0';
+ }
+ }
+
+ ret = xopen_for_read(oldpath, options->force || options->to_stdout,
+ &in);
+ if (ret != 0)
+ goto out_free_paths;
+
+ if (!options->force && isatty(in.fd)) {
+ msg("Refusing to read compressed data from terminal. "
+ "Use -f to override.\nFor help, use -h.");
+ ret = -1;
+ goto out_close_in;
+ }
+
+ ret = stat_file(&in, &stbuf, options->force || options->keep ||
+ oldpath == NULL || newpath == NULL);
+ if (ret != 0)
+ goto out_close_in;
+
+ ret = xopen_for_write(newpath, options->force, &out);
+ if (ret != 0)
+ goto out_close_in;
+
+ /* TODO: need a streaming-friendly solution */
+ ret = map_file_contents(&in, stbuf.st_size);
+ if (ret != 0)
+ goto out_close_out;
+
+ ret = do_decompress(decompressor, &in, &out, options);
+ if (ret != 0)
+ goto out_close_out;
+
+ if (oldpath != NULL && newpath != NULL)
+ restore_metadata(&out, newpath, &stbuf);
+ ret = 0;
+out_close_out:
+ ret2 = xclose(&out);
+ if (ret == 0)
+ ret = ret2;
+ if (ret != 0 && newpath != NULL)
+ tunlink(newpath);
+out_close_in:
+ xclose(&in);
+ if (ret == 0 && oldpath != NULL && newpath != NULL && !options->keep)
+ tunlink(oldpath);
+out_free_paths:
+ if (newpath != path)
+ free(newpath);
+ if (oldpath != path)
+ free(oldpath);
+ return ret;
+}
+
+static int
+compress_file(struct libdeflate_compressor *compressor, const tchar *path,
+ const struct options *options)
+{
+ tchar *newpath = NULL;
+ struct file_stream in;
+ struct file_stream out;
+ stat_t stbuf;
+ int ret;
+ int ret2;
+
+ if (path != NULL && !options->to_stdout) {
+ if (!options->force && has_suffix(path, options->suffix)) {
+ msg("%"TS": already has %"TS" suffix -- skipping",
+ path, options->suffix);
+ return 0;
+ }
+ newpath = append_suffix(path, options->suffix);
+ if (newpath == NULL)
+ return -1;
+ }
+
+ ret = xopen_for_read(path, options->force || options->to_stdout, &in);
+ if (ret != 0)
+ goto out_free_newpath;
+
+ ret = stat_file(&in, &stbuf, options->force || options->keep ||
+ path == NULL || newpath == NULL);
+ if (ret != 0)
+ goto out_close_in;
+
+ ret = xopen_for_write(newpath, options->force, &out);
+ if (ret != 0)
+ goto out_close_in;
+
+ if (!options->force && isatty(out.fd)) {
+ msg("Refusing to write compressed data to terminal. "
+ "Use -f to override.\nFor help, use -h.");
+ ret = -1;
+ goto out_close_out;
+ }
+
+ /* TODO: need a streaming-friendly solution */
+ ret = map_file_contents(&in, stbuf.st_size);
+ if (ret != 0)
+ goto out_close_out;
+
+ ret = do_compress(compressor, &in, &out);
+ if (ret != 0)
+ goto out_close_out;
+
+ if (path != NULL && newpath != NULL)
+ restore_metadata(&out, newpath, &stbuf);
+ ret = 0;
+out_close_out:
+ ret2 = xclose(&out);
+ if (ret == 0)
+ ret = ret2;
+ if (ret != 0 && newpath != NULL)
+ tunlink(newpath);
+out_close_in:
+ xclose(&in);
+ if (ret == 0 && path != NULL && newpath != NULL && !options->keep)
+ tunlink(path);
+out_free_newpath:
+ free(newpath);
+ return ret;
+}
+
+int
+tmain(int argc, tchar *argv[])
+{
+ tchar *default_file_list[] = { NULL };
+ struct options options;
+ int opt_char;
+ int i;
+ int ret;
+
+ begin_program(argv);
+
+ options.to_stdout = false;
+ options.decompress = is_gunzip();
+ options.force = false;
+ options.keep = false;
+ options.test = false;
+ options.compression_level = 6;
+ options.suffix = T(".gz");
+
+ while ((opt_char = tgetopt(argc, argv, optstring)) != -1) {
+ switch (opt_char) {
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ options.compression_level =
+ parse_compression_level(opt_char, toptarg);
+ if (options.compression_level < 0)
+ return 1;
+ break;
+ case 'c':
+ options.to_stdout = true;
+ break;
+ case 'd':
+ options.decompress = true;
+ break;
+ case 'f':
+ options.force = true;
+ break;
+ case 'h':
+ show_usage(stdout);
+ return 0;
+ case 'k':
+ options.keep = true;
+ break;
+ case 'n':
+ /*
+ * -n means don't save or restore the original filename
+ * in the gzip header. Currently this implementation
+ * already behaves this way by default, so accept the
+ * option as a no-op.
+ */
+ break;
+ case 'S':
+ options.suffix = toptarg;
+ if (options.suffix[0] == T('\0')) {
+ msg("invalid suffix");
+ return 1;
+ }
+ break;
+ case 't':
+ options.test = true;
+ options.decompress = true;
+ options.to_stdout = true;
+ /*
+ * -t behaves just like the more commonly used -c
+ * option, except that -t doesn't actually write
+ * anything. For ease of implementation, just pretend
+ * that -c was specified too.
+ */
+ break;
+ case 'V':
+ show_version();
+ return 0;
+ default:
+ show_usage(stderr);
+ return 1;
+ }
+ }
+
+ argv += toptind;
+ argc -= toptind;
+
+ if (argc == 0) {
+ argv = default_file_list;
+ argc = ARRAY_LEN(default_file_list);
+ } else {
+ for (i = 0; i < argc; i++)
+ if (argv[i][0] == '-' && argv[i][1] == '\0')
+ argv[i] = NULL;
+ }
+
+ ret = 0;
+ if (options.decompress) {
+ struct libdeflate_decompressor *d;
+
+ d = alloc_decompressor();
+ if (d == NULL)
+ return 1;
+
+ for (i = 0; i < argc; i++)
+ ret |= -decompress_file(d, argv[i], &options);
+
+ libdeflate_free_decompressor(d);
+ } else {
+ struct libdeflate_compressor *c;
+
+ c = alloc_compressor(options.compression_level);
+ if (c == NULL)
+ return 1;
+
+ for (i = 0; i < argc; i++)
+ ret |= -compress_file(c, argv[i], &options);
+
+ libdeflate_free_compressor(c);
+ }
+
+ /*
+ * If ret=0, there were no warnings or errors. Exit with status 0.
+ * If ret=2, there was at least one warning. Exit with status 2.
+ * Else, there was at least one error. Exit with status 1.
+ */
+ if (ret != 0 && ret != 2)
+ ret = 1;
+
+ return ret;
+}
diff --git a/util/compress/libdeflate/programs/prog_util.c b/util/compress/libdeflate/programs/prog_util.c
new file mode 100644
index 000000000..343828143
--- /dev/null
+++ b/util/compress/libdeflate/programs/prog_util.c
@@ -0,0 +1,496 @@
+/*
+ * prog_util.c - utility functions for programs
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "prog_util.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#ifdef _WIN32
+# include <windows.h>
+#else
+# include <unistd.h>
+# include <sys/mman.h>
+#endif
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+#ifndef O_SEQUENTIAL
+# define O_SEQUENTIAL 0
+#endif
+#ifndef O_NOFOLLOW
+# define O_NOFOLLOW 0
+#endif
+#ifndef O_NONBLOCK
+# define O_NONBLOCK 0
+#endif
+#ifndef O_NOCTTY
+# define O_NOCTTY 0
+#endif
+
+/* The invocation name of the program (filename component only) */
+const tchar *prog_invocation_name;
+
+static void
+do_msg(const char *format, bool with_errno, va_list va)
+{
+ int saved_errno = errno;
+
+ fprintf(stderr, "%"TS": ", prog_invocation_name);
+ vfprintf(stderr, format, va);
+ if (with_errno)
+ fprintf(stderr, ": %s\n", strerror(saved_errno));
+ else
+ fprintf(stderr, "\n");
+
+ errno = saved_errno;
+}
+
+/* Print a message to standard error */
+void
+msg(const char *format, ...)
+{
+ va_list va;
+
+ va_start(va, format);
+ do_msg(format, false, va);
+ va_end(va);
+}
+
+/* Print a message to standard error, including a description of errno */
+void
+msg_errno(const char *format, ...)
+{
+ va_list va;
+
+ va_start(va, format);
+ do_msg(format, true, va);
+ va_end(va);
+}
+
+/* malloc() wrapper */
+void *
+xmalloc(size_t size)
+{
+ void *p = malloc(size);
+ if (p == NULL && size == 0)
+ p = malloc(1);
+ if (p == NULL)
+ msg("Out of memory");
+ return p;
+}
+
+/*
+ * Retrieve a pointer to the filename component of the specified path.
+ *
+ * Note: this does not modify the path. Therefore, it is not guaranteed to work
+ * properly for directories, since a path to a directory might have trailing
+ * slashes.
+ */
+static const tchar *
+get_filename(const tchar *path)
+{
+ const tchar *slash = tstrrchr(path, '/');
+#ifdef _WIN32
+ const tchar *backslash = tstrrchr(path, '\\');
+ if (backslash != NULL && (slash == NULL || backslash > slash))
+ slash = backslash;
+#endif
+ if (slash != NULL)
+ return slash + 1;
+ return path;
+}
+
+void
+begin_program(tchar *argv[])
+{
+ prog_invocation_name = get_filename(argv[0]);
+
+#ifdef FREESTANDING
+ /* This allows testing freestanding library builds. */
+ libdeflate_set_memory_allocator(malloc, free);
+#endif
+}
+
+/* Create a copy of 'path' surrounded by double quotes */
+static tchar *
+quote_path(const tchar *path)
+{
+ size_t len = tstrlen(path);
+ tchar *result;
+
+ result = xmalloc((1 + len + 1 + 1) * sizeof(tchar));
+ if (result == NULL)
+ return NULL;
+ result[0] = '"';
+ tmemcpy(&result[1], path, len);
+ result[1 + len] = '"';
+ result[1 + len + 1] = '\0';
+ return result;
+}
+
+/* Open a file for reading, or set up standard input for reading */
+int
+xopen_for_read(const tchar *path, bool symlink_ok, struct file_stream *strm)
+{
+ strm->mmap_token = NULL;
+ strm->mmap_mem = NULL;
+
+ if (path == NULL) {
+ strm->is_standard_stream = true;
+ strm->name = T("standard input");
+ strm->fd = STDIN_FILENO;
+ #ifdef _WIN32
+ _setmode(strm->fd, O_BINARY);
+ #endif
+ return 0;
+ }
+
+ strm->is_standard_stream = false;
+
+ strm->name = quote_path(path);
+ if (strm->name == NULL)
+ return -1;
+
+ strm->fd = topen(path, O_RDONLY | O_BINARY | O_NONBLOCK | O_NOCTTY |
+ (symlink_ok ? 0 : O_NOFOLLOW) | O_SEQUENTIAL);
+ if (strm->fd < 0) {
+ msg_errno("Can't open %"TS" for reading", strm->name);
+ free(strm->name);
+ return -1;
+ }
+
+#if defined(HAVE_POSIX_FADVISE) && (O_SEQUENTIAL == 0)
+ (void)posix_fadvise(strm->fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+#endif
+
+ return 0;
+}
+
+/* Open a file for writing, or set up standard output for writing */
+int
+xopen_for_write(const tchar *path, bool overwrite, struct file_stream *strm)
+{
+ int ret = -1;
+
+ strm->mmap_token = NULL;
+ strm->mmap_mem = NULL;
+
+ if (path == NULL) {
+ strm->is_standard_stream = true;
+ strm->name = T("standard output");
+ strm->fd = STDOUT_FILENO;
+ #ifdef _WIN32
+ _setmode(strm->fd, O_BINARY);
+ #endif
+ return 0;
+ }
+
+ strm->is_standard_stream = false;
+
+ strm->name = quote_path(path);
+ if (strm->name == NULL)
+ goto err;
+retry:
+ strm->fd = topen(path, O_WRONLY | O_BINARY | O_NOFOLLOW |
+ O_CREAT | O_EXCL, 0644);
+ if (strm->fd < 0) {
+ if (errno != EEXIST) {
+ msg_errno("Can't open %"TS" for writing", strm->name);
+ goto err;
+ }
+ if (!overwrite) {
+ if (!isatty(STDERR_FILENO) || !isatty(STDIN_FILENO)) {
+ msg("%"TS" already exists; use -f to overwrite",
+ strm->name);
+ ret = -2; /* warning only */
+ goto err;
+ }
+ fprintf(stderr, "%"TS": %"TS" already exists; "
+ "overwrite? (y/n) ",
+ prog_invocation_name, strm->name);
+ if (getchar() != 'y') {
+ msg("Not overwriting.");
+ goto err;
+ }
+ }
+ if (tunlink(path) != 0) {
+ msg_errno("Unable to delete %"TS, strm->name);
+ goto err;
+ }
+ goto retry;
+ }
+
+ return 0;
+
+err:
+ free(strm->name);
+ return ret;
+}
+
+/* Read the full contents of a file into memory */
+static int
+read_full_contents(struct file_stream *strm)
+{
+ size_t filled = 0;
+ size_t capacity = 4096;
+ char *buf;
+ int ret;
+
+ buf = xmalloc(capacity);
+ if (buf == NULL)
+ return -1;
+ do {
+ if (filled == capacity) {
+ char *newbuf;
+
+ if (capacity == SIZE_MAX)
+ goto oom;
+ capacity += MIN(SIZE_MAX - capacity, capacity);
+ newbuf = realloc(buf, capacity);
+ if (newbuf == NULL)
+ goto oom;
+ buf = newbuf;
+ }
+ ret = xread(strm, &buf[filled], capacity - filled);
+ if (ret < 0)
+ goto err;
+ filled += ret;
+ } while (ret != 0);
+
+ strm->mmap_mem = buf;
+ strm->mmap_size = filled;
+ return 0;
+
+err:
+ free(buf);
+ return ret;
+oom:
+ msg("Out of memory! %"TS" is too large to be processed by "
+ "this program as currently implemented.", strm->name);
+ ret = -1;
+ goto err;
+}
+
+/* Map the contents of a file into memory */
+int
+map_file_contents(struct file_stream *strm, u64 size)
+{
+ if (size == 0) /* mmap isn't supported on empty files */
+ return read_full_contents(strm);
+
+ if (size > SIZE_MAX) {
+ msg("%"TS" is too large to be processed by this program",
+ strm->name);
+ return -1;
+ }
+#ifdef _WIN32
+ strm->mmap_token = CreateFileMapping(
+ (HANDLE)(intptr_t)_get_osfhandle(strm->fd),
+ NULL, PAGE_READONLY, 0, 0, NULL);
+ if (strm->mmap_token == NULL) {
+ DWORD err = GetLastError();
+ if (err == ERROR_BAD_EXE_FORMAT) /* mmap unsupported */
+ return read_full_contents(strm);
+ msg("Unable create file mapping for %"TS": Windows error %u",
+ strm->name, (unsigned int)err);
+ return -1;
+ }
+
+ strm->mmap_mem = MapViewOfFile((HANDLE)strm->mmap_token,
+ FILE_MAP_READ, 0, 0, size);
+ if (strm->mmap_mem == NULL) {
+ msg("Unable to map %"TS" into memory: Windows error %u",
+ strm->name, (unsigned int)GetLastError());
+ CloseHandle((HANDLE)strm->mmap_token);
+ return -1;
+ }
+#else /* _WIN32 */
+ strm->mmap_mem = mmap(NULL, size, PROT_READ, MAP_SHARED, strm->fd, 0);
+ if (strm->mmap_mem == MAP_FAILED) {
+ strm->mmap_mem = NULL;
+ if (errno == ENODEV) /* mmap isn't supported on this file */
+ return read_full_contents(strm);
+ if (errno == ENOMEM) {
+ msg("%"TS" is too large to be processed by this "
+ "program", strm->name);
+ } else {
+ msg_errno("Unable to map %"TS" into memory",
+ strm->name);
+ }
+ return -1;
+ }
+
+#ifdef HAVE_POSIX_MADVISE
+ (void)posix_madvise(strm->mmap_mem, size, POSIX_MADV_SEQUENTIAL);
+#endif
+ strm->mmap_token = strm; /* anything that's not NULL */
+
+#endif /* !_WIN32 */
+ strm->mmap_size = size;
+ return 0;
+}
+
+/*
+ * Read from a file, returning the full count to indicate all bytes were read, a
+ * short count (possibly 0) to indicate EOF, or -1 to indicate error.
+ */
+ssize_t
+xread(struct file_stream *strm, void *buf, size_t count)
+{
+ char *p = buf;
+ size_t orig_count = count;
+
+ while (count != 0) {
+ ssize_t res = read(strm->fd, p, MIN(count, INT_MAX));
+ if (res == 0)
+ break;
+ if (res < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ msg_errno("Error reading from %"TS, strm->name);
+ return -1;
+ }
+ p += res;
+ count -= res;
+ }
+ return orig_count - count;
+}
+
+/* Write to a file, returning 0 if all bytes were written or -1 on error */
+int
+full_write(struct file_stream *strm, const void *buf, size_t count)
+{
+ const char *p = buf;
+
+ while (count != 0) {
+ ssize_t res = write(strm->fd, p, MIN(count, INT_MAX));
+ if (res <= 0) {
+ msg_errno("Error writing to %"TS, strm->name);
+ return -1;
+ }
+ p += res;
+ count -= res;
+ }
+ return 0;
+}
+
+/* Close a file, returning 0 on success or -1 on error */
+int
+xclose(struct file_stream *strm)
+{
+ int ret = 0;
+
+ if (!strm->is_standard_stream) {
+ if (close(strm->fd) != 0) {
+ msg_errno("Error closing %"TS, strm->name);
+ ret = -1;
+ }
+ free(strm->name);
+ }
+
+ if (strm->mmap_token != NULL) {
+#ifdef _WIN32
+ UnmapViewOfFile(strm->mmap_mem);
+ CloseHandle((HANDLE)strm->mmap_token);
+#else
+ munmap(strm->mmap_mem, strm->mmap_size);
+#endif
+ strm->mmap_token = NULL;
+ } else {
+ free(strm->mmap_mem);
+ }
+ strm->mmap_mem = NULL;
+ strm->fd = -1;
+ strm->name = NULL;
+ return ret;
+}
+
+/*
+ * Parse the compression level given on the command line, returning the
+ * compression level on success or -1 on error
+ */
+int
+parse_compression_level(tchar opt_char, const tchar *arg)
+{
+ int level;
+
+ if (arg == NULL)
+ arg = T("");
+
+ if (opt_char < '0' || opt_char > '9')
+ goto invalid;
+ level = opt_char - '0';
+
+ if (arg[0] != '\0') {
+ if (arg[0] < '0' || arg[0] > '9')
+ goto invalid;
+ if (arg[1] != '\0') /* Levels are at most 2 digits */
+ goto invalid;
+ if (level == 0) /* Don't allow arguments like "-01" */
+ goto invalid;
+ level = (level * 10) + (arg[0] - '0');
+ }
+
+ if (level < 0 || level > 12)
+ goto invalid;
+
+ return level;
+
+invalid:
+ msg("Invalid compression level: \"%"TC"%"TS"\". "
+ "Must be an integer in the range [0, 12].", opt_char, arg);
+ return -1;
+}
+
+/* Allocate a new DEFLATE compressor */
+struct libdeflate_compressor *
+alloc_compressor(int level)
+{
+ struct libdeflate_compressor *c;
+
+ c = libdeflate_alloc_compressor(level);
+ if (c == NULL) {
+ msg_errno("Unable to allocate compressor with "
+ "compression level %d", level);
+ }
+ return c;
+}
+
+/* Allocate a new DEFLATE decompressor */
+struct libdeflate_decompressor *
+alloc_decompressor(void)
+{
+ struct libdeflate_decompressor *d;
+
+ d = libdeflate_alloc_decompressor();
+ if (d == NULL)
+ msg_errno("Unable to allocate decompressor");
+
+ return d;
+}
diff --git a/util/compress/libdeflate/programs/prog_util.h b/util/compress/libdeflate/programs/prog_util.h
new file mode 100644
index 000000000..fa3f7b519
--- /dev/null
+++ b/util/compress/libdeflate/programs/prog_util.h
@@ -0,0 +1,179 @@
+/*
+ * prog_util.h - utility functions for programs
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PROGRAMS_PROG_UTIL_H
+#define PROGRAMS_PROG_UTIL_H
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "libdeflate.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _WIN32
+# include <sys/types.h>
+#endif
+
+#include "../common/common_defs.h"
+
+#ifdef __GNUC__
+# define _printf(str_idx, args_idx) \
+ __attribute__((format(printf, str_idx, args_idx)))
+#else
+# define _printf(str_idx, args_idx)
+#endif
+
+#ifdef _MSC_VER
+/*
+ * Old versions (e.g. VS2010) of MSC have stdint.h but not the C99 header
+ * inttypes.h. Work around this by defining the PRI* macros ourselves.
+ */
+# define PRIu8 "hhu"
+# define PRIu16 "hu"
+# define PRIu32 "u"
+# define PRIu64 "llu"
+# define PRIi8 "hhi"
+# define PRIi16 "hi"
+# define PRIi32 "i"
+# define PRIi64 "lli"
+# define PRIx8 "hhx"
+# define PRIx16 "hx"
+# define PRIx32 "x"
+# define PRIx64 "llx"
+#else
+# include <inttypes.h>
+#endif
+
+#ifdef _WIN32
+
+/*
+ * Definitions for Windows builds. Mainly, 'tchar' is defined to be the 2-byte
+ * 'wchar_t' type instead of 'char'. This is the only "easy" way I know of to
+ * get full Unicode support on Windows...
+ */
+
+#include <wchar.h>
+int wmain(int argc, wchar_t **argv);
+# define tmain wmain
+# define tchar wchar_t
+# define _T(text) L##text
+# define T(text) _T(text)
+# define TS "ls"
+# define TC "lc"
+# define tmemcpy wmemcpy
+# define topen _wopen
+# define tstrchr wcschr
+# define tstrcmp wcscmp
+# define tstrlen wcslen
+# define tstrrchr wcsrchr
+# define tstrtoul wcstoul
+# define tstrxcmp wcsicmp
+# define tunlink _wunlink
+# define tutimbuf __utimbuf64
+# define tutime _wutime64
+# define tstat _wstat64
+# define tfstat _fstat64
+# define stat_t struct _stat64
+# ifdef _MSC_VER
+# define STDIN_FILENO 0
+# define STDOUT_FILENO 1
+# define STDERR_FILENO 2
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+# endif
+
+#else /* _WIN32 */
+
+/* Standard definitions for everyone else */
+
+# define tmain main
+# define tchar char
+# define T(text) text
+# define TS "s"
+# define TC "c"
+# define tmemcpy memcpy
+# define topen open
+# define tstrchr strchr
+# define tstrcmp strcmp
+# define tstrlen strlen
+# define tstrrchr strrchr
+# define tstrtoul strtoul
+# define tstrxcmp strcmp
+# define tunlink unlink
+# define tutimbuf utimbuf
+# define tutime utime
+# define tstat stat
+# define tfstat fstat
+# define stat_t struct stat
+
+#endif /* !_WIN32 */
+
+extern const tchar *prog_invocation_name;
+
+void _printf(1, 2) msg(const char *fmt, ...);
+void _printf(1, 2) msg_errno(const char *fmt, ...);
+
+void *xmalloc(size_t size);
+
+void begin_program(tchar *argv[]);
+
+struct file_stream {
+ int fd;
+ tchar *name;
+ bool is_standard_stream;
+ void *mmap_token;
+ void *mmap_mem;
+ size_t mmap_size;
+};
+
+int xopen_for_read(const tchar *path, bool symlink_ok,
+ struct file_stream *strm);
+int xopen_for_write(const tchar *path, bool force, struct file_stream *strm);
+int map_file_contents(struct file_stream *strm, u64 size);
+
+ssize_t xread(struct file_stream *strm, void *buf, size_t count);
+int full_write(struct file_stream *strm, const void *buf, size_t count);
+
+int xclose(struct file_stream *strm);
+
+int parse_compression_level(tchar opt_char, const tchar *arg);
+
+struct libdeflate_compressor *alloc_compressor(int level);
+struct libdeflate_decompressor *alloc_decompressor(void);
+
+/* tgetopt.c */
+
+extern tchar *toptarg;
+extern int toptind, topterr, toptopt;
+
+int tgetopt(int argc, tchar *argv[], const tchar *optstring);
+
+#endif /* PROGRAMS_PROG_UTIL_H */
diff --git a/util/compress/libdeflate/programs/test_checksums.c b/util/compress/libdeflate/programs/test_checksums.c
new file mode 100644
index 000000000..97054182f
--- /dev/null
+++ b/util/compress/libdeflate/programs/test_checksums.c
@@ -0,0 +1,196 @@
+/*
+ * test_checksums.c
+ *
+ * Verify that libdeflate's Adler-32 and CRC-32 functions produce the same
+ * results as their zlib equivalents.
+ */
+
+#include <stdlib.h>
+#include <time.h>
+
+#include "test_util.h"
+
+static unsigned int rng_seed;
+
+typedef u32 (*cksum_fn_t)(u32, const void *, size_t);
+
+static u32
+adler32_libdeflate(u32 adler, const void *buf, size_t len)
+{
+ return libdeflate_adler32(adler, buf, len);
+}
+
+static u32
+crc32_libdeflate(u32 crc, const void *buf, size_t len)
+{
+ return libdeflate_crc32(crc, buf, len);
+}
+
+static u32
+adler32_zlib(u32 adler, const void *buf, size_t len)
+{
+ return adler32(adler, buf, len);
+}
+
+static u32
+crc32_zlib(u32 crc, const void *buf, size_t len)
+{
+ return crc32(crc, buf, len);
+}
+
+static u32
+select_initial_crc(void)
+{
+ if (rand() & 1)
+ return 0;
+ return ((u32)rand() << 16) | rand();
+}
+
+static u32
+select_initial_adler(void)
+{
+ u32 lo, hi;
+
+ if (rand() & 1)
+ return 1;
+
+ lo = (rand() % 4 == 0 ? 65520 : rand() % 65521);
+ hi = (rand() % 4 == 0 ? 65520 : rand() % 65521);
+ return (hi << 16) | lo;
+}
+
+static void
+test_initial_values(cksum_fn_t cksum, u32 expected)
+{
+ ASSERT(cksum(0, NULL, 0) == expected);
+ if (cksum != adler32_zlib) /* broken */
+ ASSERT(cksum(0, NULL, 1) == expected);
+ ASSERT(cksum(0, NULL, 1234) == expected);
+ ASSERT(cksum(1234, NULL, 0) == expected);
+ ASSERT(cksum(1234, NULL, 1234) == expected);
+}
+
+static void
+test_multipart(const u8 *buffer, size_t size, const char *name,
+ cksum_fn_t cksum, u32 v, u32 expected)
+{
+ size_t division = rand() % (size + 1);
+ v = cksum(v, buffer, division);
+ v = cksum(v, buffer + division, size - division);
+ if (v != expected) {
+ fprintf(stderr, "%s checksum failed multipart test\n", name);
+ ASSERT(0);
+ }
+}
+
+static void
+test_checksums(const void *buffer, size_t size, const char *name,
+ cksum_fn_t cksum1, cksum_fn_t cksum2, u32 initial_value)
+{
+ u32 v1 = cksum1(initial_value, buffer, size);
+ u32 v2 = cksum2(initial_value, buffer, size);
+
+ if (v1 != v2) {
+ fprintf(stderr, "%s checksum mismatch\n", name);
+ fprintf(stderr, "initial_value=0x%08"PRIx32", buffer=%p, "
+ "size=%zu, buffer=", initial_value, buffer, size);
+ for (size_t i = 0; i < MIN(size, 256); i++)
+ fprintf(stderr, "%02x", ((const u8 *)buffer)[i]);
+ if (size > 256)
+ fprintf(stderr, "...");
+ fprintf(stderr, "\n");
+ ASSERT(0);
+ }
+
+ if ((rand() & 15) == 0) {
+ test_multipart(buffer, size, name, cksum1, initial_value, v1);
+ test_multipart(buffer, size, name, cksum2, initial_value, v1);
+ }
+}
+
+static void
+test_crc32(const void *buffer, size_t size, u32 initial_value)
+{
+ test_checksums(buffer, size, "CRC-32",
+ crc32_libdeflate, crc32_zlib, initial_value);
+}
+
+static void
+test_adler32(const void *buffer, size_t size, u32 initial_value)
+{
+ test_checksums(buffer, size, "Adler-32",
+ adler32_libdeflate, adler32_zlib, initial_value);
+}
+
+static void test_random_buffers(u8 *buffer, u8 *guarded_buf_end,
+ size_t limit, u32 num_iter)
+{
+ for (u32 i = 0; i < num_iter; i++) {
+ size_t start = rand() % limit;
+ size_t len = rand() % (limit - start);
+ u32 a0 = select_initial_adler();
+ u32 c0 = select_initial_crc();
+
+ for (size_t j = start; j < start + len; j++)
+ buffer[j] = rand();
+
+ /* Test with chosen size and alignment */
+ test_adler32(&buffer[start], len, a0);
+ test_crc32(&buffer[start], len, c0);
+
+ /* Test with chosen size, with guard page after input buffer */
+ memcpy(guarded_buf_end - len, &buffer[start], len);
+ test_adler32(guarded_buf_end - len, len, a0);
+ test_crc32(guarded_buf_end - len, len, c0);
+ }
+}
+
+int
+tmain(int argc, tchar *argv[])
+{
+ u8 *buffer = xmalloc(32768);
+ u8 *guarded_buf_start, *guarded_buf_end;
+
+ begin_program(argv);
+
+ alloc_guarded_buffer(32768, &guarded_buf_start, &guarded_buf_end);
+
+ rng_seed = time(NULL);
+ srand(rng_seed);
+
+ test_initial_values(adler32_libdeflate, 1);
+ test_initial_values(adler32_zlib, 1);
+ test_initial_values(crc32_libdeflate, 0);
+ test_initial_values(crc32_zlib, 0);
+
+ /* Test different buffer sizes and alignments */
+ test_random_buffers(buffer, guarded_buf_end, 256, 5000);
+ test_random_buffers(buffer, guarded_buf_end, 1024, 500);
+ test_random_buffers(buffer, guarded_buf_end, 32768, 50);
+
+ /*
+ * Test Adler-32 overflow cases. For example, given all 0xFF bytes and
+ * the highest possible initial (s1, s2) of (65520, 65520), then s2 if
+ * stored as a 32-bit unsigned integer will overflow if > 5552 bytes are
+ * processed. Implementations must make sure to reduce s2 modulo 65521
+ * before that point. Also, some implementations make use of 16-bit
+ * counters which can overflow earlier.
+ */
+ memset(buffer, 0xFF, 32768);
+ for (u32 i = 0; i < 20; i++) {
+ u32 initial_value;
+
+ if (i == 0)
+ initial_value = ((u32)65520 << 16) | 65520;
+ else
+ initial_value = select_initial_adler();
+
+ test_adler32(buffer, 5553, initial_value);
+ test_adler32(buffer, rand() % 32769, initial_value);
+ buffer[rand() % 32768] = 0xFE;
+ }
+
+ free(buffer);
+ free_guarded_buffer(guarded_buf_start, guarded_buf_end);
+ return 0;
+}
diff --git a/util/compress/libdeflate/programs/test_custom_malloc.c b/util/compress/libdeflate/programs/test_custom_malloc.c
new file mode 100644
index 000000000..2bbb7f098
--- /dev/null
+++ b/util/compress/libdeflate/programs/test_custom_malloc.c
@@ -0,0 +1,85 @@
+/*
+ * test_custom_malloc.c
+ *
+ * Test libdeflate_set_memory_allocator().
+ * Also test injecting allocation failures.
+ */
+
+#include "test_util.h"
+
+static int malloc_count = 0;
+static int free_count = 0;
+
+static void *do_malloc(size_t size)
+{
+ malloc_count++;
+ return malloc(size);
+}
+
+static void *do_fail_malloc(size_t size)
+{
+ malloc_count++;
+ return NULL;
+}
+
+static void do_free(void *ptr)
+{
+ free_count++;
+ free(ptr);
+}
+
+int
+tmain(int argc, tchar *argv[])
+{
+ int level;
+ struct libdeflate_compressor *c;
+ struct libdeflate_decompressor *d;
+
+ begin_program(argv);
+
+ /* Test that the custom allocator is actually used when requested. */
+
+ libdeflate_set_memory_allocator(do_malloc, do_free);
+ ASSERT(malloc_count == 0);
+ ASSERT(free_count == 0);
+
+ for (level = 0; level <= 12; level++) {
+ malloc_count = free_count = 0;
+ c = libdeflate_alloc_compressor(level);
+ ASSERT(c != NULL);
+ ASSERT(malloc_count == 1);
+ ASSERT(free_count == 0);
+ libdeflate_free_compressor(c);
+ ASSERT(malloc_count == 1);
+ ASSERT(free_count == 1);
+ }
+
+ malloc_count = free_count = 0;
+ d = libdeflate_alloc_decompressor();
+ ASSERT(d != NULL);
+ ASSERT(malloc_count == 1);
+ ASSERT(free_count == 0);
+ libdeflate_free_decompressor(d);
+ ASSERT(malloc_count == 1);
+ ASSERT(free_count == 1);
+
+ /* As long as we're here, also test injecting allocation failures. */
+
+ libdeflate_set_memory_allocator(do_fail_malloc, do_free);
+
+ for (level = 0; level <= 12; level++) {
+ malloc_count = free_count = 0;
+ c = libdeflate_alloc_compressor(level);
+ ASSERT(c == NULL);
+ ASSERT(malloc_count == 1);
+ ASSERT(free_count == 0);
+ }
+
+ malloc_count = free_count = 0;
+ d = libdeflate_alloc_decompressor();
+ ASSERT(d == NULL);
+ ASSERT(malloc_count == 1);
+ ASSERT(free_count == 0);
+
+ return 0;
+}
diff --git a/util/compress/libdeflate/programs/test_incomplete_codes.c b/util/compress/libdeflate/programs/test_incomplete_codes.c
new file mode 100644
index 000000000..4e441bccb
--- /dev/null
+++ b/util/compress/libdeflate/programs/test_incomplete_codes.c
@@ -0,0 +1,385 @@
+/*
+ * test_incomplete_codes.c
+ *
+ * Test that the decompressor accepts incomplete Huffman codes in certain
+ * specific cases.
+ */
+
+#include "test_util.h"
+
+static void
+verify_decompression_libdeflate(const u8 *in, size_t in_nbytes,
+ u8 *out, size_t out_nbytes_avail,
+ const u8 *expected_out,
+ size_t expected_out_nbytes)
+{
+ struct libdeflate_decompressor *d;
+ enum libdeflate_result res;
+ size_t actual_out_nbytes;
+
+ d = libdeflate_alloc_decompressor();
+ ASSERT(d != NULL);
+
+ res = libdeflate_deflate_decompress(d, in, in_nbytes,
+ out, out_nbytes_avail,
+ &actual_out_nbytes);
+ ASSERT(res == LIBDEFLATE_SUCCESS);
+ ASSERT(actual_out_nbytes == expected_out_nbytes);
+ ASSERT(memcmp(out, expected_out, actual_out_nbytes) == 0);
+
+ libdeflate_free_decompressor(d);
+}
+
+static void
+verify_decompression_zlib(const u8 *in, size_t in_nbytes,
+ u8 *out, size_t out_nbytes_avail,
+ const u8 *expected_out, size_t expected_out_nbytes)
+{
+ z_stream z;
+ int res;
+ size_t actual_out_nbytes;
+
+ memset(&z, 0, sizeof(z));
+ res = inflateInit2(&z, -15);
+ ASSERT(res == Z_OK);
+
+ z.next_in = (void *)in;
+ z.avail_in = in_nbytes;
+ z.next_out = (void *)out;
+ z.avail_out = out_nbytes_avail;
+ res = inflate(&z, Z_FINISH);
+ ASSERT(res == Z_STREAM_END);
+ actual_out_nbytes = out_nbytes_avail - z.avail_out;
+ ASSERT(actual_out_nbytes == expected_out_nbytes);
+ ASSERT(memcmp(out, expected_out, actual_out_nbytes) == 0);
+
+ inflateEnd(&z);
+}
+
+static void
+verify_decompression(const u8 *in, size_t in_nbytes,
+ u8 *out, size_t out_nbytes_avail,
+ const u8 *expected_out, size_t expected_out_nbytes)
+{
+ verify_decompression_libdeflate(in, in_nbytes, out, out_nbytes_avail,
+ expected_out, expected_out_nbytes);
+ verify_decompression_zlib(in, in_nbytes, out, out_nbytes_avail,
+ expected_out, expected_out_nbytes);
+
+}
+
+/* Test that an empty offset code is accepted. */
+static void
+test_empty_offset_code(void)
+{
+ static const u8 expected_out[] = { 'A', 'B', 'A', 'A' };
+ u8 in[128];
+ u8 out[128];
+ struct output_bitstream os = { .next = in, .end = in + sizeof(in) };
+ int i;
+
+ /*
+ * Generate a DEFLATE stream containing a "dynamic Huffman" block
+ * containing literals, but no offsets; and having an empty offset code
+ * (all codeword lengths set to 0).
+ *
+ * Litlen code:
+ * litlensym_A freq=3 len=1 codeword= 0
+ * litlensym_B freq=1 len=2 codeword=01
+ * litlensym_256 (end-of-block) freq=1 len=2 codeword=11
+ * Offset code:
+ * (empty)
+ *
+ * Litlen and offset codeword lengths:
+ * [0..'A'-1] = 0 presym_18
+ * ['A'] = 1 presym_1
+ * ['B'] = 2 presym_2
+ * ['B'+1..255] = 0 presym_18 presym_18
+ * [256] = 2 presym_2
+ * [257] = 0 presym_0
+ *
+ * Precode:
+ * presym_0 freq=1 len=3 codeword=011
+ * presym_1 freq=1 len=3 codeword=111
+ * presym_2 freq=2 len=2 codeword= 01
+ * presym_18 freq=3 len=1 codeword= 0
+ */
+
+ ASSERT(put_bits(&os, 1, 1)); /* BFINAL: 1 */
+ ASSERT(put_bits(&os, 2, 2)); /* BTYPE: DYNAMIC_HUFFMAN */
+ ASSERT(put_bits(&os, 0, 5)); /* num_litlen_syms: 0 + 257 */
+ ASSERT(put_bits(&os, 0, 5)); /* num_offset_syms: 0 + 1 */
+ ASSERT(put_bits(&os, 14, 4)); /* num_explicit_precode_lens: 14 + 4 */
+
+ /*
+ * Precode codeword lengths: order is
+ * [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]
+ */
+ for (i = 0; i < 2; i++) /* presym_{16,17}: len=0 */
+ ASSERT(put_bits(&os, 0, 3));
+ ASSERT(put_bits(&os, 1, 3)); /* presym_18: len=1 */
+ ASSERT(put_bits(&os, 3, 3)); /* presym_0: len=3 */
+ for (i = 0; i < 11; i++) /* presym_{8,...,13}: len=0 */
+ ASSERT(put_bits(&os, 0, 3));
+ ASSERT(put_bits(&os, 2, 3)); /* presym_2: len=2 */
+ ASSERT(put_bits(&os, 0, 3)); /* presym_14: len=0 */
+ ASSERT(put_bits(&os, 3, 3)); /* presym_1: len=3 */
+
+ /* Litlen and offset codeword lengths */
+ ASSERT(put_bits(&os, 0x0, 1) &&
+ put_bits(&os, 54, 7)); /* presym_18, 65 zeroes */
+ ASSERT(put_bits(&os, 0x7, 3)); /* presym_1 */
+ ASSERT(put_bits(&os, 0x1, 2)); /* presym_2 */
+ ASSERT(put_bits(&os, 0x0, 1) &&
+ put_bits(&os, 89, 7)); /* presym_18, 100 zeroes */
+ ASSERT(put_bits(&os, 0x0, 1) &&
+ put_bits(&os, 78, 7)); /* presym_18, 89 zeroes */
+ ASSERT(put_bits(&os, 0x1, 2)); /* presym_2 */
+ ASSERT(put_bits(&os, 0x3, 3)); /* presym_0 */
+
+ /* Litlen symbols */
+ ASSERT(put_bits(&os, 0x0, 1)); /* litlensym_A */
+ ASSERT(put_bits(&os, 0x1, 2)); /* litlensym_B */
+ ASSERT(put_bits(&os, 0x0, 1)); /* litlensym_A */
+ ASSERT(put_bits(&os, 0x0, 1)); /* litlensym_A */
+ ASSERT(put_bits(&os, 0x3, 2)); /* litlensym_256 (end-of-block) */
+
+ ASSERT(flush_bits(&os));
+
+ verify_decompression(in, os.next - in, out, sizeof(out),
+ expected_out, sizeof(expected_out));
+}
+
+/* Test that a litrunlen code containing only one symbol is accepted. */
+static void
+test_singleton_litrunlen_code(void)
+{
+ u8 in[128];
+ u8 out[128];
+ struct output_bitstream os = { .next = in, .end = in + sizeof(in) };
+ int i;
+
+ /*
+ * Litlen code:
+ * litlensym_256 (end-of-block) freq=1 len=1 codeword=0
+ * Offset code:
+ * (empty)
+ *
+ * Litlen and offset codeword lengths:
+ * [0..256] = 0 presym_18 presym_18
+ * [256] = 1 presym_1
+ * [257] = 0 presym_0
+ *
+ * Precode:
+ * presym_0 freq=1 len=2 codeword=01
+ * presym_1 freq=1 len=2 codeword=11
+ * presym_18 freq=2 len=1 codeword= 0
+ */
+
+ ASSERT(put_bits(&os, 1, 1)); /* BFINAL: 1 */
+ ASSERT(put_bits(&os, 2, 2)); /* BTYPE: DYNAMIC_HUFFMAN */
+ ASSERT(put_bits(&os, 0, 5)); /* num_litlen_syms: 0 + 257 */
+ ASSERT(put_bits(&os, 0, 5)); /* num_offset_syms: 0 + 1 */
+ ASSERT(put_bits(&os, 14, 4)); /* num_explicit_precode_lens: 14 + 4 */
+
+ /*
+ * Precode codeword lengths: order is
+ * [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]
+ */
+ for (i = 0; i < 2; i++) /* presym_{16,17}: len=0 */
+ ASSERT(put_bits(&os, 0, 3));
+ ASSERT(put_bits(&os, 1, 3)); /* presym_18: len=1 */
+ ASSERT(put_bits(&os, 2, 3)); /* presym_0: len=2 */
+ for (i = 0; i < 13; i++) /* presym_{8,...,14}: len=0 */
+ ASSERT(put_bits(&os, 0, 3));
+ ASSERT(put_bits(&os, 2, 3)); /* presym_1: len=2 */
+
+ /* Litlen and offset codeword lengths */
+ for (i = 0; i < 2; i++) {
+ ASSERT(put_bits(&os, 0, 1) && /* presym_18, 128 zeroes */
+ put_bits(&os, 117, 7));
+ }
+ ASSERT(put_bits(&os, 0x3, 2)); /* presym_1 */
+ ASSERT(put_bits(&os, 0x1, 2)); /* presym_0 */
+
+ /* Litlen symbols */
+ ASSERT(put_bits(&os, 0x0, 1)); /* litlensym_256 (end-of-block) */
+
+ ASSERT(flush_bits(&os));
+
+ verify_decompression(in, os.next - in, out, sizeof(out), in, 0);
+}
+
+/* Test that an offset code containing only one symbol is accepted. */
+static void
+test_singleton_offset_code(void)
+{
+ static const u8 expected_out[] = { 255, 255, 255, 255 };
+ u8 in[128];
+ u8 out[128];
+ struct output_bitstream os = { .next = in, .end = in + sizeof(in) };
+ int i;
+
+ ASSERT(put_bits(&os, 1, 1)); /* BFINAL: 1 */
+ ASSERT(put_bits(&os, 2, 2)); /* BTYPE: DYNAMIC_HUFFMAN */
+
+ /*
+ * Litlen code:
+ * litlensym_255 freq=1 len=1 codeword= 0
+ * litlensym_256 (end-of-block) freq=1 len=2 codeword=01
+ * litlensym_257 (len 3) freq=1 len=2 codeword=11
+ * Offset code:
+ * offsetsym_0 (offset 0) freq=1 len=1 codeword=0
+ *
+ * Litlen and offset codeword lengths:
+ * [0..254] = 0 presym_{18,18}
+ * [255] = 1 presym_1
+ * [256] = 1 presym_2
+ * [257] = 1 presym_2
+ * [258] = 1 presym_1
+ *
+ * Precode:
+ * presym_1 freq=2 len=2 codeword=01
+ * presym_2 freq=2 len=2 codeword=11
+ * presym_18 freq=2 len=1 codeword= 0
+ */
+
+ ASSERT(put_bits(&os, 1, 5)); /* num_litlen_syms: 1 + 257 */
+ ASSERT(put_bits(&os, 0, 5)); /* num_offset_syms: 0 + 1 */
+ ASSERT(put_bits(&os, 14, 4)); /* num_explicit_precode_lens: 14 + 4 */
+ /*
+ * Precode codeword lengths: order is
+ * [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]
+ */
+ for (i = 0; i < 2; i++) /* presym_{16,17}: len=0 */
+ ASSERT(put_bits(&os, 0, 3));
+ ASSERT(put_bits(&os, 1, 3)); /* presym_18: len=1 */
+ for (i = 0; i < 12; i++) /* presym_{0,...,13}: len=0 */
+ ASSERT(put_bits(&os, 0, 3));
+ ASSERT(put_bits(&os, 2, 3)); /* presym_2: len=2 */
+ ASSERT(put_bits(&os, 0, 3)); /* presym_14: len=0 */
+ ASSERT(put_bits(&os, 2, 3)); /* presym_1: len=2 */
+
+ /* Litlen and offset codeword lengths */
+ ASSERT(put_bits(&os, 0x0, 1) && /* presym_18, 128 zeroes */
+ put_bits(&os, 117, 7));
+ ASSERT(put_bits(&os, 0x0, 1) && /* presym_18, 127 zeroes */
+ put_bits(&os, 116, 7));
+ ASSERT(put_bits(&os, 0x1, 2)); /* presym_1 */
+ ASSERT(put_bits(&os, 0x3, 2)); /* presym_2 */
+ ASSERT(put_bits(&os, 0x3, 2)); /* presym_2 */
+ ASSERT(put_bits(&os, 0x1, 2)); /* presym_1 */
+
+ /* Literal */
+ ASSERT(put_bits(&os, 0x0, 1)); /* litlensym_255 */
+
+ /* Match */
+ ASSERT(put_bits(&os, 0x3, 2)); /* litlensym_257 */
+ ASSERT(put_bits(&os, 0x0, 1)); /* offsetsym_0 */
+
+ /* End of block */
+ ASSERT(put_bits(&os, 0x1, 2)); /* litlensym_256 */
+
+ ASSERT(flush_bits(&os));
+
+ verify_decompression(in, os.next - in, out, sizeof(out),
+ expected_out, sizeof(expected_out));
+}
+
+/* Test that an offset code containing only one symbol is accepted, even if that
+ * symbol is not symbol 0. The codeword should be '0' in either case. */
+static void
+test_singleton_offset_code_notsymzero(void)
+{
+ static const u8 expected_out[] = { 254, 255, 254, 255, 254 };
+ u8 in[128];
+ u8 out[128];
+ struct output_bitstream os = { .next = in, .end = in + sizeof(in) };
+ int i;
+
+ ASSERT(put_bits(&os, 1, 1)); /* BFINAL: 1 */
+ ASSERT(put_bits(&os, 2, 2)); /* BTYPE: DYNAMIC_HUFFMAN */
+
+ /*
+ * Litlen code:
+ * litlensym_254 len=2 codeword=00
+ * litlensym_255 len=2 codeword=10
+ * litlensym_256 (end-of-block) len=2 codeword=01
+ * litlensym_257 (len 3) len=2 codeword=11
+ * Offset code:
+ * offsetsym_1 (offset 2) len=1 codeword=0
+ *
+ * Litlen and offset codeword lengths:
+ * [0..253] = 0 presym_{18,18}
+ * [254] = 2 presym_2
+ * [255] = 2 presym_2
+ * [256] = 2 presym_2
+ * [257] = 2 presym_2
+ * [258] = 0 presym_0
+ * [259] = 1 presym_1
+ *
+ * Precode:
+ * presym_0 len=2 codeword=00
+ * presym_1 len=2 codeword=10
+ * presym_2 len=2 codeword=01
+ * presym_18 len=2 codeword=11
+ */
+
+ ASSERT(put_bits(&os, 1, 5)); /* num_litlen_syms: 1 + 257 */
+ ASSERT(put_bits(&os, 1, 5)); /* num_offset_syms: 1 + 1 */
+ ASSERT(put_bits(&os, 14, 4)); /* num_explicit_precode_lens: 14 + 4 */
+ /*
+ * Precode codeword lengths: order is
+ * [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]
+ */
+ for (i = 0; i < 2; i++) /* presym_{16,17}: len=0 */
+ ASSERT(put_bits(&os, 0, 3));
+ ASSERT(put_bits(&os, 2, 3)); /* presym_18: len=2 */
+ ASSERT(put_bits(&os, 2, 3)); /* presym_0: len=2 */
+ for (i = 0; i < 11; i++) /* presym_{8,...,13}: len=0 */
+ ASSERT(put_bits(&os, 0, 3));
+ ASSERT(put_bits(&os, 2, 3)); /* presym_2: len=2 */
+ ASSERT(put_bits(&os, 0, 3)); /* presym_14: len=0 */
+ ASSERT(put_bits(&os, 2, 3)); /* presym_1: len=2 */
+
+ /* Litlen and offset codeword lengths */
+ ASSERT(put_bits(&os, 0x3, 2) && /* presym_18, 128 zeroes */
+ put_bits(&os, 117, 7));
+ ASSERT(put_bits(&os, 0x3, 2) && /* presym_18, 126 zeroes */
+ put_bits(&os, 115, 7));
+ ASSERT(put_bits(&os, 0x1, 2)); /* presym_2 */
+ ASSERT(put_bits(&os, 0x1, 2)); /* presym_2 */
+ ASSERT(put_bits(&os, 0x1, 2)); /* presym_2 */
+ ASSERT(put_bits(&os, 0x1, 2)); /* presym_2 */
+ ASSERT(put_bits(&os, 0x0, 2)); /* presym_0 */
+ ASSERT(put_bits(&os, 0x2, 2)); /* presym_1 */
+
+ /* Literals */
+ ASSERT(put_bits(&os, 0x0, 2)); /* litlensym_254 */
+ ASSERT(put_bits(&os, 0x2, 2)); /* litlensym_255 */
+
+ /* Match */
+ ASSERT(put_bits(&os, 0x3, 2)); /* litlensym_257 */
+ ASSERT(put_bits(&os, 0x0, 1)); /* offsetsym_1 */
+
+ /* End of block */
+ ASSERT(put_bits(&os, 0x1, 2)); /* litlensym_256 */
+
+ ASSERT(flush_bits(&os));
+
+ verify_decompression(in, os.next - in, out, sizeof(out),
+ expected_out, sizeof(expected_out));
+}
+
+int
+tmain(int argc, tchar *argv[])
+{
+ begin_program(argv);
+
+ test_empty_offset_code();
+ test_singleton_litrunlen_code();
+ test_singleton_offset_code();
+ test_singleton_offset_code_notsymzero();
+
+ return 0;
+}
diff --git a/util/compress/libdeflate/programs/test_litrunlen_overflow.c b/util/compress/libdeflate/programs/test_litrunlen_overflow.c
new file mode 100644
index 000000000..7a9d5b1fe
--- /dev/null
+++ b/util/compress/libdeflate/programs/test_litrunlen_overflow.c
@@ -0,0 +1,72 @@
+/*
+ * test_litrunlen_overflow.c
+ *
+ * Regression test for commit f2f0df727444 ("deflate_compress: fix corruption
+ * with long literal run"). Try to compress a file longer than 65535 bytes
+ * where no 2-byte sequence (3 would be sufficient) is repeated <= 32768 bytes
+ * apart, and the distribution of bytes remains constant throughout, and yet not
+ * all bytes are used so the data is still slightly compressible. There will be
+ * no matches in this data, but the compressor should still output a compressed
+ * block, and this block should contain more than 65535 consecutive literals,
+ * which triggered the bug.
+ *
+ * Note: on random data, this situation is extremely unlikely if the compressor
+ * uses all matches it finds, since random data will on average have a 3-byte
+ * match every (256**3)/32768 = 512 bytes.
+ */
+
+#include "test_util.h"
+
+int
+tmain(int argc, tchar *argv[])
+{
+ const size_t data_size = 2 * 250 * 251;
+ u8 *orig_data, *compressed_data, *decompressed_data;
+ int i, stride, multiple, j = 0;
+ struct libdeflate_decompressor *d;
+ static const int levels[] = { 3, 6, 12 };
+
+ begin_program(argv);
+
+ orig_data = xmalloc(data_size);
+ compressed_data = xmalloc(data_size);
+ decompressed_data = xmalloc(data_size);
+
+ for (i = 0; i < 2; i++) {
+ for (stride = 1; stride < 251; stride++) {
+ for (multiple = 0; multiple < 251; multiple++)
+ orig_data[j++] = (stride * multiple) % 251;
+ }
+ }
+ ASSERT(j == data_size);
+
+ d = libdeflate_alloc_decompressor();
+ ASSERT(d != NULL);
+
+ for (i = 0; i < ARRAY_LEN(levels); i++) {
+ struct libdeflate_compressor *c;
+ size_t csize;
+ enum libdeflate_result res;
+
+ c = libdeflate_alloc_compressor(levels[i]);
+ ASSERT(c != NULL);
+
+ csize = libdeflate_deflate_compress(c, orig_data, data_size,
+ compressed_data, data_size);
+ ASSERT(csize > 0 && csize < data_size);
+
+ res = libdeflate_deflate_decompress(d, compressed_data, csize,
+ decompressed_data,
+ data_size, NULL);
+ ASSERT(res == LIBDEFLATE_SUCCESS);
+ ASSERT(memcmp(orig_data, decompressed_data, data_size) == 0);
+
+ libdeflate_free_compressor(c);
+ }
+
+ libdeflate_free_decompressor(d);
+ free(orig_data);
+ free(compressed_data);
+ free(decompressed_data);
+ return 0;
+}
diff --git a/util/compress/libdeflate/programs/test_slow_decompression.c b/util/compress/libdeflate/programs/test_slow_decompression.c
new file mode 100644
index 000000000..d5ac26245
--- /dev/null
+++ b/util/compress/libdeflate/programs/test_slow_decompression.c
@@ -0,0 +1,472 @@
+/*
+ * test_slow_decompression.c
+ *
+ * Test how quickly libdeflate decompresses degenerate/malicious compressed data
+ * streams that start new Huffman blocks extremely frequently.
+ */
+
+#include "test_util.h"
+
+/*
+ * Generate a DEFLATE stream containing all empty "static Huffman" blocks.
+ *
+ * libdeflate used to decompress this very slowly (~1000x slower than typical
+ * data), but now it's much faster (only ~2x slower than typical data) because
+ * now it skips rebuilding the decode tables for the static Huffman codes when
+ * they're already loaded into the decompressor.
+ */
+static void
+generate_empty_static_huffman_blocks(u8 *p, size_t len)
+{
+ struct output_bitstream os = { .next = p, .end = p + len };
+
+ while (put_bits(&os, 0, 1) && /* BFINAL: 0 */
+ put_bits(&os, 1, 2) && /* BTYPE: STATIC_HUFFMAN */
+ put_bits(&os, 0, 7)) /* litlensym_256 (end-of-block) */
+ ;
+}
+
+static bool
+generate_empty_dynamic_huffman_block(struct output_bitstream *os)
+{
+ int i;
+
+ if (!put_bits(os, 0, 1)) /* BFINAL: 0 */
+ return false;
+ if (!put_bits(os, 2, 2)) /* BTYPE: DYNAMIC_HUFFMAN */
+ return false;
+
+ /*
+ * Write a minimal Huffman code, then the end-of-block symbol.
+ *
+ * Litlen code:
+ * litlensym_256 (end-of-block) freq=1 len=1 codeword=0
+ * Offset code:
+ * offsetsym_0 (unused) freq=0 len=1 codeword=0
+ *
+ * Litlen and offset codeword lengths:
+ * [0..255] = 0 presym_{18,18}
+ * [256] = 1 presym_1
+ * [257] = 1 presym_1
+ *
+ * Precode:
+ * presym_1 freq=2 len=1 codeword=0
+ * presym_18 freq=2 len=1 codeword=1
+ */
+
+ if (!put_bits(os, 0, 5)) /* num_litlen_syms: 0 + 257 */
+ return false;
+ if (!put_bits(os, 0, 5)) /* num_offset_syms: 0 + 1 */
+ return false;
+ if (!put_bits(os, 14, 4)) /* num_explicit_precode_lens: 14 + 4 */
+ return false;
+ /*
+ * Precode codeword lengths: order is
+ * [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]
+ */
+ for (i = 0; i < 2; i++) { /* presym_{16,17}: len=0 */
+ if (!put_bits(os, 0, 3))
+ return false;
+ }
+ if (!put_bits(os, 1, 3)) /* presym_18: len=1 */
+ return false;
+ for (i = 0; i < 14; i++) { /* presym_{0,...,14}: len=0 */
+ if (!put_bits(os, 0, 3))
+ return false;
+ }
+ if (!put_bits(os, 1, 3)) /* presym_1: len=1 */
+ return false;
+
+ /* Litlen and offset codeword lengths */
+ for (i = 0; i < 2; i++) {
+ if (!put_bits(os, 1, 1) || /* presym_18, 128 zeroes */
+ !put_bits(os, 117, 7))
+ return false;
+ }
+ if (!put_bits(os, 0, 1)) /* presym_1 */
+ return false;
+ if (!put_bits(os, 0, 1)) /* presym_1 */
+ return false;
+ /* Done writing the Huffman codes */
+
+ return put_bits(os, 0, 1); /* litlensym_256 (end-of-block) */
+}
+
+/*
+ * Generate a DEFLATE stream containing all empty "dynamic Huffman" blocks.
+ *
+ * This is the worst known case currently, being ~100x slower to decompress than
+ * typical data.
+ */
+static void
+generate_empty_dynamic_huffman_blocks(u8 *p, size_t len)
+{
+ struct output_bitstream os = { .next = p, .end = p + len };
+
+ while (generate_empty_dynamic_huffman_block(&os))
+ ;
+}
+
+#define NUM_ITERATIONS 100
+
+static u64
+do_test_libdeflate(const char *input_type, const u8 *in, size_t in_nbytes,
+ u8 *out, size_t out_nbytes_avail)
+{
+ struct libdeflate_decompressor *d;
+ enum libdeflate_result res;
+ u64 t;
+ int i;
+
+ d = libdeflate_alloc_decompressor();
+ ASSERT(d != NULL);
+
+ t = timer_ticks();
+ for (i = 0; i < NUM_ITERATIONS; i++) {
+ res = libdeflate_deflate_decompress(d, in, in_nbytes, out,
+ out_nbytes_avail, NULL);
+ ASSERT(res == LIBDEFLATE_BAD_DATA ||
+ res == LIBDEFLATE_INSUFFICIENT_SPACE);
+ }
+ t = timer_ticks() - t;
+
+ printf("[%s, libdeflate]: %"PRIu64" KB/s\n", input_type,
+ timer_KB_per_s((u64)in_nbytes * NUM_ITERATIONS, t));
+
+ libdeflate_free_decompressor(d);
+ return t;
+}
+
+static u64
+do_test_zlib(const char *input_type, const u8 *in, size_t in_nbytes,
+ u8 *out, size_t out_nbytes_avail)
+{
+ z_stream z;
+ int res;
+ u64 t;
+ int i;
+
+ memset(&z, 0, sizeof(z));
+ res = inflateInit2(&z, -15);
+ ASSERT(res == Z_OK);
+
+ t = timer_ticks();
+ for (i = 0; i < NUM_ITERATIONS; i++) {
+ inflateReset(&z);
+ z.next_in = (void *)in;
+ z.avail_in = in_nbytes;
+ z.next_out = out;
+ z.avail_out = out_nbytes_avail;
+ res = inflate(&z, Z_FINISH);
+ ASSERT(res == Z_BUF_ERROR || res == Z_DATA_ERROR);
+ }
+ t = timer_ticks() - t;
+
+ printf("[%s, zlib ]: %"PRIu64" KB/s\n", input_type,
+ timer_KB_per_s((u64)in_nbytes * NUM_ITERATIONS, t));
+
+ inflateEnd(&z);
+ return t;
+}
+
+/*
+ * Test case from https://github.com/ebiggers/libdeflate/issues/33
+ * with the gzip header and footer removed to leave just the DEFLATE stream
+ */
+static const u8 orig_repro[3962] =
+ "\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a"
+ "\x6a\x6a\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20"
+ "\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80\x28"
+ "\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11"
+ "\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48"
+ "\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80"
+ "\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80\x28\x00"
+ "\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea"
+ "\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea"
+ "\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48"
+ "\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20"
+ "\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00"
+ "\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11"
+ "\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x63"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92"
+ "\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00"
+ "\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48"
+ "\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20"
+ "\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00"
+ "\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x92\x63\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea"
+ "\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48"
+ "\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11"
+ "\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00"
+ "\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x92\x63\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11"
+ "\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63"
+ "\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea"
+ "\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x92\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a"
+ "\x6a\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80"
+ "\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80\x28\x00"
+ "\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00"
+ "\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x92\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a"
+ "\x6a\x6a\x6a\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00"
+ "\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80"
+ "\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00"
+ "\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04"
+ "\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20"
+ "\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80\x28"
+ "\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00"
+ "\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04"
+ "\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00"
+ "\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28"
+ "\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00"
+ "\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x63\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04"
+ "\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00"
+ "\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28"
+ "\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x92\x63\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00"
+ "\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04"
+ "\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00"
+ "\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28"
+ "\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x92\x63\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00"
+ "\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92"
+ "\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00"
+ "\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x63\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00"
+ "\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80"
+ "\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00"
+ "\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92"
+ "\x63\x00\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00"
+ "\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04"
+ "\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00\x20"
+ "\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x00\xea\x04\x48\x00\x20\x80\x28"
+ "\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1a\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00"
+ "\xea\x04\x48\x00\x20\x80\x28\x00\x00\x11\x00\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b"
+ "\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x92\x63\x00\x04\xea\x48\x00\x20"
+ "\x80\x28\x00\x00\x11\x1b\x1b\x1b\x1b\x92\x63\x00\xea\x04\x48\x00"
+ "\x20\x80\x28\x00\x00\x11\x00\x00\x01\x04\x00\x3f\x00\x00\x00\x00"
+ "\x28\xf7\xff\x00\xff\xff\xff\xff\x00\x00";
+
+int
+tmain(int argc, tchar *argv[])
+{
+ u8 in[4096];
+ u8 out[10000];
+ u64 t, tz;
+
+ begin_program(argv);
+
+ begin_performance_test();
+
+ /* static huffman case */
+ generate_empty_static_huffman_blocks(in, sizeof(in));
+ t = do_test_libdeflate("static huffman", in, sizeof(in),
+ out, sizeof(out));
+ tz = do_test_zlib("static huffman", in, sizeof(in), out, sizeof(out));
+ /*
+ * libdeflate is faster than zlib in this case, e.g.
+ * [static huffman, libdeflate]: 215861 KB/s
+ * [static huffman, zlib ]: 73651 KB/s
+ */
+ putchar('\n');
+ ASSERT(t < tz);
+
+ /* dynamic huffman case */
+ generate_empty_dynamic_huffman_blocks(in, sizeof(in));
+ t = do_test_libdeflate("dynamic huffman", in, sizeof(in),
+ out, sizeof(out));
+ tz = do_test_zlib("dynamic huffman", in, sizeof(in), out, sizeof(out));
+ /*
+ * libdeflate is slower than zlib in this case, though not super bad.
+ * [dynamic huffman, libdeflate]: 6277 KB/s
+ * [dynamic huffman, zlib ]: 10419 KB/s
+ * FIXME: make it faster.
+ */
+ putchar('\n');
+ ASSERT(t < 4 * tz);
+
+ /* original reproducer */
+ t = do_test_libdeflate("original repro", orig_repro, sizeof(orig_repro),
+ out, sizeof(out));
+ tz = do_test_zlib("original repro", orig_repro, sizeof(orig_repro),
+ out, sizeof(out));
+ ASSERT(t < tz);
+
+ return 0;
+}
diff --git a/util/compress/libdeflate/programs/test_trailing_bytes.c b/util/compress/libdeflate/programs/test_trailing_bytes.c
new file mode 100644
index 000000000..92609ff46
--- /dev/null
+++ b/util/compress/libdeflate/programs/test_trailing_bytes.c
@@ -0,0 +1,152 @@
+/*
+ * test_trailing_bytes.c
+ *
+ * Test that decompression correctly stops at the end of the first DEFLATE,
+ * zlib, or gzip stream, and doesn't process any additional trailing bytes.
+ */
+
+#include "test_util.h"
+
+static const struct {
+ size_t (LIBDEFLATEAPI *compress)(
+ struct libdeflate_compressor *compressor,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail);
+ enum libdeflate_result (LIBDEFLATEAPI *decompress)(
+ struct libdeflate_decompressor *decompressor,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail,
+ size_t *actual_out_nbytes_ret);
+ enum libdeflate_result (LIBDEFLATEAPI *decompress_ex)(
+ struct libdeflate_decompressor *decompressor,
+ const void *in, size_t in_nbytes,
+ void *out, size_t out_nbytes_avail,
+ size_t *actual_in_nbytes_ret,
+ size_t *actual_out_nbytes_ret);
+} codecs[] = {
+ {
+ .compress = libdeflate_deflate_compress,
+ .decompress = libdeflate_deflate_decompress,
+ .decompress_ex = libdeflate_deflate_decompress_ex,
+ }, {
+ .compress = libdeflate_zlib_compress,
+ .decompress = libdeflate_zlib_decompress,
+ .decompress_ex = libdeflate_zlib_decompress_ex,
+ }, {
+ .compress = libdeflate_gzip_compress,
+ .decompress = libdeflate_gzip_decompress,
+ .decompress_ex = libdeflate_gzip_decompress_ex,
+ }
+};
+
+int
+tmain(int argc, tchar *argv[])
+{
+ const size_t original_nbytes = 32768;
+ const size_t compressed_nbytes_total = 32768;
+ /*
+ * Don't use the full buffer for compressed data, because we want to
+ * test whether decompression can deal with additional trailing bytes.
+ *
+ * Note: we can't use a guarded buffer (i.e. a buffer where the byte
+ * after compressed_nbytes is unmapped) because the decompressor may
+ * read a few bytes beyond the end of the stream (but ultimately not
+ * actually use those bytes) as long as they are within the buffer.
+ */
+ const size_t compressed_nbytes_avail = 30000;
+ size_t i;
+ u8 *original;
+ u8 *compressed;
+ u8 *decompressed;
+ struct libdeflate_compressor *c;
+ struct libdeflate_decompressor *d;
+ size_t compressed_nbytes;
+ enum libdeflate_result res;
+ size_t actual_compressed_nbytes;
+ size_t actual_decompressed_nbytes;
+
+ begin_program(argv);
+
+ ASSERT(compressed_nbytes_avail < compressed_nbytes_total);
+
+ /* Prepare some dummy data to compress */
+ original = xmalloc(original_nbytes);
+ ASSERT(original != NULL);
+ for (i = 0; i < original_nbytes; i++)
+ original[i] = (i % 123) + (i % 1023);
+
+ compressed = xmalloc(compressed_nbytes_total);
+ ASSERT(compressed != NULL);
+ memset(compressed, 0, compressed_nbytes_total);
+
+ decompressed = xmalloc(original_nbytes);
+ ASSERT(decompressed != NULL);
+
+ c = libdeflate_alloc_compressor(6);
+ ASSERT(c != NULL);
+
+ d = libdeflate_alloc_decompressor();
+ ASSERT(d != NULL);
+
+ for (i = 0; i < ARRAY_LEN(codecs); i++) {
+ compressed_nbytes = codecs[i].compress(c, original,
+ original_nbytes,
+ compressed,
+ compressed_nbytes_avail);
+ ASSERT(compressed_nbytes > 0);
+ ASSERT(compressed_nbytes <= compressed_nbytes_avail);
+
+ /* Test decompress() of stream that fills the whole buffer */
+ actual_decompressed_nbytes = 0;
+ memset(decompressed, 0, original_nbytes);
+ res = codecs[i].decompress(d, compressed, compressed_nbytes,
+ decompressed, original_nbytes,
+ &actual_decompressed_nbytes);
+ ASSERT(res == LIBDEFLATE_SUCCESS);
+ ASSERT(actual_decompressed_nbytes == original_nbytes);
+ ASSERT(memcmp(decompressed, original, original_nbytes) == 0);
+
+ /* Test decompress_ex() of stream that fills the whole buffer */
+ actual_compressed_nbytes = actual_decompressed_nbytes = 0;
+ memset(decompressed, 0, original_nbytes);
+ res = codecs[i].decompress_ex(d, compressed, compressed_nbytes,
+ decompressed, original_nbytes,
+ &actual_compressed_nbytes,
+ &actual_decompressed_nbytes);
+ ASSERT(res == LIBDEFLATE_SUCCESS);
+ ASSERT(actual_compressed_nbytes == compressed_nbytes);
+ ASSERT(actual_decompressed_nbytes == original_nbytes);
+ ASSERT(memcmp(decompressed, original, original_nbytes) == 0);
+
+ /* Test decompress() of stream with trailing bytes */
+ actual_decompressed_nbytes = 0;
+ memset(decompressed, 0, original_nbytes);
+ res = codecs[i].decompress(d, compressed,
+ compressed_nbytes_total,
+ decompressed, original_nbytes,
+ &actual_decompressed_nbytes);
+ ASSERT(res == LIBDEFLATE_SUCCESS);
+ ASSERT(actual_decompressed_nbytes == original_nbytes);
+ ASSERT(memcmp(decompressed, original, original_nbytes) == 0);
+
+ /* Test decompress_ex() of stream with trailing bytes */
+ actual_compressed_nbytes = actual_decompressed_nbytes = 0;
+ memset(decompressed, 0, original_nbytes);
+ res = codecs[i].decompress_ex(d, compressed,
+ compressed_nbytes_total,
+ decompressed, original_nbytes,
+ &actual_compressed_nbytes,
+ &actual_decompressed_nbytes);
+ ASSERT(res == LIBDEFLATE_SUCCESS);
+ ASSERT(actual_compressed_nbytes == compressed_nbytes);
+ ASSERT(actual_decompressed_nbytes == original_nbytes);
+ ASSERT(memcmp(decompressed, original, original_nbytes) == 0);
+ }
+
+ free(original);
+ free(compressed);
+ free(decompressed);
+ libdeflate_free_compressor(c);
+ libdeflate_free_decompressor(d);
+ return 0;
+}
diff --git a/util/compress/libdeflate/programs/test_util.c b/util/compress/libdeflate/programs/test_util.c
new file mode 100644
index 000000000..20e7c217f
--- /dev/null
+++ b/util/compress/libdeflate/programs/test_util.c
@@ -0,0 +1,243 @@
+/*
+ * test_util.c - utility functions for test programs
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _WIN32
+/* for MAP_ANONYMOUS or MAP_ANON, which unfortunately aren't part of POSIX... */
+# undef _POSIX_C_SOURCE
+# ifdef __APPLE__
+# define _DARWIN_C_SOURCE
+# elif defined(__linux__)
+# define _GNU_SOURCE
+# endif
+#endif
+
+#include "test_util.h"
+
+#include <fcntl.h>
+#include <time.h>
+#ifdef _WIN32
+# include <windows.h>
+#else
+# include <unistd.h>
+# include <sys/mman.h>
+# include <sys/time.h>
+#endif
+
+#ifndef MAP_ANONYMOUS
+# define MAP_ANONYMOUS MAP_ANON
+#endif
+
+/* Abort with an error message */
+_noreturn void
+assertion_failed(const char *expr, const char *file, int line)
+{
+ msg("Assertion failed: %s at %s:%d", expr, file, line);
+ abort();
+}
+
+void
+begin_performance_test(void)
+{
+ /* Skip performance tests by default, since they can be flaky. */
+ if (getenv("INCLUDE_PERF_TESTS") == NULL)
+ exit(0);
+}
+
+static size_t
+get_page_size(void)
+{
+#ifdef _WIN32
+ SYSTEM_INFO info;
+
+ GetSystemInfo(&info);
+ return info.dwPageSize;
+#else
+ return sysconf(_SC_PAGESIZE);
+#endif
+}
+
+/* Allocate a buffer with guard pages */
+void
+alloc_guarded_buffer(size_t size, u8 **start_ret, u8 **end_ret)
+{
+ const size_t pagesize = get_page_size();
+ const size_t nr_pages = (size + pagesize - 1) / pagesize;
+ u8 *base_addr;
+ u8 *start, *end;
+#ifdef _WIN32
+ DWORD oldProtect;
+#endif
+
+ *start_ret = NULL;
+ *end_ret = NULL;
+
+#ifdef _WIN32
+ /* Allocate buffer and guard pages with no access. */
+ base_addr = VirtualAlloc(NULL, (nr_pages + 2) * pagesize,
+ MEM_COMMIT | MEM_RESERVE, PAGE_NOACCESS);
+ if (!base_addr) {
+ msg("Unable to allocate memory (VirtualAlloc): Windows error %u",
+ (unsigned int)GetLastError());
+ ASSERT(0);
+ }
+ start = base_addr + pagesize;
+ end = start + (nr_pages * pagesize);
+
+ /* Grant read+write access to just the buffer. */
+ if (!VirtualProtect(start, end - start, PAGE_READWRITE, &oldProtect)) {
+ msg("Unable to protect memory (VirtualProtect): Windows error %u",
+ (unsigned int)GetLastError());
+ VirtualFree(base_addr, 0, MEM_RELEASE);
+ ASSERT(0);
+ }
+#else
+ /* Allocate buffer and guard pages. */
+ base_addr = mmap(NULL, (nr_pages + 2) * pagesize, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ if (base_addr == (u8 *)MAP_FAILED) {
+ msg_errno("Unable to allocate memory (anonymous mmap)");
+ ASSERT(0);
+ }
+ start = base_addr + pagesize;
+ end = start + (nr_pages * pagesize);
+
+ /* Unmap the guard pages. */
+ munmap(base_addr, pagesize);
+ munmap(end, pagesize);
+#endif
+ *start_ret = start;
+ *end_ret = end;
+}
+
+/* Free a buffer that was allocated by alloc_guarded_buffer() */
+void
+free_guarded_buffer(u8 *start, u8 *end)
+{
+ if (!start)
+ return;
+#ifdef _WIN32
+ VirtualFree(start - get_page_size(), 0, MEM_RELEASE);
+#else
+ munmap(start, end - start);
+#endif
+}
+
+/*
+ * Return the number of timer ticks that have elapsed since some unspecified
+ * point fixed at the start of program execution
+ */
+u64
+timer_ticks(void)
+{
+#ifdef _WIN32
+ LARGE_INTEGER count;
+
+ QueryPerformanceCounter(&count);
+ return count.QuadPart;
+#elif defined(HAVE_CLOCK_GETTIME)
+ struct timespec ts;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (1000000000 * (u64)ts.tv_sec) + ts.tv_nsec;
+#else
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ return (1000000 * (u64)tv.tv_sec) + tv.tv_usec;
+#endif
+}
+
+/*
+ * Return the number of timer ticks per second
+ */
+static u64
+timer_frequency(void)
+{
+#ifdef _WIN32
+ LARGE_INTEGER freq;
+
+ QueryPerformanceFrequency(&freq);
+ return freq.QuadPart;
+#elif defined(HAVE_CLOCK_GETTIME)
+ return 1000000000;
+#else
+ return 1000000;
+#endif
+}
+
+/*
+ * Convert a number of elapsed timer ticks to milliseconds
+ */
+u64 timer_ticks_to_ms(u64 ticks)
+{
+ return ticks * 1000 / timer_frequency();
+}
+
+/*
+ * Convert a byte count and a number of elapsed timer ticks to MB/s
+ */
+u64 timer_MB_per_s(u64 bytes, u64 ticks)
+{
+ return bytes * timer_frequency() / ticks / 1000000;
+}
+
+/*
+ * Convert a byte count and a number of elapsed timer ticks to KB/s
+ */
+u64 timer_KB_per_s(u64 bytes, u64 ticks)
+{
+ return bytes * timer_frequency() / ticks / 1000;
+}
+
+bool
+put_bits(struct output_bitstream *os, machine_word_t bits, int num_bits)
+{
+ os->bitbuf |= bits << os->bitcount;
+ os->bitcount += num_bits;
+ while (os->bitcount >= 8) {
+ if (os->next == os->end)
+ return false;
+ *os->next++ = os->bitbuf;
+ os->bitcount -= 8;
+ os->bitbuf >>= 8;
+ }
+ return true;
+}
+
+bool
+flush_bits(struct output_bitstream *os)
+{
+ while (os->bitcount > 0) {
+ if (os->next == os->end)
+ return false;
+ *os->next++ = os->bitbuf;
+ os->bitcount -= 8;
+ os->bitbuf >>= 8;
+ }
+ os->bitcount = 0;
+ return true;
+}
diff --git a/util/compress/libdeflate/programs/test_util.h b/util/compress/libdeflate/programs/test_util.h
new file mode 100644
index 000000000..e10c154a2
--- /dev/null
+++ b/util/compress/libdeflate/programs/test_util.h
@@ -0,0 +1,67 @@
+/*
+ * test_util.h - utility functions for test programs
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PROGRAMS_TEST_UTIL_H
+#define PROGRAMS_TEST_UTIL_H
+
+#include "prog_util.h"
+
+#include <zlib.h> /* for comparison purposes */
+
+#ifdef __GNUC__
+# define _noreturn __attribute__((noreturn))
+#else
+# define _noreturn
+#endif
+
+void _noreturn
+assertion_failed(const char *expr, const char *file, int line);
+
+#define ASSERT(expr) { if (unlikely(!(expr))) \
+ assertion_failed(#expr, __FILE__, __LINE__); }
+
+void begin_performance_test(void);
+
+void alloc_guarded_buffer(size_t size, u8 **start_ret, u8 **end_ret);
+void free_guarded_buffer(u8 *start, u8 *end);
+
+u64 timer_ticks(void);
+u64 timer_ticks_to_ms(u64 ticks);
+u64 timer_MB_per_s(u64 bytes, u64 ticks);
+u64 timer_KB_per_s(u64 bytes, u64 ticks);
+
+struct output_bitstream {
+ machine_word_t bitbuf;
+ int bitcount;
+ u8 *next;
+ u8 *end;
+};
+
+bool put_bits(struct output_bitstream *os, machine_word_t bits, int num_bits);
+bool flush_bits(struct output_bitstream *os);
+
+#endif /* PROGRAMS_TEST_UTIL_H */
diff --git a/util/compress/libdeflate/programs/tgetopt.c b/util/compress/libdeflate/programs/tgetopt.c
new file mode 100644
index 000000000..868600d97
--- /dev/null
+++ b/util/compress/libdeflate/programs/tgetopt.c
@@ -0,0 +1,118 @@
+/*
+ * tgetopt.c - portable replacement for GNU getopt()
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "prog_util.h"
+
+tchar *toptarg;
+int toptind = 1, topterr = 1, toptopt;
+
+/*
+ * This is a simple implementation of getopt(). It can be compiled with either
+ * 'char' or 'wchar_t' as the character type.
+ *
+ * Do *not* use this implementation if you need any of the following features,
+ * as they are not supported:
+ * - Long options
+ * - Option-related arguments retained in argv, not nulled out
+ * - '+' and '-' characters in optstring
+ */
+int
+tgetopt(int argc, tchar *argv[], const tchar *optstring)
+{
+ static tchar empty[1];
+ static tchar *nextchar;
+ static bool done;
+
+ if (toptind == 1) {
+ /* Starting to scan a new argument vector */
+ nextchar = NULL;
+ done = false;
+ }
+
+ while (!done && (nextchar != NULL || toptind < argc)) {
+ if (nextchar == NULL) {
+ /* Scanning a new argument */
+ tchar *arg = argv[toptind++];
+ if (arg[0] == '-' && arg[1] != '\0') {
+ if (arg[1] == '-' && arg[2] == '\0') {
+ /* All args after "--" are nonoptions */
+ argv[toptind - 1] = NULL;
+ done = true;
+ } else {
+ /* Start of short option characters */
+ nextchar = &arg[1];
+ }
+ }
+ } else {
+ /* More short options in previous arg */
+ tchar opt = *nextchar;
+ tchar *p = tstrchr(optstring, opt);
+ if (p == NULL) {
+ if (topterr)
+ msg("invalid option -- '%"TC"'", opt);
+ toptopt = opt;
+ return '?';
+ }
+ /* 'opt' is a valid short option character */
+ nextchar++;
+ toptarg = NULL;
+ if (*(p + 1) == ':') {
+ /* 'opt' can take an argument */
+ if (*nextchar != '\0') {
+ /* Optarg is in same argv argument */
+ toptarg = nextchar;
+ nextchar = empty;
+ } else if (toptind < argc && *(p + 2) != ':') {
+ /* Optarg is next argv argument */
+ argv[toptind - 1] = NULL;
+ toptarg = argv[toptind++];
+ } else if (*(p + 2) != ':') {
+ if (topterr && *optstring != ':') {
+ msg("option requires an "
+ "argument -- '%"TC"'", opt);
+ }
+ toptopt = opt;
+ opt = (*optstring == ':') ? ':' : '?';
+ }
+ }
+ if (*nextchar == '\0') {
+ argv[toptind - 1] = NULL;
+ nextchar = NULL;
+ }
+ return opt;
+ }
+ }
+
+ /* Done scanning. Move all nonoptions to the end, set optind to the
+ * index of the first nonoption, and return -1. */
+ toptind = argc;
+ while (--argc > 0)
+ if (argv[argc] != NULL)
+ argv[--toptind] = argv[argc];
+ done = true;
+ return -1;
+}
diff --git a/util/compress/libdeflate/scripts/afl-fuzz/Makefile b/util/compress/libdeflate/scripts/afl-fuzz/Makefile
new file mode 100644
index 000000000..c819797ba
--- /dev/null
+++ b/util/compress/libdeflate/scripts/afl-fuzz/Makefile
@@ -0,0 +1,12 @@
+SRC := $(wildcard */*.c)
+EXE := $(SRC:.c=)
+
+CFLAGS := -O2 -s
+LDLIBS := -ldeflate
+LDFLAGS := -L../..
+CPPFLAGS := -I../..
+
+all:$(EXE)
+
+clean:
+ rm -f $(EXE)
diff --git a/util/compress/libdeflate/scripts/afl-fuzz/deflate_compress/fuzz.c b/util/compress/libdeflate/scripts/afl-fuzz/deflate_compress/fuzz.c
new file mode 100644
index 000000000..d65d17e05
--- /dev/null
+++ b/util/compress/libdeflate/scripts/afl-fuzz/deflate_compress/fuzz.c
@@ -0,0 +1,40 @@
+#include <assert.h>
+#include <libdeflate.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+int main(int argc, char **argv)
+{
+ struct libdeflate_decompressor *d;
+ struct libdeflate_compressor *c;
+ int ret;
+ int fd = open(argv[1], O_RDONLY);
+ struct stat stbuf;
+ assert(fd >= 0);
+ ret = fstat(fd, &stbuf);
+ assert(!ret);
+
+ char in[stbuf.st_size];
+ ret = read(fd, in, sizeof in);
+ assert(ret == sizeof in);
+
+ c = libdeflate_alloc_compressor(6);
+ d = libdeflate_alloc_decompressor();
+
+ char out[sizeof(in)];
+ char checkarray[sizeof(in)];
+
+ size_t csize = libdeflate_deflate_compress(c, in,sizeof in, out, sizeof out);
+ if (csize) {
+ enum libdeflate_result res;
+ res = libdeflate_deflate_decompress(d, out, csize, checkarray, sizeof in, NULL);
+ assert(!res);
+ assert(!memcmp(in, checkarray, sizeof in));
+ }
+
+ libdeflate_free_compressor(c);
+ libdeflate_free_decompressor(d);
+ return 0;
+}
diff --git a/util/compress/libdeflate/scripts/afl-fuzz/deflate_compress/inputs/0 b/util/compress/libdeflate/scripts/afl-fuzz/deflate_compress/inputs/0
new file mode 100644
index 000000000..875bce73a
--- /dev/null
+++ b/util/compress/libdeflate/scripts/afl-fuzz/deflate_compress/inputs/0
Binary files differ
diff --git a/util/compress/libdeflate/scripts/afl-fuzz/deflate_decompress/fuzz.c b/util/compress/libdeflate/scripts/afl-fuzz/deflate_decompress/fuzz.c
new file mode 100644
index 000000000..8cc4ce55c
--- /dev/null
+++ b/util/compress/libdeflate/scripts/afl-fuzz/deflate_decompress/fuzz.c
@@ -0,0 +1,28 @@
+#include <assert.h>
+#include <libdeflate.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+int main(int argc, char **argv)
+{
+ struct libdeflate_decompressor *d;
+ int ret;
+ int fd = open(argv[1], O_RDONLY);
+ struct stat stbuf;
+ assert(fd >= 0);
+ ret = fstat(fd, &stbuf);
+ assert(!ret);
+
+ char in[stbuf.st_size];
+ ret = read(fd, in, sizeof in);
+ assert(ret == sizeof in);
+
+ char out[sizeof(in) * 3];
+
+ d = libdeflate_alloc_decompressor();
+
+ libdeflate_deflate_decompress(d, in, sizeof in, out, sizeof out, NULL);
+ libdeflate_free_decompressor(d);
+ return 0;
+}
diff --git a/util/compress/libdeflate/scripts/afl-fuzz/deflate_decompress/inputs/0 b/util/compress/libdeflate/scripts/afl-fuzz/deflate_decompress/inputs/0
new file mode 100644
index 000000000..19e3a346e
--- /dev/null
+++ b/util/compress/libdeflate/scripts/afl-fuzz/deflate_decompress/inputs/0
@@ -0,0 +1,3 @@
+uŽ1
+Â@EgÅBl5
+‚°VÅÒè6j—«X{i=•èl=€àΟ¬Ñlóßü™?tíÐç½D í¨ò=¯GÑ% ¾©—2xÔ‡7eðD½ÓÐs[ÔиUkÅ÷q¹ |R/åêµùë®°*F¢Mzš¼v°•`ÐÇórÐ1ªóB÷,lDuYj#0<ÅÕž2È0hE`¹øI°ÿìW \ No newline at end of file
diff --git a/util/compress/libdeflate/scripts/afl-fuzz/gzip_decompress/fuzz.c b/util/compress/libdeflate/scripts/afl-fuzz/gzip_decompress/fuzz.c
new file mode 100644
index 000000000..aec50804c
--- /dev/null
+++ b/util/compress/libdeflate/scripts/afl-fuzz/gzip_decompress/fuzz.c
@@ -0,0 +1,28 @@
+#include <assert.h>
+#include <libdeflate.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+int main(int argc, char **argv)
+{
+ struct libdeflate_decompressor *d;
+ int ret;
+ int fd = open(argv[1], O_RDONLY);
+ struct stat stbuf;
+ assert(fd >= 0);
+ ret = fstat(fd, &stbuf);
+ assert(!ret);
+
+ char in[stbuf.st_size];
+ ret = read(fd, in, sizeof in);
+ assert(ret == sizeof in);
+
+ char out[sizeof(in) * 3];
+
+ d = libdeflate_alloc_decompressor();
+
+ libdeflate_gzip_decompress(d, in, sizeof in, out, sizeof out, NULL);
+ libdeflate_free_decompressor(d);
+ return 0;
+}
diff --git a/util/compress/libdeflate/scripts/afl-fuzz/gzip_decompress/inputs/0 b/util/compress/libdeflate/scripts/afl-fuzz/gzip_decompress/inputs/0
new file mode 100644
index 000000000..813c75359
--- /dev/null
+++ b/util/compress/libdeflate/scripts/afl-fuzz/gzip_decompress/inputs/0
Binary files differ
diff --git a/util/compress/libdeflate/scripts/afl-fuzz/prepare_for_fuzz.sh b/util/compress/libdeflate/scripts/afl-fuzz/prepare_for_fuzz.sh
new file mode 100755
index 000000000..06911c18b
--- /dev/null
+++ b/util/compress/libdeflate/scripts/afl-fuzz/prepare_for_fuzz.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+set -e
+
+make -C ../../ clean
+make clean
+AFL_HARDEN=1 make CC=afl-gcc -C ../../
+AFL_HARDEN=1 make CC=afl-gcc
+
+for dir in $(find . -mindepth 1 -maxdepth 1 -type d); do
+ rm -rf /tmp/$dir
+ cp -va $dir /tmp/$dir
+ mkdir -p /tmp/$dir/outputs
+done
diff --git a/util/compress/libdeflate/scripts/afl-fuzz/zlib_decompress/fuzz.c b/util/compress/libdeflate/scripts/afl-fuzz/zlib_decompress/fuzz.c
new file mode 100644
index 000000000..797343bbf
--- /dev/null
+++ b/util/compress/libdeflate/scripts/afl-fuzz/zlib_decompress/fuzz.c
@@ -0,0 +1,28 @@
+#include <assert.h>
+#include <libdeflate.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+int main(int argc, char **argv)
+{
+ struct libdeflate_decompressor *d;
+ int ret;
+ int fd = open(argv[1], O_RDONLY);
+ struct stat stbuf;
+ assert(fd >= 0);
+ ret = fstat(fd, &stbuf);
+ assert(!ret);
+
+ char in[stbuf.st_size];
+ ret = read(fd, in, sizeof in);
+ assert(ret == sizeof in);
+
+ char out[sizeof(in) * 3];
+
+ d = libdeflate_alloc_decompressor();
+
+ libdeflate_zlib_decompress(d, in, sizeof in, out, sizeof out, NULL);
+ libdeflate_free_decompressor(d);
+ return 0;
+}
diff --git a/util/compress/libdeflate/scripts/afl-fuzz/zlib_decompress/inputs/0 b/util/compress/libdeflate/scripts/afl-fuzz/zlib_decompress/inputs/0
new file mode 100644
index 000000000..292e9726d
--- /dev/null
+++ b/util/compress/libdeflate/scripts/afl-fuzz/zlib_decompress/inputs/0
@@ -0,0 +1,3 @@
+xœuŽ1
+Â@EgÅBl5
+‚°VÅÒè6j—«X{i=•èl=€àΟ¬Ñlóßü™?tíÐç½D í¨ò=¯GÑ% ¾©—2xÔ‡7eðD½ÓÐs[ÔиUkÅ÷q¹ |R/åêµùë®°*F¢Mzš¼v°•`ÐÇórÐ1ªóB÷,lDuYj#0<ÅÕž2È0hE`¹øI°ÿìWÂ-© \ No newline at end of file
diff --git a/util/compress/libdeflate/scripts/android_build.sh b/util/compress/libdeflate/scripts/android_build.sh
new file mode 100755
index 000000000..204ead2dc
--- /dev/null
+++ b/util/compress/libdeflate/scripts/android_build.sh
@@ -0,0 +1,108 @@
+#!/bin/bash
+
+set -eu -o pipefail
+
+API_LEVEL=28
+ARCH=arm64
+CFLAGS=
+ENABLE_CRC=false
+ENABLE_CRYPTO=false
+NDKDIR=$HOME/android-ndk-r21d
+
+usage() {
+ cat << EOF
+Usage: $0 [OPTION]... -- [MAKE_TARGET]...
+Build libdeflate for Android.
+
+ --api-level=LEVEL Android API level to target (default: $API_LEVEL)
+ --arch=ARCH Architecture: arm32|arm64 (default: $ARCH)
+ --enable-crc Enable crc instructions
+ --enable-crypto Enable crypto instructions
+ --ndkdir=NDKDIR Android NDK directory (default: $NDKDIR)
+EOF
+}
+if ! options=$(getopt -o '' \
+ -l 'api-level:,arch:,enable-crc,enable-crypto,help,ndkdir:' -- "$@"); then
+ usage 1>&2
+ exit 1
+fi
+
+eval set -- "$options"
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --api-level)
+ API_LEVEL="$2"
+ shift
+ ;;
+ --arch)
+ ARCH="$2"
+ shift
+ ;;
+ --enable-crc)
+ ENABLE_CRC=true
+ ;;
+ --enable-crypto)
+ ENABLE_CRYPTO=true
+ ;;
+ --help)
+ usage
+ exit 0
+ ;;
+ --ndkdir)
+ NDKDIR="$2"
+ shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ *)
+ echo 1>&2 "Unknown option \"$1\""
+ usage 1>&2
+ exit 1
+ esac
+ shift
+done
+
+BINDIR=$NDKDIR/toolchains/llvm/prebuilt/linux-x86_64/bin/
+
+case "$ARCH" in
+arm|arm32|aarch32)
+ CC=$BINDIR/armv7a-linux-androideabi$API_LEVEL-clang
+ if $ENABLE_CRC || $ENABLE_CRYPTO; then
+ CFLAGS="-march=armv8-a"
+ if $ENABLE_CRC; then
+ CFLAGS+=" -mcrc"
+ else
+ CFLAGS+=" -mnocrc"
+ fi
+ if $ENABLE_CRYPTO; then
+ CFLAGS+=" -mfpu=crypto-neon-fp-armv8"
+ else
+ CFLAGS+=" -mfpu=neon"
+ fi
+ fi
+ ;;
+arm64|aarch64)
+ CC=$BINDIR/aarch64-linux-android$API_LEVEL-clang
+ features=""
+ if $ENABLE_CRC; then
+ features+="+crc"
+ fi
+ if $ENABLE_CRYPTO; then
+ features+="+crypto"
+ fi
+ if [ -n "$features" ]; then
+ CFLAGS="-march=armv8-a$features"
+ fi
+ ;;
+*)
+ echo 1>&2 "Unknown architecture: \"$ARCH\""
+ usage 1>&2
+ exit 1
+esac
+
+cmd=(make "-j$(grep -c processor /proc/cpuinfo)" "CC=$CC" "CFLAGS=$CFLAGS" "$@")
+echo "${cmd[*]}"
+"${cmd[@]}"
diff --git a/util/compress/libdeflate/scripts/android_tests.sh b/util/compress/libdeflate/scripts/android_tests.sh
new file mode 100755
index 000000000..fe70ce906
--- /dev/null
+++ b/util/compress/libdeflate/scripts/android_tests.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+#
+# Test libdeflate on a connected arm64 Android device.
+# Requires the Android NDK (release 19 or later) and adb.
+
+set -eu -o pipefail
+cd "$(dirname "$0")/.."
+
+if [ $# -ne 0 ]; then
+ echo 1>&2 "Usage: $0"
+ exit 2
+fi
+
+# Use NDKDIR if specified in environment, else use default value.
+: "${NDKDIR:=$HOME/android-ndk-r21d}"
+if [ ! -e "$NDKDIR" ]; then
+ cat 1>&2 << EOF
+Android NDK was not found in NDKDIR=$NDKDIR! Set the
+environmental variable NDKDIR to the location of your Android NDK installation.
+EOF
+ exit 1
+fi
+
+CLEANUP_CMDS=()
+cleanup() {
+ for cmd in "${CLEANUP_CMDS[@]}"; do
+ eval "$cmd"
+ done
+}
+trap cleanup EXIT
+
+# Use TESTDATA if specified in environment, else generate it.
+if [ -z "${TESTDATA:-}" ]; then
+ # Generate default TESTDATA file.
+ TESTDATA=$(mktemp -t libdeflate_testdata.XXXXXXXXXX)
+ export TESTDATA
+ CLEANUP_CMDS+=("rm -f '$TESTDATA'")
+ find . '(' -name '*.c' -o -name '*.h' -o -name '*.sh' ')' \
+ -exec cat '{}' ';' | head -c 1000000 > "$TESTDATA"
+fi
+
+TMPDIR=$(mktemp -d -t libdeflate_test.XXXXXXXXX)
+CLEANUP_CMDS+=("rm -r '$TMPDIR'")
+
+android_build_and_test() {
+ echo "Running Android tests with $*"
+
+ ./scripts/android_build.sh --ndkdir="$NDKDIR" "$@" \
+ all test_programs > /dev/null
+ adb push "$TESTDATA" ./scripts/exec_tests.sh benchmark test_* \
+ /data/local/tmp/ > /dev/null
+
+ # Note: adb shell always returns 0, even if the shell command fails...
+ adb shell "cd /data/local/tmp && WRAPPER= TESTDATA=$(basename "$TESTDATA") sh exec_tests.sh" \
+ > "$TMPDIR/adb.out"
+ if ! grep -q "exec_tests finished successfully" "$TMPDIR/adb.out"; then
+ echo 1>&2 "Android test failure! adb shell output:"
+ cat "$TMPDIR/adb.out"
+ exit 1
+ fi
+}
+
+for arch in arm32 arm64; do
+ android_build_and_test --arch=$arch
+ android_build_and_test --arch=$arch --enable-crc
+ android_build_and_test --arch=$arch --enable-crypto
+ android_build_and_test --arch=$arch --enable-crc --enable-crypto
+done
+echo "Android tests passed"
diff --git a/util/compress/libdeflate/scripts/checksum_benchmarks.sh b/util/compress/libdeflate/scripts/checksum_benchmarks.sh
new file mode 100755
index 000000000..23b5984eb
--- /dev/null
+++ b/util/compress/libdeflate/scripts/checksum_benchmarks.sh
@@ -0,0 +1,167 @@
+#!/bin/bash
+
+set -eu -o pipefail
+
+have_cpu_feature() {
+ local feature="$1"
+ local tag
+ case $ARCH in
+ arm*|aarch*)
+ tag="Features"
+ ;;
+ *)
+ tag="flags"
+ ;;
+ esac
+ grep -q "^$tag"$'[ \t]'"*:.*\<$feature\>" /proc/cpuinfo
+}
+
+make_and_test() {
+ # Build the checksum program and tests. Set the special test support
+ # flag to get support for LIBDEFLATE_DISABLE_CPU_FEATURES.
+ make "$@" TEST_SUPPORT__DO_NOT_USE=1 checksum test_checksums > /dev/null
+
+ # Run the checksum tests, for good measure. (This isn't actually part
+ # of the benchmarking.)
+ ./test_checksums > /dev/null
+}
+
+__do_benchmark() {
+ local impl="$1" speed
+ shift
+ local flags=("$@")
+
+ speed=$(./checksum "${CKSUM_FLAGS[@]}" "${flags[@]}" -t "$FILE" | \
+ grep -o '[0-9]\+ MB/s' | grep -o '[0-9]\+')
+ printf "%-45s%-10s\n" "$CKSUM_NAME ($impl)" "$speed"
+}
+
+do_benchmark() {
+ local impl="$1"
+
+ if [ "$impl" = zlib ]; then
+ __do_benchmark "$impl" "-Z"
+ else
+ make_and_test CFLAGS="${EXTRA_CFLAGS[*]}"
+ __do_benchmark "libdeflate, $impl"
+ if [ "$ARCH" = x86_64 ]; then
+ make_and_test CFLAGS="-m32 ${EXTRA_CFLAGS[*]}"
+ __do_benchmark "libdeflate, $impl, 32-bit"
+ fi
+ fi
+}
+
+sort_by_speed() {
+ awk '{print $NF, $0}' | sort -nr | cut -f2- -d' '
+}
+
+disable_cpu_feature() {
+ local name="$1"
+ shift
+ local extra_cflags=("$@")
+
+ LIBDEFLATE_DISABLE_CPU_FEATURES+=",$name"
+ EXTRA_CFLAGS+=("${extra_cflags[@]}")
+}
+
+cleanup() {
+ if $USING_TMPFILE; then
+ rm "$FILE"
+ fi
+}
+
+ARCH="$(uname -m)"
+USING_TMPFILE=false
+
+if (( $# > 1 )); then
+ echo "Usage: $0 [FILE]" 1>&2
+ exit 1
+fi
+
+trap cleanup EXIT
+
+if (( $# == 0 )); then
+ # Generate default test data file.
+ FILE=$(mktemp -t checksum_testdata.XXXXXXXXXX)
+ USING_TMPFILE=true
+ echo "Generating 100 MB test file: $FILE"
+ head -c 100000000 /dev/urandom > "$FILE"
+else
+ FILE="$1"
+fi
+
+cat << EOF
+Method Speed (MB/s)
+------ ------------
+EOF
+
+# CRC-32
+CKSUM_NAME="CRC-32"
+CKSUM_FLAGS=()
+EXTRA_CFLAGS=()
+export LIBDEFLATE_DISABLE_CPU_FEATURES=""
+{
+case $ARCH in
+i386|x86_64)
+ if have_cpu_feature pclmulqdq && have_cpu_feature avx; then
+ do_benchmark "PCLMUL/AVX"
+ disable_cpu_feature "avx" "-mno-avx"
+ fi
+ if have_cpu_feature pclmulqdq; then
+ do_benchmark "PCLMUL"
+ disable_cpu_feature "pclmul" "-mno-pclmul"
+ fi
+ ;;
+arm*|aarch*)
+ if have_cpu_feature crc32; then
+ do_benchmark "ARM"
+ disable_cpu_feature "crc32" "-march=armv8-a+nocrc"
+ fi
+ if have_cpu_feature pmull; then
+ do_benchmark "PMULL"
+ disable_cpu_feature "pmull" "-march=armv8-a+nocrc+nocrypto"
+ fi
+ ;;
+esac
+do_benchmark "generic"
+do_benchmark "zlib"
+} | sort_by_speed
+
+# Adler-32
+CKSUM_NAME="Adler-32"
+CKSUM_FLAGS=(-A)
+EXTRA_CFLAGS=()
+export LIBDEFLATE_DISABLE_CPU_FEATURES=""
+echo
+{
+case $ARCH in
+i386|x86_64)
+ if have_cpu_feature avx512bw; then
+ do_benchmark "AVX-512BW"
+ disable_cpu_feature "avx512bw" "-mno-avx512bw"
+ fi
+ if have_cpu_feature avx2; then
+ do_benchmark "AVX2"
+ disable_cpu_feature "avx2" "-mno-avx2"
+ fi
+ if have_cpu_feature sse2; then
+ do_benchmark "SSE2"
+ disable_cpu_feature "sse2" "-mno-sse2"
+ fi
+ ;;
+arm*)
+ if have_cpu_feature neon; then
+ do_benchmark "NEON"
+ disable_cpu_feature "neon" "-mfpu=vfpv3"
+ fi
+ ;;
+aarch*)
+ if have_cpu_feature asimd; then
+ do_benchmark "NEON"
+ disable_cpu_feature "neon" "-march=armv8-a+nosimd"
+ fi
+ ;;
+esac
+do_benchmark "generic"
+do_benchmark "zlib"
+} | sort_by_speed
diff --git a/util/compress/libdeflate/scripts/detect.sh b/util/compress/libdeflate/scripts/detect.sh
new file mode 100755
index 000000000..93064b8b2
--- /dev/null
+++ b/util/compress/libdeflate/scripts/detect.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+set -eu
+
+# Use CC if specified in environment, else default to "cc".
+: "${CC:=cc}"
+
+# Use CFLAGS if specified in environment.
+: "${CFLAGS:=}"
+
+echo "/* THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. */"
+echo "#ifndef CONFIG_H"
+echo "#define CONFIG_H"
+
+program_compiles() {
+ echo "$1" | $CC $CFLAGS -Wno-error -x c - -o /dev/null > /dev/null 2>&1
+}
+
+check_function() {
+ funcname=$1
+ macro="HAVE_$(echo "$funcname" | tr '[:lower:]' '[:upper:]')"
+
+ echo
+ echo "/* Is the $funcname() function available? */"
+ if program_compiles "int main() { $funcname(); }"; then
+ echo "#define $macro 1"
+ else
+ echo "/* $macro is not set */"
+ fi
+}
+
+have_stat_field() {
+ program_compiles "#include <sys/types.h>
+ #include <sys/stat.h>
+ int main() { struct stat st; st.$1; }"
+}
+
+check_stat_nanosecond_precision() {
+ echo
+ echo "/* Does stat() provide nanosecond-precision timestamps? */"
+ if have_stat_field st_atim; then
+ echo "#define HAVE_STAT_NANOSECOND_PRECISION 1"
+ elif have_stat_field st_atimespec; then
+ # Nonstandard field names used by OS X and older BSDs
+ echo "#define HAVE_STAT_NANOSECOND_PRECISION 1"
+ echo "#define st_atim st_atimespec"
+ echo "#define st_mtim st_mtimespec"
+ echo "#define st_ctim st_ctimespec"
+ else
+ echo "/* HAVE_STAT_NANOSECOND_PRECISION is not set */"
+ fi
+}
+
+check_function clock_gettime
+check_function futimens
+check_function futimes
+check_function posix_fadvise
+check_function posix_madvise
+
+check_stat_nanosecond_precision
+
+echo
+echo "#endif /* CONFIG_H */"
diff --git a/util/compress/libdeflate/scripts/exec_tests.sh b/util/compress/libdeflate/scripts/exec_tests.sh
new file mode 100644
index 000000000..c748e423e
--- /dev/null
+++ b/util/compress/libdeflate/scripts/exec_tests.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# Helper script used by run_tests.sh and android_tests.sh,
+# not intended to be run directly
+#
+
+set -eu
+
+run_cmd() {
+ echo "$WRAPPER $*"
+ $WRAPPER "$@" > /dev/null
+}
+
+for prog in ./test_*; do
+ run_cmd "$prog"
+done
+
+for format in '' '-g' '-z'; do
+ for ref_impl in '' '-Y' '-Z'; do
+ run_cmd ./benchmark $format $ref_impl "$TESTDATA"
+ done
+done
+for level in 0 1 3 7 9; do
+ for ref_impl in '' '-Y'; do
+ run_cmd ./benchmark -$level $ref_impl "$TESTDATA"
+ done
+done
+for level in 0 1 3 7 9 12; do
+ for ref_impl in '' '-Z'; do
+ run_cmd ./benchmark -$level $ref_impl "$TESTDATA"
+ done
+done
+
+echo "exec_tests finished successfully" # Needed for 'adb shell'
diff --git a/util/compress/libdeflate/scripts/gen_crc32_multipliers.c b/util/compress/libdeflate/scripts/gen_crc32_multipliers.c
new file mode 100644
index 000000000..c607d73f8
--- /dev/null
+++ b/util/compress/libdeflate/scripts/gen_crc32_multipliers.c
@@ -0,0 +1,108 @@
+/*
+ * gen_crc32_multipliers.c
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+
+/* generator polynomial G(x) */
+#define CRCPOLY 0xEDB88320 /* G(x) without x^32 term */
+#define CRCPOLY_FULL (((uint64_t)CRCPOLY << 1) | 1) /* G(x) */
+
+/* Compute x^D mod G(x) */
+static uint32_t
+compute_multiplier(int D)
+{
+ /* Start with x^0 mod G(x) */
+ uint32_t remainder = 0x80000000;
+
+ /* Each iteration, 'remainder' becomes x^i mod G(x) */
+ for (int i = 1; i <= D; i++)
+ remainder = (remainder >> 1) ^ ((remainder & 1) ? CRCPOLY : 0);
+
+ /* Now 'remainder' is x^D mod G(x) */
+ return remainder;
+}
+
+/* Compute floor(x^64 / G(x)) */
+static uint64_t
+compute_barrett_reduction_constant(void)
+{
+ uint64_t quotient = 0;
+ uint64_t dividend = 0x1;
+
+ for (int i = 0; i < 64 - 32 + 1; i++) {
+ if ((dividend >> i) & 1) {
+ quotient |= (uint64_t)1 << i;
+ dividend ^= CRCPOLY_FULL << i;
+ }
+ }
+
+ return quotient;
+}
+
+/*
+ * This program computes the constant multipliers needed for carryless
+ * multiplication accelerated CRC-32. It assumes 128-bit vectors divided into
+ * two 64-bit halves which are multiplied separately with different 32-bit
+ * multipliers, producing two 95-bit products. For a given number of 128-bit
+ * vectors per iteration, the program outputs a pair of multipliers, one for
+ * each 64-bit half.
+ *
+ * Careful: all polynomials are "bit-reversed", meaning that the low-order bits
+ * have the highest degree and the high-order bits have the lowest degree!
+ */
+int
+main(void)
+{
+ printf("\t/* Constants precomputed by gen_crc32_multipliers.c. "
+ "Do not edit! */\n");
+
+ /* High and low multipliers for each needed vector count */
+ for (int order = 2; order >= 0; order--) {
+ int vecs_per_iteration = 1 << order;
+ int right = (128 * vecs_per_iteration) + 95;
+ printf("\tconst __v2di multipliers_%d = (__v2di)"
+ "{ 0x%08"PRIX32", 0x%08"PRIX32" };\n",
+ vecs_per_iteration,
+ compute_multiplier(right - 64) /* higher degree half */,
+ compute_multiplier(right - 128) /* lower degree half */);
+ }
+
+ /* Multiplier for final 96 => 64 bit fold */
+ printf("\tconst __v2di final_multiplier = (__v2di){ 0x%08"PRIX32" };\n",
+ compute_multiplier(63));
+
+ /* 32-bit mask */
+ printf("\tconst __m128i mask32 = (__m128i)(__v4si){ 0xFFFFFFFF };\n");
+
+ /* Constants for final 64 => 32 bit reduction */
+ printf("\tconst __v2di barrett_reduction_constants =\n"
+ "\t\t\t(__v2di){ 0x%016"PRIX64", 0x%016"PRIX64" };\n",
+ compute_barrett_reduction_constant(), CRCPOLY_FULL);
+
+ return 0;
+}
diff --git a/util/compress/libdeflate/scripts/gen_crc32_table.c b/util/compress/libdeflate/scripts/gen_crc32_table.c
new file mode 100644
index 000000000..ab39376a7
--- /dev/null
+++ b/util/compress/libdeflate/scripts/gen_crc32_table.c
@@ -0,0 +1,100 @@
+/*
+ * gen_crc32_table.c - a program for CRC-32 table generation
+ *
+ * Originally public domain; changes after 2016-09-07 are copyrighted.
+ *
+ * Copyright 2016 Eric Biggers
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+
+static uint32_t crc32_table[0x800];
+
+static uint32_t
+crc32_update_bit(uint32_t remainder, uint8_t next_bit)
+{
+ return (remainder >> 1) ^
+ (((remainder ^ next_bit) & 1) ? 0xEDB88320 : 0);
+}
+
+static uint32_t
+crc32_update_byte(uint32_t remainder, uint8_t next_byte)
+{
+ for (int j = 0; j < 8; j++, next_byte >>= 1)
+ remainder = crc32_update_bit(remainder, next_byte & 1);
+ return remainder;
+}
+
+static void
+print_256_entries(const uint32_t *entries)
+{
+ for (size_t i = 0; i < 256 / 4; i++) {
+ printf("\t");
+ for (size_t j = 0; j < 4; j++) {
+ printf("0x%08x,", entries[i * 4 + j]);
+ if (j != 3)
+ printf(" ");
+ }
+ printf("\n");
+ }
+}
+
+int
+main(void)
+{
+ /* crc32_table[i] for 0 <= i < 0x100 is the CRC-32 of byte i. */
+ for (int i = 0; i < 0x100; i++)
+ crc32_table[i] = crc32_update_byte(0, i);
+
+ /* crc32_table[i] for 0x100 <= i < 0x800 is the CRC-32 of byte i % 0x100
+ * followed by i / 0x100 zero bytes. */
+ for (int i = 0x100; i < 0x800; i++)
+ crc32_table[i] = crc32_update_byte(crc32_table[i - 0x100], 0);
+
+ printf("/*\n");
+ printf(" * crc32_table.h - data table to accelerate CRC-32 computation\n");
+ printf(" *\n");
+ printf(" * THIS FILE WAS AUTOMATICALLY GENERATED "
+ "BY gen_crc32_table.c. DO NOT EDIT.\n");
+ printf(" */\n");
+ printf("\n");
+ printf("#include <stdint.h>\n");
+ printf("\n");
+ printf("static const uint32_t crc32_table[] = {\n");
+ print_256_entries(&crc32_table[0x000]);
+ printf("#if defined(CRC32_SLICE4) || defined(CRC32_SLICE8)\n");
+ print_256_entries(&crc32_table[0x100]);
+ print_256_entries(&crc32_table[0x200]);
+ print_256_entries(&crc32_table[0x300]);
+ printf("#endif /* CRC32_SLICE4 || CRC32_SLICE8 */\n");
+ printf("#if defined(CRC32_SLICE8)\n");
+ print_256_entries(&crc32_table[0x400]);
+ print_256_entries(&crc32_table[0x500]);
+ print_256_entries(&crc32_table[0x600]);
+ print_256_entries(&crc32_table[0x700]);
+ printf("#endif /* CRC32_SLICE8 */\n");
+ printf("};\n");
+ return 0;
+}
diff --git a/util/compress/libdeflate/scripts/gzip_tests.sh b/util/compress/libdeflate/scripts/gzip_tests.sh
new file mode 100755
index 000000000..58fe325bb
--- /dev/null
+++ b/util/compress/libdeflate/scripts/gzip_tests.sh
@@ -0,0 +1,490 @@
+#!/bin/bash
+#
+# Test script for libdeflate's gzip and gunzip programs.
+#
+# To run, you must set GZIP and GUNZIP in the environment to the absolute paths
+# to the gzip and gunzip programs to test. All tests should pass regardless of
+# whether the GNU versions or the libdeflate versions, or a combination, of
+# these programs are used.
+#
+# The environmental variable TESTDATA must also be set to a file containing
+# test data.
+#
+
+set -eu -o pipefail
+
+export -n GZIP GUNZIP TESTDATA
+
+TMPDIR="$(mktemp -d)"
+CURRENT_TEST=
+
+cleanup() {
+ if [ -n "$CURRENT_TEST" ]; then
+ echo "TEST FAILED: \"$CURRENT_TEST\""
+ fi
+ rm -rf -- "$TMPDIR"
+}
+
+trap cleanup EXIT
+
+TESTDATA="$(readlink -f "$TESTDATA")"
+cd "$TMPDIR"
+
+begin_test() {
+ CURRENT_TEST="$1"
+ rm -rf -- "${TMPDIR:?}"/*
+ cp "$TESTDATA" file
+}
+
+gzip() {
+ $GZIP "$@"
+}
+
+gunzip() {
+ $GUNZIP "$@"
+}
+
+assert_status() {
+ local expected_status="$1"
+ local expected_msg="$2"
+ shift 2
+ (
+ set +e
+ { eval "$*" > /dev/null; } 2>&1
+ local actual_status=$?
+ if [ "$actual_status" != "$expected_status" ]; then
+ echo 1>&2 "Command '$*' exited with status" \
+ "$actual_status but expected status" \
+ "$expected_status"
+ exit 1
+ fi
+ exit 0
+ ) > command_output
+ if ! grep -E -q "$expected_msg" command_output; then
+ echo 1>&2 "Expected output of command '$*' to match regex" \
+ "'$expected_msg'"
+ echo 1>&2 "Actual output was:"
+ echo 1>&2 "---------------------------------------------------"
+ cat 1>&2 command_output
+ echo 1>&2 "---------------------------------------------------"
+ return 1
+ fi
+}
+
+assert_error() {
+ assert_status 1 "$@"
+}
+
+assert_warning() {
+ assert_status 2 "$@"
+}
+
+assert_skipped() {
+ assert_warning '\<(ignored|skipping|unchanged)\>' "$@"
+}
+
+assert_equals() {
+ local expected="$1"
+ local actual="$2"
+
+ if [ "$expected" != "$actual" ]; then
+ echo 1>&2 "Expected '$expected', but got '$actual'"
+ return 1
+ fi
+}
+
+# Get the filesystem type.
+FSTYPE=$(df -T . | tail -1 | awk '{print $2}')
+
+# If gzip or gunzip is the GNU version, require that it supports the '-k'
+# option. This option was added in v1.6, released in 2013.
+check_version_prereq() {
+ local prog=$1
+
+ if ! echo | { $prog -k || true; } |& grep -q 'invalid option'; then
+ return 0
+ fi
+ if ! $prog -V |& grep -q 'Free Software Foundation'; then
+ echo 1>&2 "Unexpected case: not GNU $prog, but -k option is invalid"
+ exit 1
+ fi
+ echo "GNU $prog is too old; skipping gzip/gunzip tests"
+ exit 0
+}
+check_version_prereq gzip
+check_version_prereq gunzip
+
+begin_test 'Basic compression and decompression works'
+cp file orig
+gzip file
+[ ! -e file ] && [ -e file.gz ]
+gunzip file.gz
+[ -e file ] && [ ! -e file.gz ]
+cmp file orig
+
+
+begin_test 'gzip -d is gunzip'
+cp file orig
+gzip file
+gzip -d file.gz
+cmp file orig
+
+
+begin_test '-k (keep original file) works'
+cp file orig
+gzip -k file
+cmp file orig
+rm file
+cp file.gz orig.gz
+gunzip -k file.gz
+cmp file.gz orig.gz
+
+
+begin_test '-c (write to stdout) works'
+cp file orig
+gzip -k file
+gzip -c file > 2.gz
+cmp file orig
+cmp file.gz 2.gz
+gunzip -c 2.gz > file
+cmp file.gz 2.gz
+cmp file orig
+
+
+# Note: in some of the commands below, we intentionally use 'cat file | gzip'
+# rather than 'gzip < file', in order to test the use of a pipe. This produces
+# a shellcheck warning about 'cat' being unnecessary. Suppress that warning by
+# using { cat file; true; }.
+begin_test 'Reading from stdin works'
+gzip < file > 1.gz
+gzip - < file > 2.gz
+{ cat file; true; } | gzip > 3.gz
+{ cat file; true; } | gzip - > 4.gz
+cmp file <(gunzip < 1.gz)
+cmp file <(gunzip - < 2.gz)
+cmp file <({ cat 3.gz; true; } | gunzip)
+cmp file <({ cat 4.gz; true; } | gunzip -)
+
+
+begin_test '-n option is accepted'
+gzip -n file
+gunzip -n file.gz
+
+
+begin_test 'can specify multiple options'
+gzip -fk1 file
+cmp <(gzip -c -1 file) file.gz
+gunzip -kfd file.gz
+
+
+begin_test 'Compression levels'
+if [ "$GZIP" = /bin/gzip ]; then
+ assert_error '\<invalid option\>' gzip -10
+ max_level=9
+else
+ for level in 13 99999 1a; do
+ assert_error '\<Invalid compression level\>' gzip -$level
+ done
+ max_level=12
+fi
+for level in $(seq 1 $max_level); do
+ gzip -c "-$level" file > "file$level"
+ cmp file <(gunzip -c "file$level")
+done
+rm file command_output
+
+
+begin_test 'Overwriting output file requires -f'
+cp file orig
+echo -n > file.gz
+gzip -c file > 2.gz
+assert_warning 'already exists' gzip file </dev/null
+cmp file.gz /dev/null
+gzip -f file
+cmp 2.gz file.gz
+echo -n > file
+assert_warning 'already exists' gunzip file.gz </dev/null
+gunzip -f file.gz
+cmp file orig
+
+
+begin_test 'Nonexistent input file fails, even with -f'
+for prog in 'gzip' 'gzip -f' 'gunzip' 'gunzip -f'; do
+ assert_error 'No such file or directory' "$prog" NONEXISTENT
+done
+
+
+begin_test 'Compressing already-suffixed file requires -f or -c'
+gzip file
+gzip -c file.gz > c.gz
+gzip file.gz 2>&1 >/dev/null | grep -q 'already has .gz suffix'
+[ -e file.gz ] && [ ! -e file.gz.gz ]
+gzip -f file.gz
+[ ! -e file.gz ] && [ -e file.gz.gz ]
+cmp file.gz.gz c.gz
+
+
+begin_test 'Decompressing unsuffixed file only works with -c'
+gzip file && mv file.gz file
+assert_skipped gunzip file
+assert_skipped gunzip -f file
+gunzip -c file > orig
+mv file file.gz && gunzip file.gz && cmp file orig
+
+
+begin_test '... unless there is a corresponding suffixed file'
+cp file orig
+gzip file
+[ ! -e file ] && [ -e file.gz ]
+gunzip -c file > tmp
+cmp tmp orig
+rm tmp
+ln -s NONEXISTENT file
+gunzip -c file > tmp
+cmp tmp orig
+rm tmp file
+gunzip file
+[ -e file ] && [ ! -e file.gz ]
+cmp file orig
+
+
+begin_test 'Directory is skipped, even with -f'
+mkdir dir
+mkdir dir.gz
+for opt in '' '-f' '-c'; do
+ assert_skipped gzip $opt dir
+done
+#assert_skipped gzip dir.gz # XXX: GNU gzip warns, libdeflate gzip no-ops
+for opt in '' '-f' '-c'; do
+ for name in dir dir.gz; do
+ assert_skipped gunzip $opt $name
+ done
+done
+
+
+begin_test '(gzip) symlink is rejected without -f or -c'
+ln -s file symlink1
+ln -s file symlink2
+assert_error 'Too many levels of symbolic links' gzip symlink1
+[ -e file ] && [ -e symlink1 ] && [ ! -e symlink1.gz ]
+gzip -f symlink1
+[ -e file ] && [ ! -e symlink1 ] && [ -e symlink1.gz ]
+gzip -c symlink2 > /dev/null
+
+
+begin_test '(gunzip) symlink is rejected without -f or -c'
+gzip file
+ln -s file.gz symlink1.gz
+ln -s file.gz symlink2.gz
+assert_error 'Too many levels of symbolic links' gunzip symlink1
+[ -e file.gz ] && [ -e symlink1.gz ] && [ ! -e symlink1 ]
+gunzip -f symlink1.gz
+[ -e file.gz ] && [ ! -e symlink1.gz ] && [ -e symlink1 ]
+gunzip -c symlink2.gz > /dev/null
+
+
+begin_test 'FIFO is skipped, even with -f'
+mkfifo foo
+mkfifo foo.gz
+assert_skipped gzip foo
+assert_skipped gzip -f foo
+#assert_skipped gzip -c foo # XXX: works with GNU gzip, not libdeflate's
+assert_skipped gunzip foo.gz
+assert_skipped gunzip -f foo.gz
+#assert_skipped gunzip -c foo.gz # XXX: works with GNU gzip, not libdeflate's
+
+
+begin_test '(gzip) overwriting symlink does not follow symlink'
+echo a > a
+echo b > b
+gzip a
+ln -s a.gz b.gz
+gzip -f b
+gunzip a.gz
+cmp <(echo a) a
+
+
+begin_test '(gunzip) overwriting symlink does not follow symlink'
+echo a > a
+echo b > b
+gzip b
+ln -s a b
+gunzip -f b.gz
+cmp <(echo a) a
+cmp <(echo b) b
+
+
+begin_test '(gzip) hard linked file skipped without -f or -c'
+cp file orig
+ln file link
+assert_equals 2 "$(stat -c %h file)"
+assert_skipped gzip file
+gzip -c file > /dev/null
+assert_equals 2 "$(stat -c %h file)"
+gzip -f file
+assert_equals 1 "$(stat -c %h link)"
+assert_equals 1 "$(stat -c %h file.gz)"
+cmp link orig
+# XXX: GNU gzip skips hard linked files with -k, libdeflate's doesn't
+
+
+begin_test '(gunzip) hard linked file skipped without -f or -c'
+gzip file
+ln file.gz link.gz
+cp file.gz orig.gz
+assert_equals 2 "$(stat -c %h file.gz)"
+assert_skipped gunzip file.gz
+gunzip -c file.gz > /dev/null
+assert_equals 2 "$(stat -c %h file.gz)"
+gunzip -f file
+assert_equals 1 "$(stat -c %h link.gz)"
+assert_equals 1 "$(stat -c %h file)"
+cmp link.gz orig.gz
+
+
+begin_test 'Multiple files'
+cp file file2
+gzip file file2
+[ ! -e file ] && [ ! -e file2 ] && [ -e file.gz ] && [ -e file2.gz ]
+gunzip file.gz file2.gz
+[ -e file ] && [ -e file2 ] && [ ! -e file.gz ] && [ ! -e file2.gz ]
+
+
+begin_test 'Multiple files, continue on warning'
+mkdir 1
+cp file 2
+assert_skipped gzip 1 2
+[ ! -e 1.gz ]
+cmp file <(gunzip -c 2.gz)
+rmdir 1
+mkdir 1.gz
+assert_skipped gunzip 1.gz 2.gz
+[ ! -e 1 ]
+cmp 2 file
+
+
+if (( $(id -u) != 0 )); then
+ begin_test 'Multiple files, continue on error'
+ cp file 1
+ cp file 2
+ chmod a-r 1
+ assert_error 'Permission denied' gzip 1 2
+ [ ! -e 1.gz ]
+ cmp file <(gunzip -c 2.gz)
+ rm -f 1
+ cp 2.gz 1.gz
+ chmod a-r 1.gz
+ assert_error 'Permission denied' gunzip 1.gz 2.gz
+ [ ! -e 1 ]
+ cmp 2 file
+fi
+
+
+begin_test 'Compressing empty file'
+echo -n > empty
+gzip empty
+gunzip empty.gz
+cmp /dev/null empty
+
+
+begin_test 'Decompressing malformed file'
+echo -n > foo.gz
+assert_error '\<(not in gzip format|unexpected end of file)\>' \
+ gunzip foo.gz
+echo 1 > foo.gz
+assert_error '\<not in gzip format\>' gunzip foo.gz
+echo abcdefgh > foo.gz
+assert_error '\<not in gzip format\>' gunzip foo.gz
+echo -ne '\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4b\x4c\x4a\x4e\x49\x24\x16\x73\x01\x00\x6c\x5b\xa2\x62\x2e\x00\x00\x00' \
+ > foo.gz
+assert_error '\<(not in gzip format|crc error)\>' gunzip foo.gz
+
+
+for suf in .foo foo .blaaaaaaaaaaaaaaaargh; do
+ begin_test "Custom suffix: $suf"
+ gzip -S $suf file
+ [ ! -e file ] && [ ! -e file.gz ] && [ -e file$suf ]
+ assert_skipped gunzip file$suf
+ gunzip -S $suf file$suf
+ [ -e file ] && [ ! -e file.gz ] && [ ! -e file$suf ]
+done
+# DIFFERENCE: GNU gzip lower cases suffix, we don't
+
+
+begin_test 'Empty suffix is rejected'
+assert_error '\<invalid suffix\>' gzip -S '""' file
+assert_error '\<invalid suffix\>' gunzip -S '""' file
+
+
+begin_test 'Timestamps and mode are preserved'
+if [ "$FSTYPE" = shiftfs ]; then
+ # In Travis CI, the filesystem (shiftfs) only supports seconds precision
+ # timestamps. Nanosecond precision still sometimes seems to work,
+ # probably due to caching, but it is unreliable.
+ format='%a;%X;%Y'
+else
+ format='%a;%x;%y'
+fi
+chmod 777 file
+orig_stat="$(stat -c "$format" file)"
+gzip file
+sleep 1
+gunzip file.gz
+assert_equals "$orig_stat" "$(stat -c "$format" file)"
+
+
+begin_test 'Decompressing multi-member gzip file'
+cat file file > orig
+gzip -c file > file.gz
+gzip -c file >> file.gz
+gunzip -f file.gz
+cmp file orig
+
+
+begin_test 'Decompressing multi-member gzip file (final member smaller)'
+echo 'hello world' > hello
+cat file hello > orig
+gzip -c file > file.gz
+gzip -c hello >> file.gz
+gunzip -f file.gz
+cmp file orig
+
+
+begin_test 'Help option'
+gzip -h 2>&1 | grep -q 'Usage'
+gunzip -h 2>&1 | grep -q 'Usage'
+
+
+begin_test 'Incorrect usage'
+for prog in gzip gunzip; do
+ for opt in '--invalid-option' '-0'; do
+ assert_error '\<(unrecognized|invalid) option\>' $prog $opt
+ done
+done
+
+
+begin_test '-t (test) option works'
+good_files=(
+'H4sIAAAAAAAAA3PMSVTITVTIzi9JVABTIJ5jzpGZelwAX+86ehsAAAA='
+'H4sIAAAAAAAAAwvJSFUoLM1MzlZIKsovz1NIy69QyCrNLShWyC9LLVIoAUrnJFZVKqTkp+txAQBqzFDrLQAAAA==')
+bad_files=(
+'H4sIAO1YYmAAA3PMSVTITVTIzi9JVABTIJ5jzpGZelwAX+46ehsAAAA='
+'H4sIAO1YYmAAA3PMSVTITVTIzi85VABTIJ5jzpGZelwAX+86ehsAAAA='
+'H4sIAAAAAAAAA3PMSVTITVTIzi9JVABTIJ5jzpGZelwAX+86ehsBAAA='
+'H4sIAAAAAAAAAwvJSFUoLM1MzlZIKsovz1NIy69QyCrNLShWyC9LLVIogUrnJFZVKqTkp+txAQBqzFDrLQAAAA=='
+'H4sIAAAAAAAAAwvJSFUoLM1MzlZIKsovz1NIy69QyCrNLShWyC9L')
+for contents in "${good_files[@]}"; do
+ echo "$contents" | base64 -d | gzip -t
+done
+for contents in "${bad_files[@]}"; do
+ echo "$contents" | base64 -d > file
+ assert_error '\<invalid compressed data|file corrupt|unexpected end of file|Out of memory\>' \
+ gzip -t file
+done
+
+
+begin_test 'Version information'
+gzip -V | grep -q Copyright
+gunzip -V | grep -q Copyright
+
+CURRENT_TEST=
diff --git a/util/compress/libdeflate/scripts/make-windows-releases.sh b/util/compress/libdeflate/scripts/make-windows-releases.sh
new file mode 100755
index 000000000..1c143e106
--- /dev/null
+++ b/util/compress/libdeflate/scripts/make-windows-releases.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+set -eu -o pipefail
+
+for arch in 'i686' 'x86_64'; do
+ make clean
+ make -j CC=${arch}-w64-mingw32-gcc CFLAGS="-Werror" all \
+ benchmark.exe checksum.exe
+ dir=libdeflate-$(git describe --tags | tr -d v)-windows-${arch}-bin
+ rm -rf "$dir" "$dir.zip"
+ mkdir "$dir"
+ cp libdeflate.{dll,lib,def} libdeflatestatic.lib libdeflate.h ./*.exe \
+ "$dir"
+ ${arch}-w64-mingw32-strip "$dir/libdeflate.dll" "$dir"/*.exe
+ for file in COPYING NEWS; do
+ sed < $file > "$dir/${file}.txt" -e 's/$/\r/g'
+ done
+ sed < README.md > "$dir/README.md" -e 's/$/\r/g'
+ (cd "$dir" && zip -r "../${dir}.zip" .)
+done
diff --git a/util/compress/libdeflate/scripts/msc_test.bat b/util/compress/libdeflate/scripts/msc_test.bat
new file mode 100755
index 000000000..f5e44bd09
--- /dev/null
+++ b/util/compress/libdeflate/scripts/msc_test.bat
@@ -0,0 +1,3 @@
+nmake /f Makefile.msc clean
+nmake /f Makefile.msc
+copy /y *.exe j:\exe\
diff --git a/util/compress/libdeflate/scripts/pgo_build.sh b/util/compress/libdeflate/scripts/pgo_build.sh
new file mode 100755
index 000000000..2eb2b2311
--- /dev/null
+++ b/util/compress/libdeflate/scripts/pgo_build.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+# Try gcc profile-guided optimizations
+
+set -eu
+
+MAKE="make -j$(grep -c processor /proc/cpuinfo)"
+DATAFILE="$HOME/data/silesia"
+
+$MAKE benchmark > /dev/null
+echo "====================="
+echo "Original performance:"
+echo "---------------------"
+./benchmark "$@" "$DATAFILE"
+
+$MAKE CFLAGS=-fprofile-generate LDFLAGS=-fprofile-generate benchmark > /dev/null
+./benchmark "$@" "$DATAFILE" > /dev/null
+$MAKE CFLAGS=-fprofile-use benchmark > /dev/null
+rm -f {lib,programs}/*.gcda
+echo "=========================="
+echo "PGO-optimized performance:"
+echo "--------------------------"
+./benchmark "$@" "$DATAFILE"
diff --git a/util/compress/libdeflate/scripts/produce_gzip_benchmark_table.sh b/util/compress/libdeflate/scripts/produce_gzip_benchmark_table.sh
new file mode 100755
index 000000000..03fc927e5
--- /dev/null
+++ b/util/compress/libdeflate/scripts/produce_gzip_benchmark_table.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+set -eu -o pipefail
+topdir="$(dirname "$0")/.."
+
+do_benchmark() {
+ "$topdir/benchmark" -g -s "$(stat -c %s "$file")" "$@" "$file" \
+ | grep Compressed | cut -f 4 -d ' '
+}
+
+echo "File | zlib -6 | zlib -9 | libdeflate -6 | libdeflate -9 | libdeflate -12"
+echo "-----|---------|---------|---------------|---------------|---------------"
+
+for file in "$@"; do
+ echo -n "$(basename "$file")"
+ results=()
+ results+=("$(do_benchmark -Y -6)")
+ results+=("$(do_benchmark -Y -9)")
+ results+=("$(do_benchmark -6)")
+ results+=("$(do_benchmark -9)")
+ results+=("$(do_benchmark -12)")
+ best=2000000000
+ for result in "${results[@]}"; do
+ if (( result < best)); then
+ best=$result
+ fi
+ done
+ for result in "${results[@]}"; do
+ if (( result == best )); then
+ em="**"
+ else
+ em=""
+ fi
+ echo -n " | ${em}${result}${em}"
+ done
+ echo
+done
diff --git a/util/compress/libdeflate/scripts/run_tests.sh b/util/compress/libdeflate/scripts/run_tests.sh
new file mode 100755
index 000000000..bdfd139b2
--- /dev/null
+++ b/util/compress/libdeflate/scripts/run_tests.sh
@@ -0,0 +1,329 @@
+#!/bin/bash
+#
+# Test script for libdeflate
+
+set -eu -o pipefail
+cd "$(dirname "$0")/.."
+
+if [ $# -ne 0 ]; then
+ echo 1>&2 "Usage: $0"
+ exit 2
+fi
+
+# Use CC if specified in environment, else default to "cc".
+: "${CC:=cc}"
+
+# Use CFLAGS if specified in environment.
+: "${CFLAGS:=}"
+
+CLEANUP_CMDS=()
+cleanup() {
+ for cmd in "${CLEANUP_CMDS[@]}"; do
+ eval "$cmd"
+ done
+}
+trap cleanup EXIT
+
+# Use TESTDATA if specified in environment, else generate it.
+if [ -z "${TESTDATA:-}" ]; then
+ # Generate default TESTDATA file.
+ TESTDATA=$(mktemp -t libdeflate_testdata.XXXXXXXXXX)
+ export TESTDATA
+ CLEANUP_CMDS+=("rm -f '$TESTDATA'")
+ find . '(' -name '*.c' -o -name '*.h' -o -name '*.sh' ')' \
+ -exec cat '{}' ';' | head -c 1000000 > "$TESTDATA"
+fi
+
+TMPDIR=$(mktemp -d -t libdeflate_test.XXXXXXXXX)
+CLEANUP_CMDS+=("rm -r '$TMPDIR'")
+
+MAKE="make -j$(getconf _NPROCESSORS_ONLN)"
+
+CC_VERSION=$($CC --version | head -1)
+
+ARCH=$(uname -m)
+
+for skip in SKIP_FREESTANDING SKIP_VALGRIND SKIP_UBSAN SKIP_ASAN SKIP_CFI \
+ SKIP_SHARED_LIB; do
+ if [ "${!skip:-}" = "1" ]; then
+ eval $skip=true
+ else
+ eval $skip=false
+ fi
+done
+
+###############################################################################
+
+INDENT=0
+
+log() {
+ echo -n "[$(date)] "
+ head -c $(( INDENT * 4 )) /dev/zero | tr '\0' ' '
+ echo "$@"
+}
+
+begin() {
+ log "$@"
+ (( INDENT++ )) || true
+}
+
+end() {
+ (( INDENT-- )) || true
+}
+
+run_cmd() {
+ log "$@"
+ "$@" > /dev/null
+}
+
+fail() {
+ echo 1>&2 "$@"
+ exit 1
+}
+
+file_count() {
+ local dir=$1
+
+ find "$dir" -type f -o -type l | wc -l
+}
+
+cflags_supported() {
+ # -Werror is needed here in order for old versions of clang to reject
+ # invalid options.
+ echo 'int main(void){ return 0; }' \
+ | $CC $CFLAGS "$@" -Werror -x c - -o /dev/null 2>/dev/null
+}
+
+valgrind_version_at_least() {
+ local want_vers=$1
+ local vers
+
+ vers=$(valgrind --version | grep -E -o '[0-9\.]+' | head -1)
+
+ [ "$want_vers" = "$(echo -e "$vers\n$want_vers" | sort -V | head -1)" ]
+}
+
+build_and_run_tests() {
+ local quick=false
+ if [ "${1:-}" = "--quick" ]; then
+ quick=true
+ shift
+ fi
+
+ begin "CC=$CC CFLAGS=\"$CFLAGS\" WRAPPER=\"$WRAPPER\" $*"
+
+ # Build libdeflate, including the test programs. Set the special test
+ # support flag to get support for LIBDEFLATE_DISABLE_CPU_FEATURES.
+ $MAKE "$@" TEST_SUPPORT__DO_NOT_USE=1 all test_programs > /dev/null
+
+ # When not using -march=native, run the tests multiple times with
+ # different combinations of CPU features disabled. This is needed to
+ # test all variants of dynamically-dispatched code.
+ #
+ # For now, we aren't super exhausive in which combinations of features
+ # we test disabling. We just disable the features roughly in order from
+ # newest to oldest for each architecture, cumulatively. In practice,
+ # that's good enough to cover all the code.
+ local features=('')
+ if ! [[ "$CFLAGS" =~ "-march=native" ]] && ! $quick; then
+ case "$ARCH" in
+ i386|x86_64)
+ features+=(avx512bw avx2 avx bmi2 pclmul sse2)
+ ;;
+ arm*|aarch*)
+ features+=(crc32 pmull neon)
+ ;;
+ esac
+ fi
+ local disable_str=""
+ local feature
+ for feature in "${features[@]}"; do
+ if [ -n "$feature" ]; then
+ if [ -n "$disable_str" ]; then
+ disable_str+=","
+ fi
+ disable_str+="$feature"
+ fi
+ log "Using LIBDEFLATE_DISABLE_CPU_FEATURES=$disable_str"
+ LIBDEFLATE_DISABLE_CPU_FEATURES="$disable_str" \
+ sh ./scripts/exec_tests.sh > /dev/null
+ done
+ end
+}
+
+verify_freestanding_build() {
+ # It is expected that sanitizer builds link to external functions.
+ if [[ "$CFLAGS" =~ "-fsanitize" ]]; then
+ return 0
+ fi
+ log "Verifying that freestanding build is really freestanding"
+ if nm libdeflate.so | grep -q ' U '; then
+ echo 1>&2 "Freestanding lib links to external functions!:"
+ nm libdeflate.so | grep ' U '
+ return 1
+ fi
+ if ldd libdeflate.so | grep -q -v '\<statically linked\>'; then
+ echo 1>&2 "Freestanding lib links to external libraries!:"
+ ldd libdeflate.so
+ return 1
+ fi
+}
+
+gzip_tests() {
+ local gzips=("$PWD/gzip")
+ local gunzips=("$PWD/gunzip")
+ if [ "${1:-}" != "--quick" ]; then
+ gzips+=(/bin/gzip)
+ gunzips+=(/bin/gunzip)
+ fi
+ local gzip gunzip
+
+ begin "Running gzip program tests with CC=\"$CC\" CFLAGS=\"$CFLAGS\""
+ $MAKE gzip gunzip > /dev/null
+ for gzip in "${gzips[@]}"; do
+ for gunzip in "${gunzips[@]}"; do
+ log "GZIP=$gzip, GUNZIP=$gunzip"
+ GZIP="$gzip" GUNZIP="$gunzip" TESTDATA="$TESTDATA" \
+ ./scripts/gzip_tests.sh
+ done
+ done
+ end
+}
+
+do_run_tests() {
+ build_and_run_tests "$@"
+ if [ "${1:-}" != "--quick" ]; then
+ if $SKIP_FREESTANDING; then
+ log "Skipping freestanding build tests due to SKIP_FREESTANDING=1"
+ else
+ build_and_run_tests FREESTANDING=1
+ verify_freestanding_build
+ fi
+ fi
+ gzip_tests "$@"
+}
+
+check_symbol_prefixes() {
+ log "Checking that all global symbols are prefixed with \"libdeflate_\""
+ $MAKE libdeflate.a > /dev/null
+ if nm libdeflate.a | grep ' T ' | grep -E -v " _?libdeflate_"; then
+ fail "Some global symbols aren't prefixed with \"libdeflate_\""
+ fi
+ log "Checking that all exported symbols are prefixed with \"libdeflate\""
+ $MAKE libdeflate.so > /dev/null
+ if nm libdeflate.so | grep ' T ' \
+ | grep -E -v " (libdeflate_|_init\>|_fini\>)"; then
+ fail "Some exported symbols aren't prefixed with \"libdeflate_\""
+ fi
+}
+
+test_use_shared_lib() {
+ if $SKIP_SHARED_LIB; then
+ log "Skipping USE_SHARED_LIB=1 tests due to SKIP_SHARED_LIB=1"
+ return
+ fi
+ log "Testing USE_SHARED_LIB=1"
+ $MAKE gzip > /dev/null
+ if ldd gzip | grep -q 'libdeflate.so'; then
+ fail "Binary should be statically linked by default"
+ fi
+ $MAKE USE_SHARED_LIB=1 all check > /dev/null
+ ldd gzip > "$TMPDIR/ldd.out"
+ if ! grep -q 'libdeflate.so' "$TMPDIR/ldd.out"; then
+ cat 1>&2 "$TMPDIR/ldd.out"
+ fail "Binary isn't dynamically linked"
+ fi
+ rm "$TMPDIR/ldd.out"
+}
+
+install_uninstall_tests() {
+ local shell
+
+ begin "Testing 'make install' and 'make uninstall'"
+ for shell in '/bin/bash' '/bin/dash'; do
+ log "Trying SHELL=$shell"
+ $MAKE SHELL=$shell clean > /dev/null
+ $MAKE SHELL=$shell DESTDIR="$TMPDIR/inst" install > /dev/null
+ if (( "$(file_count "$TMPDIR/inst")" == 0 )); then
+ fail "'make install' didn't install any files"
+ fi
+ make SHELL=$shell DESTDIR="$TMPDIR/inst" uninstall > /dev/null
+ if (( "$(file_count "$TMPDIR/inst")" != 0 )); then
+ fail "'make uninstall' didn't uninstall all files"
+ fi
+ rm -r "$TMPDIR/inst"
+ done
+ end
+}
+
+run_tests() {
+ export WRAPPER="" # no wrapper by default; overridden by valgrind tests
+ local cflags
+
+ begin "Running tests"
+ do_run_tests
+ end
+
+ cflags=("-O3")
+ if cflags_supported "${cflags[@]}" "-march=native"; then
+ cflags+=("-march=native")
+ fi
+ begin "Running tests with ${cflags[*]}"
+ CFLAGS="$CFLAGS ${cflags[*]}" do_run_tests
+ end
+
+ # Need valgrind 3.9.0 for '--errors-for-leak-kinds=all'
+ # Need valgrind 3.12.0 for armv8 crypto and crc instructions
+ if $SKIP_VALGRIND; then
+ log "Skipping valgrind tests due to SKIP_VALGRIND=1"
+ elif valgrind_version_at_least 3.12.0; then
+ begin "Running tests with Valgrind"
+ WRAPPER="valgrind --quiet --error-exitcode=100 --leak-check=full --errors-for-leak-kinds=all" \
+ do_run_tests --quick
+ end
+ fi
+
+ cflags=("-fsanitize=undefined" "-fno-sanitize-recover=undefined")
+ if $SKIP_UBSAN; then
+ log "Skipping UBSAN tests due to SKIP_UBSAN=1"
+ elif cflags_supported "${cflags[@]}"; then
+ begin "Running tests with UBSAN"
+ CFLAGS="$CFLAGS ${cflags[*]}" do_run_tests --quick
+ end
+ else
+ log "Skipping UBSAN tests because compiler ($CC_VERSION) doesn't support UBSAN"
+ fi
+
+ cflags=("-fsanitize=address" "-fno-sanitize-recover=address")
+ if $SKIP_ASAN; then
+ log "Skipping ASAN tests due to SKIP_ASAN=1"
+ elif cflags_supported "${cflags[@]}"; then
+ begin "Running tests with ASAN"
+ CFLAGS="$CFLAGS ${cflags[*]}" do_run_tests --quick
+ end
+ else
+ log "Skipping ASAN tests because compiler ($CC_VERSION) doesn't support ASAN"
+ fi
+
+ cflags=("-fsanitize=cfi" "-fno-sanitize-recover=cfi" "-flto"
+ "-fvisibility=hidden")
+ if $SKIP_CFI; then
+ log "Skipping CFI tests due to SKIP_CFI=1"
+ elif cflags_supported "${cflags[@]}"; then
+ begin "Running tests with CFI"
+ CFLAGS="$CFLAGS ${cflags[*]}" AR=llvm-ar do_run_tests --quick
+ end
+ else
+ log "Skipping CFI tests because compiler ($CC_VERSION) doesn't support CFI"
+ fi
+
+ install_uninstall_tests
+ check_symbol_prefixes
+ test_use_shared_lib
+}
+
+###############################################################################
+
+log "Starting libdeflate tests"
+run_tests
+log "All tests passed!"
diff --git a/util/timers/deadlineMonitor.go b/util/timers/deadlineMonitor.go
new file mode 100644
index 000000000..823d3d8cc
--- /dev/null
+++ b/util/timers/deadlineMonitor.go
@@ -0,0 +1,48 @@
+// Copyright (C) 2019-2021 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+// Package timers provides a Clock abstraction useful for simulating timeouts.
+package timers
+
+import (
+ "time"
+)
+
+// MonotonicDeadlineMonitor is a concerete implementation of the DeadlineMonitor interface
+type MonotonicDeadlineMonitor struct {
+ clock WallClock
+ expiration time.Duration
+ expired bool
+}
+
+// MakeMonotonicDeadlineMonitor creates an instance of the MonotonicDeadlineMonitor type, implementing DeadlineMonitor
+func MakeMonotonicDeadlineMonitor(clock WallClock, expiration time.Duration) *MonotonicDeadlineMonitor {
+ return &MonotonicDeadlineMonitor{
+ clock: clock,
+ expiration: expiration,
+ }
+}
+
+// Expired return true if the deadline has passed, or false otherwise.
+func (m *MonotonicDeadlineMonitor) Expired() bool {
+ if m.expired {
+ return true
+ }
+ if m.clock.Since() >= m.expiration {
+ m.expired = true
+ }
+ return m.expired
+}
diff --git a/util/timers/interface.go b/util/timers/interface.go
index aec9a424c..7e4393ab0 100644
--- a/util/timers/interface.go
+++ b/util/timers/interface.go
@@ -41,3 +41,24 @@ type Clock interface {
// the same timeouts as the original Clock.
Decode([]byte) (Clock, error)
}
+
+// WallClock extends the Clock interface by providing a referencial timing, allowing to create
+// timed events that are differential.
+type WallClock interface {
+ Clock
+
+ // Since returns the time spent between the last time the clock was zeroed out and the current
+ // wall clock time.
+ Since() time.Duration
+
+ // DeadlineMonitorAt returns a DeadlineMonitor that expires after the provided delta time from zero has passed.
+ //
+ // DeadlineMonitorAt must be called after Zero; otherwise, the context's behavior is undefined.
+ DeadlineMonitorAt(at time.Duration) DeadlineMonitor
+}
+
+// DeadlineMonitor test to see if the deadline it was created for has been reached yet or not.
+type DeadlineMonitor interface {
+ // Expired return true if the deadline has passed, or false otherwise.
+ Expired() bool
+}
diff --git a/util/timers/monotonic.go b/util/timers/monotonic.go
index 2788a6caa..afe33ae35 100644
--- a/util/timers/monotonic.go
+++ b/util/timers/monotonic.go
@@ -30,7 +30,7 @@ type Monotonic struct {
}
// MakeMonotonicClock creates a new monotonic clock with a given zero point.
-func MakeMonotonicClock(zero time.Time) Clock {
+func MakeMonotonicClock(zero time.Time) WallClock {
return &Monotonic{
zero: zero,
}
@@ -86,3 +86,14 @@ func (m *Monotonic) Decode(data []byte) (Clock, error) {
func (m *Monotonic) String() string {
return time.Time(m.zero).String()
}
+
+// Since returns the time that has passed between the time the clock was last zeroed out and now
+func (m *Monotonic) Since() time.Duration {
+ return time.Since(m.zero)
+}
+
+// DeadlineMonitorAt returns a DeadlineMonitor that expires after the provided delta time from zero has passed.
+// The method must be called after Zero; otherwise, the context's behavior is undefined.
+func (m *Monotonic) DeadlineMonitorAt(at time.Duration) DeadlineMonitor {
+ return MakeMonotonicDeadlineMonitor(m, at)
+}