summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Lee <64482439+algojohnlee@users.noreply.github.com>2021-07-26 11:40:19 -0400
committerGitHub <noreply@github.com>2021-07-26 11:40:19 -0400
commit1ad773e0f9a11592e7ffdce749ed585183938105 (patch)
tree0681d406d5f191a6251d2d9ceeb2bd1485d9b664
parent5e00bcd6c137396afc8835ff330ddf34f44756f8 (diff)
parent7e09c41c548c41d0ff349abf5814c5837029dd2f (diff)
Merge pull request #2622 from Algo-devops-service/relstable2.8.0v2.8.0-stable
go-algorand 2.8.0-stable
-rw-r--r--.circleci/config.yml8
-rw-r--r--.github/ISSUE_TEMPLATE/algorand-engineering-team-issue-template.md15
-rw-r--r--.golangci.yml37
-rw-r--r--.travis.yml32
-rw-r--r--README.md16
-rw-r--r--agreement/abstractions.go2
-rw-r--r--agreement/fuzzer/fuzzer_test.go2
-rw-r--r--agreement/fuzzer/networkFacade_test.go2
-rw-r--r--agreement/fuzzer/tests_test.go2
-rw-r--r--agreement/fuzzer/validator_test.go2
-rw-r--r--agreement/player_permutation_test.go519
-rw-r--r--agreement/player_test.go2
-rw-r--r--agreement/proposalManager.go2
-rw-r--r--agreement/service_test.go1
-rw-r--r--agreement/state_machine_test.go4
-rw-r--r--agreement/voteAuxiliary_test.go2
-rw-r--r--agreement/voteTracker.go2
-rw-r--r--buildnumber.dat2
-rw-r--r--catchup/catchpointService.go62
-rw-r--r--catchup/peerSelector.go120
-rw-r--r--catchup/peerSelector_test.go235
-rw-r--r--catchup/service.go33
-rw-r--r--catchup/service_test.go31
-rw-r--r--cmd/goal/account.go14
-rw-r--r--cmd/goal/clerk.go2
-rw-r--r--cmd/opdoc/opdoc.go17
-rw-r--r--cmd/opdoc/tmLanguage.go4
-rw-r--r--cmd/tealdbg/cdtSession.go2
-rw-r--r--cmd/tealdbg/debugger.go4
-rw-r--r--cmd/tealdbg/debugger_test.go2
-rw-r--r--config/config.go2
-rw-r--r--config/config_test.go2
-rw-r--r--config/consensus.go9
-rw-r--r--config/defaultsGenerator/defaultsGenerator.go2
-rw-r--r--config/migrate.go2
-rw-r--r--config/version.go2
-rw-r--r--crypto/curve25519.go2
-rw-r--r--crypto/curve25519_test.go4
-rw-r--r--crypto/include/sodium/utils.h2
-rw-r--r--crypto/libsodium-fork/src/libsodium/crypto_aead/aes256gcm/aesni/aead_aes256gcm_aesni.c2
-rw-r--r--crypto/libsodium-fork/src/libsodium/include/sodium/utils.h2
-rw-r--r--crypto/merkletrie/cache.go6
-rw-r--r--crypto/merkletrie/node.go4
-rw-r--r--crypto/multisig.go4
-rw-r--r--daemon/algod/api/algod.oas2.json21
-rw-r--r--daemon/algod/api/algod.oas3.yml24
-rw-r--r--daemon/algod/api/server/lib/middlewares/logger.go2
-rw-r--r--daemon/algod/api/server/v1/handlers/handlers.go23
-rw-r--r--daemon/algod/api/server/v2/account.go9
-rw-r--r--daemon/algod/api/server/v2/dryrun.go2
-rw-r--r--daemon/algod/api/server/v2/dryrun_test.go48
-rw-r--r--daemon/algod/api/server/v2/generated/private/routes.go260
-rw-r--r--daemon/algod/api/server/v2/generated/private/types.go15
-rw-r--r--daemon/algod/api/server/v2/generated/routes.go348
-rw-r--r--daemon/algod/api/server/v2/generated/types.go15
-rw-r--r--daemon/algod/api/server/v2/utils.go16
-rw-r--r--daemon/kmd/README.md2
-rw-r--r--daemon/kmd/api/swagger.json16
-rw-r--r--daemon/kmd/lib/kmdapi/bundledSpecInject.go3586
-rw-r--r--daemon/kmd/lib/kmdapi/responses.go16
-rw-r--r--data/basics/userBalance.go2
-rw-r--r--data/bookkeeping/genesis.go7
-rw-r--r--data/bookkeeping/msgp_gen.go53
-rw-r--r--data/pools/transactionPool.go23
-rw-r--r--data/transactions/logic/README.md44
-rw-r--r--data/transactions/logic/README_in.md10
-rw-r--r--data/transactions/logic/TEAL_opcodes.md92
-rw-r--r--data/transactions/logic/assembler.go188
-rw-r--r--data/transactions/logic/assembler_test.go76
-rw-r--r--data/transactions/logic/doc.go230
-rw-r--r--data/transactions/logic/doc_test.go22
-rw-r--r--data/transactions/logic/eval.go150
-rw-r--r--data/transactions/logic/evalStateful_test.go352
-rw-r--r--data/transactions/logic/eval_test.go90
-rw-r--r--data/transactions/logic/fields.go73
-rw-r--r--data/transactions/logic/fields_string.go34
-rw-r--r--data/transactions/logic/fields_test.go28
-rw-r--r--data/transactions/logic/opcodes.go39
-rw-r--r--data/transactions/verify/txn.go4
-rw-r--r--data/transactions/verify/verifiedTxnCache.go4
-rw-r--r--data/txHandler.go4
-rw-r--r--debug/logfilter/main_test.go2
-rw-r--r--docker/build/Dockerfile-deploy2
-rwxr-xr-xdocker/releases/build_releases.sh77
-rw-r--r--gen/generate.go5
-rw-r--r--gen/walletData.go1
-rw-r--r--installer/external/node_exporter-stable-darwin-arm64.tar.gzbin0 -> 137 bytes
-rwxr-xr-xinstaller/rpm/algorand/0dnf-algorand-hourly.cron2
-rwxr-xr-xinstaller/rpm/algorand/0yum-algorand-hourly.cron2
-rw-r--r--installer/rpm/algorand/algorand.spec23
-rw-r--r--installer/rpm/algorand/dnf-cron-algorand.conf (renamed from installer/rpm/algorand/yum-cron-algorand.conf)2
-rw-r--r--ledger/accountdb.go6
-rw-r--r--ledger/accountdb_test.go4
-rw-r--r--ledger/acctupdates.go6
-rw-r--r--ledger/acctupdates_test.go10
-rw-r--r--ledger/applications.go40
-rw-r--r--ledger/applications_test.go5
-rw-r--r--ledger/blockqueue_test.go96
-rw-r--r--ledger/catchpointwriter.go2
-rw-r--r--ledger/cow.go4
-rw-r--r--ledger/eval.go2
-rw-r--r--ledger/ledger.go16
-rw-r--r--ledger/ledger_test.go2
-rw-r--r--ledger/lruaccts.go29
-rw-r--r--ledger/lruaccts_test.go55
-rw-r--r--ledger/onlineacct.go1
-rw-r--r--ledger/onlineacct_test.go138
-rw-r--r--ledger/persistedaccts_list.go144
-rw-r--r--ledger/persistedaccts_list_test.go211
-rw-r--r--ledger/roundlru.go2
-rw-r--r--ledger/roundlru_test.go29
-rw-r--r--ledger/txtail.go59
-rw-r--r--ledger/txtail_test.go95
-rw-r--r--libgoal/libgoal.go31
-rw-r--r--logging/telemetry.go52
-rw-r--r--logging/telemetryConfig.go21
-rw-r--r--logging/telemetryConfig_test.go56
-rw-r--r--logging/telemetryhook.go2
-rw-r--r--logging/telemetryhook_test.go24
-rw-r--r--netdeploy/network.go15
-rw-r--r--network/connPerfMon.go6
-rw-r--r--network/netprio.go2
-rw-r--r--network/phonebook.go4
-rw-r--r--network/requestLogger.go2
-rw-r--r--network/requestTracker.go2
-rw-r--r--network/wsNetwork.go70
-rw-r--r--network/wsNetwork_test.go78
-rw-r--r--network/wsPeer.go4
-rw-r--r--node/impls.go2
-rw-r--r--node/indexer/indexer_test.go2
-rw-r--r--node/node.go51
-rw-r--r--node/node_test.go2
-rw-r--r--nodecontrol/algodControl.go2
-rw-r--r--nodecontrol/nodeControlErrors.go2
-rw-r--r--protocol/codec_tester.go127
-rwxr-xr-xscripts/archtype.sh2
-rwxr-xr-xscripts/build_packages.sh1
-rwxr-xr-xscripts/buildhost/linux-arm.sh2
-rwxr-xr-xscripts/buildhost/run.sh2
-rwxr-xr-xscripts/buildtools/install_buildtools.sh8
-rwxr-xr-xscripts/compute_package_name.sh5
-rwxr-xr-xscripts/configure_dev-deps.sh2
-rwxr-xr-xscripts/install_linux_deps.sh3
-rw-r--r--scripts/release/mule/Makefile.mule4
-rwxr-xr-xscripts/release/mule/deploy/docker/docker.sh22
-rwxr-xr-xscripts/release/mule/deploy/releases_page/generate_releases_page.py2
-rwxr-xr-xscripts/release/mule/test/test.sh2
-rwxr-xr-xscripts/release/test/util/test_package.sh10
-rwxr-xr-xscripts/travis/after_build.sh8
-rwxr-xr-xscripts/travis/build_test.sh8
-rwxr-xr-xscripts/travis/codegen_verification.sh3
-rwxr-xr-xscripts/travis/external_build.sh2
-rwxr-xr-xscripts/travis/run_tests.sh13
-rwxr-xr-xscripts/travis/test.sh2
-rwxr-xr-xscripts/travis/travis_retry.sh30
-rwxr-xr-xscripts/travis/travis_wait.sh2
-rw-r--r--test/commandandcontrol/cc_agent/main.go4
-rw-r--r--test/e2e-go/cli/algoh/expect/algohExpectCommon.exp2
-rw-r--r--test/e2e-go/cli/goal/expect/goalFormattingTest.exp2
-rw-r--r--test/e2e-go/cli/goal/expect/goalNodeTest.exp2
-rw-r--r--test/e2e-go/cli/goal/expect/statefulTealCreateLargeAppTest.exp143
-rw-r--r--test/e2e-go/features/catchup/catchpointCatchup_test.go10
-rw-r--r--test/e2e-go/features/multisig/multisig_test.go4
-rw-r--r--test/e2e-go/features/participation/onlineOfflineParticipation_test.go81
-rw-r--r--test/e2e-go/features/participation/participationRewards_test.go8
-rw-r--r--test/e2e-go/features/transactions/asset_test.go2
-rw-r--r--test/e2e-go/features/transactions/sendReceive_test.go57
-rw-r--r--test/e2e-go/features/transactions/transactionPool_test.go169
-rw-r--r--test/e2e-go/restAPI/restClient_test.go40
-rw-r--r--test/framework/fixtures/expectFixture.go2
-rw-r--r--test/framework/fixtures/restClientFixture.go41
-rw-r--r--test/muleCI/mule.yaml25
-rw-r--r--test/netperf-go/puppeteer/main.go2
-rwxr-xr-xtest/scripts/e2e_client_runner.py12
-rwxr-xr-xtest/scripts/e2e_subs/e2e-app-extra-pages.sh83
-rwxr-xr-xtest/scripts/e2e_subs/rest-applications-endpoint.sh2
-rwxr-xr-xtest/scripts/e2e_subs/rest-assets-endpoint.sh19
-rwxr-xr-xtest/scripts/e2e_subs/rest.sh63
-rwxr-xr-xtest/scripts/e2e_subs/teal-app-params.sh30
-rw-r--r--test/scripts/e2e_subs/tealprogs/app-params.teal78
-rw-r--r--test/testdata/configs/logging/logging.config.test24
-rw-r--r--test/testdata/nettemplates/DevModeNetwork.json34
-rw-r--r--test/testdata/nettemplates/OneNode.json (renamed from test/testdata/nettemplates/TwoNodesOneOnline.json)10
-rw-r--r--tools/network/cloudflare/createRecord.go2
-rw-r--r--tools/network/cloudflare/deleteRecord.go2
-rw-r--r--tools/network/cloudflare/listRecords.go2
-rw-r--r--tools/network/cloudflare/updateRecord.go2
-rw-r--r--util/db/dbutil.go6
-rw-r--r--util/db/dbutil_test.go2
-rw-r--r--util/metrics/counter_test.go12
-rw-r--r--util/metrics/gauge_test.go4
-rw-r--r--util/metrics/reporter.go6
-rw-r--r--util/metrics/segment_test.go27
-rw-r--r--util/s3/s3Helper.go2
-rw-r--r--util/timers/frozen.go57
-rw-r--r--util/watchdogStreamReader.go4
196 files changed, 6119 insertions, 3851 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 000000000..f54db5324
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,8 @@
+version: 2.1
+orbs:
+ welcome: circleci/welcome-orb@0.4.1
+workflows:
+ welcome:
+ jobs:
+ - welcome/run
+
diff --git a/.github/ISSUE_TEMPLATE/algorand-engineering-team-issue-template.md b/.github/ISSUE_TEMPLATE/algorand-engineering-team-issue-template.md
index 254724fe9..246ad6018 100644
--- a/.github/ISSUE_TEMPLATE/algorand-engineering-team-issue-template.md
+++ b/.github/ISSUE_TEMPLATE/algorand-engineering-team-issue-template.md
@@ -8,11 +8,14 @@ assignees: ''
---
-## Summary
-<!-- *Describe the problem identified or the general goal of this issue* -->
+## Problem
+<!-- What is the problem that we’re trying to solve? -->
-## Scope/Requirements
-<!-- *What's involved in this issue? What's required to achieve the goal?* -->
+## Solution
+<!-- Do you have a potential/suggested solution? Document more than one if possible. -->
-## Urgency/Relative Priority
-<!-- *How urgent is this issue? What are the timing considerations to take into account?* -->
+## Dependencies
+<!-- Does the solution have any team or design dependencies? -->
+
+## Urgency
+<!-- What is the urgency here and why? -->
diff --git a/.golangci.yml b/.golangci.yml
new file mode 100644
index 000000000..46e7b8b73
--- /dev/null
+++ b/.golangci.yml
@@ -0,0 +1,37 @@
+run:
+ timeout: 5m
+ tests: false
+
+linters:
+ enable:
+ - golint
+ - misspell
+ - govet
+
+ disable:
+ - deadcode
+ - errcheck
+ - gosimple
+ - ineffassign
+ - staticcheck
+ - structcheck
+ - unused
+ - varcheck
+
+linters-settings:
+# govet:
+# check-shadowing: true
+
+issues:
+ # don't use default exclude rules listed in `golangci-lint run --help`
+ exclude-use-default: false
+
+ exclude-rules:
+ # ignore govet false positive fixed in https://github.com/golang/go/issues/45043
+ - linters:
+ - govet
+ text: "sigchanyzer: misuse of unbuffered os.Signal channel as argument to signal.Notify"
+ # ignore golint false positive fixed in https://github.com/golang/lint/pull/487
+ - linters:
+ - golint
+ text: "exported method (.*).Unwrap` should have comment or be unexported"
diff --git a/.travis.yml b/.travis.yml
index 6b32ad675..c71c66279 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -28,7 +28,7 @@ jobs:
- stage: build_commit
os: linux
script:
- - travis_retry scripts/travis/build_test.sh
+ - scripts/travis/build_test.sh
- stage: build_pr
os: linux
@@ -39,12 +39,12 @@ jobs:
os: linux
name: Ubuntu AMD64 Build
script:
- - travis_retry scripts/travis/build_test.sh
+ - scripts/travis/build_test.sh
- # same stage, parallel job
os: linux
name: Ubuntu AMD64 Integration Test
script:
- - travis_retry ./scripts/travis/integration_test.sh
+ - ./scripts/travis/integration_test.sh
- # same stage, parallel job
name: External ARM64 Build
os: linux
@@ -56,7 +56,7 @@ jobs:
packages:
- awscli
script:
- - travis_retry scripts/travis/external_build.sh ./scripts/travis/build_test.sh
+ - scripts/travis/external_build.sh ./scripts/travis/build_test.sh
- # same stage, parallel job
name: External ARM64 Integration Test
os: linux
@@ -74,13 +74,13 @@ jobs:
osx_image: xcode11
name: MacOS AMD64 Build
script:
- - travis_retry scripts/travis/build_test.sh
+ - scripts/travis/build_test.sh
- # same stage, parallel job
os: osx
osx_image: xcode11
name: MacOS AMD64 Integration Test
script:
- - travis_retry ./scripts/travis/integration_test.sh
+ - ./scripts/travis/integration_test.sh
- # same stage, parallel job
os: windows
name: Windows x64 Build
@@ -89,7 +89,7 @@ jobs:
- $HOME/AppData/Local/Temp/chocolatey
- /C/tools/msys64
script:
- - travis_retry $mingw64 scripts/travis/build_test.sh
+ - $mingw64 scripts/travis/build_test.sh
- stage: build_release
os: linux
@@ -100,12 +100,12 @@ jobs:
os: linux
name: Ubuntu AMD64 Build
script:
- - travis_retry ./scripts/travis/build_test.sh
+ - ./scripts/travis/build_test.sh
- # same stage, parallel job
os: linux
name: Ubuntu AMD64 Integration Test
script:
- - travis_retry ./scripts/travis/integration_test.sh
+ - ./scripts/travis/integration_test.sh
- # same stage, parallel job
name: External ARM64 Build
os: linux
@@ -117,7 +117,7 @@ jobs:
packages:
- awscli
script:
- - travis_retry scripts/travis/external_build.sh ./scripts/travis/build_test.sh
+ - scripts/travis/external_build.sh ./scripts/travis/build_test.sh
- # same stage, parallel job
name: External ARM64 Integration Test
os: linux
@@ -135,13 +135,13 @@ jobs:
osx_image: xcode11
name: MacOS AMD64 Build
script:
- - travis_retry scripts/travis/build_test.sh
+ - scripts/travis/build_test.sh
- # same stage, parallel job
os: osx
osx_image: xcode11
name: MacOS AMD64 Integration Test
script:
- - travis_retry ./scripts/travis/integration_test.sh
+ - ./scripts/travis/integration_test.sh
- # same stage, parallel job
os: windows
name: Windows x64 Build
@@ -150,7 +150,7 @@ jobs:
- $HOME/AppData/Local/Temp/chocolatey
- /C/tools/msys64
script:
- - travis_retry $mingw64 scripts/travis/build_test.sh
+ - $mingw64 scripts/travis/build_test.sh
- stage: deploy
name: Ubuntu Deploy
@@ -236,8 +236,10 @@ addons:
notifications:
slack:
- secure: lBomhenfQvDzpUGxLadga188zavtGRr05GVWI6iI8ll/uwXewij8ginQ716Axg3pJvvRMNCuTNEmg0+fVlHf0JxTG3qWG35qOUexAHGcmimPD4ugmVkufua8Oc8Nl1LRSdWvbwIKvrAU1HDA37M5tCdEOm+Sf/OL72iVWbXhlHRvhdeiKHkbkcpI/15dOH4RpXuvPeYBrgcB2Ixs7gTSVyIAU458aT0JORu7expElQ+iBP9Kqze1V4dvjJyzHTgE01z2nyAm2Xpko447y//fYX2e20iDBE5S/GukaK/TeB3pD+FoC+Z2R7Gg1qA7a/gdGFbVgP12zWmzNaKVwY1YOvx8IIwP13XutioAE7bQbnHI1zGlQ+jxk3odWKZPhZSN/YvWD3i7g/xVksaTo++zwon2UlZ7x8LmKg1kOMeA3o2TUlzjQrwZZ4cB+4HqYHEqVdsSAadaMhKK82XE1OtGImdrIX1Y/02X2F/myJXwaE4Ap8smULHWGghCL/ALad+hdyE0K4/2SYDcoaOONgX9+VgaSEtYDO00Bt4/GMcuM+gwILsfCA9ZQuxCgIFEL1QWwDud8aGU1qF20yaimDlstlLnZXsv3Oli6r/CEEUVXltI5dkJyRd/jTlqWGjFGL8agGg34EPLP24Vn4h4QcIzoMfGWXkz2yrd6i0fvMAPXds=
+ if: branch = "rel/nightly"
+ rooms:
+ - secure: jx2gllL8A8QXkV/wVpfKBRfK7cMQkuHOxxFmN2eYEGR8AR6bAGfo5HVmb6VKBRpwVzOgXwhvjbxNdYlmRkKXeJ5o0DDDUG6YSKIrNkA38JulNKzdG3K3d6DoGJV3Iturp6O9W/IdweRSz2rjJsHP1RpYG3w39giSNTMR/Q4ent68CNoYHC3XEsUHmwGVA8bQpfu2AKfr98twgTzmTcvmx93B/ZHlR8GoLh+Vq2eAwiYuyYnoNYww3ekttqeqAr21X5xTjQyAwntnk1gfRKbdiEXcxlnNKCQn3yaD7qNorJZm9U/fhGiA1eLHOxtLLJD8HSEzLvNj9gShgw/YPaYjZJLZJe0kDpR4oFwVd+lVzBManVGOwfHJIsug8dnVxY1O/PLHPV4iM4tyGwcZfxSLOXsutN3PCJhYjKUrKaJ75+L5d1tXe3DoXtGH5e/GV2kGxWr25woAZrKCeBOPFZdhAc30XLOzTk3FN3hzRKVbL9O4zxFgJllOvQTWDQ9bmXxa3bk6cDwxaF8IJk+hP1k3VaOdaxmd28pnyR/X7xRF0l1W8S6SZfDFXAFBvVyH/Q1nfvXAez//cK0He959reubjUGM8HaSWw73n9Bj5Ri4ub92xfJqSAZItI5dS1hjfdh7moS50dYbBwSozgOgWdFXHdzGNnCv+/8v0LJcnSPRdT8=
+
env:
global:
secure: YMLx+QaBPgg97tVn2efZJSqwPRxybX9oR6Xe9oXUD4fEiVbOIv2BAsLP+MzSJGaFC+VXKha83kyDbAZnatDXTJYsBPOUgmIZDObQnktueR1v3TCKn3aw14G+/w6S4eQL+c7uW3idPE+KP3VWixjrBpWTHEfnZdnH9+qWeIWzy8A8UEAYPY/HXyDmwt5ceCJoITtdsuiuZNO2o7NGN8q+NP5A3ii8f5UyDa9/krxuA+x1e193wSGRdGcqxexM7zIq0uMhBF+2nOk4RAsDsqU33NpQw+dB1VJMta1XF+P6A7m16UKUjllTyOfUPGD068jKobVyWzbvZ79G2FZXGZ7HGE0711JZco3YenwtxXP8oGLgaIds6McoJnn3rbxe1i+PjRX09IXNQM/dNp53uxrtyi1y8ZEjzHjbb6z3rSOZrzaBhdVxBFR9Oc1Ek7i8MS1tlRlH58+U+Z1WPTvbcIQtFA5HmmTcDdBRkZtPC8bpVLHOZTGUcple9k39VtOGuSCvAAfHKENhieCaw/bBXX4bxAHAfiI0NEmdDrULDJLApWjtRCrUIqIqkdsJmtiZhE+iX1FKR9CP5lBXCAwDlPB3XOe0bSmiiGQ1/sf/1CovqOBg/vLwCpjQE0IZPofCiDZZdZbv4n4aCOjiAqhS8MjJ/LfLyUuAtPmQG5g47FzS1K4=
-
diff --git a/README.md b/README.md
index be1e559c0..8c6fa230a 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ decentralization, scalability, security, and transaction finality.
## Getting Started ##
Our [developer website][developer site url] has the most up to date information
-about using and installing the algorand platform.
+about using and installing the Algorand platform.
## Building from source ##
@@ -21,7 +21,7 @@ the [official Go documentation website](https://golang.org/doc/).
### Linux / OSX ###
-We currently strive to support Debian based distributions with Ubuntu 18.04
+We currently strive to support Debian-based distributions with Ubuntu 18.04
being our official release target.
Building on Arch Linux works as well.
Our core engineering team uses Linux and OSX, so both environments are well
@@ -39,7 +39,7 @@ cd go-algorand
./scripts/buildtools/install_buildtools.sh
```
-At this point you are ready to build go-algorand. We use `make` and have a
+At this point, you are ready to build go-algorand. We use `make` and have a
number of targets to automate common tasks.
#### build
@@ -108,17 +108,17 @@ daemons, as well as other tools and commands:
locally by the node as well as parameters which must be agreed upon by the
protocol.
- `data` defines various types used throughout the codebase.
- - `basics` holds basic types such as MicroAlgos, account data, and
+ - `basics` hold basic types such as MicroAlgos, account data, and
addresses.
- `account` defines accounts, including "root" accounts (which can
spend money) and "participation" accounts (which can participate in
the agreement protocol).
- - `transactions` defines transactions that accounts can issue against
+ - `transactions` define transactions that accounts can issue against
the Algorand state. These include standard payments and also
participation key registration transactions.
- `bookkeeping` defines blocks, which are batches of transactions
atomically committed to Algorand.
- - `pools` implements the transaction pool. The transaction pool holds
+ - `pools` implement the transaction pool. The transaction pool holds
transactions seen by a node in memory before they are proposed in a
block.
- `committee` implements the credentials that authenticate a
@@ -132,7 +132,7 @@ daemons, as well as other tools and commands:
routing network messages, and prefixes for domain separation of
cryptographic inputs. It also implements the canonical encoder.
- `network` contains the code for participating in a mesh network based on
- websockets. Maintains connection to some number of peers, (optionally)
+ WebSockets. Maintains connection to some number of peers, (optionally)
accepts connections from peers, sends point to point and broadcast messages,
and receives messages routing them to various handler code
(e.g. agreement/gossip/network.go registers three handlers).
@@ -179,7 +179,7 @@ of their own:
A number of packages provide utilities for the various components:
- `logging` is a wrapper around `logrus`.
- - `util` contains a variety of utilities, including a codec, a sqlite wrapper,
+ - `util` contains a variety of utilities, including a codec, a SQLite wrapper,
a goroutine pool, a timer interface, node metrics, and more.
`test` ([README](test/README.md)) contains end-to-end tests and utilities for the above components.
diff --git a/agreement/abstractions.go b/agreement/abstractions.go
index 2384ef50e..99bd45d98 100644
--- a/agreement/abstractions.go
+++ b/agreement/abstractions.go
@@ -51,7 +51,7 @@ type BlockValidator interface {
Validate(context.Context, bookkeeping.Block) (ValidatedBlock, error)
}
-// A ValidatedBlock represents an Block that has been successfuly validated
+// A ValidatedBlock represents an Block that has been successfully validated
// and can now be recorded in the ledger. This is an optimized version of
// calling EnsureBlock() on the Ledger.
type ValidatedBlock interface {
diff --git a/agreement/fuzzer/fuzzer_test.go b/agreement/fuzzer/fuzzer_test.go
index bd3b6bb14..8c526b13d 100644
--- a/agreement/fuzzer/fuzzer_test.go
+++ b/agreement/fuzzer/fuzzer_test.go
@@ -229,7 +229,7 @@ func (n *Fuzzer) initAccountsAndBalances(rootSeed []byte, onlineNodes []bool) er
return nil
}
-// Disconnect would disconnect node diconnectingNode from node disconnectedNode ensuring that no futher messages
+// Disconnect would disconnect node diconnectingNode from node disconnectedNode ensuring that no further messages
// from disconnectedNode would reach diconnectingNode
func (n *Fuzzer) Disconnect(diconnectingNode, disconnectedNode int) {
n.disconnectMu.Lock()
diff --git a/agreement/fuzzer/networkFacade_test.go b/agreement/fuzzer/networkFacade_test.go
index a7acff407..01d9f0437 100644
--- a/agreement/fuzzer/networkFacade_test.go
+++ b/agreement/fuzzer/networkFacade_test.go
@@ -352,7 +352,7 @@ func (n *NetworkFacade) Zero() timers.Clock {
n.zeroClock = n.fuzzer.WallClock()
// we don't want to expire all the pending clocks here.
- // this callback is coming *only* from the agreement sevice.
+ // this callback is coming *only* from the agreement service.
// it also means that we're not in the demux loop, so no one is blocking
// on any of the clocks.
diff --git a/agreement/fuzzer/tests_test.go b/agreement/fuzzer/tests_test.go
index 192b32a18..bb0e9a292 100644
--- a/agreement/fuzzer/tests_test.go
+++ b/agreement/fuzzer/tests_test.go
@@ -78,7 +78,7 @@ func printResults(t *testing.T, r *RunResult) {
r.PostRecoveryLowRound, r.PostRecoveryHighRound,
)
if r.PreRecoveryHighRound != r.PreRecoveryLowRound {
- // network got disupted by the filters.
+ // network got disputed by the filters.
fmt.Printf("%v partitioned the network ( %d - %d ), but recovered correctly reaching round %d\n", t.Name(), r.PreRecoveryLowRound, r.PreRecoveryHighRound, r.PostRecoveryHighRound)
} else {
if r.PreRecoveryHighRound == r.StartLowRound {
diff --git a/agreement/fuzzer/validator_test.go b/agreement/fuzzer/validator_test.go
index 705a90588..726e09dba 100644
--- a/agreement/fuzzer/validator_test.go
+++ b/agreement/fuzzer/validator_test.go
@@ -82,7 +82,7 @@ func (v *Validator) CheckNetworkRecovery() {
v.runResult.PostRecoveryLowRound, v.runResult.PostRecoveryHighRound,
)
if v.runResult.PreRecoveryHighRound != v.runResult.PreRecoveryLowRound {
- // network got disupted by the filters.
+ // network got disputed by the filters.
fmt.Printf("%v partitioned the network ( %d - %d ), but recovered correctly reaching round %d\n", v.tb.Name(), v.runResult.PreRecoveryLowRound, v.runResult.PreRecoveryHighRound, v.runResult.PostRecoveryHighRound)
} else {
if v.runResult.PreRecoveryHighRound == v.runResult.StartLowRound {
diff --git a/agreement/player_permutation_test.go b/agreement/player_permutation_test.go
index f315a9dea..74d1292ef 100644
--- a/agreement/player_permutation_test.go
+++ b/agreement/player_permutation_test.go
@@ -42,17 +42,29 @@ func makeRandomProposalPayload(r round) *proposal {
var errTestVerifyFailed = makeSerErrStr("test error")
+type playerPermutation int
+
+const (
+ playerSameRound = iota
+ playerNextRound
+ playerPrevRoundPendingPayloadPresent
+ playerSameRoundProcessedProposalVote
+ playerSameRoundReachedSoftThreshold
+ playerSameRoundReachedCertThreshold
+ playerSameRoundProcessedProposal
+)
+
func getPlayerPermutation(t *testing.T, n int) (plyr *player, pMachine ioAutomata, helper *voteMakerHelper) {
const r = round(209)
const p = period(0)
var payload = makeRandomProposalPayload(r)
var pV = payload.value()
switch n {
- case 0: // same round and period as proposal
+ case playerSameRound: // same round and period as proposal
return setupP(t, r, p, soft)
- case 1: // one round ahead of proposal
+ case playerNextRound: // one round ahead of proposal
return setupP(t, r+1, p, soft)
- case 2:
+ case playerPrevRoundPendingPayloadPresent:
plyr, pMachine, helper = setupP(t, r-1, p, soft)
plyr.Pending.push(&messageEvent{
T: payloadPresent,
@@ -61,7 +73,7 @@ func getPlayerPermutation(t *testing.T, n int) (plyr *player, pMachine ioAutomat
UnauthenticatedProposal: payload.u(),
},
})
- case 3: // already processed proposal vote
+ case playerSameRoundProcessedProposalVote: // already processed proposal vote
plyr, pMachine, helper = setupP(t, r, p, soft)
pM := pMachine.(*ioAutomataConcretePlayer)
pM.update(*plyr, r, true)
@@ -73,7 +85,7 @@ func getPlayerPermutation(t *testing.T, n int) (plyr *player, pMachine ioAutomat
pM.Children[r].Children[p].ProposalTracker.Duplicate[helper.addresses[0]] = true
pM.Children[r].Children[p].ProposalTrackerContract.SawOneVote = true
pM.Children[r].Children[p].update(0)
- case 4: // already reached soft threshold
+ case playerSameRoundReachedSoftThreshold: // already reached soft threshold
plyr, pMachine, helper = setupP(t, r, p, soft)
pM := pMachine.(*ioAutomataConcretePlayer)
pM.update(*plyr, r, true)
@@ -86,7 +98,7 @@ func getPlayerPermutation(t *testing.T, n int) (plyr *player, pMachine ioAutomat
pM.Children[r].Children[p].ProposalTracker.Staging = pV
pM.Children[r].Children[p].ProposalTrackerContract.SawOneVote = true
pM.Children[r].Children[p].update(0)
- case 5: // already reached cert threshold
+ case playerSameRoundReachedCertThreshold: // already reached cert threshold
plyr, pMachine, helper = setupP(t, r, p, soft)
pM := pMachine.(*ioAutomataConcretePlayer)
pM.update(*plyr, r, true)
@@ -101,7 +113,7 @@ func getPlayerPermutation(t *testing.T, n int) (plyr *player, pMachine ioAutomat
pM.Children[r].Children[p].ProposalTracker.Staging = pV
pM.Children[r].Children[p].ProposalTrackerContract.SawOneVote = true
pM.Children[r].Children[p].update(0)
- case 6: // already processed proposal
+ case playerSameRoundProcessedProposal: // already processed proposal
plyr, pMachine, helper = setupP(t, r, p, soft)
pM := pMachine.(*ioAutomataConcretePlayer)
pM.update(*plyr, r, true)
@@ -119,13 +131,32 @@ func getPlayerPermutation(t *testing.T, n int) (plyr *player, pMachine ioAutomat
return
}
+type messageEventPermutation int
+
+const (
+ softVoteVerifiedEventSamePeriod = iota
+ softVotePresentEventSamePeriod
+ proposeVoteVerifiedEventNextPeriod
+ proposeVoteVerifiedEventSamePeriod
+ proposeVotePresentEventSamePeriod
+ payloadPresentEvent
+ payloadVerifiedEvent
+ payloadVerifiedEventNoMessageHandle
+ bundleVerifiedEventSamePeriod
+ bundlePresentEventSamePeriod
+ softVoteVerifiedErrorEventSamePeriod
+ proposeVoteVerifiedErrorEventSamePeriod
+ bundleVerifiedErrorEvent
+ payloadVerifiedErrorEvent
+)
+
func getMessageEventPermutation(t *testing.T, n int, helper *voteMakerHelper) (e messageEvent) {
const r = round(209)
const p = period(0)
var payload = makeRandomProposalPayload(r)
var pV = payload.value()
switch n {
- case 0:
+ case softVoteVerifiedEventSamePeriod:
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
e = messageEvent{
T: voteVerified,
@@ -136,7 +167,7 @@ func getMessageEventPermutation(t *testing.T, n int, helper *voteMakerHelper) (e
},
Proto: ConsensusVersionView{Version: protocol.ConsensusCurrentVersion},
}
- case 1:
+ case softVotePresentEventSamePeriod:
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
e = messageEvent{
T: votePresent,
@@ -146,7 +177,7 @@ func getMessageEventPermutation(t *testing.T, n int, helper *voteMakerHelper) (e
},
Proto: ConsensusVersionView{Version: protocol.ConsensusCurrentVersion},
}
- case 2:
+ case proposeVoteVerifiedEventNextPeriod:
vvote := helper.MakeVerifiedVote(t, 0, r, p+1, propose, pV)
e = messageEvent{
T: voteVerified,
@@ -157,7 +188,7 @@ func getMessageEventPermutation(t *testing.T, n int, helper *voteMakerHelper) (e
},
Proto: ConsensusVersionView{Version: protocol.ConsensusCurrentVersion},
}
- case 3:
+ case proposeVoteVerifiedEventSamePeriod:
vvote := helper.MakeVerifiedVote(t, 0, r, p, propose, pV)
e = messageEvent{
T: voteVerified,
@@ -169,7 +200,7 @@ func getMessageEventPermutation(t *testing.T, n int, helper *voteMakerHelper) (e
TaskIndex: 1,
Proto: ConsensusVersionView{Version: protocol.ConsensusCurrentVersion},
}
- case 4:
+ case proposeVotePresentEventSamePeriod:
vvote := helper.MakeVerifiedVote(t, 0, r, p, propose, pV)
e = messageEvent{
T: votePresent,
@@ -179,7 +210,7 @@ func getMessageEventPermutation(t *testing.T, n int, helper *voteMakerHelper) (e
},
Proto: ConsensusVersionView{Version: protocol.ConsensusCurrentVersion},
}
- case 5:
+ case payloadPresentEvent:
e = messageEvent{
T: payloadPresent,
Input: message{
@@ -187,7 +218,7 @@ func getMessageEventPermutation(t *testing.T, n int, helper *voteMakerHelper) (e
UnauthenticatedProposal: payload.u(),
},
}
- case 6:
+ case payloadVerifiedEvent:
e = messageEvent{
T: payloadVerified,
Input: message{
@@ -196,7 +227,7 @@ func getMessageEventPermutation(t *testing.T, n int, helper *voteMakerHelper) (e
Proposal: *payload,
},
}
- case 7:
+ case payloadVerifiedEventNoMessageHandle:
e = messageEvent{
T: payloadVerified,
Input: message{
@@ -204,7 +235,7 @@ func getMessageEventPermutation(t *testing.T, n int, helper *voteMakerHelper) (e
Proposal: *payload,
},
}
- case 8:
+ case bundleVerifiedEventSamePeriod:
votes := make([]vote, int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])))
for i := 0; i < int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])); i++ {
votes[i] = helper.MakeVerifiedVote(t, i, r, p, cert, pV)
@@ -225,7 +256,7 @@ func getMessageEventPermutation(t *testing.T, n int, helper *voteMakerHelper) (e
},
Proto: ConsensusVersionView{Version: protocol.ConsensusCurrentVersion},
}
- case 9:
+ case bundlePresentEventSamePeriod:
votes := make([]vote, int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])))
for i := 0; i < int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])); i++ {
votes[i] = helper.MakeVerifiedVote(t, i, r, p, cert, pV)
@@ -242,7 +273,7 @@ func getMessageEventPermutation(t *testing.T, n int, helper *voteMakerHelper) (e
},
Proto: ConsensusVersionView{Version: protocol.ConsensusCurrentVersion},
}
- case 10:
+ case softVoteVerifiedErrorEventSamePeriod:
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
e = messageEvent{
T: voteVerified,
@@ -254,7 +285,7 @@ func getMessageEventPermutation(t *testing.T, n int, helper *voteMakerHelper) (e
Err: errTestVerifyFailed,
Proto: ConsensusVersionView{Version: protocol.ConsensusCurrentVersion},
}
- case 11:
+ case proposeVoteVerifiedErrorEventSamePeriod:
vvote := helper.MakeVerifiedVote(t, 0, r, p, propose, pV)
e = messageEvent{
T: voteVerified,
@@ -266,7 +297,7 @@ func getMessageEventPermutation(t *testing.T, n int, helper *voteMakerHelper) (e
Err: errTestVerifyFailed,
Proto: ConsensusVersionView{Version: protocol.ConsensusCurrentVersion},
}
- case 12:
+ case bundleVerifiedErrorEvent:
e = messageEvent{
T: bundleVerified,
Input: message{
@@ -276,7 +307,7 @@ func getMessageEventPermutation(t *testing.T, n int, helper *voteMakerHelper) (e
},
Err: errTestVerifyFailed,
}
- case 13:
+ case payloadVerifiedErrorEvent:
e = messageEvent{
T: payloadVerified,
Input: message{
@@ -325,409 +356,383 @@ func expectDisconnect(t *testing.T, trace ioTrace, errMsg string, playerN int, e
}), errMsg, playerN, eventN)
}
+func requireActionCount(t *testing.T, trace ioTrace, expectedCount, playerN, eventN int) {
+ require.Equalf(t, trace.countAction(), expectedCount, "Player should not emit extra actions, player: %v, event: %v", playerN, eventN)
+}
+
+func requireTraceContains(t *testing.T, trace ioTrace, expected event, playerN, eventN int) {
+ require.Truef(t, trace.Contains(expected), "Player should emit action, player: %v, event: %v", playerN, eventN)
+}
+
func verifyPermutationExpectedActions(t *testing.T, playerN int, eventN int, helper *voteMakerHelper, trace ioTrace) {
const r = round(209)
const p = period(0)
var payload = makeRandomProposalPayload(r)
var pV = payload.value()
switch playerN {
- case 0:
+ case playerSameRound:
switch eventN {
- case 0:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case softVoteVerifiedEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
a := networkAction{T: relay, Tag: protocol.AgreementVoteTag, UnauthenticatedVote: vvote.u()}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 1:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case softVotePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
a := cryptoAction{T: verifyVote, M: message{UnauthenticatedVote: vvote.u()}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 2:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case proposeVoteVerifiedEventNextPeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p+1, propose, pV)
a := networkAction{T: relay, Tag: protocol.AgreementVoteTag, UnauthenticatedVote: vvote.u()}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 3:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case proposeVoteVerifiedEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, propose, pV)
a := networkAction{T: relay, Tag: protocol.AgreementVoteTag, UnauthenticatedVote: vvote.u()}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 4:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case proposeVotePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, propose, pV)
a := cryptoAction{T: verifyVote, M: message{UnauthenticatedVote: vvote.u()}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 5, 6, 7:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case payloadPresentEvent, payloadVerifiedEvent, payloadVerifiedEventNoMessageHandle:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore proposal with no vvote, player: %v, event: %v", playerN, eventN)
- case 8:
- require.Equalf(t, trace.countAction(), 2, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case bundleVerifiedEventSamePeriod:
+ requireActionCount(t, trace, 2, playerN, eventN)
votes := make([]vote, int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])))
for i := 0; i < int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])); i++ {
votes[i] = helper.MakeVerifiedVote(t, i, r, p, cert, pV)
}
- bun := unauthenticatedBundle{
- Round: r,
- Period: p,
- Proposal: pV,
- }
+ bun := unauthenticatedBundle{Round: r, Period: p, Proposal: pV}
ra := networkAction{T: relay, Tag: protocol.VoteBundleTag, UnauthenticatedBundle: bun}
- require.Truef(t, trace.Contains(ev(ra)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ra), playerN, eventN)
sa := stageDigestAction{Certificate: Certificate(bun)}
- require.Truef(t, trace.Contains(ev(sa)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 9:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(sa), playerN, eventN)
+ case bundlePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
votes := make([]vote, int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])))
for i := 0; i < int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])); i++ {
votes[i] = helper.MakeVerifiedVote(t, i, r, p, cert, pV)
}
- bun := unauthenticatedBundle{
- Round: r,
- Period: p,
- Proposal: pV,
- }
+ bun := unauthenticatedBundle{Round: r, Period: p, Proposal: pV}
ca := cryptoAction{T: verifyBundle, M: message{Bundle: bundle{U: bun, Votes: votes}, UnauthenticatedBundle: bun}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(ca)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- //ea := ensureAction{Certificate: Certificate(bun), Payload: *payload}
- //require.Truef(t, trace.Contains(ev(ea)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 10, 11, 12:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ca), playerN, eventN)
+ case softVoteVerifiedErrorEventSamePeriod, proposeVoteVerifiedErrorEventSamePeriod, bundleVerifiedErrorEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectDisconnect(t, trace, "Player should disconnect malformed vote/bundle, player: %v, event: %v", playerN, eventN)
- case 13:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case payloadVerifiedErrorEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore malformed proposal, player: %v, event: %v", playerN, eventN)
default:
require.Fail(t, "event permutation %v does not exist", eventN)
}
- case 1:
+ case playerNextRound:
switch eventN {
- case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case softVoteVerifiedEventSamePeriod, softVotePresentEventSamePeriod, proposeVoteVerifiedEventNextPeriod, proposeVoteVerifiedEventSamePeriod, proposeVotePresentEventSamePeriod, payloadPresentEvent, payloadVerifiedEvent, payloadVerifiedEventNoMessageHandle, bundleVerifiedEventSamePeriod, bundlePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore msg from past rounds, player: %v, event: %v", playerN, eventN)
- case 10, 11, 12:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case softVoteVerifiedErrorEventSamePeriod, proposeVoteVerifiedErrorEventSamePeriod, bundleVerifiedErrorEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectDisconnect(t, trace, "Player should disconnect malformed vote/bundle, player: %v, event: %v", playerN, eventN)
- case 13:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case payloadVerifiedErrorEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore malformed proposal, player: %v, event: %v", playerN, eventN)
default:
require.Fail(t, "event permutation %v does not exist", eventN)
}
- case 2:
+ case playerPrevRoundPendingPayloadPresent:
switch eventN {
- case 0:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case softVoteVerifiedEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
a := networkAction{T: relay, Tag: protocol.AgreementVoteTag, UnauthenticatedVote: vvote.u()}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 1:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case softVotePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
a := cryptoAction{T: verifyVote, M: message{UnauthenticatedVote: vvote.u()}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 2:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case proposeVoteVerifiedEventNextPeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore future msg from bad period, player: %v, event: %v", playerN, eventN)
- case 3:
- require.Equalf(t, trace.countAction(), 2, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case proposeVoteVerifiedEventSamePeriod:
+ requireActionCount(t, trace, 2, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, propose, pV)
a := networkAction{T: relay, Tag: protocol.AgreementVoteTag, UnauthenticatedVote: vvote.u()}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
na := networkAction{T: relay, Tag: protocol.ProposalPayloadTag, CompoundMessage: compoundMessage{Proposal: payload.u()}}
- require.Truef(t, trace.Contains(ev(na)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 4:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(na), playerN, eventN)
+ case proposeVotePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, propose, pV)
a := cryptoAction{T: verifyVote, M: message{UnauthenticatedVote: vvote.u()}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 5, 6, 7:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case payloadPresentEvent, payloadVerifiedEvent, payloadVerifiedEventNoMessageHandle:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore proposal with no vvote, player: %v, event: %v", playerN, eventN)
- case 8, 9:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case bundleVerifiedEventSamePeriod, bundlePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore bundle from different round, player: %v, event: %v", playerN, eventN)
- case 10, 11, 12:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case softVoteVerifiedErrorEventSamePeriod, proposeVoteVerifiedErrorEventSamePeriod, bundleVerifiedErrorEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectDisconnect(t, trace, "Player should disconnect malformed vote/bundle, player: %v, event: %v", playerN, eventN)
- case 13:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case payloadVerifiedErrorEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore malformed proposal, player: %v, event: %v", playerN, eventN)
default:
require.Fail(t, "event permutation %v does not exist", eventN)
}
- case 3:
+ case playerSameRoundProcessedProposalVote:
switch eventN {
- case 0:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case softVoteVerifiedEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
a := networkAction{T: relay, Tag: protocol.AgreementVoteTag, UnauthenticatedVote: vvote.u()}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 1:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case softVotePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
a := cryptoAction{T: verifyVote, M: message{UnauthenticatedVote: vvote.u()}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 2:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case proposeVoteVerifiedEventNextPeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p+1, propose, pV)
a := networkAction{T: relay, Tag: protocol.AgreementVoteTag, UnauthenticatedVote: vvote.u()}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 3, 4:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case proposeVoteVerifiedEventSamePeriod, proposeVotePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore proposalvvote already received: %v, event: %v", playerN, eventN)
- case 5:
- require.Equalf(t, trace.countAction(), 2, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case payloadPresentEvent:
+ requireActionCount(t, trace, 2, playerN, eventN)
ca := cryptoAction{T: verifyPayload, M: message{UnauthenticatedProposal: payload.u()}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(ca)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ca), playerN, eventN)
na := networkAction{T: relay, Tag: protocol.ProposalPayloadTag, CompoundMessage: compoundMessage{Proposal: payload.u()}}
- require.Truef(t, trace.Contains(ev(na)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 6:
- require.Equalf(t, trace.countAction(), 0, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
- case 7:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(na), playerN, eventN)
+ case payloadVerifiedEvent:
+ requireActionCount(t, trace, 0, playerN, eventN)
+ case payloadVerifiedEventNoMessageHandle:
+ requireActionCount(t, trace, 1, playerN, eventN)
na := networkAction{T: relay, Tag: protocol.ProposalPayloadTag, CompoundMessage: compoundMessage{Proposal: payload.u()}}
- require.Truef(t, trace.Contains(ev(na)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 8:
- require.Equalf(t, trace.countAction(), 2, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(na), playerN, eventN)
+ case bundleVerifiedEventSamePeriod:
+ requireActionCount(t, trace, 2, playerN, eventN)
votes := make([]vote, int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])))
for i := 0; i < int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])); i++ {
votes[i] = helper.MakeVerifiedVote(t, i, r, p, cert, pV)
}
- bun := unauthenticatedBundle{
- Round: r,
- Period: p,
- Proposal: pV,
- }
+ bun := unauthenticatedBundle{Round: r, Period: p, Proposal: pV}
ra := networkAction{T: relay, Tag: protocol.VoteBundleTag, UnauthenticatedBundle: bun}
- require.Truef(t, trace.Contains(ev(ra)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ra), playerN, eventN)
sa := stageDigestAction{Certificate: Certificate(bun)}
- require.Truef(t, trace.Contains(ev(sa)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 9:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(sa), playerN, eventN)
+ case bundlePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
votes := make([]vote, int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])))
for i := 0; i < int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])); i++ {
votes[i] = helper.MakeVerifiedVote(t, i, r, p, cert, pV)
}
- bun := unauthenticatedBundle{
- Round: r,
- Period: p,
- Proposal: pV,
- }
+ bun := unauthenticatedBundle{Round: r, Period: p, Proposal: pV}
ca := cryptoAction{T: verifyBundle, M: message{Bundle: bundle{U: bun, Votes: votes}, UnauthenticatedBundle: bun}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(ca)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 10, 11, 12:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ca), playerN, eventN)
+ case softVoteVerifiedErrorEventSamePeriod, proposeVoteVerifiedErrorEventSamePeriod, bundleVerifiedErrorEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectDisconnect(t, trace, "Player should disconnect malformed vote/bundle, player: %v, event: %v", playerN, eventN)
- case 13:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case payloadVerifiedErrorEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore malformed proposal, player: %v, event: %v", playerN, eventN)
+
default:
require.Fail(t, "event permutation %v does not exist", eventN)
}
- case 4:
+ case playerSameRoundReachedSoftThreshold:
switch eventN {
- case 0:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case softVoteVerifiedEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
a := networkAction{T: relay, Tag: protocol.AgreementVoteTag, UnauthenticatedVote: vvote.u()}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 1:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case softVotePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
a := cryptoAction{T: verifyVote, M: message{UnauthenticatedVote: vvote.u()}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 2:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case proposeVoteVerifiedEventNextPeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p+1, propose, pV)
a := networkAction{T: relay, Tag: protocol.AgreementVoteTag, UnauthenticatedVote: vvote.u()}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 3, 4:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case proposeVoteVerifiedEventSamePeriod, proposeVotePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore proposalvvote already received: %v, event: %v", playerN, eventN)
- case 5:
- require.Equalf(t, trace.countAction(), 2, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case payloadPresentEvent:
+ requireActionCount(t, trace, 2, playerN, eventN)
ca := cryptoAction{T: verifyPayload, M: message{UnauthenticatedProposal: payload.u()}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(ca)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ca), playerN, eventN)
na := networkAction{T: relay, Tag: protocol.ProposalPayloadTag, CompoundMessage: compoundMessage{Proposal: payload.u()}}
- require.Truef(t, trace.Contains(ev(na)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 6:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(na), playerN, eventN)
+ case payloadVerifiedEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
pa := pseudonodeAction{T: attest, Round: r, Period: p, Step: cert, Proposal: pV}
- require.Truef(t, trace.Contains(ev(pa)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 7:
- require.Equalf(t, trace.countAction(), 2, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(pa), playerN, eventN)
+ case payloadVerifiedEventNoMessageHandle:
+ requireActionCount(t, trace, 2, playerN, eventN)
na := networkAction{T: relay, Tag: protocol.ProposalPayloadTag, CompoundMessage: compoundMessage{Proposal: payload.u()}}
- require.Truef(t, trace.Contains(ev(na)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(na), playerN, eventN)
pa := pseudonodeAction{T: attest, Round: r, Period: p, Step: cert, Proposal: pV}
- require.Truef(t, trace.Contains(ev(pa)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 8:
- require.Equalf(t, trace.countAction(), 2, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(pa), playerN, eventN)
+ case bundleVerifiedEventSamePeriod:
+ requireActionCount(t, trace, 2, playerN, eventN)
votes := make([]vote, int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])))
for i := 0; i < int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])); i++ {
votes[i] = helper.MakeVerifiedVote(t, i, r, p, cert, pV)
}
- bun := unauthenticatedBundle{
- Round: r,
- Period: p,
- Proposal: pV,
- }
+ bun := unauthenticatedBundle{Round: r, Period: p, Proposal: pV}
ra := networkAction{T: relay, Tag: protocol.VoteBundleTag, UnauthenticatedBundle: bun}
- require.Truef(t, trace.Contains(ev(ra)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ra), playerN, eventN)
sa := stageDigestAction{Certificate: Certificate(bun)}
- require.Truef(t, trace.Contains(ev(sa)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 9:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(sa), playerN, eventN)
+ case bundlePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
votes := make([]vote, int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])))
for i := 0; i < int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])); i++ {
votes[i] = helper.MakeVerifiedVote(t, i, r, p, cert, pV)
}
- bun := unauthenticatedBundle{
- Round: r,
- Period: p,
- Proposal: pV,
- }
+ bun := unauthenticatedBundle{Round: r, Period: p, Proposal: pV}
ca := cryptoAction{T: verifyBundle, M: message{Bundle: bundle{U: bun, Votes: votes}, UnauthenticatedBundle: bun}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(ca)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 10, 11, 12:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ca), playerN, eventN)
+ case softVoteVerifiedErrorEventSamePeriod, proposeVoteVerifiedErrorEventSamePeriod, bundleVerifiedErrorEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectDisconnect(t, trace, "Player should disconnect malformed vote/bundle, player: %v, event: %v", playerN, eventN)
- case 13:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case payloadVerifiedErrorEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore malformed proposal, player: %v, event: %v", playerN, eventN)
+
default:
require.Fail(t, "event permutation %v does not exist", eventN)
}
- case 5:
+ case playerSameRoundReachedCertThreshold:
switch eventN {
- case 0:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case softVoteVerifiedEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
a := networkAction{T: relay, Tag: protocol.AgreementVoteTag, UnauthenticatedVote: vvote.u()}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 1:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case softVotePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
a := cryptoAction{T: verifyVote, M: message{UnauthenticatedVote: vvote.u()}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 2:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case proposeVoteVerifiedEventNextPeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p+1, propose, pV)
a := networkAction{T: relay, Tag: protocol.AgreementVoteTag, UnauthenticatedVote: vvote.u()}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 3, 4:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case proposeVoteVerifiedEventSamePeriod, proposeVotePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore proposalvvote already received: %v, event: %v", playerN, eventN)
- case 5:
- require.Equalf(t, trace.countAction(), 2, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case payloadPresentEvent:
+ requireActionCount(t, trace, 2, playerN, eventN)
ca := cryptoAction{T: verifyPayload, M: message{UnauthenticatedProposal: payload.u()}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(ca)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ca), playerN, eventN)
na := networkAction{T: relay, Tag: protocol.ProposalPayloadTag, CompoundMessage: compoundMessage{Proposal: payload.u()}}
- require.Truef(t, trace.Contains(ev(na)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 6:
- require.Equalf(t, trace.countAction(), 3, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(na), playerN, eventN)
+ case payloadVerifiedEvent:
+ requireActionCount(t, trace, 3, playerN, eventN)
ea := ensureAction{Certificate: Certificate(unauthenticatedBundle{Round: r}), Payload: *payload}
- require.Truef(t, trace.Contains(ev(ea)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ea), playerN, eventN)
ra := rezeroAction{Round: r + 1}
- require.Truef(t, trace.Contains(ev(ra)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ra), playerN, eventN)
pa := pseudonodeAction{T: assemble, Round: r + 1, Period: 0, Step: 0}
- require.Truef(t, trace.Contains(ev(pa)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 7:
- require.Equalf(t, trace.countAction(), 4, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(pa), playerN, eventN)
+ case payloadVerifiedEventNoMessageHandle:
+ requireActionCount(t, trace, 4, playerN, eventN)
na := networkAction{T: relay, Tag: protocol.ProposalPayloadTag, CompoundMessage: compoundMessage{Proposal: payload.u()}}
- require.Truef(t, trace.Contains(ev(na)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(na), playerN, eventN)
ea := ensureAction{Certificate: Certificate(unauthenticatedBundle{Round: r}), Payload: *payload}
- require.Truef(t, trace.Contains(ev(ea)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ea), playerN, eventN)
ra := rezeroAction{Round: r + 1}
- require.Truef(t, trace.Contains(ev(ra)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ra), playerN, eventN)
pa := pseudonodeAction{T: assemble, Round: r + 1, Period: 0, Step: 0}
- require.Truef(t, trace.Contains(ev(pa)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 8:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(pa), playerN, eventN)
+ case bundleVerifiedEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore, already hit thresh, player: %v, event: %v", playerN, eventN)
- case 9:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case bundlePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
votes := make([]vote, int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])))
for i := 0; i < int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])); i++ {
votes[i] = helper.MakeVerifiedVote(t, i, r, p, cert, pV)
}
- bun := unauthenticatedBundle{
- Round: r,
- Period: p,
- Proposal: pV,
- }
+ bun := unauthenticatedBundle{Round: r, Period: p, Proposal: pV}
ca := cryptoAction{T: verifyBundle, M: message{Bundle: bundle{U: bun, Votes: votes}, UnauthenticatedBundle: bun}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(ca)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 10, 11, 12:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ca), playerN, eventN)
+ case softVoteVerifiedErrorEventSamePeriod, proposeVoteVerifiedErrorEventSamePeriod, bundleVerifiedErrorEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectDisconnect(t, trace, "Player should disconnect malformed vote/bundle, player: %v, event: %v", playerN, eventN)
- case 13:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case payloadVerifiedErrorEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore malformed proposal, player: %v, event: %v", playerN, eventN)
+
default:
require.Fail(t, "event permutation %v does not exist", eventN)
}
- case 6:
+ case playerSameRoundProcessedProposal:
switch eventN {
- case 0:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case softVoteVerifiedEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
a := networkAction{T: relay, Tag: protocol.AgreementVoteTag, UnauthenticatedVote: vvote.u()}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 1:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case softVotePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p, soft, pV)
a := cryptoAction{T: verifyVote, M: message{UnauthenticatedVote: vvote.u()}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 2:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case proposeVoteVerifiedEventNextPeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
vvote := helper.MakeVerifiedVote(t, 0, r, p+1, propose, pV)
a := networkAction{T: broadcast, Tag: protocol.ProposalPayloadTag, CompoundMessage: compoundMessage{Proposal: payload.u(), Vote: vvote.u()}}
- require.Truef(t, trace.Contains(ev(a)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 3, 4:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(a), playerN, eventN)
+ case proposeVoteVerifiedEventSamePeriod, proposeVotePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore proposalvvote already received: %v, event: %v", playerN, eventN)
- case 5, 6, 7:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case payloadPresentEvent, payloadVerifiedEvent, payloadVerifiedEventNoMessageHandle:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore proposal already assembled: %v, event: %v", playerN, eventN)
- case 8:
- require.Equalf(t, trace.countAction(), 4, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case bundleVerifiedEventSamePeriod:
+ requireActionCount(t, trace, 4, playerN, eventN)
votes := make([]vote, int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])))
for i := 0; i < int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])); i++ {
votes[i] = helper.MakeVerifiedVote(t, i, r, p, cert, pV)
}
- bun := unauthenticatedBundle{
- Round: r,
- Period: p,
- Proposal: pV,
- }
+ bun := unauthenticatedBundle{Round: r, Period: p, Proposal: pV}
na := networkAction{T: relay, Tag: protocol.VoteBundleTag, UnauthenticatedBundle: bun}
- require.Truef(t, trace.Contains(ev(na)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(na), playerN, eventN)
ea := ensureAction{Certificate: Certificate(bun), Payload: *payload}
- require.Truef(t, trace.Contains(ev(ea)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ea), playerN, eventN)
ra := rezeroAction{Round: r + 1}
- require.Truef(t, trace.Contains(ev(ra)), "Player should emit action, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ra), playerN, eventN)
pa := pseudonodeAction{T: assemble, Round: r + 1, Period: 0, Step: 0}
- require.Truef(t, trace.Contains(ev(pa)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 9:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(pa), playerN, eventN)
+ case bundlePresentEventSamePeriod:
+ requireActionCount(t, trace, 1, playerN, eventN)
votes := make([]vote, int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])))
for i := 0; i < int(cert.threshold(config.Consensus[protocol.ConsensusCurrentVersion])); i++ {
votes[i] = helper.MakeVerifiedVote(t, i, r, p, cert, pV)
}
- bun := unauthenticatedBundle{
- Round: r,
- Period: p,
- Proposal: pV,
- }
+ bun := unauthenticatedBundle{Round: r, Period: p, Proposal: pV}
ca := cryptoAction{T: verifyBundle, M: message{Bundle: bundle{U: bun, Votes: votes}, UnauthenticatedBundle: bun}, TaskIndex: 0}
- require.Truef(t, trace.Contains(ev(ca)), "Player should emit action, player: %v, event: %v", playerN, eventN)
- case 10, 11, 12:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ requireTraceContains(t, trace, ev(ca), playerN, eventN)
+ case softVoteVerifiedErrorEventSamePeriod, proposeVoteVerifiedErrorEventSamePeriod, bundleVerifiedErrorEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectDisconnect(t, trace, "Player should disconnect malformed vote/bundle, player: %v, event: %v", playerN, eventN)
- case 13:
- require.Equalf(t, trace.countAction(), 1, "Plyaer should not emit extra actions, player: %v, event: %v", playerN, eventN)
+ case payloadVerifiedErrorEvent:
+ requireActionCount(t, trace, 1, playerN, eventN)
expectIgnore(t, trace, "Player should ignore malformed proposal, player: %v, event: %v", playerN, eventN)
+
default:
require.Fail(t, "event permutation %v does not exist", eventN)
}
diff --git a/agreement/player_test.go b/agreement/player_test.go
index c81c464ae..1b565e9f9 100644
--- a/agreement/player_test.go
+++ b/agreement/player_test.go
@@ -2972,7 +2972,7 @@ func TestPlayer_CertThresholdCommitsFuturePeriodIfAlreadyHasBlock(t *testing.T)
require.Equalf(t, r+1, pWhite.Round, "player did not enter new round... bad!")
require.Equalf(t, period(0), pWhite.Period, "player should have entered period 0 of new round but didn't")
commitEvent := ev(ensureAction{Certificate: Certificate(bun), Payload: *payload})
- require.Truef(t, pM.getTrace().Contains(commitEvent), "Player should have commited a block but didn't")
+ require.Truef(t, pM.getTrace().Contains(commitEvent), "Player should have committed a block but didn't")
}
func TestPlayer_PayloadAfterCertThresholdCommits(t *testing.T) {
diff --git a/agreement/proposalManager.go b/agreement/proposalManager.go
index 7d6336f51..b701d2971 100644
--- a/agreement/proposalManager.go
+++ b/agreement/proposalManager.go
@@ -23,7 +23,7 @@ import (
)
// A proposalManager is a proposalMachine which applies relay rules to incoming
-// proposal-votes and proposal payloads, absorbes threshold events, and emits
+// proposal-votes and proposal payloads, absorbs threshold events, and emits
// proposalCommittable events as proposals become committable.
//
// It handles the following type(s) of event: vote{Present,Verified},
diff --git a/agreement/service_test.go b/agreement/service_test.go
index f3db45a85..d698ef93e 100644
--- a/agreement/service_test.go
+++ b/agreement/service_test.go
@@ -948,6 +948,7 @@ func TestAgreementSynchronous5(t *testing.T) {
}
func TestAgreementSynchronous10(t *testing.T) {
+ t.Skip("Skipping flaky agreement integration test")
if testing.Short() {
t.Skip("Skipping agreement integration test")
}
diff --git a/agreement/state_machine_test.go b/agreement/state_machine_test.go
index 7023bad61..e91cf82b0 100644
--- a/agreement/state_machine_test.go
+++ b/agreement/state_machine_test.go
@@ -164,7 +164,7 @@ type ioSafetyProp interface {
// returns bool whether trace is in the safety property. If false,
// optionally accompanied by an informational message pertaining to why
// the trace is not in the safety property. Err is set if we saw an
- // unforseen error.
+ // unforeseen error.
containsTrace(trace ioTrace) (contains bool, info string, err error)
// every safety prop also exposes the option to check it dynamically
@@ -283,7 +283,7 @@ type ioAutomataConcrete struct {
listener
// listeners need additional context. For now, we keep it static.
- routerCtx router // optional, set to router{} on defualt
+ routerCtx router // optional, set to router{} on default
playerCtx player // optional, set to player{} by default
// private
diff --git a/agreement/voteAuxiliary_test.go b/agreement/voteAuxiliary_test.go
index 7ede4d8bf..82a94d594 100644
--- a/agreement/voteAuxiliary_test.go
+++ b/agreement/voteAuxiliary_test.go
@@ -99,7 +99,7 @@ func TestVoteTrackerPeriodStepCachedThresholdPrivate(t *testing.T) {
require.NoError(t, err)
require.NoErrorf(t, res, "Expected threshold event not relayed")
- // now, given that a bottom threshold was emmited, make sure private state was set (so we can appropriately respond to queries)
+ // now, given that a bottom threshold was emitted, make sure private state was set (so we can appropriately respond to queries)
vt := perRouter.voteRoot.underlying().(*voteTrackerPeriod)
require.Truef(t, vt.Cached.Bottom, "VoteTrackerPeriod didn't set bottom to true")
diff --git a/agreement/voteTracker.go b/agreement/voteTracker.go
index f211b9949..1363a2896 100644
--- a/agreement/voteTracker.go
+++ b/agreement/voteTracker.go
@@ -216,7 +216,7 @@ func (tracker *voteTracker) handle(r routerHandle, p player, e0 event) event {
// We've just moved the vote around ( regular vote -> equivocator vote ) but that did not
// change the total weight. Since the total weight for the proposal in the vote wasn't altered,
- // we know for sure that we haven't reached a threshold for that proposal. ( but maybe for a diffrent one )
+ // we know for sure that we haven't reached a threshold for that proposal. ( but maybe for a different one )
// at this point, we need to check if this is the very last vote or not.
// if we have no regular votes, we won't be generating a bundle so we can abort right here.
diff --git a/buildnumber.dat b/buildnumber.dat
index d00491fd7..573541ac9 100644
--- a/buildnumber.dat
+++ b/buildnumber.dat
@@ -1 +1 @@
-1
+0
diff --git a/catchup/catchpointService.go b/catchup/catchpointService.go
index c6bdf8ac0..bac14d4e8 100644
--- a/catchup/catchpointService.go
+++ b/catchup/catchpointService.go
@@ -174,7 +174,7 @@ func (cs *CatchpointCatchupService) GetLatestBlockHeader() bookkeeping.BlockHead
return cs.lastBlockHeader
}
-// run is the main stage-swtiching background service function. It switches the current stage into the correct stage handler.
+// run is the main stage-switching background service function. It switches the current stage into the correct stage handler.
func (cs *CatchpointCatchupService) run() {
defer cs.running.Done()
var err error
@@ -281,11 +281,12 @@ func (cs *CatchpointCatchupService) processStageLedgerDownload() (err error) {
}
return cs.abort(fmt.Errorf("processStageLedgerDownload failed to reset staging balances : %v", err))
}
- peer, err := peerSelector.GetNextPeer()
+ psp, err := peerSelector.getNextPeer()
if err != nil {
err = fmt.Errorf("processStageLedgerDownload: catchpoint catchup was unable to obtain a list of peers to retrieve the catchpoint file from")
return cs.abort(err)
}
+ peer := psp.Peer
err = ledgerFetcher.downloadLedger(cs.ctx, peer, round)
if err == nil {
err = cs.ledgerAccessor.BuildMerkleTrie(cs.ctx, cs.updateVerifiedAccounts)
@@ -293,9 +294,9 @@ func (cs *CatchpointCatchupService) processStageLedgerDownload() (err error) {
break
}
// failed to build the merkle trie for the above catchpoint file.
- peerSelector.RankPeer(peer, peerRankInvalidDownload)
+ peerSelector.rankPeer(psp, peerRankInvalidDownload)
} else {
- peerSelector.RankPeer(peer, peerRankDownloadFailed)
+ peerSelector.rankPeer(psp, peerRankDownloadFailed)
}
// instead of testing for err == cs.ctx.Err() , we'll check on the context itself.
@@ -345,11 +346,11 @@ func (cs *CatchpointCatchupService) processStageLastestBlockDownload() (err erro
for {
attemptsCount++
- peer := network.Peer(0)
+ var psp *peerSelectorPeer
blockDownloadDuration := time.Duration(0)
if blk == nil {
var stop bool
- blk, blockDownloadDuration, peer, stop, err = cs.fetchBlock(blockRound, uint64(attemptsCount))
+ blk, blockDownloadDuration, psp, stop, err = cs.fetchBlock(blockRound, uint64(attemptsCount))
if stop {
return err
} else if blk == nil {
@@ -364,7 +365,7 @@ func (cs *CatchpointCatchupService) processStageLastestBlockDownload() (err erro
if attemptsCount <= cs.config.CatchupBlockDownloadRetryAttempts {
// try again.
blk = nil
- cs.blocksDownloadPeerSelector.RankPeer(peer, peerRankInvalidDownload)
+ cs.blocksDownloadPeerSelector.rankPeer(psp, peerRankInvalidDownload)
continue
}
return cs.abort(fmt.Errorf("processStageLastestBlockDownload: unsupported protocol version detected: '%v'", blk.BlockHeader.CurrentProtocol))
@@ -376,7 +377,7 @@ func (cs *CatchpointCatchupService) processStageLastestBlockDownload() (err erro
if attemptsCount <= cs.config.CatchupBlockDownloadRetryAttempts {
// try again.
blk = nil
- cs.blocksDownloadPeerSelector.RankPeer(peer, peerRankInvalidDownload)
+ cs.blocksDownloadPeerSelector.rankPeer(psp, peerRankInvalidDownload)
continue
}
return cs.abort(fmt.Errorf("processStageLastestBlockDownload: genesis hash mismatches : genesis hash on genesis.json file is %v while genesis hash of downloaded block is %v", cs.ledger.GenesisHash(), blk.GenesisHash()))
@@ -389,7 +390,7 @@ func (cs *CatchpointCatchupService) processStageLastestBlockDownload() (err erro
if attemptsCount <= cs.config.CatchupBlockDownloadRetryAttempts {
// try again.
blk = nil
- cs.blocksDownloadPeerSelector.RankPeer(peer, peerRankInvalidDownload)
+ cs.blocksDownloadPeerSelector.rankPeer(psp, peerRankInvalidDownload)
continue
}
return cs.abort(fmt.Errorf("processStageLastestBlockDownload: downloaded block content does not match downloaded block header"))
@@ -405,14 +406,14 @@ func (cs *CatchpointCatchupService) processStageLastestBlockDownload() (err erro
// try again.
blk = nil
cs.log.Infof("processStageLastestBlockDownload: block %d verification against catchpoint failed, another attempt will be made; err = %v", blockRound, err)
- cs.blocksDownloadPeerSelector.RankPeer(peer, peerRankInvalidDownload)
+ cs.blocksDownloadPeerSelector.rankPeer(psp, peerRankInvalidDownload)
continue
}
return cs.abort(fmt.Errorf("processStageLastestBlockDownload failed when calling VerifyCatchpoint : %v", err))
}
// give a rank to the download, as the download was successful.
- peerRank := cs.blocksDownloadPeerSelector.PeerDownloadDurationToRank(peer, blockDownloadDuration)
- cs.blocksDownloadPeerSelector.RankPeer(peer, peerRank)
+ peerRank := cs.blocksDownloadPeerSelector.peerDownloadDurationToRank(psp, blockDownloadDuration)
+ cs.blocksDownloadPeerSelector.rankPeer(psp, peerRank)
err = cs.ledgerAccessor.StoreBalancesRound(cs.ctx, blk)
if err != nil {
@@ -495,11 +496,11 @@ func (cs *CatchpointCatchupService) processStageBlocksDownload() (err error) {
}
}
- peer := network.Peer(0)
+ var psp *peerSelectorPeer
blockDownloadDuration := time.Duration(0)
if blk == nil {
var stop bool
- blk, blockDownloadDuration, peer, stop, err = cs.fetchBlock(topBlock.Round()-basics.Round(blocksFetched), retryCount)
+ blk, blockDownloadDuration, psp, stop, err = cs.fetchBlock(topBlock.Round()-basics.Round(blocksFetched), retryCount)
if stop {
return err
} else if blk == nil {
@@ -515,7 +516,7 @@ func (cs *CatchpointCatchupService) processStageBlocksDownload() (err error) {
// not identical, retry download.
cs.log.Warnf("processStageBlocksDownload downloaded block(%d) did not match it's successor(%d) block hash %v != %v", blk.Round(), prevBlock.Round(), blk.Hash(), prevBlock.BlockHeader.Branch)
cs.updateBlockRetrievalStatistics(-1, 0)
- cs.blocksDownloadPeerSelector.RankPeer(peer, peerRankInvalidDownload)
+ cs.blocksDownloadPeerSelector.rankPeer(psp, peerRankInvalidDownload)
if retryCount <= uint64(cs.config.CatchupBlockDownloadRetryAttempts) {
// try again.
retryCount++
@@ -528,7 +529,7 @@ func (cs *CatchpointCatchupService) processStageBlocksDownload() (err error) {
if _, ok := config.Consensus[blk.BlockHeader.CurrentProtocol]; !ok {
cs.log.Warnf("processStageBlocksDownload: unsupported protocol version detected: '%v'", blk.BlockHeader.CurrentProtocol)
cs.updateBlockRetrievalStatistics(-1, 0)
- cs.blocksDownloadPeerSelector.RankPeer(peer, peerRankInvalidDownload)
+ cs.blocksDownloadPeerSelector.rankPeer(psp, peerRankInvalidDownload)
if retryCount <= uint64(cs.config.CatchupBlockDownloadRetryAttempts) {
// try again.
retryCount++
@@ -541,7 +542,7 @@ func (cs *CatchpointCatchupService) processStageBlocksDownload() (err error) {
if !blk.ContentsMatchHeader() {
cs.log.Warnf("processStageBlocksDownload: downloaded block content does not match downloaded block header")
// try again.
- cs.blocksDownloadPeerSelector.RankPeer(peer, peerRankInvalidDownload)
+ cs.blocksDownloadPeerSelector.rankPeer(psp, peerRankInvalidDownload)
cs.updateBlockRetrievalStatistics(-1, 0)
if retryCount <= uint64(cs.config.CatchupBlockDownloadRetryAttempts) {
// try again.
@@ -552,8 +553,8 @@ func (cs *CatchpointCatchupService) processStageBlocksDownload() (err error) {
}
cs.updateBlockRetrievalStatistics(0, 1)
- peerRank := cs.blocksDownloadPeerSelector.PeerDownloadDurationToRank(peer, blockDownloadDuration)
- cs.blocksDownloadPeerSelector.RankPeer(peer, peerRank)
+ peerRank := cs.blocksDownloadPeerSelector.peerDownloadDurationToRank(psp, blockDownloadDuration)
+ cs.blocksDownloadPeerSelector.rankPeer(psp, peerRank)
// all good, persist and move on.
err = cs.ledgerAccessor.StoreBlock(cs.ctx, blk)
@@ -581,39 +582,40 @@ func (cs *CatchpointCatchupService) processStageBlocksDownload() (err error) {
// fetchBlock uses the internal peer selector blocksDownloadPeerSelector to pick a peer and then attempt to fetch the block requested from that peer.
// The method return stop=true if the caller should exit the current operation
// If the method return a nil block, the caller is expected to retry the operation, increasing the retry counter as needed.
-func (cs *CatchpointCatchupService) fetchBlock(round basics.Round, retryCount uint64) (blk *bookkeeping.Block, downloadDuration time.Duration, peer network.Peer, stop bool, err error) {
- peer, err = cs.blocksDownloadPeerSelector.GetNextPeer()
+func (cs *CatchpointCatchupService) fetchBlock(round basics.Round, retryCount uint64) (blk *bookkeeping.Block, downloadDuration time.Duration, psp *peerSelectorPeer, stop bool, err error) {
+ psp, err = cs.blocksDownloadPeerSelector.getNextPeer()
if err != nil {
err = fmt.Errorf("fetchBlock: unable to obtain a list of peers to retrieve the latest block from")
- return nil, time.Duration(0), peer, true, cs.abort(err)
+ return nil, time.Duration(0), psp, true, cs.abort(err)
}
+ peer := psp.Peer
httpPeer, validPeer := peer.(network.HTTPPeer)
if !validPeer {
cs.log.Warnf("fetchBlock: non-HTTP peer was provided by the peer selector")
- cs.blocksDownloadPeerSelector.RankPeer(peer, peerRankInvalidDownload)
+ cs.blocksDownloadPeerSelector.rankPeer(psp, peerRankInvalidDownload)
if retryCount <= uint64(cs.config.CatchupBlockDownloadRetryAttempts) {
// try again.
- return nil, time.Duration(0), peer, false, nil
+ return nil, time.Duration(0), psp, false, nil
}
- return nil, time.Duration(0), peer, true, cs.abort(fmt.Errorf("fetchBlock: recurring non-HTTP peer was provided by the peer selector"))
+ return nil, time.Duration(0), psp, true, cs.abort(fmt.Errorf("fetchBlock: recurring non-HTTP peer was provided by the peer selector"))
}
fetcher := makeUniversalBlockFetcher(cs.log, cs.net, cs.config)
blk, _, downloadDuration, err = fetcher.fetchBlock(cs.ctx, round, httpPeer)
if err != nil {
if cs.ctx.Err() != nil {
- return nil, time.Duration(0), peer, true, cs.stopOrAbort()
+ return nil, time.Duration(0), psp, true, cs.stopOrAbort()
}
if retryCount <= uint64(cs.config.CatchupBlockDownloadRetryAttempts) {
// try again.
cs.log.Infof("Failed to download block %d on attempt %d out of %d. %v", round, retryCount, cs.config.CatchupBlockDownloadRetryAttempts, err)
- cs.blocksDownloadPeerSelector.RankPeer(peer, peerRankDownloadFailed)
- return nil, time.Duration(0), peer, false, nil
+ cs.blocksDownloadPeerSelector.rankPeer(psp, peerRankDownloadFailed)
+ return nil, time.Duration(0), psp, false, nil
}
- return nil, time.Duration(0), peer, true, cs.abort(fmt.Errorf("fetchBlock failed after multiple blocks download attempts"))
+ return nil, time.Duration(0), psp, true, cs.abort(fmt.Errorf("fetchBlock failed after multiple blocks download attempts"))
}
// success
- return blk, downloadDuration, peer, false, nil
+ return blk, downloadDuration, psp, false, nil
}
// processStageLedgerDownload is the fifth catchpoint catchup stage. It completes the catchup process, swap the new tables and restart the node functionality.
diff --git a/catchup/peerSelector.go b/catchup/peerSelector.go
index d8b3313d9..3b374691c 100644
--- a/catchup/peerSelector.go
+++ b/catchup/peerSelector.go
@@ -65,6 +65,13 @@ const (
var errPeerSelectorNoPeerPoolsAvailable = errors.New("no peer pools available")
+// peerSelectorPeer is a peer wrapper, adding to it the peerClass information
+// There can be multiple peer elements with the same address but different peer classes, and it is important to distinguish between them.
+type peerSelectorPeer struct {
+ network.Peer
+ peerClass network.PeerOption
+}
+
// peerClass defines the type of peer we want to have in a particular "class",
// and define the network.PeerOption that would be used to retrieve that type of
// peer
@@ -112,18 +119,19 @@ type peerSelector struct {
// peer in the past, and to be forgiving of occasional performance
// variations which may not be representative of the peer's overall
// performance. It also stores the penalty history in the form or peer
-// selection gaps.
+// selection gaps, and the count of peerRankDownloadFailed incidents.
type historicStats struct {
- windowSize int
- rankSamples []int
- rankSum uint64
- requestGaps []uint64
- gapSum float64
- counter uint64
+ windowSize int
+ rankSamples []int
+ rankSum uint64
+ requestGaps []uint64
+ gapSum float64
+ counter uint64
+ downloadFailures int
}
-func makeHistoricStatus(windowSize int) *historicStats {
- // Initialize the window (rankSamples) with zeros.
+func makeHistoricStatus(windowSize int, class peerClass) *historicStats {
+ // Initialize the window (rankSamples) with zeros but rankSum with the equivalent sum of class initial rank.
// This way, every peer will slowly build up its profile.
// Otherwise, if the best peer gets a bad download the first time,
// that will determine the rank of the peer.
@@ -131,8 +139,11 @@ func makeHistoricStatus(windowSize int) *historicStats {
windowSize: windowSize,
rankSamples: make([]int, windowSize, windowSize),
requestGaps: make([]uint64, 0, windowSize),
- rankSum: 0,
+ rankSum: uint64(class.initialRank) * uint64(windowSize),
gapSum: 0.0}
+ for i := 0; i < windowSize; i++ {
+ hs.rankSamples[i] = class.initialRank
+ }
return &hs
}
@@ -146,7 +157,7 @@ func (hs *historicStats) computerPenalty() float64 {
// counter for ranking a peer. It calculates newGap, which is the
// number of counter ticks since it last was updated (i.e. last ranked
// after being selected). The number of gaps stored is bounded by the
-// windowSize. Calculages and returns the new penalty.
+// windowSize. Calculates and returns the new penalty.
func (hs *historicStats) updateRequestPenalty(counter uint64) float64 {
newGap := counter - hs.counter
hs.counter = counter
@@ -188,7 +199,7 @@ func (hs *historicStats) resetRequestPenalty(steps int, initialRank int, class p
hs.gapSum -= 1.0 / float64(hs.requestGaps[s])
}
hs.requestGaps = hs.requestGaps[steps:]
- return int(hs.computerPenalty() * (float64(hs.rankSum) / float64(len(hs.rankSamples))))
+ return boundRankByClass(int(hs.computerPenalty()*(float64(hs.rankSum)/float64(len(hs.rankSamples)))), class)
}
// push pushes a new rank to the historicStats, and returns the new
@@ -213,13 +224,20 @@ func (hs *historicStats) push(value int, counter uint64, class peerClass) (avera
// Download may fail for various reasons. Give it additional tries
// and see if it recovers/improves.
if value == peerRankDownloadFailed {
- // Set the rank to 10 + the class upper bound, to evict
- // the peer from the class if it is repeatedly
- // failing. This is to make sure to switch to the next
- // class when all peers in this class are failing.
- // Here, +10 is added. This is of little consequence, and the
- // purpose is to avoid rounding errors.
- value = upperBound(class) + 10
+ hs.downloadFailures++
+ // - Set the rank to the class upper bound multiplied
+ // by the number of downloadFailures.
+ // - Each downloadFailure increments the counter, and
+ // each non-failure decrements it, until it gets to 0.
+ // - When the peer is consistently failing to
+ // download, the value added to rankSum will
+ // increase at an increasing rate to evict the peer
+ // from the class sooner.
+ value = upperBound(class) * int(math.Exp2(float64(hs.downloadFailures)))
+ } else {
+ if hs.downloadFailures > 0 {
+ hs.downloadFailures--
+ }
}
hs.rankSamples = append(hs.rankSamples, value)
@@ -259,10 +277,10 @@ func makePeerSelector(net peersRetriever, initialPeersClasses []peerClass) *peer
return selector
}
-// GetNextPeer returns the next peer. It randomally selects a peer from a pool that has
+// getNextPeer returns the next peer. It randomally selects a peer from a pool that has
// the lowest rank value. Given that the peers are grouped by their ranks, allow us to
// prioritize peers based on their class and/or performance.
-func (ps *peerSelector) GetNextPeer() (peer network.Peer, err error) {
+func (ps *peerSelector) getNextPeer() (psp *peerSelectorPeer, err error) {
ps.mu.Lock()
defer ps.mu.Unlock()
ps.refreshAvailablePeers()
@@ -273,25 +291,24 @@ func (ps *peerSelector) GetNextPeer() (peer network.Peer, err error) {
// provide the needed test.
// pick one of the peers from this pool at random
peerIdx := crypto.RandUint64() % uint64(len(pool.peers))
- peer = pool.peers[peerIdx].peer
+ psp = &peerSelectorPeer{pool.peers[peerIdx].peer, pool.peers[peerIdx].class.peerClass}
return
}
}
-
return nil, errPeerSelectorNoPeerPoolsAvailable
}
-// RankPeer ranks a given peer.
+// rankPeer ranks a given peer.
// return the old value and the new updated value.
// updated value could be different from the input rank.
-func (ps *peerSelector) RankPeer(peer network.Peer, rank int) (int, int) {
- if peer == nil {
+func (ps *peerSelector) rankPeer(psp *peerSelectorPeer, rank int) (int, int) {
+ if psp == nil {
return -1, -1
}
ps.mu.Lock()
defer ps.mu.Unlock()
- poolIdx, peerIdx := ps.findPeer(peer)
+ poolIdx, peerIdx := ps.findPeer(psp)
if poolIdx < 0 || peerIdx < 0 {
return -1, -1
}
@@ -313,15 +330,15 @@ func (ps *peerSelector) RankPeer(peer network.Peer, rank int) (int, int) {
ps.pools = append(ps.pools[:poolIdx], ps.pools[poolIdx+1:]...)
}
- sortNeeded = ps.addToPool(peer, rank, class, peerHistory)
+ sortNeeded = ps.addToPool(psp.Peer, rank, class, peerHistory)
}
- // Update the ranks of the peers by reducing the penalty for not beeing selected
+ // Update the ranks of the peers by reducing the penalty for not being selected
for pl := len(ps.pools) - 1; pl >= 0; pl-- {
pool := ps.pools[pl]
for pr := len(pool.peers) - 1; pr >= 0; pr-- {
localPeer := pool.peers[pr]
- if pool.peers[pr].peer == peer {
+ if pool.peers[pr].peer == psp.Peer {
continue
}
// make the removal of penalty at a faster rate than adding it, so that the
@@ -350,11 +367,11 @@ func (ps *peerSelector) RankPeer(peer network.Peer, rank int) (int, int) {
return initialRank, rank
}
-// PeerDownloadDurationToRank calculates the rank for a peer given a peer and the block download time.
-func (ps *peerSelector) PeerDownloadDurationToRank(peer network.Peer, blockDownloadDuration time.Duration) (rank int) {
+// peerDownloadDurationToRank calculates the rank for a peer given a peer and the block download time.
+func (ps *peerSelector) peerDownloadDurationToRank(psp *peerSelectorPeer, blockDownloadDuration time.Duration) (rank int) {
ps.mu.Lock()
defer ps.mu.Unlock()
- poolIdx, peerIdx := ps.findPeer(peer)
+ poolIdx, peerIdx := ps.findPeer(psp)
if poolIdx < 0 || peerIdx < 0 {
return peerRankInvalidDownload
}
@@ -387,7 +404,7 @@ func (ps *peerSelector) addToPool(peer network.Peer, rank int, class peerClass,
return true
}
-// sort the pools array in an accending order according to the rank of each pool.
+// sort the pools array in an ascending order according to the rank of each pool.
func (ps *peerSelector) sort() {
sort.SliceStable(ps.pools, func(i, j int) bool {
return ps.pools[i].rank < ps.pools[j].rank
@@ -409,11 +426,15 @@ func peerAddress(peer network.Peer) string {
// refreshAvailablePeers reload the available peers from the network package, add new peers along with their
// corresponding initial rank, and deletes peers that have been dropped by the network package.
func (ps *peerSelector) refreshAvailablePeers() {
- existingPeers := make(map[string]network.Peer)
+ existingPeers := make(map[network.PeerOption]map[string]bool)
for _, pool := range ps.pools {
for _, localPeer := range pool.peers {
if peerAddress := peerAddress(localPeer.peer); peerAddress != "" {
- existingPeers[peerAddress] = localPeer.peer
+ // Init the existingPeers map
+ if _, has := existingPeers[localPeer.class.peerClass]; !has {
+ existingPeers[localPeer.class.peerClass] = make(map[string]bool)
+ }
+ existingPeers[localPeer.class.peerClass][peerAddress] = true
}
}
}
@@ -425,12 +446,13 @@ func (ps *peerSelector) refreshAvailablePeers() {
if peerAddress == "" {
continue
}
- if _, has := existingPeers[peerAddress]; has {
- delete(existingPeers, peerAddress)
+ if _, has := existingPeers[initClass.peerClass][peerAddress]; has {
+ // Setting to false instead of deleting the element to be safe against duplicate peer addresses.
+ existingPeers[initClass.peerClass][peerAddress] = false
continue
}
// it's an entry which we did not have before.
- sortNeeded = ps.addToPool(peer, initClass.initialRank, initClass, makeHistoricStatus(peerHistoryWindowSize)) || sortNeeded
+ sortNeeded = ps.addToPool(peer, initClass.initialRank, initClass, makeHistoricStatus(peerHistoryWindowSize, initClass)) || sortNeeded
}
}
@@ -440,7 +462,7 @@ func (ps *peerSelector) refreshAvailablePeers() {
for peerIdx := len(pool.peers) - 1; peerIdx >= 0; peerIdx-- {
peer := pool.peers[peerIdx].peer
if peerAddress := peerAddress(peer); peerAddress != "" {
- if _, has := existingPeers[peerAddress]; has {
+ if toRemove, _ := existingPeers[pool.peers[peerIdx].class.peerClass][peerAddress]; toRemove {
// need to be removed.
pool.peers = append(pool.peers[:peerIdx], pool.peers[peerIdx+1:]...)
}
@@ -461,14 +483,16 @@ func (ps *peerSelector) refreshAvailablePeers() {
// findPeer look into the peer pool and find the given peer.
// The method returns the pool and peer indices if a peer was found, or (-1, -1) otherwise.
-func (ps *peerSelector) findPeer(peer network.Peer) (poolIdx, peerIdx int) {
- peerAddr := peerAddress(peer)
- if peerAddr != "" {
- for i, pool := range ps.pools {
- for j, localPeerEntry := range pool.peers {
- if peerAddress(localPeerEntry.peer) == peerAddr {
- return i, j
- }
+func (ps *peerSelector) findPeer(psp *peerSelectorPeer) (poolIdx, peerIdx int) {
+ peerAddr := peerAddress(psp.Peer)
+ if peerAddr == "" {
+ return -1, -1
+ }
+ for i, pool := range ps.pools {
+ for j, localPeerEntry := range pool.peers {
+ if peerAddress(localPeerEntry.peer) == peerAddr &&
+ localPeerEntry.class.peerClass == psp.peerClass {
+ return i, j
}
}
}
diff --git a/catchup/peerSelector_test.go b/catchup/peerSelector_test.go
index 170aba1f1..c86267e51 100644
--- a/catchup/peerSelector_test.go
+++ b/catchup/peerSelector_test.go
@@ -17,8 +17,9 @@
package catchup
import (
+ "bytes"
"context"
- "fmt"
+ "encoding/binary"
"net/http"
"testing"
"time"
@@ -119,46 +120,50 @@ func TestPeerSelector(t *testing.T) {
}), []peerClass{{initialRank: peerRankInitialFirstPriority, peerClass: network.PeersPhonebookArchivers}},
)
- peer, err := peerSelector.GetNextPeer()
+ psp, err := peerSelector.getNextPeer()
require.NoError(t, err)
+ peer := psp.Peer
require.Equal(t, "12345", peerAddress(peer))
// replace peer.
peers = []network.Peer{&mockHTTPPeer{address: "54321"}}
- peer, err = peerSelector.GetNextPeer()
+ psp, err = peerSelector.getNextPeer()
require.NoError(t, err)
+ peer = psp.Peer
require.Equal(t, "54321", peerAddress(peer))
// add another peer
peers = []network.Peer{&mockHTTPPeer{address: "54321"}, &mockHTTPPeer{address: "abcde"}}
- r1, r2 := peerSelector.RankPeer(peer, 5)
+ r1, r2 := peerSelector.rankPeer(psp, 5)
require.True(t, r1 != r2)
- peer, err = peerSelector.GetNextPeer()
+ psp, err = peerSelector.getNextPeer()
require.NoError(t, err)
+ peer = psp.Peer
require.Equal(t, "abcde", peerAddress(peer))
- r1, r2 = peerSelector.RankPeer(peer, 10)
+ r1, r2 = peerSelector.rankPeer(psp, 200)
require.True(t, r1 != r2)
- peer, err = peerSelector.GetNextPeer()
+ psp, err = peerSelector.getNextPeer()
require.NoError(t, err)
+ peer = psp.Peer
require.Equal(t, "54321", peerAddress(peer))
peers = []network.Peer{t} // include a non-peer object, to test the refreshAvailablePeers handling of empty addresses.
- peer, err = peerSelector.GetNextPeer()
+ psp, err = peerSelector.getNextPeer()
require.Equal(t, errPeerSelectorNoPeerPoolsAvailable, err)
- require.Nil(t, peer)
+ require.Nil(t, psp)
// create an empty entry ( even though the code won't let it happen )
peerSelector.pools = []peerPool{{rank: peerRankInitialFirstPriority}}
- peer, err = peerSelector.GetNextPeer()
+ psp, err = peerSelector.getNextPeer()
require.Equal(t, errPeerSelectorNoPeerPoolsAvailable, err)
- require.Nil(t, peer)
+ require.Nil(t, psp)
- r1, r2 = peerSelector.RankPeer(nil, 10)
+ r1, r2 = peerSelector.rankPeer(nil, 10)
require.False(t, r1 != r2)
- r2, r2 = peerSelector.RankPeer(&mockHTTPPeer{address: "abc123"}, 10)
+ r2, r2 = peerSelector.rankPeer(&peerSelectorPeer{&mockHTTPPeer{address: "abc123"}, 1}, 10)
require.False(t, r1 != r2)
return
@@ -181,36 +186,36 @@ func TestPeerDownloadRanking(t *testing.T) {
}), []peerClass{{initialRank: peerRankInitialFirstPriority, peerClass: network.PeersPhonebookArchivers},
{initialRank: peerRankInitialSecondPriority, peerClass: network.PeersPhonebookRelays}},
)
- archivalPeer, err := peerSelector.GetNextPeer()
+ archivalPeer, err := peerSelector.getNextPeer()
require.NoError(t, err)
- require.Equal(t, downloadDurationToRank(500*time.Millisecond, lowBlockDownloadThreshold, highBlockDownloadThreshold, peerRank0LowBlockTime, peerRank0HighBlockTime), peerSelector.PeerDownloadDurationToRank(archivalPeer, 500*time.Millisecond))
+ require.Equal(t, downloadDurationToRank(500*time.Millisecond, lowBlockDownloadThreshold, highBlockDownloadThreshold, peerRank0LowBlockTime, peerRank0HighBlockTime), peerSelector.peerDownloadDurationToRank(archivalPeer, 500*time.Millisecond))
- peerSelector.RankPeer(archivalPeer, peerRankInvalidDownload)
+ peerSelector.rankPeer(archivalPeer, peerRankInvalidDownload)
- archivalPeer, err = peerSelector.GetNextPeer()
+ archivalPeer, err = peerSelector.getNextPeer()
require.NoError(t, err)
- require.Equal(t, downloadDurationToRank(500*time.Millisecond, lowBlockDownloadThreshold, highBlockDownloadThreshold, peerRank0LowBlockTime, peerRank0HighBlockTime), peerSelector.PeerDownloadDurationToRank(archivalPeer, 500*time.Millisecond))
+ require.Equal(t, downloadDurationToRank(500*time.Millisecond, lowBlockDownloadThreshold, highBlockDownloadThreshold, peerRank0LowBlockTime, peerRank0HighBlockTime), peerSelector.peerDownloadDurationToRank(archivalPeer, 500*time.Millisecond))
- peerSelector.RankPeer(archivalPeer, peerRankInvalidDownload)
+ peerSelector.rankPeer(archivalPeer, peerRankInvalidDownload)
// and now test the relay peers
- relayPeer, err := peerSelector.GetNextPeer()
+ relayPeer, err := peerSelector.getNextPeer()
require.NoError(t, err)
- require.Equal(t, downloadDurationToRank(500*time.Millisecond, lowBlockDownloadThreshold, highBlockDownloadThreshold, peerRank1LowBlockTime, peerRank1HighBlockTime), peerSelector.PeerDownloadDurationToRank(relayPeer, 500*time.Millisecond))
+ require.Equal(t, downloadDurationToRank(500*time.Millisecond, lowBlockDownloadThreshold, highBlockDownloadThreshold, peerRank1LowBlockTime, peerRank1HighBlockTime), peerSelector.peerDownloadDurationToRank(relayPeer, 500*time.Millisecond))
- peerSelector.RankPeer(relayPeer, peerRankInvalidDownload)
+ peerSelector.rankPeer(relayPeer, peerRankInvalidDownload)
- relayPeer, err = peerSelector.GetNextPeer()
+ relayPeer, err = peerSelector.getNextPeer()
require.NoError(t, err)
- require.Equal(t, downloadDurationToRank(500*time.Millisecond, lowBlockDownloadThreshold, highBlockDownloadThreshold, peerRank1LowBlockTime, peerRank1HighBlockTime), peerSelector.PeerDownloadDurationToRank(relayPeer, 500*time.Millisecond))
+ require.Equal(t, downloadDurationToRank(500*time.Millisecond, lowBlockDownloadThreshold, highBlockDownloadThreshold, peerRank1LowBlockTime, peerRank1HighBlockTime), peerSelector.peerDownloadDurationToRank(relayPeer, 500*time.Millisecond))
- peerSelector.RankPeer(relayPeer, peerRankInvalidDownload)
+ peerSelector.rankPeer(relayPeer, peerRankInvalidDownload)
- require.Equal(t, peerRankInvalidDownload, peerSelector.PeerDownloadDurationToRank(&mockHTTPPeer{address: "abc123"}, time.Millisecond))
+ require.Equal(t, peerRankInvalidDownload, peerSelector.peerDownloadDurationToRank(&peerSelectorPeer{mockHTTPPeer{address: "abc123"}, 0}, time.Millisecond))
}
func TestFindMissingPeer(t *testing.T) {
@@ -220,7 +225,7 @@ func TestFindMissingPeer(t *testing.T) {
}), []peerClass{{initialRank: peerRankInitialFirstPriority, peerClass: network.PeersPhonebookArchivers}},
)
- poolIdx, peerIdx := peerSelector.findPeer(&mockHTTPPeer{address: "abcd"})
+ poolIdx, peerIdx := peerSelector.findPeer(&peerSelectorPeer{mockHTTPPeer{address: "abcd"}, 0})
require.Equal(t, -1, poolIdx)
require.Equal(t, -1, peerIdx)
}
@@ -246,7 +251,9 @@ func TestHistoricData(t *testing.T) {
var counters [5]int
for i := 0; i < 1000; i++ {
- peer, getPeerErr := peerSelector.GetNextPeer()
+ psp, getPeerErr := peerSelector.getNextPeer()
+ require.NoError(t, getPeerErr)
+ peer := psp.Peer
switch peer.(*mockHTTPPeer).address {
case "a1":
@@ -259,11 +266,11 @@ func TestHistoricData(t *testing.T) {
counters[3]++
case "b2":
counters[4]++
+ default:
+ require.Fail(t, "unexpected peer address `%s`", peer.(*mockHTTPPeer).address)
}
- require.NoError(t, getPeerErr)
- randVal := float64(crypto.RandUint64()%uint64(100)) / 100
- randVal = randVal + 1
+ randVal := peerSelectorTestRandVal(t, i)
if randVal < 1.98 {
var duration time.Duration
switch peer.(*mockHTTPPeer).address {
@@ -274,24 +281,27 @@ func TestHistoricData(t *testing.T) {
case "a3":
duration = time.Duration(100 * float64(time.Millisecond) * randVal)
}
- peerRank := peerSelector.PeerDownloadDurationToRank(peer, duration)
- peerSelector.RankPeer(peer, peerRank)
+ peerRank := peerSelector.peerDownloadDurationToRank(psp, duration)
+ peerSelector.rankPeer(psp, peerRank)
} else {
- peerSelector.RankPeer(peer, peerRankDownloadFailed)
+ peerSelector.rankPeer(psp, peerRankDownloadFailed)
}
}
- fmt.Printf("a1: %d\n", counters[0])
- fmt.Printf("a2: %d\n", counters[1])
- fmt.Printf("a3: %d\n", counters[2])
- fmt.Printf("b1: %d\n", counters[3])
- fmt.Printf("b2: %d\n", counters[4])
require.GreaterOrEqual(t, counters[2], counters[1])
require.GreaterOrEqual(t, counters[2], counters[0])
require.Equal(t, counters[3], 0)
require.Equal(t, counters[4], 0)
}
+func peerSelectorTestRandVal(t *testing.T, seed int) float64 {
+ iterationDigest := crypto.Hash([]byte{byte(seed), byte(seed >> 8), byte(seed >> 16)})
+ randUint64, err := binary.ReadUvarint(bytes.NewReader(append([]byte{0}, iterationDigest[:]...)))
+ require.NoError(t, err)
+ randVal := float64(randUint64%uint64(100)) / 100
+ randVal = randVal + 1
+ return randVal
+}
func TestPeersDownloadFailed(t *testing.T) {
peers1 := []network.Peer{&mockHTTPPeer{address: "a1"}, &mockHTTPPeer{address: "a2"}, &mockHTTPPeer{address: "a3"}}
@@ -313,7 +323,8 @@ func TestPeersDownloadFailed(t *testing.T) {
var counters [5]int
for i := 0; i < 1000; i++ {
- peer, getPeerErr := peerSelector.GetNextPeer()
+ psp, getPeerErr := peerSelector.getNextPeer()
+ peer := psp.Peer
switch peer.(*mockHTTPPeer).address {
case "a1":
@@ -331,25 +342,19 @@ func TestPeersDownloadFailed(t *testing.T) {
require.NoError(t, getPeerErr)
if i < 500 || peerAddress(peer) == "b1" || peerAddress(peer) == "b2" {
- randVal := float64(crypto.RandUint64()%uint64(100)) / 100
- randVal = randVal + 1
+ randVal := peerSelectorTestRandVal(t, i)
if randVal < 1.98 {
duration := time.Duration(100 * float64(time.Millisecond) * randVal)
- peerRank := peerSelector.PeerDownloadDurationToRank(peer, duration)
- peerSelector.RankPeer(peer, peerRank)
+ peerRank := peerSelector.peerDownloadDurationToRank(psp, duration)
+ peerSelector.rankPeer(psp, peerRank)
} else {
- peerSelector.RankPeer(peer, peerRankDownloadFailed)
+ peerSelector.rankPeer(psp, peerRankDownloadFailed)
}
} else {
- peerSelector.RankPeer(peer, peerRankDownloadFailed)
+ peerSelector.rankPeer(psp, peerRankDownloadFailed)
}
}
- fmt.Printf("a1: %d\n", counters[0])
- fmt.Printf("a2: %d\n", counters[1])
- fmt.Printf("a3: %d\n", counters[2])
- fmt.Printf("b1: %d\n", counters[3])
- fmt.Printf("b2: %d\n", counters[4])
require.GreaterOrEqual(t, counters[3], 20)
require.GreaterOrEqual(t, counters[4], 20)
@@ -360,7 +365,7 @@ func TestPeersDownloadFailed(t *testing.T) {
require.True(t, b1orb2)
require.Equal(t, peerSelector.pools[1].rank, 900)
require.Equal(t, len(peerSelector.pools[1].peers), 3)
- } else {
+ } else { // len(pools) == 3
b1orb2 := peerAddress(peerSelector.pools[1].peers[0].peer) == "b1" || peerAddress(peerSelector.pools[1].peers[0].peer) == "b2"
require.True(t, b1orb2)
require.Equal(t, peerSelector.pools[2].rank, 900)
@@ -392,7 +397,8 @@ func TestPenalty(t *testing.T) {
var counters [5]int
for i := 0; i < 1000; i++ {
- peer, getPeerErr := peerSelector.GetNextPeer()
+ psp, getPeerErr := peerSelector.getNextPeer()
+ peer := psp.Peer
switch peer.(*mockHTTPPeer).address {
case "a1":
counters[0]++
@@ -416,28 +422,23 @@ func TestPenalty(t *testing.T) {
case "a3":
duration = time.Duration(100 * float64(time.Millisecond))
}
- peerRank := peerSelector.PeerDownloadDurationToRank(peer, duration)
- peerSelector.RankPeer(peer, peerRank)
+ peerRank := peerSelector.peerDownloadDurationToRank(psp, duration)
+ peerSelector.rankPeer(psp, peerRank)
}
- fmt.Printf("a1: %d\n", counters[0])
- fmt.Printf("a2: %d\n", counters[1])
- fmt.Printf("a3: %d\n", counters[2])
- fmt.Printf("b1: %d\n", counters[3])
- fmt.Printf("b2: %d\n", counters[4])
require.GreaterOrEqual(t, counters[1], 50)
require.GreaterOrEqual(t, counters[2], 2*counters[1])
require.Equal(t, counters[3], 0)
require.Equal(t, counters[4], 0)
}
-// TestPeerDownloadDurationToRank tests all the cases handled by PeerDownloadDurationToRank
+// TestPeerDownloadDurationToRank tests all the cases handled by peerDownloadDurationToRank
func TestPeerDownloadDurationToRank(t *testing.T) {
peers1 := []network.Peer{&mockHTTPPeer{address: "a1"}, &mockHTTPPeer{address: "a2"}, &mockHTTPPeer{address: "a3"}}
peers2 := []network.Peer{&mockHTTPPeer{address: "b1"}, &mockHTTPPeer{address: "b2"}}
peers3 := []network.Peer{&mockHTTPPeer{address: "c1"}, &mockHTTPPeer{address: "c2"}}
- peers4 := []network.Peer{&mockHTTPPeer{address: "d1"}, &mockHTTPPeer{address: "d2"}}
+ peers4 := []network.Peer{&mockHTTPPeer{address: "d1"}, &mockHTTPPeer{address: "b2"}}
peerSelector := makePeerSelector(
makePeersRetrieverStub(func(options ...network.PeerOption) (peers []network.Peer) {
@@ -459,17 +460,17 @@ func TestPeerDownloadDurationToRank(t *testing.T) {
{initialRank: peerRankInitialFourthPriority, peerClass: network.PeersConnectedIn}},
)
- _, err := peerSelector.GetNextPeer()
+ _, err := peerSelector.getNextPeer()
require.NoError(t, err)
require.Equal(t, downloadDurationToRank(500*time.Millisecond, lowBlockDownloadThreshold, highBlockDownloadThreshold, peerRank0LowBlockTime, peerRank0HighBlockTime),
- peerSelector.PeerDownloadDurationToRank(peers1[0], 500*time.Millisecond))
+ peerSelector.peerDownloadDurationToRank(&peerSelectorPeer{peers1[0], network.PeersPhonebookArchivers}, 500*time.Millisecond))
require.Equal(t, downloadDurationToRank(500*time.Millisecond, lowBlockDownloadThreshold, highBlockDownloadThreshold, peerRank1LowBlockTime, peerRank1HighBlockTime),
- peerSelector.PeerDownloadDurationToRank(peers2[0], 500*time.Millisecond))
+ peerSelector.peerDownloadDurationToRank(&peerSelectorPeer{peers2[0], network.PeersPhonebookRelays}, 500*time.Millisecond))
require.Equal(t, downloadDurationToRank(500*time.Millisecond, lowBlockDownloadThreshold, highBlockDownloadThreshold, peerRank2LowBlockTime, peerRank2HighBlockTime),
- peerSelector.PeerDownloadDurationToRank(peers3[0], 500*time.Millisecond))
+ peerSelector.peerDownloadDurationToRank(&peerSelectorPeer{peers3[0], network.PeersConnectedOut}, 500*time.Millisecond))
require.Equal(t, downloadDurationToRank(500*time.Millisecond, lowBlockDownloadThreshold, highBlockDownloadThreshold, peerRank3LowBlockTime, peerRank3HighBlockTime),
- peerSelector.PeerDownloadDurationToRank(peers4[0], 500*time.Millisecond))
+ peerSelector.peerDownloadDurationToRank(&peerSelectorPeer{peers4[0], network.PeersConnectedIn}, 500*time.Millisecond))
}
func TestLowerUpperBounds(t *testing.T) {
@@ -491,10 +492,108 @@ func TestLowerUpperBounds(t *testing.T) {
func TestFullResetRequestPenalty(t *testing.T) {
class := peerClass{initialRank: 10, peerClass: network.PeersPhonebookArchivers}
- hs := makeHistoricStatus(10)
+ hs := makeHistoricStatus(10, class)
hs.push(5, 1, class)
require.Equal(t, 1, len(hs.requestGaps))
hs.resetRequestPenalty(0, 0, class)
require.Equal(t, 0, len(hs.requestGaps))
}
+
+// TestClassUpperBound makes sure the peer rank does not exceed the class upper bound
+// This was a bug where the resetRequestPenalty was not bounding the returned rank, and was having download failures.
+// Initializing rankSamples to 0 makes this works, since the dropped value subtracts 0 from rankSum.
+func TestClassUpperBound(t *testing.T) {
+
+ peers1 := []network.Peer{&mockHTTPPeer{address: "a1"}, &mockHTTPPeer{address: "a2"}}
+ pClass := peerClass{initialRank: peerRankInitialSecondPriority, peerClass: network.PeersPhonebookArchivers}
+ peerSelector := makePeerSelector(
+ makePeersRetrieverStub(func(options ...network.PeerOption) (peers []network.Peer) {
+ for _, opt := range options {
+ if opt == network.PeersPhonebookArchivers {
+ peers = append(peers, peers1...)
+ }
+ }
+ return
+ }), []peerClass{pClass})
+
+ _, err := peerSelector.getNextPeer()
+ require.NoError(t, err)
+ for i := 0; i < 200; i++ {
+ psp, err := peerSelector.getNextPeer()
+ require.NoError(t, err)
+ if i < 6 {
+ peerSelector.rankPeer(psp, peerRankDownloadFailed)
+ } else {
+ peerSelector.rankPeer(psp, upperBound(pClass))
+ }
+ for _, pool := range peerSelector.pools {
+ require.LessOrEqual(t, pool.rank, upperBound(pClass))
+ }
+ }
+}
+
+// TestClassLowerBound makes sure the peer rank does not go under the class lower bound
+// This was a bug where the resetRequestPenalty was not bounding the returned rank, and the rankSum was not
+// initialized to give the average of class.initialRank
+func TestClassLowerBound(t *testing.T) {
+
+ peers1 := []network.Peer{&mockHTTPPeer{address: "a1"}, &mockHTTPPeer{address: "a2"}}
+ pClass := peerClass{initialRank: peerRankInitialSecondPriority, peerClass: network.PeersPhonebookArchivers}
+ peerSelector := makePeerSelector(
+ makePeersRetrieverStub(func(options ...network.PeerOption) (peers []network.Peer) {
+ for _, opt := range options {
+ if opt == network.PeersPhonebookArchivers {
+ peers = append(peers, peers1...)
+ }
+ }
+ return
+ }), []peerClass{pClass})
+
+ _, err := peerSelector.getNextPeer()
+ require.NoError(t, err)
+ for i := 0; i < 10; i++ {
+ psp, err := peerSelector.getNextPeer()
+ require.NoError(t, err)
+ peerSelector.rankPeer(psp, lowerBound(pClass))
+
+ for _, pool := range peerSelector.pools {
+ require.GreaterOrEqual(t, pool.rank, pool.peers[0].class.initialRank)
+ }
+ }
+}
+
+// TestEviction tests that the peer is evicted after several download failures, and it handles same address for different peer classes
+func TestEvictionAndUpgrade(t *testing.T) {
+
+ peers1 := []network.Peer{&mockHTTPPeer{address: "a1"}}
+ peers2 := []network.Peer{&mockHTTPPeer{address: "a1"}}
+
+ peerSelector := makePeerSelector(
+ makePeersRetrieverStub(func(options ...network.PeerOption) (peers []network.Peer) {
+ for _, opt := range options {
+ if opt == network.PeersPhonebookArchivers {
+ peers = append(peers, peers1...)
+ } else {
+ peers = append(peers, peers2...)
+ }
+ }
+ return
+ }), []peerClass{{initialRank: peerRankInitialFirstPriority, peerClass: network.PeersPhonebookArchivers},
+ {initialRank: peerRankInitialSecondPriority, peerClass: network.PeersPhonebookRelays}},
+ )
+
+ _, err := peerSelector.getNextPeer()
+ require.NoError(t, err)
+ for i := 0; i < 10; i++ {
+ if peerSelector.pools[len(peerSelector.pools)-1].rank == 900 {
+ require.Equal(t, 6, i)
+ break
+ }
+ psp, err := peerSelector.getNextPeer()
+ require.NoError(t, err)
+ peerSelector.rankPeer(psp, peerRankDownloadFailed)
+ }
+ psp, err := peerSelector.getNextPeer()
+ require.Equal(t, psp.peerClass, network.PeersPhonebookRelays)
+}
diff --git a/catchup/service.go b/catchup/service.go
index 7d34b4a7c..9e762e377 100644
--- a/catchup/service.go
+++ b/catchup/service.go
@@ -208,18 +208,19 @@ func (s *Service) fetchAndWrite(r basics.Round, prevFetchCompleteChan chan bool,
return false
}
- peer, getPeerErr := peerSelector.GetNextPeer()
+ psp, getPeerErr := peerSelector.getNextPeer()
if getPeerErr != nil {
s.log.Debugf("fetchAndWrite: was unable to obtain a peer to retrieve the block from")
break
}
+ peer := psp.Peer
// Try to fetch, timing out after retryInterval
block, cert, blockDownloadDuration, err := s.innerFetch(r, peer)
if err != nil {
s.log.Debugf("fetchAndWrite(%v): Could not fetch: %v (attempt %d)", r, err, i)
- peerSelector.RankPeer(peer, peerRankDownloadFailed)
+ peerSelector.rankPeer(psp, peerRankDownloadFailed)
// we've just failed to retrieve a block; wait until the previous block is fetched before trying again
// to avoid the usecase where the first block doesn't exists and we're making many requests down the chain
// for no reason.
@@ -245,7 +246,7 @@ func (s *Service) fetchAndWrite(r basics.Round, prevFetchCompleteChan chan bool,
// Check that the block's contents match the block header (necessary with an untrusted block because b.Hash() only hashes the header)
if s.cfg.CatchupVerifyPaysetHash() {
if !block.ContentsMatchHeader() {
- peerSelector.RankPeer(peer, peerRankInvalidDownload)
+ peerSelector.rankPeer(psp, peerRankInvalidDownload)
// Check if this mismatch is due to an unsupported protocol version
if _, ok := config.Consensus[block.BlockHeader.CurrentProtocol]; !ok {
s.log.Errorf("fetchAndWrite(%v): unsupported protocol version detected: '%v'", r, block.BlockHeader.CurrentProtocol)
@@ -274,13 +275,13 @@ func (s *Service) fetchAndWrite(r basics.Round, prevFetchCompleteChan chan bool,
err = s.auth.Authenticate(block, cert)
if err != nil {
s.log.Warnf("fetchAndWrite(%v): cert did not authenticate block (attempt %d): %v", r, i, err)
- peerSelector.RankPeer(peer, peerRankInvalidDownload)
+ peerSelector.rankPeer(psp, peerRankInvalidDownload)
continue // retry the fetch
}
}
- peerRank := peerSelector.PeerDownloadDurationToRank(peer, blockDownloadDuration)
- r1, r2 := peerSelector.RankPeer(peer, peerRank)
+ peerRank := peerSelector.peerDownloadDurationToRank(psp, blockDownloadDuration)
+ r1, r2 := peerSelector.rankPeer(psp, peerRank)
s.log.Debugf("fetchAndWrite(%d): ranked peer with %d from %d to %d", r, peerRank, r1, r2)
// Write to ledger, noting that ledger writes must be in order
@@ -383,7 +384,7 @@ func (s *Service) pipelinedFetch(seedLookback uint64) {
peerSelector := s.createPeerSelector(true)
- if _, err := peerSelector.GetNextPeer(); err == errPeerSelectorNoPeerPoolsAvailable {
+ if _, err := peerSelector.getNextPeer(); err == errPeerSelectorNoPeerPoolsAvailable {
s.log.Debugf("pipelinedFetch: was unable to obtain a peer to retrieve the block from")
return
}
@@ -481,7 +482,7 @@ func (s *Service) periodicSync() {
defer close(s.done)
// if the catchup is disabled in the config file, just skip it.
if s.parallelBlocks != 0 && !s.cfg.DisableNetworking {
- // The following request might be redundent, but it ensures we wait long enough for the DNS records to be loaded,
+ // The following request might be redundant, but it ensures we wait long enough for the DNS records to be loaded,
// which are required for the sync operation.
s.net.RequestConnectOutgoing(false, s.ctx.Done())
s.sync()
@@ -599,15 +600,25 @@ func (s *Service) syncCert(cert *PendingUnmatchedCertificate) {
// TODO this doesn't actually use the digest from cert!
func (s *Service) fetchRound(cert agreement.Certificate, verifier *agreement.AsyncVoteVerifier) {
+ // is there any point attempting to retrieve the block ?
+ if s.nextRoundIsNotSupported(cert.Round) {
+ // we might get here if the agreement service was seeing the certs votes for the next
+ // block, without seeing the actual block. Since it hasn't seen the block, it couldn't
+ // tell that it's an unsupported protocol, and would try to request it from the catchup.
+ s.handleUnsupportedRound(cert.Round)
+ return
+ }
+
blockHash := bookkeeping.BlockHash(cert.Proposal.BlockDigest) // semantic digest (i.e., hash of the block header), not byte-for-byte digest
peerSelector := s.createPeerSelector(false)
for s.ledger.LastRound() < cert.Round {
- peer, getPeerErr := peerSelector.GetNextPeer()
+ psp, getPeerErr := peerSelector.getNextPeer()
if getPeerErr != nil {
s.log.Debugf("fetchRound: was unable to obtain a peer to retrieve the block from")
s.net.RequestConnectOutgoing(true, s.ctx.Done())
continue
}
+ peer := psp.Peer
// Ask the fetcher to get the block somehow
block, fetchedCert, _, err := s.innerFetch(cert.Round, peer)
@@ -620,7 +631,7 @@ func (s *Service) fetchRound(cert agreement.Certificate, verifier *agreement.Asy
default:
}
logging.Base().Warnf("fetchRound could not acquire block, fetcher errored out: %v", err)
- peerSelector.RankPeer(peer, peerRankDownloadFailed)
+ peerSelector.rankPeer(psp, peerRankDownloadFailed)
continue
}
@@ -630,7 +641,7 @@ func (s *Service) fetchRound(cert agreement.Certificate, verifier *agreement.Asy
}
// Otherwise, fetcher gave us the wrong block
logging.Base().Warnf("fetcher gave us bad/wrong block (for round %d): fetched hash %v; want hash %v", cert.Round, block.Hash(), blockHash)
- peerSelector.RankPeer(peer, peerRankInvalidDownload)
+ peerSelector.rankPeer(psp, peerRankInvalidDownload)
// As a failsafe, if the cert we fetched is valid but for the wrong block, panic as loudly as possible
if cert.Round == fetchedCert.Round &&
diff --git a/catchup/service_test.go b/catchup/service_test.go
index c01e5ffe1..1ca3aa63b 100644
--- a/catchup/service_test.go
+++ b/catchup/service_test.go
@@ -161,8 +161,23 @@ func TestServiceFetchBlocksSameRange(t *testing.T) {
require.Equal(t, rr, lr)
}
+type periodicSyncLogger struct {
+ logging.Logger
+ WarnfCallback func(string, ...interface{})
+}
+
+func (cl *periodicSyncLogger) Warnf(s string, args ...interface{}) {
+ // filter out few non-interesting warnings.
+ switch s {
+ case "fetchAndWrite(%v): lookback block doesn't exist, cannot authenticate new block":
+ return
+ case "fetchAndWrite(%v): cert did not authenticate block (attempt %d): %v":
+ return
+ }
+ cl.Logger.Warnf(s, args...)
+}
+
func TestPeriodicSync(t *testing.T) {
- t.Skip("Disabling since they need work and shouldn't block releases")
// Make Ledger
local := new(mockedLedger)
local.blocks = append(local.blocks, bookkeeping.Block{})
@@ -192,18 +207,29 @@ func TestPeriodicSync(t *testing.T) {
// Make Service
s := MakeService(logging.Base(), defaultConfig, net, local, auth, nil, nil)
+ s.log = &periodicSyncLogger{Logger: logging.Base()}
s.deadlineTimeout = 2 * time.Second
s.Start()
defer s.Stop()
+ // wait past the initial sync - which is known to fail due to the above "auth"
time.Sleep(s.deadlineTimeout*2 - 200*time.Millisecond)
require.Equal(t, initialLocalRound, local.LastRound())
auth.alter(-1, false)
- time.Sleep(2 * time.Second)
+ // wait until the catchup is done. Since we've might have missed the sleep window, we need to wait
+ // until the synchronization is complete.
+ waitStart := time.Now()
+ for time.Now().Sub(waitStart) < 10*s.deadlineTimeout {
+ if remote.LastRound() == local.LastRound() {
+ break
+ }
+ time.Sleep(20 * time.Millisecond)
+ }
// Asserts that the last block is the one we expect
rr, lr := remote.LastRound(), local.LastRound()
require.Equal(t, rr, lr)
+
for r := basics.Round(1); r < remote.LastRound(); r++ {
localBlock, err := local.Block(r)
require.NoError(t, err)
@@ -412,6 +438,7 @@ func TestServiceFetchBlocksMalformed(t *testing.T) {
// Make Service
s := MakeService(logging.Base(), defaultConfig, net, local, &mockedAuthenticator{errorRound: int(lastRoundAtStart + 1)}, nil, nil)
+ s.log = &periodicSyncLogger{Logger: logging.Base()}
// Start the service ( dummy )
s.testStart()
diff --git a/cmd/goal/account.go b/cmd/goal/account.go
index e508a71ce..ebda0935e 100644
--- a/cmd/goal/account.go
+++ b/cmd/goal/account.go
@@ -591,22 +591,28 @@ func printAccountInfo(client libgoal.Client, address string, account v1.Account)
}
for _, id := range heldAssets {
assetHolding := account.Assets[id]
- assetParams, err := client.AssetInformation(id)
+ assetParams, err := client.AssetInformationV2(id)
if err != nil {
hasError = true
fmt.Fprintf(errorReport, "Error: Unable to retrieve asset information for asset %d referred to by account %s: %v\n", id, address, err)
fmt.Fprintf(report, "\tID %d, error\n", id)
}
- amount := assetDecimalsFmt(assetHolding.Amount, assetParams.Decimals)
+ amount := assetDecimalsFmt(assetHolding.Amount, uint32(assetParams.Params.Decimals))
- assetName := assetParams.AssetName
+ var assetName string
+ if assetParams.Params.Name != nil {
+ assetName = *assetParams.Params.Name
+ }
if len(assetName) == 0 {
assetName = "<unnamed>"
}
_, assetName = unicodePrintable(assetName)
- unitName := assetParams.UnitName
+ var unitName string
+ if assetParams.Params.UnitName != nil {
+ unitName = *assetParams.Params.UnitName
+ }
if len(unitName) == 0 {
unitName = "units"
}
diff --git a/cmd/goal/clerk.go b/cmd/goal/clerk.go
index 466c175a3..cb41ff4e7 100644
--- a/cmd/goal/clerk.go
+++ b/cmd/goal/clerk.go
@@ -837,7 +837,7 @@ var groupCmd = &cobra.Command{
transactionIdx := 0
for {
var stxn transactions.SignedTxn
- // we decode the file into a SignedTxn since we want to verify the absense of the signature as well as preserve the AuthAddr.
+ // we decode the file into a SignedTxn since we want to verify the absence of the signature as well as preserve the AuthAddr.
err = dec.Decode(&stxn)
if err == io.EOF {
break
diff --git a/cmd/opdoc/opdoc.go b/cmd/opdoc/opdoc.go
index 6ceaf851b..334942a32 100644
--- a/cmd/opdoc/opdoc.go
+++ b/cmd/opdoc/opdoc.go
@@ -105,6 +105,11 @@ func assetParamsFieldsMarkdown(out io.Writer) {
fieldTableMarkdown(out, logic.AssetParamsFieldNames, logic.AssetParamsFieldTypes, logic.AssetParamsFieldDocs)
}
+func appParamsFieldsMarkdown(out io.Writer) {
+ fmt.Fprintf(out, "\n`app_params_get` Fields:\n\n")
+ fieldTableMarkdown(out, logic.AppParamsFieldNames, logic.AppParamsFieldTypes, logic.AppParamsFieldDocs)
+}
+
func immediateMarkdown(op *logic.OpSpec) string {
markdown := ""
for _, imm := range op.Details.Immediates {
@@ -179,6 +184,8 @@ func opToMarkdown(out io.Writer, op *logic.OpSpec) (err error) {
assetHoldingFieldsMarkdown(out)
} else if op.Name == "asset_params_get" {
assetParamsFieldsMarkdown(out)
+ } else if op.Name == "app_params_get" {
+ appParamsFieldsMarkdown(out)
}
ode := logic.OpDocExtra(op.Name)
if ode != "" {
@@ -240,6 +247,9 @@ func argEnum(name string) []string {
if name == "asset_params_get" {
return logic.AssetParamsFieldNames
}
+ if name == "app_params_get" {
+ return logic.AppParamsFieldNames
+ }
return nil
}
@@ -281,6 +291,9 @@ func argEnumTypes(name string) string {
if name == "asset_params_get" {
return typeString(logic.AssetParamsFieldTypes)
}
+ if name == "app_params_get" {
+ return typeString(logic.AppParamsFieldTypes)
+ }
return ""
}
@@ -344,6 +357,10 @@ func main() {
fieldTableMarkdown(assetparams, logic.AssetParamsFieldNames, logic.AssetParamsFieldTypes, logic.AssetParamsFieldDocs)
assetparams.Close()
+ appparams, _ := os.Create("app_params_fields.md")
+ fieldTableMarkdown(appparams, logic.AppParamsFieldNames, logic.AppParamsFieldTypes, logic.AppParamsFieldDocs)
+ appparams.Close()
+
langspecjs, _ := os.Create("langspec.json")
enc := json.NewEncoder(langspecjs)
enc.Encode(buildLanguageSpec(opGroups))
diff --git a/cmd/opdoc/tmLanguage.go b/cmd/opdoc/tmLanguage.go
index 35e513888..dda9a7976 100644
--- a/cmd/opdoc/tmLanguage.go
+++ b/cmd/opdoc/tmLanguage.go
@@ -172,10 +172,10 @@ func buildSyntaxHighlight() *tmLanguage {
Name: "keyword.other.unit.teal",
Match: fmt.Sprintf("^(%s)\\b", strings.Join(names, "|")),
})
- // For these three, accumulate into allArithmetics,
+ // For these four, accumulate into allArithmetics,
// and only add to keyword.Patterns later, when all
// have been collected.
- case "Arithmetic", "Byteslice Arithmetic", "Byteslice Logic":
+ case "Arithmetic", "Byte Array Slicing", "Byteslice Arithmetic", "Byteslice Logic":
escape := map[rune]bool{
'*': true,
'+': true,
diff --git a/cmd/tealdbg/cdtSession.go b/cmd/tealdbg/cdtSession.go
index 4845e7657..73cf03776 100644
--- a/cmd/tealdbg/cdtSession.go
+++ b/cmd/tealdbg/cdtSession.go
@@ -224,7 +224,7 @@ func (s *cdtSession) websocketHandler(w http.ResponseWriter, r *http.Request) {
select {
case devtoolResp := <-cdtRespCh:
if s.verbose {
- log.Printf("responsing: %v\n", devtoolResp)
+ log.Printf("responding: %v\n", devtoolResp)
}
err := ws.WriteJSON(&devtoolResp)
if err != nil {
diff --git a/cmd/tealdbg/debugger.go b/cmd/tealdbg/debugger.go
index 4ac43da08..0ed24bf85 100644
--- a/cmd/tealdbg/debugger.go
+++ b/cmd/tealdbg/debugger.go
@@ -29,7 +29,7 @@ import (
)
// Notification is sent to the client over their websocket connection
-// on each new TEAL execution/update/complation
+// on each new TEAL execution/update/completion
type Notification struct {
Event string `codec:"event"`
DebugState logic.DebugState `codec:"state"`
@@ -41,7 +41,7 @@ type DebugAdapter interface {
// Control interface must be used to manage execution (step, break, resume, etc).
// Notification channel must be used for receiving events from the debugger.
SessionStarted(sid string, debugger Control, ch chan Notification)
- // SessionStarted is called by the debugging core on the competion of execution.
+ // SessionStarted is called by the debugging core on the competition of execution.
SessionEnded(sid string)
// WaitForCompletion must returns only when all session were completed and block otherwise.
WaitForCompletion()
diff --git a/cmd/tealdbg/debugger_test.go b/cmd/tealdbg/debugger_test.go
index 42c2050a8..be517d5b4 100644
--- a/cmd/tealdbg/debugger_test.go
+++ b/cmd/tealdbg/debugger_test.go
@@ -129,7 +129,7 @@ func TestSession(t *testing.T) {
require.NoError(t, err)
// create a sample disassembly line to pc mapping
- // this simple source is similar to disassembly except intcblock at the begining
+ // this simple source is similar to disassembly except intcblock at the beginning
pcOffset := make(map[int]int, len(ops.OffsetToLine))
for pc, line := range ops.OffsetToLine {
pcOffset[line+1] = pc
diff --git a/config/config.go b/config/config.go
index 0ab143b89..7ba869c06 100644
--- a/config/config.go
+++ b/config/config.go
@@ -324,7 +324,7 @@ type Local struct {
CatchupBlockDownloadRetryAttempts int `version[9]:"1000"`
// EnableDeveloperAPI enables teal/compile, teal/dryrun API endpoints.
- // This functionlity is disabled by default.
+ // This functionality is disabled by default.
EnableDeveloperAPI bool `version[9]:"false"`
// OptimizeAccountsDatabaseOnStartup controls whether the accounts database would be optimized
diff --git a/config/config_test.go b/config/config_test.go
index 62a194da5..259044363 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -244,7 +244,7 @@ func loadWithoutDefaults(cfg Local) (Local, error) {
}
func TestConfigMigrate(t *testing.T) {
- t.Skip()
+
a := require.New(t)
c0, err := loadWithoutDefaults(getVersionedDefaultLocalConfig(0))
diff --git a/config/consensus.go b/config/consensus.go
index 718b4c5ff..5bee45ac6 100644
--- a/config/consensus.go
+++ b/config/consensus.go
@@ -546,7 +546,7 @@ func (cp ConsensusProtocols) Merge(configurableConsensus ConsensusProtocols) Con
return staticConsensus
}
-// LoadConfigurableConsensusProtocols loads the configurable protocols from the data directroy
+// LoadConfigurableConsensusProtocols loads the configurable protocols from the data directory
func LoadConfigurableConsensusProtocols(dataDirectory string) error {
newConsensus, err := PreloadConfigurableConsensusProtocols(dataDirectory)
if err != nil {
@@ -562,7 +562,7 @@ func LoadConfigurableConsensusProtocols(dataDirectory string) error {
return nil
}
-// PreloadConfigurableConsensusProtocols loads the configurable protocols from the data directroy
+// PreloadConfigurableConsensusProtocols loads the configurable protocols from the data directory
// and merge it with a copy of the Consensus map. Then, it returns it to the caller.
func PreloadConfigurableConsensusProtocols(dataDirectory string) (ConsensusProtocols, error) {
consensusProtocolPath := filepath.Join(dataDirectory, ConfigurableConsensusProtocolsFilename)
@@ -942,7 +942,7 @@ func initConsensusProtocols() {
v28 := v27
v28.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
- // Enable TEAL 4
+ // Enable TEAL 4 / AVM 0.9
v28.LogicSigVersion = 4
// Enable support for larger app program size
v28.MaxExtraAppProgramPages = 3
@@ -984,6 +984,9 @@ func initConsensusProtocols() {
vFuture.CompactCertWeightThreshold = (1 << 32) * 30 / 100
vFuture.CompactCertSecKQ = 128
+ // Enable TEAL 5 / AVM 1.0
+ vFuture.LogicSigVersion = 5
+
Consensus[protocol.ConsensusFuture] = vFuture
}
diff --git a/config/defaultsGenerator/defaultsGenerator.go b/config/defaultsGenerator/defaultsGenerator.go
index 0c6175df5..df5f4e14f 100644
--- a/config/defaultsGenerator/defaultsGenerator.go
+++ b/config/defaultsGenerator/defaultsGenerator.go
@@ -43,7 +43,7 @@ var autoGenHeader = `
`
// printExit prints the given formatted string ( i.e. just like fmt.Printf ), with the defaultGenerator executable program name
-// at the begining, and exit the process with a error code of 1.
+// at the beginning, and exit the process with a error code of 1.
func printExit(fmtStr string, args ...interface{}) {
fmt.Printf("%s: "+fmtStr, append([]interface{}{filepath.Base(os.Args[0])}, args...)...)
os.Exit(1)
diff --git a/config/migrate.go b/config/migrate.go
index b42bd66af..bc0392989 100644
--- a/config/migrate.go
+++ b/config/migrate.go
@@ -25,7 +25,7 @@ import (
//go:generate $GOROOT/bin/go run ./defaultsGenerator/defaultsGenerator.go -h ../scripts/LICENSE_HEADER -p config -o ./local_defaults.go -j ../installer/config.json.example
//go:generate $GOROOT/bin/go fmt local_defaults.go
-// AutogenLocal - this variable is the "input" for the config default generator which automatically updates the above defaultLocal varaible.
+// AutogenLocal - this variable is the "input" for the config default generator which automatically updates the above defaultLocal variable.
// it's implemented in ./config/defaults_gen.go, and should be the only "consumer" of this exported variable
var AutogenLocal = getVersionedDefaultLocalConfig(getLatestConfigVersion())
diff --git a/config/version.go b/config/version.go
index 3bd7f3fbc..6b19636e1 100644
--- a/config/version.go
+++ b/config/version.go
@@ -33,7 +33,7 @@ const VersionMajor = 2
// VersionMinor is the Minor semantic version number (x.#.z) - changed when backwards-compatible features are introduced.
// Not enforced until after initial public release (x > 0).
-const VersionMinor = 7
+const VersionMinor = 8
// Version is the type holding our full version information.
type Version struct {
diff --git a/crypto/curve25519.go b/crypto/curve25519.go
index acca76981..e0bf278de 100644
--- a/crypto/curve25519.go
+++ b/crypto/curve25519.go
@@ -19,6 +19,8 @@ package crypto
// #cgo CFLAGS: -Wall -std=c99
// #cgo darwin,amd64 CFLAGS: -I${SRCDIR}/libs/darwin/amd64/include
// #cgo darwin,amd64 LDFLAGS: ${SRCDIR}/libs/darwin/amd64/lib/libsodium.a
+// #cgo darwin,arm64 CFLAGS: -I${SRCDIR}/libs/darwin/arm64/include
+// #cgo darwin,arm64 LDFLAGS: ${SRCDIR}/libs/darwin/arm64/lib/libsodium.a
// #cgo linux,amd64 CFLAGS: -I${SRCDIR}/libs/linux/amd64/include
// #cgo linux,amd64 LDFLAGS: ${SRCDIR}/libs/linux/amd64/lib/libsodium.a
// #cgo linux,arm64 CFLAGS: -I${SRCDIR}/libs/linux/arm64/include
diff --git a/crypto/curve25519_test.go b/crypto/curve25519_test.go
index a001a0291..ea155e070 100644
--- a/crypto/curve25519_test.go
+++ b/crypto/curve25519_test.go
@@ -52,11 +52,11 @@ func TestGenerateSignatureSecrets(t *testing.T) {
for i := 0; i < 10; i++ {
secrets := GenerateSignatureSecrets(s)
if bytes.Compare(ref.SignatureVerifier[:], secrets.SignatureVerifier[:]) != 0 {
- t.Errorf("SignatureSecrets.SignatureVerifier is inconsistent; diffrent results generated for the same seed")
+ t.Errorf("SignatureSecrets.SignatureVerifier is inconsistent; different results generated for the same seed")
return
}
if bytes.Compare(ref.SK[:], secrets.SK[:]) != 0 {
- t.Errorf("SignatureSecrets.SK is inconsistent; diffrent results generated for the same seed")
+ t.Errorf("SignatureSecrets.SK is inconsistent; different results generated for the same seed")
return
}
}
diff --git a/crypto/include/sodium/utils.h b/crypto/include/sodium/utils.h
index 84feeea6a..021da8866 100644
--- a/crypto/include/sodium/utils.h
+++ b/crypto/include/sodium/utils.h
@@ -137,7 +137,7 @@ int sodium_munlock(void * const addr, const size_t len)
* either 357 or 361 bytes. For this reason, when using sodium_malloc() to
* allocate a crypto_generichash_state structure, padding must be added in
* order to ensure proper alignment. crypto_generichash_statebytes()
- * returns the rounded up structure size, and should be prefered to sizeof():
+ * returns the rounded up structure size, and should be preferred to sizeof():
* state = sodium_malloc(crypto_generichash_statebytes());
*/
diff --git a/crypto/libsodium-fork/src/libsodium/crypto_aead/aes256gcm/aesni/aead_aes256gcm_aesni.c b/crypto/libsodium-fork/src/libsodium/crypto_aead/aes256gcm/aesni/aead_aes256gcm_aesni.c
index 69707a685..d322bb4aa 100644
--- a/crypto/libsodium-fork/src/libsodium/crypto_aead/aes256gcm/aesni/aead_aes256gcm_aesni.c
+++ b/crypto/libsodium-fork/src/libsodium/crypto_aead/aes256gcm/aesni/aead_aes256gcm_aesni.c
@@ -365,7 +365,7 @@ do { \
*/ \
MAKE4(RED_MUL_MID); \
\
-/* substracts x1*h1 and x0*h0 */ \
+/* subtracts x1*h1 and x0*h0 */ \
tmp0 = _mm_xor_si128(tmp0, lo); \
tmp0 = _mm_xor_si128(tmp0, hi); \
tmp0 = _mm_xor_si128(tmp1, tmp0); \
diff --git a/crypto/libsodium-fork/src/libsodium/include/sodium/utils.h b/crypto/libsodium-fork/src/libsodium/include/sodium/utils.h
index 84feeea6a..021da8866 100644
--- a/crypto/libsodium-fork/src/libsodium/include/sodium/utils.h
+++ b/crypto/libsodium-fork/src/libsodium/include/sodium/utils.h
@@ -137,7 +137,7 @@ int sodium_munlock(void * const addr, const size_t len)
* either 357 or 361 bytes. For this reason, when using sodium_malloc() to
* allocate a crypto_generichash_state structure, padding must be added in
* order to ensure proper alignment. crypto_generichash_statebytes()
- * returns the rounded up structure size, and should be prefered to sizeof():
+ * returns the rounded up structure size, and should be preferred to sizeof():
* state = sodium_malloc(crypto_generichash_statebytes());
*/
diff --git a/crypto/merkletrie/cache.go b/crypto/merkletrie/cache.go
index e4dc387dc..8c41a05b4 100644
--- a/crypto/merkletrie/cache.go
+++ b/crypto/merkletrie/cache.go
@@ -24,7 +24,7 @@ import (
"sort"
)
-// storedNodeIdentifier is the "equivilent" of a node-ptr, but oriented around persisting the
+// storedNodeIdentifier is the "equivalent" of a node-ptr, but oriented around persisting the
// nodes to disk. ( i.e. think of a virtual memory address )
type storedNodeIdentifier uint64
@@ -424,11 +424,11 @@ func (mtc *merkleTrieCache) commit() (CommitStats, error) {
return stats, nil
}
-// reallocatePendingPages is called by the commit() function, and is reponsible for performing two tasks -
+// reallocatePendingPages is called by the commit() function, and is responsible for performing two tasks -
// 1. calculate the hashes of all the newly created nodes
// 2. reornigize the pending flush nodes into an optimal page list, and construct a list of pages that need to be created, deleted and updated.
func (mtc *merkleTrieCache) reallocatePendingPages(stats *CommitStats) (pagesToCreate []uint64, pagesToDelete map[uint64]bool, pagesToUpdate map[uint64]map[storedNodeIdentifier]*node, err error) {
- // newPageThreshold is the threshold at which all the pages are newly created pages that were never commited.
+ // newPageThreshold is the threshold at which all the pages are newly created pages that were never committed.
newPageThreshold := uint64(mtc.mt.lastCommittedNodeID) / uint64(mtc.nodesPerPage)
if int64(mtc.mt.lastCommittedNodeID)%mtc.nodesPerPage > 0 {
newPageThreshold++
diff --git a/crypto/merkletrie/node.go b/crypto/merkletrie/node.go
index ac9605e66..8d6d05d5b 100644
--- a/crypto/merkletrie/node.go
+++ b/crypto/merkletrie/node.go
@@ -71,7 +71,7 @@ func (n *node) stats(cache *merkleTrieCache, stats *Stats, depth int) (err error
}
// indexOf returns the index into the children array of the first child whose hashIndex field is less or equal to b
-// it's being used in conjuction with the bitset, so we test only the equality path ( i.e. get the index of the
+// it's being used in conjunction with the bitset, so we test only the equality path ( i.e. get the index of the
// child that has hashIndex of value x )
func (n *node) indexOf(b byte) byte {
// find the child using binary search:
@@ -224,7 +224,7 @@ func (n *node) add(cache *merkleTrieCache, d []byte, path []byte) (nodeID stored
// calculateHash calculate the hash of the non-leaf nodes
// when this function is called, the hashes of all the child node are expected
-// to have been calculated already. This is achived by doing the following:
+// to have been calculated already. This is achieved by doing the following:
// 1. all node id allocations are done in incremental monolitic order, from the bottom up.
// 2. hash calculations are being doing in node id incremental ordering
func (n *node) calculateHash(cache *merkleTrieCache) error {
diff --git a/crypto/multisig.go b/crypto/multisig.go
index 91c568842..6dcb2589a 100644
--- a/crypto/multisig.go
+++ b/crypto/multisig.go
@@ -99,7 +99,7 @@ func MultisigAddrGen(version, threshold uint8, pk []PublicKey) (addr Digest, err
return Hash(buffer), nil
}
-// MultisigAddrGenWithSubsigs is similiar to MultisigAddrGen
+// MultisigAddrGenWithSubsigs is similar to MultisigAddrGen
// except the input is []Subsig rather than []PublicKey
func MultisigAddrGenWithSubsigs(version uint8, threshold uint8,
subsigs []MultisigSubsig) (addr Digest, err error) {
@@ -317,7 +317,7 @@ func MultisigAdd(unisig []MultisigSig, msig *MultisigSig) (err error) {
for j := 0; j < len(msig.Subsigs); j++ {
if (unisig[i].Subsigs[j].Sig != Signature{}) {
if (msig.Subsigs[j].Sig == Signature{}) {
- // add the siganture
+ // add the signature
msig.Subsigs[j].Sig = unisig[i].Subsigs[j].Sig
} else if msig.Subsigs[j].Sig != unisig[i].Subsigs[j].Sig {
// invalid duplicates
diff --git a/daemon/algod/api/algod.oas2.json b/daemon/algod/api/algod.oas2.json
index 8382687ed..b71ed0231 100644
--- a/daemon/algod/api/algod.oas2.json
+++ b/daemon/algod/api/algod.oas2.json
@@ -1416,9 +1416,14 @@
"format": "byte"
},
"name": {
- "description": "\\[an\\] Name of this asset, as supplied by the creator.",
+ "description": "\\[an\\] Name of this asset, as supplied by the creator. Included only when the asset name is composed of printable utf-8 characters.",
"type": "string"
},
+ "name-b64": {
+ "description": "Base64 encoded name of this asset, as supplied by the creator.",
+ "type": "string",
+ "format": "byte"
+ },
"reserve": {
"description": "\\[r\\] Address of account holding reserve (non-minted) units of this asset.",
"type": "string"
@@ -1429,12 +1434,22 @@
"x-algorand-format": "uint64"
},
"unit-name": {
- "description": "\\[un\\] Name of a unit of this asset, as supplied by the creator.",
+ "description": "\\[un\\] Name of a unit of this asset, as supplied by the creator. Included only when the name of a unit of this asset is composed of printable utf-8 characters.",
"type": "string"
},
+ "unit-name-b64": {
+ "description": "Base64 encoded name of a unit of this asset, as supplied by the creator.",
+ "type": "string",
+ "format": "byte"
+ },
"url": {
- "description": "\\[au\\] URL where more information about the asset can be retrieved.",
+ "description": "\\[au\\] URL where more information about the asset can be retrieved. Included only when the URL is composed of printable utf-8 characters.",
"type": "string"
+ },
+ "url-b64": {
+ "description": "Base64 encoded URL where more information about the asset can be retrieved.",
+ "type": "string",
+ "format": "byte"
}
}
},
diff --git a/daemon/algod/api/algod.oas3.yml b/daemon/algod/api/algod.oas3.yml
index 661a79441..08c6289b1 100644
--- a/daemon/algod/api/algod.oas3.yml
+++ b/daemon/algod/api/algod.oas3.yml
@@ -1027,7 +1027,13 @@
"type": "string"
},
"name": {
- "description": "\\[an\\] Name of this asset, as supplied by the creator.",
+ "description": "\\[an\\] Name of this asset, as supplied by the creator. Included only when the asset name is composed of printable utf-8 characters.",
+ "type": "string"
+ },
+ "name-b64": {
+ "description": "Base64 encoded name of this asset, as supplied by the creator.",
+ "format": "byte",
+ "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$",
"type": "string"
},
"reserve": {
@@ -1040,11 +1046,23 @@
"x-algorand-format": "uint64"
},
"unit-name": {
- "description": "\\[un\\] Name of a unit of this asset, as supplied by the creator.",
+ "description": "\\[un\\] Name of a unit of this asset, as supplied by the creator. Included only when the name of a unit of this asset is composed of printable utf-8 characters.",
+ "type": "string"
+ },
+ "unit-name-b64": {
+ "description": "Base64 encoded name of a unit of this asset, as supplied by the creator.",
+ "format": "byte",
+ "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$",
"type": "string"
},
"url": {
- "description": "\\[au\\] URL where more information about the asset can be retrieved.",
+ "description": "\\[au\\] URL where more information about the asset can be retrieved. Included only when the URL is composed of printable utf-8 characters.",
+ "type": "string"
+ },
+ "url-b64": {
+ "description": "Base64 encoded URL where more information about the asset can be retrieved.",
+ "format": "byte",
+ "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$",
"type": "string"
}
},
diff --git a/daemon/algod/api/server/lib/middlewares/logger.go b/daemon/algod/api/server/lib/middlewares/logger.go
index 25398dae7..7ccfaed19 100644
--- a/daemon/algod/api/server/lib/middlewares/logger.go
+++ b/daemon/algod/api/server/lib/middlewares/logger.go
@@ -48,7 +48,7 @@ func (logger *LoggerMiddleware) handler(next echo.HandlerFunc) echo.HandlerFunc
res := ctx.Response()
req := ctx.Request()
- // Propogate the error if the next middleware has a problem
+ // Propagate the error if the next middleware has a problem
if err = next(ctx); err != nil {
ctx.Error(err)
}
diff --git a/daemon/algod/api/server/v1/handlers/handlers.go b/daemon/algod/api/server/v1/handlers/handlers.go
index 1e3b0f634..f956fb417 100644
--- a/daemon/algod/api/server/v1/handlers/handlers.go
+++ b/daemon/algod/api/server/v1/handlers/handlers.go
@@ -24,8 +24,9 @@ import (
"io"
"net/http"
"strconv"
- "strings"
"time"
+ "unicode"
+ "unicode/utf8"
"github.com/labstack/echo/v4"
@@ -163,6 +164,20 @@ func participationKeysEncode(r basics.AccountData) *v1.Participation {
return &apiParticipation
}
+// printableUTF8OrEmpty checks to see if the entire string is a UTF8 printable string.
+// If this is the case, the string is returned as is. Otherwise, the empty string is returned.
+func printableUTF8OrEmpty(in string) string {
+ // iterate throughout all the characters in the string to see if they are all printable.
+ // when range iterating on go strings, go decode each element as a utf8 rune.
+ for _, c := range in {
+ // is this a printable character, or invalid rune ?
+ if c == utf8.RuneError || !unicode.IsPrint(c) {
+ return ""
+ }
+ }
+ return in
+}
+
func modelAssetParams(creator basics.Address, params basics.AssetParams) v1.AssetParams {
paramsModel := v1.AssetParams{
Total: params.Total,
@@ -170,9 +185,9 @@ func modelAssetParams(creator basics.Address, params basics.AssetParams) v1.Asse
Decimals: params.Decimals,
}
- paramsModel.UnitName = strings.TrimRight(string(params.UnitName[:]), "\x00")
- paramsModel.AssetName = strings.TrimRight(string(params.AssetName[:]), "\x00")
- paramsModel.URL = strings.TrimRight(string(params.URL[:]), "\x00")
+ paramsModel.UnitName = printableUTF8OrEmpty(params.UnitName)
+ paramsModel.AssetName = printableUTF8OrEmpty(params.AssetName)
+ paramsModel.URL = printableUTF8OrEmpty(params.URL)
if params.MetadataHash != [32]byte{} {
paramsModel.MetadataHash = params.MetadataHash[:]
}
diff --git a/daemon/algod/api/server/v2/account.go b/daemon/algod/api/server/v2/account.go
index 534f06020..018618265 100644
--- a/daemon/algod/api/server/v2/account.go
+++ b/daemon/algod/api/server/v2/account.go
@@ -430,9 +430,12 @@ func AssetParamsToAsset(creator string, idx basics.AssetIndex, params *basics.As
Total: params.Total,
Decimals: uint64(params.Decimals),
DefaultFrozen: &frozen,
- Name: strOrNil(params.AssetName),
- UnitName: strOrNil(params.UnitName),
- Url: strOrNil(params.URL),
+ Name: strOrNil(printableUTF8OrEmpty(params.AssetName)),
+ NameB64: byteOrNil([]byte(params.AssetName)),
+ UnitName: strOrNil(printableUTF8OrEmpty(params.UnitName)),
+ UnitNameB64: byteOrNil([]byte(params.UnitName)),
+ Url: strOrNil(printableUTF8OrEmpty(params.URL)),
+ UrlB64: byteOrNil([]byte(params.URL)),
Clawback: addrOrNil(params.Clawback),
Freeze: addrOrNil(params.Freeze),
Manager: addrOrNil(params.Manager),
diff --git a/daemon/algod/api/server/v2/dryrun.go b/daemon/algod/api/server/v2/dryrun.go
index 27f52e6bc..4e0b21581 100644
--- a/daemon/algod/api/server/v2/dryrun.go
+++ b/daemon/algod/api/server/v2/dryrun.go
@@ -400,7 +400,7 @@ func doDryrunRequest(dr *DryrunRequest, response *generated.DryrunResponse) {
response.Txns = make([]generated.DryrunTxnResult, len(dr.Txns))
for ti, stxn := range dr.Txns {
- pse := logic.MakePastSideEffects(1)
+ pse := logic.MakePastSideEffects(len(dr.Txns))
ep := logic.EvalParams{
Txn: &stxn,
Proto: &proto,
diff --git a/daemon/algod/api/server/v2/dryrun_test.go b/daemon/algod/api/server/v2/dryrun_test.go
index a3d1a6f36..421025dab 100644
--- a/daemon/algod/api/server/v2/dryrun_test.go
+++ b/daemon/algod/api/server/v2/dryrun_test.go
@@ -689,6 +689,54 @@ func TestDryrunLocalCheck(t *testing.T) {
doDryrunRequest(&dr, &response)
checkAppCallPass(t, &response)
}
+
+func TestDryrunMultipleTxns(t *testing.T) {
+ t.Parallel()
+
+ var dr DryrunRequest
+ var response generated.DryrunResponse
+
+ dr.ProtocolVersion = string(dryrunProtoVersion)
+
+ txn := transactions.SignedTxn{
+ Txn: transactions.Transaction{
+ Type: protocol.ApplicationCallTx,
+ ApplicationCallTxnFields: transactions.ApplicationCallTxnFields{
+ ApplicationID: 1,
+ ApplicationArgs: [][]byte{
+ []byte("write"),
+ },
+ },
+ },
+ }
+
+ dr.Txns = []transactions.SignedTxn{txn, txn}
+ gkv := generated.TealKeyValueStore{
+ generated.TealKeyValue{
+ Key: b64("foo"),
+ Value: generated.TealValue{Type: uint64(basics.TealBytesType), Bytes: b64("bar")},
+ },
+ }
+ dr.Apps = []generated.Application{
+ {
+ Id: 1,
+ Params: generated.ApplicationParams{
+ ApprovalProgram: globalTestProgram,
+ GlobalState: &gkv,
+ GlobalStateSchema: &generated.ApplicationStateSchema{
+ NumByteSlice: 10,
+ NumUint: 10,
+ },
+ },
+ },
+ }
+ doDryrunRequest(&dr, &response)
+ checkAppCallPass(t, &response)
+ if t.Failed() {
+ logResponse(t, &response)
+ }
+}
+
func TestDryrunEncodeDecode(t *testing.T) {
t.Parallel()
diff --git a/daemon/algod/api/server/v2/generated/private/routes.go b/daemon/algod/api/server/v2/generated/private/routes.go
index d142d558c..73c3e0faa 100644
--- a/daemon/algod/api/server/v2/generated/private/routes.go
+++ b/daemon/algod/api/server/v2/generated/private/routes.go
@@ -235,135 +235,137 @@ func RegisterHandlers(router interface {
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "H4sIAAAAAAAC/+x9/XfbtrLgv4LVe+fkY0XJ+eq98Tk9b32TtNfbNM2Jfbu7L862EDmSUJMAS4C21Kz/",
- "9z0zAEiQBCXZ8ctuz7s/JRZBYDDfmBkMP09SVZRKgjR6cvx5UvKKF2Cgor94mqpamkRk+FcGOq1EaYSS",
- "k2P/jGlTCbmaTCcCfy25WU+mE8kLaMfg+9NJBb/XooJscmyqGqYTna6h4Dix2ZY4uplpk6xU4qY4sVOc",
- "vp7c7HjAs6wCrYdQ/iTzLRMyzesMmKm41DzFR5pdC7NmZi00cy8zIZmSwNSSmXVnMFsKyDM985v8vYZq",
- "G+zSLT6+pZsWxKRSOQzhfKWKhZDgoYIGqIYgzCiWwZIGrblhuALC6gcaxTTwKl2zpar2gGqBCOEFWReT",
- "448TDTKDiqiVgrii/y4rgD8gMbxagZl8msY2tzRQJUYUka2dOuxXoOvcaEZjaY8rcQWS4Vsz9mOtDVsA",
- "45J9+O4Ve/bs2UvcSMGNgcwx2eiu2tXDPdnXJ8eTjBvwj4e8xvOVqrjMkmb8h+9e0fpnboOHjuJaQ1xY",
- "TvAJO309tgH/YoSFhDSwIjp0uB/fiAhF+/MClqqCA2liB98rUcL1/59SJeUmXZdKSBOhC6OnzD6O6rDg",
- "9V06rAGgM75ETFU46cej5OWnz0+mT45u/uXjSfLv7s8Xz24O3P6rZt49GIgOTOuqApluk1UFnKRlzeUQ",
- "Hx8cP+i1qvOMrfkVEZ8XpOrduwzftarziuc18olIK3WSr5Rm3LFRBkte54b5hVktc1RTOJvjdiY0Kyt1",
- "JTLIpqh9r9ciXbOUazsFjWPXIs+RB2sN2RivxXe3Q5huQpQgXHfCB23o/19ktPvagwnYkDZI0lxpSIza",
- "Y568xeEyY6FBaW2Vvp2xYudrYLQ4PrDGlnAnkafzfMsM0TVjXDPOvGmaMrFkW1WzayJOLi7pfbcbxFrB",
- "EGlEnI4dReEdQ98AGRHkLZTKgUtCnpe7IcrkUqzqCjS7XoNZO5tXgS6V1MDU4jdIDZL9v5/99I6piv0I",
- "WvMVvOfpJQOZqmycxm7RmAX/TSskeKFXJU8v4+Y6F4WIgPwj34iiLpisiwVUSC9vH4xiFZi6kmMA2Rn3",
- "8FnBN8NFz6tapkTcdtmOo4asJHSZ8+2MnS5ZwTffHk0dOJrxPGclyEzIFTMbOeqk4dr7wUsqVcvsAB/G",
- "IMECq6lLSMVSQMaaWXZA4pbZB4+Qt4On9awCcPwko+A0q+wBR8ImwjMouviElXwFAcvM2D+c5qKnRl2C",
- "bBQcW2zpUVnBlVC1bl4agZGW3u1eS2UgKStYigiPnTl0oPawY5x6LZyDkyppuJCQoeYloJUBq4lGYQoW",
- "3H2YGZroBdfwzfMxA94+PZD6S9Wn+k6KH0RtGpRYkYzYRXzqBDbuNnXeP+DwF66txSqxPw8IKVbnaEqW",
- "Iicz8xvSz6Oh1qQEOojwhkeLleSmruD4Qj7Gv1jCzgyXGa8y/KWwP/1Y50aciRX+lNuf3qqVSM/EagSZ",
- "DazR0xS9Vth/cL64Ojab6KHhrVKXdRluKO2cShdbdvp6jMh2ztsy5klzlA1PFecbf9K47Rtm0xByBMhR",
- "3JUcB17CtgKElqdL+mezJH7iy+oP/Kcs8xhOkYGdoaWggAsWfHC/4U8o8mDPBDiLSDkidU7m8/hzANC/",
- "VrCcHE/+Zd5GSub2qZ67eXHFm+nkpJ3n/ldq37T76x1k2sdMSEsdGjq1Z8L7hwdnjUJCjmoPhr/lKr28",
- "EwxlpUqojLB0XOA8Q0mh6dkaeAYVy7jhs/ZQZf2sEX6nF/9O79EpCaqIifuJ/sNzho9RCrnx7hu6rkKj",
- "E6eCQFOGHp+1I3YlHECeqGKFdfIYOme3gvJVu7hV0I1G/ejQ8qk/W4Q6b6xfyegNvwncentqPFmo6m78",
- "0mMEydqzMOM4a+P94s67lKWhdZk4/ET8aTugN1Ebfhyq1RBD/eljuOpg4czw/wAsaJz1PrDQnei+saCK",
- "UuRwD/K65no93AQ6OM+esrO/n7x48vSXpy++QQtdVmpV8YIttgY0e+jsCtNmm8Oj4c5Iwde5ic/+zXN/",
- "gurOuxdDBHAz9yESdQ6oGSzGmI0XIHSvq21Vy3tAIVSVqiI+L7GOUanKkyuotFCR8MV7N4K5EaiHrN/d",
- "+91Cy665Zrg2HcdqmUE1i2Eez1lk0g0Uep+hsFOfb2SLGzchryq+HVDA7jeyO7fuITTpIt9795qVUCVm",
- "I1kGi3oV2ii2rFTBOMvoRVKI71QGZ4abWt+DFmgna4FBQoQg8IWqDeNMqgwFGgfH9cNILJOCKBT7MaHK",
- "MWtrfxaA3nHK69XaMHQrVYy07YsJTy1RErIVeuTo15zZ7Si7nI2T5RXwbMsWAJKphTtfuZMfbZJTWMb4",
- "jIvTTi1YzZmgA1dZqRS0hixx6aW9oPlxlspmB54IcAK4WYVpxZa8uiOwRhme7wGUxsTAbdwJdygdQn3Y",
- "8rsI2F88JCOv8IxpuQB9F5TuHAyMofBAnFxBRYez/1D6+UXuSr66HEmdOAt8LgoUXya5VBpSJTMdnSzn",
- "2iT7xBYHddwE3EEgKTFJpYlHAgRvuTb2iC5kRi6jVTe0Dr1DS4wDPGpRcOafvTEZzp2inpS61o1l0XVZ",
- "qspAFtuDhM2Otd7BpllLLYO5G/NlFKs17Jt5DEvB/A5ZdicWQdy4GFETwxpujsLxaAe2UVR2gGgRsQuQ",
- "Mz8qwG4YPh4BBM8XzZvEOEL3OKeJWU8n2qiyRPkzSS2b98bQdGZHn5h/tGOHzMVNq9czBbi68TA5yK8t",
- "Zm3iYM3Rt6OZWcEv0TaRp2ZjCUOYURgTLWQKyS7OR7E8w1GhCOwR0hEn2aUmg9V6wtHj3yjTjTLBHiqM",
- "bXjEY39vI+DnbXToHpyW12C4yHXjmDRh9nYVisj3qyXQi6wgBWnyLfLqUlSFTWqROdP+N+v2ZG4Vm75p",
- "xU9mrIJrXmV+xPC0FGwmETKDTVy78k5sJIMNE3Ggl83KwrDUp5xkOMEsKug2iZfmSgu5Smx2cJ9Ra5J6",
- "DzSrpXAG7BoqB9cSKmd2jc+OJUb5DNouOHahwgVn7oIEfDW+rAXOUkvHkqj0AAWxEGmluM2NIlJ7G2QV",
- "FByhoyydM/vja+5C9iv73KdqfYg85N34vJ5fRzVMw6LXayIWqto+EkOux6MtaBjbyCpXC54n6PBDkkFu",
- "9obe8CABr2kk2muVDl/vgnxx8THPLi4+sbc4ls4WwC5hO6eMNUvXXK6gTSOE8mJPDbCBtA5NSw+NBx0E",
- "Xay0C333KDidlErlSXPk7ac9Buamj/dLkV5CxlBfkYg5K/igSyFchD1EFtdNYuh6vfUuZFmChOzRjLET",
- "yaAozdbFV3oeT29x+cDsWn9Dq2Y15ai5ZLTJ2YWMhzZshvsLZcpPs1uSbMnXFy5lJ9m9kNnIEXHi15Sg",
- "wemi8rkzOnpGbwamb2DRA6ayUBwSQ/ie6qB4h8oio+NIa910vSgEFUMFw6aoOX1+enjCF2bG2DnpDjxg",
- "abiCiudU6aF94FhoVgg8qOs6TQGy4wuZdCBJVeEWftj+16qli/ro6Bmwo0f9d7RBd9WdJa0M9N/9lh1N",
- "7SNCF/uWXUwuJoOZKijUFWT2PBbytX1r77T/pZn3Qv40UMys4Ft7kvOyyHS9XIpUWKTnCvX6SvW8Tqno",
- "CVQIHqCZ1UyYKZkywih565YurQBOot7TfcR8IrOin46mFLWdz0p2eUcz2PAUd8lJyWytR9Dw2dAJMqpM",
- "wgmiIegdK7okgO7o8TvK3VCf2wDEbvjOeyGIDjoCdp3t990HyIhCcIj4n7BSIdWFqz/yRSq50GYApAtH",
- "UAaoYciI0Zmx/6VqlnKS37I20JztVEUHJjpI4wpkY/2azlNrMQQ5FGAjRPTk8eP+xh8/djQXmi3h2hft",
- "4cA+Oh4/tkKgtPliCeix5uY04kBRYB6taaTQes31erY3SE/zHhSbD6Y+fe0XJGHSmkwMbrxSankPuxXZ",
- "JuqzwCa2U0c5Crc90Kzk21H3ukQAI9VaUF3mFMtXyx5HMqf/1qLEKdvKkq2BTlXq/374b8cfT5J/58kf",
- "R8nL/zr/9Pn5zaPHgx+f3nz77f/p/vTs5ttH//avMedFG7GI533+zvUaIXWaYyNPpc3coudJAbutiwOo",
- "5deGu8diSEyP+WBLhzDd+xhBBLoSRGziubO6LPPtPRgZOxGrwJ0xdCc8qu1TtQyLUh3n6a02UAwzDPbV",
- "X0ZOPx98dGLApUrmQkJSKAnb6D0MIeFHehj1DUktjbxMBmLs3X70pgN/D6zuOocQ80vxS9QO1ND7pkT2",
- "Hojfn7eXXArLcelkA3nJOEtzQaFzJbWp6tRcSE7BuZ7r3WMLH3IcD9e+8kPi8eFI+NZNdSG5Rhw2Ibto",
- "0nEJkWD8dwA+aqvr1Qp0zxVnS4AL6UYJSYEWWotOMoklWAkVZYdndiR6n0ueU3T5D6gUW9Sma+6patB6",
- "0zbThcswtbyQ3LAcuDbsRyHPNzSdP1V7npFgrlV12WBhJCoAErTQSVyRfm+fkj5121873UpXOOxjr2++",
- "tgHwsMdq2hzkp6+dK3z6mvydNsc1gP2rJT4KIZMok+ERtRCSSqN7vMUeotfmGehRmy1zVL+QZiORka54",
- "LjJu7sYOfRU3kEUrHT2u6RCiF8f2e/0UO2KvVFLy9JLqTyYrYdb1YpaqYu6PAPOVao4D84xDoSQ9y+a8",
- "FHNdQjq/erLHHfsCfcUi6upmOnFaR997pZubOLah/ppNBsn/bRR78P2bczZ3lNIPbIGrnTqoTIyc2tz9",
- "yk4AATdvL2jZCl88QL+GpZACnx9fyIwbPl9wLVI9rzVUf+M5lynMVoodMzfla244xZ160fSxO5QUE3TQ",
- "lPUiFym7DE1xK5pjwdiLi4/IIBcXnwb55qHhdEvFA9y0QHItzFrVJnEZifHYVRvfo5ltLHjXqlPm5rYc",
- "6TIebv6RoHtZ6iSIwsa3X5Y5bj9gQ83oJapXZNqoyitB1Iwujob0fadcxr3i1/7WSK1Bs18LXn4U0nxi",
- "iYv5nJQlhXgpxvqr0zXIk9sSDo/TtiC2k8XO9rRx61DBxlQ8KfkKdHT7BnhJ1CdDXVAULc8ZvdaJN/tq",
- "LZqq3cDOuGIAx61raWlzZ/Ytn0CJb4EeEQlpDGqnNh5+V3rhVH9XOTLZnckVzBGlUm3WCcp2dFcaWdxT",
- "prnYtUKd7PPfWqwkCoG7A7cAlq4hvYSMkn8UH592XvclFs7CedUhtL22Zktm6W4FhUIWwOoy484H4HLb",
- "L3LXYIyv7P8Al7A9V+3VjNtUtd9MJy6hlSDPjAkqcWpgjJBZQ7H1SbEe8V1+k5JOZclsXsdWI3u2OG74",
- "wr8zLsjWQt6DEMeYokHDDn4veRVBhGX+ERTcYaM43xexfjSLxCsjUlHa/R+Wl3rfeQcn2WdcouZELftW",
- "Y6DUo0rMDk4WXMcNCOATpAfKUL+aya9ko4o2Uc2o9YFj3EUOQUZVO8nmFTldftv2LvcYaHEugUq2Vt2D",
- "0cVI6D6sXWmAuGoLAijkc4ih3ZuQRS7yNTuim3oRuG4OV3w0CzZ65+g0KMQJrrI2N4q8YusLw7S5XWa7",
- "SvibR/66kb9jNJne6r7QdOJqQ2PkUJK8jAxyWHGX9KGqU19wYEF7oAMCIRw/LZe5kMCSWE0P11qlwtYB",
- "tLrcrQHohD5mzAZ42MEzxNg4AJui5TQxe6dC2ZSr2wApQVB4nfu5Kc4e/A37o81tew/n3u51Q4e6oxWi",
- "aXv9zpJxGIWaTqIqaeyE0BnF7JAFDI5UMRZF1TSMywyjPxpyIHOcdDRrchmL1qFXAcSGZ/614NjAHool",
- "GvlHQdKkgpXQBtpzM0qrDwR93djFlTKQLEWlTUJH9uj2cNB3mpzB73BoXP10UMVsfwCRxbUPLXsJ2yQT",
- "eR2ntlv3h9e47Lvm/KTrxSVsycgAT9dsQf0s0Ap1lscxO5a2dW07N/zWbvgtv7f9HsZLOBQXrpQyvTX+",
- "JFzV0ye7hCnCgDHmGFJtFKU71EtQiTPULcGZzNYLUW3RbFfUYCBMt65mGtW8dqboXgJHd+cubNGbrWsL",
- "2kEM71iMyAAvS5Ftemd4O+tI2o4c+Fs46tbjj6SiJs1kezAQnNdjZbwV+JiDJWlgM21jj0Gp437M9Ass",
- "A4UQLiW0b0s1RBSyNlWi7cPVOfD8B9j+jGNpO5Ob6eTLjvwxXLsZ9+D6fUPeKJ4plm2PgJ0I3i1Rzsuy",
- "Ulc8T1xgZIw1K3XlWJOG+zjKV1Z18eP3+ZuTt+8d+FS5CbxyBYu7dkXjyj/NrvBEHKtaPA8iI+St+rOz",
- "dcQC4jd3icNgii8y7fhyqMUcc1nxagNlgSi64MoynlLbGypxMT27xR2xPSib0F57IraRvW40j19xkfuj",
- "qId2f1HsnbRCp6r2S6OCYYntvaqbgXTHpaPlrj06KVxrRxOUwvb50UzJfmERupB0wiVWLfgWOcgGp4fK",
- "SdZFguKX6Fyk8bCFXGhkDmljvjiY0eARZxRnrMVICkHWIpgLh+kDsmU9IIM1osikkNIO3C2Ua9BYS/F7",
- "DUxkIA0+qlyhYUdQUS597fzQnMbr9N3ErlS/mf5LfAycasy7ICB2OxhhhDlyS8QfOP1Gm9A4/hAEBm+R",
- "qApXHJjEHUkmxx+Om222f92NFIf9FIf6DxnD9t7Z38zRhy3WFtCRNaLNGUetxcm4paD7F4fbiNYkELih",
- "MbA1sTzXKjJNLa+5tL3W8D2LQ/e2BhszwLeuVUWXFjVEs/RCJ8tK/QHxk+wSCRWpfXSoJHeR3p5FLoP1",
- "lWgTlWm7aHr8hnCMsvaYJxc8ZN1E4oiEE5cHoXMq5vYBLi4tW9u+cJ30dVw4wpKTuZ2/FQ4H86BMJ+fX",
- "Cx5rkYIOFcJ00iZpOqE4o5h/2VNBN3cYHO8F+Z5mrLA3/Uqo2gLl4a3yOzpHfy6WzyAVBc/jXlJG2O9e",
- "AcvEStjmerWGoHubm8h2JbVc5Drg2TRYi5rTJTuaBv0hHTUycSW0WORAI57YEQuuwd40C2+fucIoA9Ks",
- "NQ1/esDwdS2zCjKz1haxWrHGgbWXinzsewHmGkCyIxr35CV7SFF/La7gEWLR+SKT4ycvqSzF/nEUM3au",
- "i+YuvZKRYvkfTrHE+ZjSHnYONFJu1ln01qltfTyuwnZIk331EFmikU7r7Zelgku+gng2t9gDk32XqElB",
- "wx5eZGb7dmpTqS0TJr4+GI76aaQ0DdWfBcPdUSlQgIxiWhXIT21rNruon842AXXtkjxc/iGlWEp/16h3",
- "YP66AWJry2O7pkTYO15AF61Txu3lbLou5S71O4U4G+lrA9VVfJFqhMDebrp32UOpZFKg7GSP2qLHgP+i",
- "bV2U4Xm8fMPrrn71zu6pD3W1cJZkFLF1B7E80El3RnFdxffJa1zqHx/eOsNQqCrWo6XVhs5IVGAqAVdR",
- "ie0X7zWeSWMuPOZjDsrfapFnP7clt712aBWX6Toae13gi7+0/RsbtFusR6++rrmUkEens7L8i5f5iFb6",
- "TR26TiHkgWP7bc7sdnubawHvgumB8gsieoXJcYEQq90axKZoJV+pjNE6bZOFlhGGdxODlk+/16BN7B4l",
- "PbD1XnTGRn/FdhxiIDOy9jNm7x0iLJ2bY2RlRVHn9hYSZCuoXPCnLnPFsynDec7fnLxldlXt7tDTfTfq",
- "eLSyd1g7u+idrYKOLLe51DtWHnb4PLvrVXDX2lBLBm14UcYqf3HEuR9A5cVhvInMT4idGXttLb/2dsUu",
- "0t7dZs1yTtcQT+B/jOHpmkxqxwCNs/zhrbo8V+qgZW3T/bNpqmKvIxvlu3XZZl1TptDvuRbatt2GK+gW",
- "GzeV986l88XH3e1VtZSWU+L2acfNkLug3QNnk4o+JBWFrIf4W5oZreoqhdt2Ljujt6J3G/tt0Aa9au0t",
- "p6ZXpP+cQsqlkiKlm4VBo+8GZNfC+5B47QGXMPvHZS/iTkIjwhVtvtaULTgsjrZj84rQIW4YMAqeIlEt",
- "d9g/DfWKxoPgCox2mg2yqW+w585xQmpwTXKom3ugJ/E43s9dRtMqbZuMW7IRlR6OuCvf4TNyVYQrF7oU",
- "ki6NO7S5yiR70qIOwwaPd8KwlQLt9tO9Kqg/4jszui6XwebTzHckpjlsCBm3bfMlw6lOfPbEZStw7Csc",
- "yyhc3P7cKXO0i56UpVs0etOvoXCsReAogiNR8MSHIQPkNvOHs+1gt51pT7KnyGhwRUkTKMkODxhjpPXE",
- "GzzUWo6yN9htuUH0eoqQETDeCgltv+yIgUijJoEIQ/I68p5OK26sC3iQTjsHnlOmJKbQtHGhoy+dqkdg",
- "Qgnt0a8xTsa2UeSI4mgGtI4bl9umTTdyd+BMvKLvAzhEDts+klflnKiMCsp6jSBjigMVt2+h2jUAQzEY",
- "+kT2dVNxKzm3sURjhfiZ0HgcKRZ5pITmdfMwaIZKtXqLLf0bu/g/vgOXWLtzoxp68db+5e6mMTnSPtFi",
- "dUeqtO/fI1l6MhDSKMb9b1CthHeXBj0crOJprhZR+YDyranpUNEUxXd5lhRd9NDWdhnefWgd7xc8JdU4",
- "UkT0ob01y632tbHBsVKidLTyjRtX1mo429W9yTb5jc1g85C2ubD9UE80MDCWe7SpR3w8ePswv2HghdHc",
- "OxHqk9pDgH7wFTOs5MIFvlsRGWLW1dYNqx0PqbppCdzfhKtYo0liO7ljgdlBsjfEUkSww9KAPex52UGp",
- "vYnS8yRVBfeM2sCE3hK1w6KHQ7dH+yCOqTUM93kwATq4HcH9IYhv9cIQuePibBaHiHO8oB9fJ31iEeKv",
- "nAy1yVfTBp3e5G7dGNV/Hose2BPySKCqh9Na5Nk+4nbCju2Vbgqs/bL45nknevc1L5X/YhPyQ3Fz92tv",
- "Y/j7RCDERPbaWTxYKggoHhBLdK9FIofUgy2tK2G2VLvjPU3xS7Qm+nuQrkO7++BFkwF1CTj7rSUXml41",
- "o9vP43yvbMv6At1fcgUNNSd6s+FFmYOTi28fLP4Cz/76PDt69uQvi78evThK4fmLl0dH/OVz/uTlsyfw",
- "9K8vnh/Bk+U3LxdPs6fPny6eP33+zYuX6bPnTxbPv3n5lwf+2zQW0Pa7L/+TOi8kJ+9Pk3MEtsUJL8UP",
- "sLV3rZGN/S1unpIkQsFFPjn2P/03L2GzVBXB5zTdrxMX6Z+sjSn18Xx+fX09C1+Zr6hdZmJUna7nfp1h",
- "L6j3p02A1ib8iaI29oasQER1rHBCzz68OTtnJ+9PZy3DTI4nR7Oj2RNqllKC5KWYHE+e0U8kPWui+9wx",
- "2+T48810Ml8Dz83a/VGAqUTqH+lrvlpBNXPX2fGnq6dzH9+Zf3ZJ7ptdz7pVBu7aSvBCcO9x/rnTbzUL",
- "56VbgfPPvgIjeGT7ic8/U/ho9PcuGJ/NRmQ3c9/3yL3h+vLOP7eNsm+sdOQQO/n7Bn7tcGrMR98P0fZX",
- "FAifVxS621e9oe5phlTFt141TcPDzyR//E/6UdFPvW8sPT06+k/2tZjnt9zxTn+2c/6L9Jr4G8+Yzy3R",
- "2k++3tqnkm6ZoEJjVmHfTCcvvubuTyWyPM8ZjQyqQYak/4e8lOpa+pFoXeui4NXWi7HuKAX/KQDS4Xyl",
- "qWFoJa7wUP+JOtLGknkjyoU+y3Nr5ULfGvqncvlayuXP8RGmp7cU8D//jv+pTv9s6vTMqrvD1alz5Wz5",
- "wty2z2s9PH9jc3iNsevNjulkd9RhDylOKuH6kSuBsNNGrsQ26WaV2ZiIb6/kC6uCdvtdnf3BTdq5ff0D",
- "bPU+BX6+Bvarmz4R2a9U/knJhylTFfuV53nwG7XJ8W77LK7v22uSe7+y2gpoDKwlgC9GpaJT13UYDdkl",
- "+Au1FgedBOUwp98241vC6Je2bc+yUIM5FnxydHQUKwbqw+ziNxZiKv69VkkOV5APST0GRO9e7a7v0o5+",
- "uWd4HTo8d0e4zn/GvbkhPfqZ3u4d39tA91rJB4Zdc+E+fhD01LGfciqE8V+wtkVCroCwsRHxrx4nOOXu",
- "j6J/qfH+83URvtmh7PS6Npm6luOKi24X8dyV51LBbBNuMIr5CRpNNWP+k6T51n9Tm3EqV1K16X7q3rfK",
- "6DVLb5o5rYSkBUjKaRVbh86DKk/36ZyhEjxzkL2zXxrq6b3oF38tjHG5jwn9l/LS0NHYSSvfWqXz9xxZ",
- "Ht1V+yW1hDA0DGkY4PncFar0frXp5ODHbkP0yK/z5mpX9GE/UBN76uIoflAbIQ0jjkSpJtb48RMinGqI",
- "HRHbANrxfE4p3LXSZj5BhdMNroUPPzU4/uwp73F98+nm/wYAAP//UWHRAXWKAAA=",
+ "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",
+ "IKRqN9e3SQ7LVypjNE9bzKSVsuEb4KC02t9r0Cb2XpkabF4l+bLwXmArezGQGVnVM2bf9yIunReaZM2K",
+ "os7taz/IVlA5J2td5opnU4Zwzt+evGN2Vu1qVdC7UqostrJvxTur6PkwgspHt3k8P5aGeTic3XlhuGpt",
+ "qPSJNrwoYxn22OPcd6A0/tCvS2ZeSJ0Ze2MtbO3tNztJWyOBNdM5HU8ygf8xhqdrMl072mRc5A8vieel",
+ "UgeloZsqu03xIvvs3yhfFc8WxZsyhfeLa6FteXu4gm5Sf/PCxV2dfJJ/d3lVLaWVlKiO3vUC6y5k98jZ",
+ "4L13/UYx6xH+loaLVnWVwm0rBJ7RqOgb4n65wUFNaPuasKnJ6j9bknKppEjpBW9QUL9B2ZXKPyQucsBj",
+ "575bym9xt0Mjmyta5LBJD3JUHC176BWhI9zQMRu0IlOtdNg/DdVkX3PDVmC002yQTX0hS+cvEVKDK0ZF",
+ "X00I9KSqOrEm0pDR8GVbjuaWYkQpviMG8PfY9t5djygt71JIMoQc2VwGoPVoUCVvg9aTMGylQLv1dJ/k",
+ "6k84ZkbPUjPYfJ75yt8Ew4ZqcNk2LjkEdeKjlC4qiH1fY19GYZn25046sZ30pCzdpNEXtQ2HY6U4Rwkc",
+ "iTYl3t0fELeBH0LbIW470wvoPEVBgysKTkJJ5/BAMEZKvLy94nltJcpWirBpPdFnYEJG0HgnJLR16SMH",
+ "RBo9EogxtF9Hxum04saagAfptHPgOUUkYwpNG+eivS+oHoOJJLRGP8c4G9uCrCOKo+nQGm5cbpty+Cjd",
+ "gTHxmr7D4Qg5LK9KVpUzojJK3OwVXI0pDlTcvlRx9wAYboOhTWSHm4rbnXObk2jswUsmNN51ikUeSVV7",
+ "0zQGRYcpJ3axpX9jBTbGV+AC2HcuCEUDb21f7i7OlCPvEy1Wd+RKO/4B2dLbAyGPYtL/FtVK+EZwUCvF",
+ "Kp7mCR+l6ShfAp4uFc3jk67MkqKLXtraat67L63jdbmnpBpHkvU+tq/TudW+1gc/lrKXjmaYcuPSxw1n",
+ "u6qk2WLaMQg23m+LeNsPYkX9D2Mxfhvix+bB6MPshoEVRrB3EtQnjwwR+tFnprGSCxdgarfIkLIuh3WY",
+ "VXxIdlvL4P4iXGYoAYmt5I6JnAftvSGVIhs7TMHZI56XHZLaF189S1JV8MCkDY7QW5J2mFx06PJoHSQx",
+ "tYbhOg9mQIe2I7Q/hPCtXhgSd3w7m8Uh2zn+cAaHkz6xBPFPu4ba5Ktpg843ANy8Ma7/dcx7YG/II46q",
+ "Hk1rkWf7mNtxO7alE8ix9otz0P5Dijf8YhNfhtvNvWO/zcHfZwIRJrLWzuTBVIFD8QBfohsW8RxSrcO0",
+ "roTZUo6ctzTFL9G3Bz+AdF9CcB+WaTINXKDbftPM+b1XTe/2M1Q/KPtpiALNXzIFDRUBe7vhRZmD2xff",
+ "PVr8AV788WV29OLZHxZ/PPrmKIWX37w6OuKvXvJnr148g+d//OblETxbfvtq8Tx7/vL54uXzl99+8yp9",
+ "8fLZ4uW3r/7wyH8DyiLafl/pf1OFk+Tkw2lyjsi2NOGl+BG2tqYBirGvlsBT2olQcJFPjv1P/8PvsFmq",
+ "iuCzte7XiQuCTNbGlPp4Pr++vp6FQ+YrKkubGFWn67mfZ1hz7cNp46C1iTXEUet7Q1EgpjpROKG2j2/P",
+ "ztnJh9NZKzCT48nR7Gj2jIoSlSB5KSbHkxf0E+2eNfF97oRtcvzlZjqZr4HnZu3+KMBUIvVN+pqvVlDN",
+ "XNkI/Onq+dz7d+ZfXDLJza62bjaPex4WDAjeF8+/dOoaZyFcen07/+IznYImW7d//oXcR6O/d9H4YjYi",
+ "u5n7+mJuhKt/Pf/SFqS/sbsjh9jN3xfKbLtTAUz6To+2v+KG8PF7obvfL2i4e5ohV3HU66Y4f/g58k//",
+ "RT/e+7n3LbPnR0f/xb7K9PKWK95pz3buf5GaLn/iGfOxJZr72deb+1TSay5UaMwq7Jvp5JuvufpTiSLP",
+ "c0Y9g6yrIev/Ii+lupa+J56udVHwauu3se4oBf/JDdLhfKWpMG8lrvBS/5kqP8eCeSPKhT5/dWvlQt/0",
+ "+qdy+VrK5ffxsbPnt9zgv/8V/1Od/t7U6ZlVd4erU2fK2fSFuS1T2Vp4/mX08Llw15od08nuqsMek59U",
+ "wvUTlwJhwUaenjfhZpVZn4gvY+ZT9YLPWnR19kcHtFPl4EfY6n0K/HwN7FcHPhHZr5RmTcGHKVMV+5Xn",
+ "efAblaPyZvssru/b58h7v2bcbtAYWksAn/RNOV2uujceZJfgH65bGnQClMOYflv0cgmjX7S3tQFDDeZE",
+ "8NnR0VEsGaiPs/PfWIwpyf5aJTlcQT5k9RgSvffru77/PPqFrGHZgfDeHZE6qvi+gLYSwejnsLtv6W+D",
+ "3RslHxl2zYX7yEhQu8p+Mq0Qxn8p3iYJuZTU5oyIf108QZAxXNp3MPc9vH9/1bpvdig7va5Npq7luOKi",
+ "V3w8d2nwlJjeuBuMYh5Ao6lmzH/6N9/6b9czTulKqjatPwgH+5I0vY8SNEXTVkLSBLTLaRb73oMHecPu",
+ "E1VDJXjmMHtvv+jV03vRL2tbHOP7Prbp7ytLQ0NjJ698CaPO33MUeTRX7RcLE6LQ0KVhgOdzl6jS+9WG",
+ "k4Mfux8eiPw6b55QRhv7jppYq/Oj+E6thzT0OBKnGl/jp89IcMpKd0xsHWjH8zmFcNdKm/kEFU7XuRY2",
+ "fm5o/MVz3tP65vPN/w8AAP//J+D4wN2NAAA=",
}
// GetSwagger returns the Swagger specification corresponding to the generated code
diff --git a/daemon/algod/api/server/v2/generated/private/types.go b/daemon/algod/api/server/v2/generated/private/types.go
index 2184a38f9..ac0f2e670 100644
--- a/daemon/algod/api/server/v2/generated/private/types.go
+++ b/daemon/algod/api/server/v2/generated/private/types.go
@@ -217,20 +217,29 @@ type AssetParams struct {
// \[am\] A commitment to some unspecified asset metadata. The format of this metadata is up to the application.
MetadataHash *[]byte `json:"metadata-hash,omitempty"`
- // \[an\] Name of this asset, as supplied by the creator.
+ // \[an\] Name of this asset, as supplied by the creator. Included only when the asset name is composed of printable utf-8 characters.
Name *string `json:"name,omitempty"`
+ // Base64 encoded name of this asset, as supplied by the creator.
+ NameB64 *[]byte `json:"name-b64,omitempty"`
+
// \[r\] Address of account holding reserve (non-minted) units of this asset.
Reserve *string `json:"reserve,omitempty"`
// \[t\] The total number of units of this asset.
Total uint64 `json:"total"`
- // \[un\] Name of a unit of this asset, as supplied by the creator.
+ // \[un\] Name of a unit of this asset, as supplied by the creator. Included only when the name of a unit of this asset is composed of printable utf-8 characters.
UnitName *string `json:"unit-name,omitempty"`
- // \[au\] URL where more information about the asset can be retrieved.
+ // Base64 encoded name of a unit of this asset, as supplied by the creator.
+ UnitNameB64 *[]byte `json:"unit-name-b64,omitempty"`
+
+ // \[au\] URL where more information about the asset can be retrieved. Included only when the URL is composed of printable utf-8 characters.
Url *string `json:"url,omitempty"`
+
+ // Base64 encoded URL where more information about the asset can be retrieved.
+ UrlB64 *[]byte `json:"url-b64,omitempty"`
}
// BuildVersion defines model for BuildVersion.
diff --git a/daemon/algod/api/server/v2/generated/routes.go b/daemon/algod/api/server/v2/generated/routes.go
index a1e72467a..952a49eb4 100644
--- a/daemon/algod/api/server/v2/generated/routes.go
+++ b/daemon/algod/api/server/v2/generated/routes.go
@@ -616,179 +616,181 @@ func RegisterHandlers(router interface {
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "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",
- "Sud2BOfgKyW7wGr1H67+fwAAAP//rYSwcWn0AAA=",
+ "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",
+ "9wAA",
}
// GetSwagger returns the Swagger specification corresponding to the generated code
diff --git a/daemon/algod/api/server/v2/generated/types.go b/daemon/algod/api/server/v2/generated/types.go
index 985e4ab75..f26919b69 100644
--- a/daemon/algod/api/server/v2/generated/types.go
+++ b/daemon/algod/api/server/v2/generated/types.go
@@ -217,20 +217,29 @@ type AssetParams struct {
// \[am\] A commitment to some unspecified asset metadata. The format of this metadata is up to the application.
MetadataHash *[]byte `json:"metadata-hash,omitempty"`
- // \[an\] Name of this asset, as supplied by the creator.
+ // \[an\] Name of this asset, as supplied by the creator. Included only when the asset name is composed of printable utf-8 characters.
Name *string `json:"name,omitempty"`
+ // Base64 encoded name of this asset, as supplied by the creator.
+ NameB64 *[]byte `json:"name-b64,omitempty"`
+
// \[r\] Address of account holding reserve (non-minted) units of this asset.
Reserve *string `json:"reserve,omitempty"`
// \[t\] The total number of units of this asset.
Total uint64 `json:"total"`
- // \[un\] Name of a unit of this asset, as supplied by the creator.
+ // \[un\] Name of a unit of this asset, as supplied by the creator. Included only when the name of a unit of this asset is composed of printable utf-8 characters.
UnitName *string `json:"unit-name,omitempty"`
- // \[au\] URL where more information about the asset can be retrieved.
+ // Base64 encoded name of a unit of this asset, as supplied by the creator.
+ UnitNameB64 *[]byte `json:"unit-name-b64,omitempty"`
+
+ // \[au\] URL where more information about the asset can be retrieved. Included only when the URL is composed of printable utf-8 characters.
Url *string `json:"url,omitempty"`
+
+ // Base64 encoded URL where more information about the asset can be retrieved.
+ UrlB64 *[]byte `json:"url-b64,omitempty"`
}
// BuildVersion defines model for BuildVersion.
diff --git a/daemon/algod/api/server/v2/utils.go b/daemon/algod/api/server/v2/utils.go
index ef6f6712d..678889062 100644
--- a/daemon/algod/api/server/v2/utils.go
+++ b/daemon/algod/api/server/v2/utils.go
@@ -21,6 +21,8 @@ import (
"fmt"
"net/http"
"strings"
+ "unicode"
+ "unicode/utf8"
"github.com/algorand/go-codec/codec"
"github.com/labstack/echo/v4"
@@ -263,3 +265,17 @@ func convertToDeltas(txn node.TxnWithStatus) (*[]generated.AccountStateDelta, *g
return localStateDelta, stateDeltaToStateDelta(txn.ApplyData.EvalDelta.GlobalDelta)
}
+
+// printableUTF8OrEmpty checks to see if the entire string is a UTF8 printable string.
+// If this is the case, the string is returned as is. Otherwise, the empty string is returned.
+func printableUTF8OrEmpty(in string) string {
+ // iterate throughout all the characters in the string to see if they are all printable.
+ // when range iterating on go strings, go decode each element as a utf8 rune.
+ for _, c := range in {
+ // is this a printable character, or invalid rune ?
+ if c == utf8.RuneError || !unicode.IsPrint(c) {
+ return ""
+ }
+ }
+ return in
+}
diff --git a/daemon/kmd/README.md b/daemon/kmd/README.md
index e95b923b7..b7a0a0cae 100644
--- a/daemon/kmd/README.md
+++ b/daemon/kmd/README.md
@@ -22,7 +22,7 @@ In order for the `mlockall` call to succeed, your kernel must support `mlockall`
- The `client` package provides `client.KMDClient`. `client.KMDClient.DoV1Request` infers the HTTP endpoint and method from the request type, serializes the request with msgpack, makes the request over the unix socket, and deserializes a `kmdapi.APIV1Response`.
- The `client` package also provides wrappers for these API calls in `wrappers.go`
- `config/`
- - This folder contains code that parses `kmd_config.json` and merges values from that file with any defualt values.
+ - This folder contains code that parses `kmd_config.json` and merges values from that file with any default values.
- `lib/`
- This folder contains the `kmdapi` package, which provides the canonical structs used for requests and responses.
- `server/`
diff --git a/daemon/kmd/api/swagger.json b/daemon/kmd/api/swagger.json
index fce64be4b..3d1812a6e 100644
--- a/daemon/kmd/api/swagger.json
+++ b/daemon/kmd/api/swagger.json
@@ -644,7 +644,7 @@
"x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi"
},
"APIV1POSTKeyExportResponse": {
- "description": "APIV1POSTKeyExportResponse is the reponse to `POST /v1/key/export`\nfriendly:ExportKeyResponse",
+ "description": "APIV1POSTKeyExportResponse is the response to `POST /v1/key/export`\nfriendly:ExportKeyResponse",
"type": "object",
"properties": {
"error": {
@@ -662,7 +662,7 @@
"x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi"
},
"APIV1POSTKeyImportResponse": {
- "description": "APIV1POSTKeyImportResponse is the repsonse to `POST /v1/key/import`\nfriendly:ImportKeyResponse",
+ "description": "APIV1POSTKeyImportResponse is the response to `POST /v1/key/import`\nfriendly:ImportKeyResponse",
"type": "object",
"properties": {
"address": {
@@ -722,7 +722,7 @@
"x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi"
},
"APIV1POSTMasterKeyExportResponse": {
- "description": "APIV1POSTMasterKeyExportResponse is the reponse to `POST /v1/master-key/export`\nfriendly:ExportMasterKeyResponse",
+ "description": "APIV1POSTMasterKeyExportResponse is the response to `POST /v1/master-key/export`\nfriendly:ExportMasterKeyResponse",
"type": "object",
"properties": {
"error": {
@@ -853,7 +853,7 @@
"x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi"
},
"APIV1POSTProgramSignResponse": {
- "description": "APIV1POSTProgramSignResponse is the repsonse to `POST /v1/data/sign`\nfriendly:SignProgramResponse",
+ "description": "APIV1POSTProgramSignResponse is the response to `POST /v1/data/sign`\nfriendly:SignProgramResponse",
"type": "object",
"properties": {
"error": {
@@ -873,7 +873,7 @@
"x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi"
},
"APIV1POSTTransactionSignResponse": {
- "description": "APIV1POSTTransactionSignResponse is the repsonse to `POST /v1/transaction/sign`\nfriendly:SignTransactionResponse",
+ "description": "APIV1POSTTransactionSignResponse is the response to `POST /v1/transaction/sign`\nfriendly:SignTransactionResponse",
"type": "object",
"properties": {
"error": {
@@ -1570,13 +1570,13 @@
}
},
"ExportKeyResponse": {
- "description": "Reponse to `POST /v1/key/export`",
+ "description": "Response to `POST /v1/key/export`",
"schema": {
"$ref": "#/definitions/APIV1POSTKeyExportResponse"
}
},
"ExportMasterKeyResponse": {
- "description": "Reponse to `POST /v1/master-key/export`",
+ "description": "Response to `POST /v1/master-key/export`",
"schema": {
"$ref": "#/definitions/APIV1POSTMasterKeyExportResponse"
}
@@ -1594,7 +1594,7 @@
}
},
"ImportKeyResponse": {
- "description": "Repsonse to `POST /v1/key/import`",
+ "description": "Response to `POST /v1/key/import`",
"schema": {
"$ref": "#/definitions/APIV1POSTKeyImportResponse"
}
diff --git a/daemon/kmd/lib/kmdapi/bundledSpecInject.go b/daemon/kmd/lib/kmdapi/bundledSpecInject.go
index 944e28f07..d4682e9a6 100644
--- a/daemon/kmd/lib/kmdapi/bundledSpecInject.go
+++ b/daemon/kmd/lib/kmdapi/bundledSpecInject.go
@@ -1168,13 +1168,260 @@ func init() {
0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A,
0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x45, 0x78,
0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20,
- 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60,
- 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x2F, 0x65, 0x78, 0x70,
- 0x6F, 0x72, 0x74, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x45,
- 0x78, 0x70, 0x6F, 0x72, 0x74, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
+ 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20,
+ 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x2F, 0x65, 0x78,
+ 0x70, 0x6F, 0x72, 0x74, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A,
+ 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
+ 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
+ 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65,
+ 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F,
+ 0x6E, 0x73, 0x2F, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61,
+ 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E,
+ 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D,
+ 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F,
+ 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56,
+ 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65,
+ 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20,
+ 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x49, 0x6D, 0x70,
+ 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60,
+ 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x2F, 0x69, 0x6D, 0x70,
+ 0x6F, 0x72, 0x74, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x49,
+ 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
+ 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61,
+ 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
+ 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61,
+ 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72,
+ 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C,
+ 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54,
+ 0x4B, 0x65, 0x79, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22,
+ 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72,
+ 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50,
+ 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
+ 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E,
+ 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F,
+ 0x6B, 0x65, 0x79, 0x2F, 0x6C, 0x69, 0x73, 0x74, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E,
+ 0x64, 0x6C, 0x79, 0x3A, 0x4C, 0x69, 0x73, 0x74, 0x4B, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70,
+ 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79,
+ 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x61, 0x64,
+ 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61,
+ 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x64,
+ 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72,
+ 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61,
+ 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
+ 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F,
+ 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A,
+ 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79,
+ 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E,
+ 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70,
+ 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
+ 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F,
+ 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E,
+ 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49,
+ 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
+ 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56,
+ 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
+ 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65,
+ 0x79, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x47, 0x65, 0x6E,
+ 0x65, 0x72, 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
+ 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
+ 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
+ 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61,
+ 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
+ 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61,
+ 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72,
+ 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C,
+ 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54,
+ 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x4B, 0x65, 0x79, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52,
+ 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A,
+ 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x61, 0x73, 0x74, 0x65,
+ 0x72, 0x4B, 0x65, 0x79, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
+ 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E,
+ 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F,
+ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2D, 0x6B, 0x65, 0x79, 0x2F, 0x65, 0x78, 0x70, 0x6F, 0x72,
+ 0x74, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x45, 0x78, 0x70,
+ 0x6F, 0x72, 0x74, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70,
+ 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79,
+ 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72,
+ 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65,
+ 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72,
+ 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5F, 0x64,
+ 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65,
+ 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F,
+ 0x6E, 0x73, 0x2F, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x44, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74,
+ 0x69, 0x6F, 0x6E, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E,
+ 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
+ 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
+ 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67,
+ 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61,
+ 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64,
+ 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D,
+ 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69,
+ 0x73, 0x69, 0x67, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
+ 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56,
+ 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x45, 0x78, 0x70,
+ 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60,
+ 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69,
+ 0x67, 0x2F, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E,
+ 0x64, 0x6C, 0x79, 0x3A, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73,
+ 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65,
+ 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70,
+ 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72,
+ 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x75, 0x6C, 0x74, 0x69,
+ 0x73, 0x69, 0x67, 0x5F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A,
+ 0x20, 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A,
+ 0x20, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70,
+ 0x6B, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65,
+ 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65,
+ 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63,
+ 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
+ 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x50, 0x4B, 0x73, 0x22, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6F, 0x6C, 0x64, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22,
+ 0x3A, 0x20, 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6F, 0x6C, 0x64, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63,
+ 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63,
+ 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61,
+ 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B,
+ 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31,
+ 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x49, 0x6D, 0x70, 0x6F,
+ 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F,
+ 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75,
+ 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70,
+ 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70,
+ 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76,
+ 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x69, 0x6D, 0x70, 0x6F, 0x72,
+ 0x74, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x49, 0x6D, 0x70,
+ 0x6F, 0x72, 0x74, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F,
+ 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22,
+ 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x61, 0x64, 0x64,
+ 0x72, 0x65, 0x73, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69,
+ 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x64, 0x64,
+ 0x72, 0x65, 0x73, 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22,
0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C,
@@ -1186,36 +1433,68 @@ func init() {
0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65,
0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66,
- 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E,
- 0x73, 0x2F, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63,
- 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63,
- 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61,
- 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B,
- 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31,
- 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73,
- 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22,
- 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x49, 0x6D, 0x70, 0x6F,
- 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
- 0x65, 0x20, 0x72, 0x65, 0x70, 0x73, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50,
- 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x2F, 0x69, 0x6D, 0x70, 0x6F,
- 0x72, 0x74, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x49, 0x6D,
- 0x70, 0x6F, 0x72, 0x74, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
- 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
- 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B,
+ 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F,
+ 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C,
+ 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D,
+ 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50,
+ 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x4C, 0x69, 0x73, 0x74, 0x52,
+ 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A,
+ 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69,
+ 0x73, 0x69, 0x67, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20,
+ 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C,
+ 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x6C, 0x69, 0x73, 0x74, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69,
+ 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x4C, 0x69, 0x73, 0x74, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73,
+ 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65,
+ 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70,
+ 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
+ 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
+ 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A,
+ 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69,
+ 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22,
+ 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72,
+ 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F,
+ 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B,
+ 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74,
+ 0x69, 0x73, 0x69, 0x67, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52,
+ 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A,
+ 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69,
+ 0x73, 0x69, 0x67, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65,
+ 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
+ 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20,
+ 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x73, 0x69, 0x67,
+ 0x6E, 0x64, 0x61, 0x74, 0x61, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79,
+ 0x3A, 0x53, 0x69, 0x67, 0x6E, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x4D, 0x75, 0x6C, 0x74,
+ 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62,
+ 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72,
+ 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
@@ -1227,45 +1506,53 @@ func init() {
0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22,
0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C,
- 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61,
- 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69,
- 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B,
- 0x65, 0x79, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F,
- 0x53, 0x54, 0x4B, 0x65, 0x79, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
- 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
- 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B,
- 0x65, 0x79, 0x2F, 0x6C, 0x69, 0x73, 0x74, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64,
- 0x6C, 0x79, 0x3A, 0x4C, 0x69, 0x73, 0x74, 0x4B, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6F,
- 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22,
- 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x61, 0x64, 0x64,
- 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72,
- 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x64, 0x64,
- 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F,
- 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E,
+ 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x75, 0x6C,
+ 0x74, 0x69, 0x73, 0x69, 0x67, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72,
+ 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x79, 0x74, 0x65, 0x22,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
+ 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73,
+ 0x69, 0x67, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
+ 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69,
+ 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E,
+ 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61,
+ 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64,
+ 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73,
+ 0x69, 0x67, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67,
+ 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E,
+ 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C,
+ 0x74, 0x69, 0x73, 0x69, 0x67, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20,
+ 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73,
+ 0x69, 0x67, 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64,
+ 0x6C, 0x79, 0x3A, 0x53, 0x69, 0x67, 0x6E, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52,
+ 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74,
+ 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F,
+ 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22,
+ 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
- 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72,
- 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61,
- 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20,
+ 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D,
+ 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x22, 0x0A, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61,
0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E,
@@ -1273,51 +1560,54 @@ func init() {
0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F,
0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56,
- 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
- 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31,
- 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20,
+ 0x31, 0x50, 0x4F, 0x53, 0x54, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E,
+ 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22,
+ 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x50, 0x72, 0x6F, 0x67,
+ 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20,
0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20,
- 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79,
- 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x47, 0x65, 0x6E, 0x65,
- 0x72, 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
+ 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x64, 0x61, 0x74,
+ 0x61, 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C,
+ 0x79, 0x3A, 0x53, 0x69, 0x67, 0x6E, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x52, 0x65, 0x73,
+ 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
+ 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65,
+ 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65,
+ 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C,
+ 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72,
+ 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
+ 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73,
- 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x69, 0x67, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x62,
+ 0x79, 0x74, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x53, 0x69,
+ 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22,
0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C,
0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61,
0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69,
0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D,
- 0x61, 0x73, 0x74, 0x65, 0x72, 0x4B, 0x65, 0x79, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x54,
+ 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65,
0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20,
- 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72,
- 0x4B, 0x65, 0x79, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
- 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x70, 0x6F, 0x6E, 0x73, 0x65,
- 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x61,
- 0x73, 0x74, 0x65, 0x72, 0x2D, 0x6B, 0x65, 0x79, 0x2F, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x60,
- 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x45, 0x78, 0x70, 0x6F, 0x72,
- 0x74, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
+ 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
+ 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
+ 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x74,
+ 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x60,
+ 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x53, 0x69, 0x67, 0x6E, 0x54,
+ 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A,
@@ -1327,210 +1617,111 @@ func init() {
0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72,
0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5F, 0x64, 0x65, 0x72,
- 0x69, 0x76, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22,
- 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73,
- 0x2F, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x44, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6F,
- 0x6E, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67,
- 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
- 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67,
- 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
- 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74,
- 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64,
- 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65,
- 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61,
- 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69,
- 0x67, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22,
- 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50,
- 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x45, 0x78, 0x70, 0x6F, 0x72,
- 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65,
- 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F,
- 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F,
- 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C,
- 0x79, 0x3A, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67,
- 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72,
- 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62,
- 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73,
- 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E,
- 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
- 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73,
- 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69,
- 0x67, 0x5F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22,
- 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x6B, 0x73,
- 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73,
- 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69,
- 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65,
- 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D,
- 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x50, 0x4B, 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6F, 0x6C, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20,
- 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6F, 0x6C, 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61,
- 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D,
- 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67,
- 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64,
- 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F,
- 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74,
- 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22,
- 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74,
- 0x69, 0x73, 0x69, 0x67, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
- 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E,
- 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F,
- 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x60,
- 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x49, 0x6D, 0x70, 0x6F, 0x72,
- 0x74, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
- 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65,
- 0x73, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
- 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x64, 0x64, 0x72, 0x65,
- 0x73, 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20,
0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E,
- 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F,
- 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F,
- 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F,
- 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53,
- 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61,
+ 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x5F, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72,
+ 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x79, 0x74, 0x65, 0x22,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
+ 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x64,
+ 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B,
+ 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F,
+ 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C,
+ 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D,
+ 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50,
+ 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x66, 0x6F, 0x52, 0x65, 0x73,
0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22,
- 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69,
- 0x67, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73,
- 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F,
- 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69,
- 0x73, 0x69, 0x67, 0x2F, 0x6C, 0x69, 0x73, 0x74, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E,
- 0x64, 0x6C, 0x79, 0x3A, 0x4C, 0x69, 0x73, 0x74, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67,
- 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72,
- 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x0A, 0x20, 0x20, 0x20,
+ 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49,
+ 0x6E, 0x66, 0x6F, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60,
+ 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F,
+ 0x69, 0x6E, 0x66, 0x6F, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A,
+ 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x66, 0x6F, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
+ 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A,
+ 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F,
+ 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E,
+ 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
+ 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72,
+ 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61,
+ 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69,
+ 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x57, 0x61, 0x6C, 0x6C, 0x65,
+ 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C,
+ 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61,
+ 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69,
+ 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57,
+ 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
+ 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56,
+ 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x69, 0x74, 0x52,
+ 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72,
+ 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54,
+ 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x69, 0x6E, 0x69, 0x74,
+ 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x49, 0x6E, 0x69, 0x74,
+ 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65,
+ 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63,
+ 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65,
+ 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
+ 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F,
- 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61,
- 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
- 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61,
- 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
- 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69,
- 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E,
- 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61,
- 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64,
- 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73,
- 0x69, 0x67, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73,
- 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22,
- 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69,
- 0x67, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70,
- 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70,
- 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76,
- 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x64,
- 0x61, 0x74, 0x61, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x53,
- 0x69, 0x67, 0x6E, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73,
- 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65,
- 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70,
- 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65,
- 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72,
- 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65,
- 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x75, 0x6C, 0x74, 0x69,
- 0x73, 0x69, 0x67, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E,
- 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66,
- 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D,
- 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67,
- 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68,
- 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F,
- 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D,
- 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70,
- 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41,
- 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67,
- 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x52,
- 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A,
- 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69,
- 0x73, 0x69, 0x67, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69,
- 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
- 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50,
- 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67,
- 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79,
- 0x3A, 0x53, 0x69, 0x67, 0x6E, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73,
+ 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69,
+ 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74,
+ 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61,
+ 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64,
+ 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C,
+ 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61,
+ 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69,
+ 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57,
+ 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70,
+ 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41,
+ 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65,
+ 0x6C, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F,
+ 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65,
+ 0x74, 0x2F, 0x72, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65,
+ 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x52, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x57, 0x61, 0x6C, 0x6C,
+ 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x52, 0x65, 0x73,
0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65,
@@ -1545,214 +1736,59 @@ func init() {
0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
- 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79,
- 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74,
- 0x22, 0x3A, 0x20, 0x22, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x22, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B,
- 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F,
- 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C,
- 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D,
- 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50,
- 0x4F, 0x53, 0x54, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65,
- 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20,
- 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61,
- 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73,
- 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x70, 0x73, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F,
- 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x2F,
- 0x73, 0x69, 0x67, 0x6E, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A,
- 0x53, 0x69, 0x67, 0x6E, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x52, 0x65, 0x73, 0x70, 0x6F,
- 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22,
- 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72,
- 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61,
- 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
- 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F,
- 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A,
+ 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
+ 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68,
+ 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F,
+ 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D,
+ 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70,
+ 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41,
+ 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65,
+ 0x6E, 0x61, 0x6D, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54,
+ 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x52, 0x65, 0x73, 0x70,
+ 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70,
+ 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76,
+ 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x72, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x60,
+ 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x52, 0x65, 0x6E, 0x61, 0x6D,
+ 0x65, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A,
0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79,
- 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E,
- 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x73, 0x69, 0x67, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73,
- 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x79, 0x74,
- 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
- 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E,
- 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F,
- 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64,
- 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F,
- 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x54, 0x72, 0x61,
- 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70,
- 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41,
- 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74,
- 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20,
- 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x70, 0x73, 0x6F, 0x6E, 0x73, 0x65, 0x20,
- 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x74, 0x72, 0x61,
- 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x60, 0x5C, 0x6E,
- 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x53, 0x69, 0x67, 0x6E, 0x54, 0x72, 0x61,
- 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22,
- 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
- 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65,
- 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x5F, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74,
- 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E,
- 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66,
- 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x0A,
+ 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D,
- 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x54, 0x72,
- 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F,
- 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F,
- 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F,
- 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53,
- 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x66, 0x6F, 0x52, 0x65, 0x73, 0x70, 0x6F,
- 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64,
- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50,
- 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x66,
- 0x6F, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65,
- 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F,
- 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x69, 0x6E,
- 0x66, 0x6F, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x57, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x66, 0x6F, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22,
- 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
- 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65,
- 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72,
- 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69,
- 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48,
- 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F,
- 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64,
- 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F,
- 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C,
- 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22,
- 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50,
- 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x69, 0x74, 0x52, 0x65, 0x73,
- 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73,
- 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F,
- 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x69, 0x6E, 0x69, 0x74, 0x60, 0x5C,
- 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x49, 0x6E, 0x69, 0x74, 0x57, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x52,
- 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74,
- 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F,
- 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61,
- 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
- 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61,
- 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68,
- 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65,
- 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65,
- 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F,
- 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64,
- 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F,
- 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C,
- 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
+ 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
+ 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F,
+ 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56,
+ 0x31, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C,
+ 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61,
+ 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69,
+ 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57,
+ 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E, 0x65, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49,
- 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6C, 0x65,
- 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74,
- 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60,
- 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F,
- 0x72, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64,
- 0x6C, 0x79, 0x3A, 0x52, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74,
- 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F,
- 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22,
- 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72,
- 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61,
- 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
- 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F,
- 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79,
- 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E,
- 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70,
- 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
- 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F,
- 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E,
- 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49,
- 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E, 0x61,
- 0x6D, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F,
- 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
- 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E,
- 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F,
- 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x72, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x60, 0x5C, 0x6E,
- 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x52, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x57,
- 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A,
+ 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E, 0x65,
+ 0x77, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F,
+ 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x72, 0x65,
+ 0x6E, 0x65, 0x77, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x52,
+ 0x65, 0x6E, 0x65, 0x77, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65,
+ 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F,
0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70,
0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
@@ -1768,230 +1804,233 @@ func init() {
0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65,
- 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x57,
- 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F,
- 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64,
- 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F,
- 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C,
- 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E, 0x65, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
+ 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22,
+ 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73,
+ 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64,
+ 0x6C, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
+ 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69,
+ 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E,
+ 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61,
+ 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64,
+ 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74,
+ 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22,
+ 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C,
+ 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50,
+ 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x60, 0x5C,
+ 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
+ 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
+ 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E,
+ 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A,
+ 0x20, 0x22, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77,
+ 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64,
+ 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31,
+ 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A,
+ 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67,
+ 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E,
+ 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62,
+ 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74,
0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31,
- 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E, 0x65, 0x77, 0x52,
- 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72,
- 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54,
- 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x72, 0x65, 0x6E, 0x65,
- 0x77, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x52, 0x65, 0x6E,
- 0x65, 0x77, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F,
- 0x6B, 0x65, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A,
- 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F,
- 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x50,
+ 0x49, 0x27, 0x73, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6E, 0x74, 0x61, 0x74, 0x69,
+ 0x6F, 0x6E, 0x20, 0x6F, 0x66, 0x20, 0x61, 0x20, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x22, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
+ 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x5F, 0x6E,
+ 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E,
+ 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
+ 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x44, 0x72, 0x69, 0x76,
+ 0x65, 0x72, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x72, 0x69, 0x76,
+ 0x65, 0x72, 0x5F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65,
- 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D,
- 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74,
- 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4D,
- 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C,
- 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20,
- 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41,
- 0x50, 0x49, 0x56, 0x31, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65,
- 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68,
- 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F,
- 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D,
- 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70,
- 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x41,
- 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65,
- 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20,
- 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74,
- 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
- 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53,
- 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x60, 0x5C, 0x6E, 0x66,
- 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62,
- 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72,
- 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20,
+ 0x22, 0x75, 0x69, 0x6E, 0x74, 0x33, 0x32, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A,
+ 0x20, 0x22, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73,
0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C,
- 0x6C, 0x65, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66,
- 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x57, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72,
- 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F,
- 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B,
- 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x57, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x50, 0x49, 0x27,
- 0x73, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6E, 0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E,
- 0x20, 0x6F, 0x66, 0x20, 0x61, 0x20, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62,
- 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72,
- 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x5F, 0x6E, 0x61, 0x6D,
- 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
- 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72,
- 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72,
- 0x5F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x75,
- 0x69, 0x6E, 0x74, 0x33, 0x32, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x49, 0x44, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x6E, 0x65, 0x6D, 0x6F, 0x6E, 0x69, 0x63,
+ 0x5F, 0x75, 0x78, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65,
+ 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x53, 0x75, 0x70,
+ 0x70, 0x6F, 0x72, 0x74, 0x73, 0x4D, 0x6E, 0x65, 0x6D, 0x6F, 0x6E, 0x69, 0x63, 0x55, 0x58, 0x22,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A,
+ 0x20, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x75, 0x70, 0x70,
+ 0x6F, 0x72, 0x74, 0x65, 0x64, 0x5F, 0x74, 0x78, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22,
+ 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73,
+ 0x2F, 0x54, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x53, 0x75,
+ 0x70, 0x70, 0x6F, 0x72, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
+ 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67,
+ 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61,
+ 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64,
+ 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D,
+ 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E,
+ 0x64, 0x6C, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64,
+ 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50,
+ 0x49, 0x56, 0x31, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20,
+ 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x6C,
+ 0x6C, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x63,
+ 0x6F, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x64, 0x73, 0x20, 0x74, 0x6F, 0x5C, 0x6E, 0x61,
+ 0x6E, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x20, 0x6F, 0x66,
+ 0x20, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x20, 0x6F, 0x66, 0x20, 0x73, 0x65, 0x63, 0x6F, 0x6E,
+ 0x64, 0x73, 0x20, 0x74, 0x6F, 0x20, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E,
+ 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
+ 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65,
+ 0x73, 0x5F, 0x73, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22,
+ 0x69, 0x6E, 0x74, 0x36, 0x34, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x69, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x53, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x73, 0x22, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A,
+ 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F,
+ 0x41, 0x50, 0x49, 0x56, 0x31, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x22, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B,
+ 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F,
+ 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C,
+ 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D,
+ 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
+ 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
+ 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53,
+ 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F,
+ 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C,
+ 0x65, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22,
+ 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x61, 0x73,
+ 0x74, 0x65, 0x72, 0x5F, 0x64, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x5F, 0x6B,
+ 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69,
+ 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x44, 0x65,
+ 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x5F, 0x6E,
+ 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E,
+ 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
+ 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C,
+ 0x65, 0x74, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61,
+ 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65,
+ 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x73,
+ 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72,
0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x49, 0x44,
- 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x6E, 0x65, 0x6D, 0x6F, 0x6E, 0x69, 0x63, 0x5F, 0x75,
- 0x78, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
- 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x53, 0x75, 0x70, 0x70, 0x6F,
- 0x72, 0x74, 0x73, 0x4D, 0x6E, 0x65, 0x6D, 0x6F, 0x6E, 0x69, 0x63, 0x55, 0x58, 0x22, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73,
- 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x75, 0x70, 0x70, 0x6F, 0x72,
- 0x74, 0x65, 0x64, 0x5F, 0x74, 0x78, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61,
- 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20,
- 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x54,
- 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
- 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x53, 0x75, 0x70, 0x70,
- 0x6F, 0x72, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E,
- 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
- 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74,
- 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64,
- 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65,
- 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61,
- 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x41, 0x50, 0x49, 0x56, 0x31, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C,
- 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73,
- 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56,
- 0x31, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x69, 0x6E,
- 0x63, 0x6C, 0x75, 0x64, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x6C, 0x6C, 0x65,
- 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x63, 0x6F, 0x72,
- 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x64, 0x73, 0x20, 0x74, 0x6F, 0x5C, 0x6E, 0x61, 0x6E, 0x64,
- 0x20, 0x74, 0x68, 0x65, 0x20, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x20, 0x6F, 0x66, 0x20, 0x6E,
- 0x75, 0x6D, 0x62, 0x65, 0x72, 0x20, 0x6F, 0x66, 0x20, 0x73, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x73,
- 0x20, 0x74, 0x6F, 0x20, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5F,
- 0x73, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x69,
- 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E,
- 0x74, 0x36, 0x34, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x45, 0x78,
- 0x70, 0x69, 0x72, 0x65, 0x73, 0x53, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x73, 0x22, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22,
- 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50,
- 0x49, 0x56, 0x31, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
+ 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61,
+ 0x6C, 0x6C, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61,
+ 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67,
0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F,
0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F,
0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F,
0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
- 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57,
- 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20,
- 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20,
- 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74,
- 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x61, 0x73, 0x74, 0x65,
- 0x72, 0x5F, 0x64, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x5F, 0x6B, 0x65, 0x79,
- 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69,
- 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x44, 0x65, 0x72, 0x69,
- 0x76, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77,
- 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x5F, 0x6E, 0x61, 0x6D,
- 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
- 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74,
- 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65,
- 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77,
- 0x6F, 0x72, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E,
- 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
- 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C,
- 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C,
- 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C,
- 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61,
- 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69,
- 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20,
- 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x4B, 0x65, 0x79, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x44, 0x45, 0x4C, 0x45, 0x54,
- 0x45, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x4B, 0x65,
+ 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22,
+ 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x4B, 0x65,
+ 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x44, 0x45, 0x4C,
+ 0x45, 0x54, 0x45, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x60, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62,
+ 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72,
+ 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61,
+ 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65,
+ 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74,
+ 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57,
+ 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E,
+ 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x73,
+ 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72,
+ 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61,
+ 0x6C, 0x6C, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x44, 0x45, 0x4C, 0x45, 0x54, 0x45,
+ 0x4B, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61,
+ 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72,
+ 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C,
+ 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x4D, 0x75, 0x6C,
+ 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x44, 0x45, 0x4C, 0x45,
+ 0x54, 0x45, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x20, 0x2F, 0x76, 0x31,
+ 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65,
0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70,
0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
@@ -2016,21 +2055,38 @@ func init() {
0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x4B, 0x65,
- 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67,
- 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E,
- 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62,
- 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x4D, 0x75, 0x6C, 0x74, 0x69,
- 0x73, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F,
- 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x44, 0x45, 0x4C, 0x45, 0x54, 0x45,
- 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20,
+ 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x4D, 0x75,
+ 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B,
+ 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F,
+ 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C,
+ 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D,
+ 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x44, 0x69, 0x67, 0x65,
+ 0x73, 0x74, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6E, 0x74, 0x73, 0x20, 0x61, 0x20,
+ 0x33, 0x32, 0x2D, 0x62, 0x79, 0x74, 0x65, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x68, 0x6F,
+ 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x32, 0x35, 0x36, 0x2D, 0x62, 0x69,
+ 0x74, 0x20, 0x48, 0x61, 0x73, 0x68, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x2E, 0x22, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22,
+ 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B,
+ 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F,
+ 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C,
+ 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x22, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x45, 0x78, 0x70, 0x6F, 0x72,
+ 0x74, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
+ 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B,
+ 0x65, 0x79, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20,
0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66,
- 0x6F, 0x72, 0x20, 0x60, 0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D,
- 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79,
+ 0x2F, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74,
0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72,
0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
@@ -2055,153 +2111,128 @@ func init() {
0x50, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x4D, 0x75, 0x6C, 0x74,
- 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F,
- 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F,
- 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F,
- 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74,
- 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6E, 0x74, 0x73, 0x20, 0x61, 0x20, 0x33, 0x32,
- 0x2D, 0x62, 0x79, 0x74, 0x65, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x68, 0x6F, 0x6C, 0x64,
- 0x69, 0x6E, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x32, 0x35, 0x36, 0x2D, 0x62, 0x69, 0x74, 0x20,
- 0x48, 0x61, 0x73, 0x68, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x2E, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x75, 0x69,
- 0x6E, 0x74, 0x38, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F,
- 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F,
- 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x22, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x4B,
- 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E,
- 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79,
+ 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x45, 0x78, 0x70,
+ 0x6F, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61,
+ 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72,
+ 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C,
+ 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x4D, 0x61, 0x73,
+ 0x74, 0x65, 0x72, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
+ 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53,
+ 0x54, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x4B, 0x65, 0x79, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54,
+ 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2D, 0x6B, 0x65, 0x79, 0x2F,
+ 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74,
+ 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74,
+ 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69,
+ 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C,
+ 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77,
+ 0x6F, 0x72, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E,
+ 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
+ 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C,
+ 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x61, 0x73, 0x74,
+ 0x65, 0x72, 0x4B, 0x65, 0x79, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
+ 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68,
+ 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F,
+ 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D,
+ 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70,
+ 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x45,
+ 0x78, 0x70, 0x6F, 0x72, 0x74, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41,
+ 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67,
0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73,
0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72,
- 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x2F, 0x65,
- 0x78, 0x70, 0x6F, 0x72, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69,
- 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73,
- 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C,
- 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E,
- 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48,
- 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22,
- 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
- 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D,
- 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x50, 0x61,
- 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41,
- 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x45, 0x78, 0x70, 0x6F, 0x72,
- 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67,
- 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E,
- 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62,
- 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x4D, 0x61, 0x73, 0x74, 0x65,
- 0x72, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
- 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D,
- 0x61, 0x73, 0x74, 0x65, 0x72, 0x4B, 0x65, 0x79, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F,
- 0x76, 0x31, 0x2F, 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2D, 0x6B, 0x65, 0x79, 0x2F, 0x65, 0x78,
- 0x70, 0x6F, 0x72, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
+ 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69,
+ 0x73, 0x69, 0x67, 0x2F, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A,
+ 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F,
+ 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F,
+ 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72,
+ 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61,
+ 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D,
+ 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53,
+ 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22,
+ 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72,
+ 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F,
+ 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B,
+ 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x47, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22,
+ 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31,
+ 0x2F, 0x6B, 0x65, 0x79, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65,
- 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77,
- 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B,
- 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
- 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65,
- 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72,
- 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64,
+ 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x5F, 0x6D, 0x6E, 0x65, 0x6D, 0x6F, 0x6E, 0x69, 0x63, 0x22,
+ 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
+ 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
+ 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x44, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79,
+ 0x4D, 0x6E, 0x65, 0x6D, 0x6F, 0x6E, 0x69, 0x63, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61,
+ 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65,
+ 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22,
0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74,
- 0x50, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72,
- 0x4B, 0x65, 0x79, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70,
- 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
- 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F,
- 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E,
- 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x45, 0x78, 0x70,
- 0x6F, 0x72, 0x74, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49,
- 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x45, 0x78,
- 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74,
- 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60,
- 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69,
- 0x67, 0x2F, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63,
- 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65,
- 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F,
- 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E,
- 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
- 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C,
- 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61,
- 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D,
- 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
- 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69,
- 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E,
- 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61,
- 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64,
- 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x47, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64,
- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50,
- 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B,
- 0x65, 0x79, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22,
- 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x69, 0x73,
- 0x70, 0x6C, 0x61, 0x79, 0x5F, 0x6D, 0x6E, 0x65, 0x6D, 0x6F, 0x6E, 0x69, 0x63, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E,
- 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x44, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x4D, 0x6E,
- 0x65, 0x6D, 0x6F, 0x6E, 0x69, 0x63, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F,
+ 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64,
+ 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F,
+ 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41,
+ 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x49, 0x6D, 0x70, 0x6F, 0x72,
+ 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53,
+ 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x2F, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74,
+ 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x69, 0x76, 0x61,
+ 0x74, 0x65, 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F,
+ 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x50, 0x72, 0x69, 0x76,
+ 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C,
0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22,
0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
@@ -2211,82 +2242,110 @@ func init() {
0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
- 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67,
- 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61,
- 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64,
- 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D,
- 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49,
- 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x52,
+ 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x49, 0x6D,
+ 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F,
+ 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F,
+ 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F,
+ 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x4D, 0x75,
+ 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
+ 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53,
+ 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20,
- 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x2F, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x60, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
- 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65,
- 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74,
- 0x65, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74,
- 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x69, 0x6D, 0x70,
+ 0x6F, 0x72, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79,
+ 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x75,
+ 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x5F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x3A,
+ 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79,
+ 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61,
+ 0x74, 0x22, 0x3A, 0x20, 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x70, 0x6B, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72,
+ 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23,
+ 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x50, 0x75, 0x62,
+ 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x50, 0x4B, 0x73,
+ 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6F, 0x6C, 0x64, 0x22,
+ 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
+ 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D,
+ 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x2C, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61,
- 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64,
- 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x49, 0x6D, 0x70, 0x6F,
+ 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6F, 0x6C, 0x64, 0x22,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64,
+ 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
+ 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B,
+ 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
+ 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31,
+ 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x49, 0x6D, 0x70, 0x6F,
0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22,
0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C,
0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61,
0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69,
0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x4D, 0x75, 0x6C, 0x74,
- 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
- 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D,
- 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76,
- 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x69, 0x6D, 0x70, 0x6F, 0x72,
- 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
- 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6D, 0x75, 0x6C, 0x74,
- 0x69, 0x73, 0x69, 0x67, 0x5F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x7B,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
- 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22,
- 0x3A, 0x20, 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x49, 0x6E, 0x69, 0x74, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74,
+ 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49,
+ 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x69, 0x74,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54,
+ 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x69, 0x6E, 0x69, 0x74,
+ 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65,
+ 0x74, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69,
+ 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C,
+ 0x6C, 0x65, 0x74, 0x49, 0x44, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65,
+ 0x74, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
+ 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x70, 0x6B, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74,
- 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64,
- 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x50, 0x75, 0x62, 0x6C, 0x69,
- 0x63, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
- 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x50, 0x4B, 0x73, 0x22, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6F, 0x6C, 0x64, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74,
- 0x22, 0x3A, 0x20, 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65,
- 0x22, 0x3A, 0x20, 0x22, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6F, 0x6C, 0x64, 0x22, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72,
+ 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
+ 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50,
+ 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x69, 0x74, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
+ 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69,
+ 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E,
+ 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61,
+ 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64,
+ 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x4C, 0x69, 0x73, 0x74, 0x4B, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31,
+ 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F,
+ 0x6B, 0x65, 0x79, 0x2F, 0x6C, 0x69, 0x73, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63,
+ 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65,
+ 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65,
0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74,
@@ -2296,446 +2355,340 @@ func init() {
0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F,
- 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F,
- 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64,
- 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F,
- 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x49, 0x6E, 0x69, 0x74, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61,
- 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x53, 0x54, 0x4B, 0x65, 0x79, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70,
+ 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
+ 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F,
+ 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E,
+ 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4C, 0x69, 0x73,
+ 0x74, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31,
- 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x69, 0x74, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F,
- 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x69, 0x6E, 0x69, 0x74, 0x60, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F,
- 0x69, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
- 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65,
- 0x74, 0x49, 0x44, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F,
- 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D,
- 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53,
- 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68,
- 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F,
- 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D,
- 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70,
- 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4C,
- 0x69, 0x73, 0x74, 0x4B, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F,
- 0x53, 0x54, 0x4B, 0x65, 0x79, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20,
- 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65,
- 0x79, 0x2F, 0x6C, 0x69, 0x73, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74,
- 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74,
- 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69,
- 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C,
- 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E,
- 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54,
- 0x4B, 0x65, 0x79, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63,
- 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63,
- 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61,
- 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B,
- 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4C, 0x69, 0x73, 0x74, 0x4D,
- 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F,
- 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F,
- 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x6C, 0x69, 0x73, 0x74,
- 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65,
- 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79,
- 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E,
- 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E,
- 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73,
- 0x69, 0x67, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B,
- 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F,
- 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C,
- 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D,
- 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4C, 0x69, 0x73, 0x74, 0x57, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
- 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x47, 0x45, 0x54, 0x57,
- 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73,
- 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72,
- 0x20, 0x60, 0x47, 0x45, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74,
- 0x73, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
- 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x47, 0x45, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x73,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F,
- 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64,
- 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F,
- 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x44, 0x65, 0x72, 0x69, 0x76, 0x61,
- 0x74, 0x69, 0x6F, 0x6E, 0x4B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A,
- 0x20, 0x22, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x44, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69,
- 0x6F, 0x6E, 0x4B, 0x65, 0x79, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6F,
- 0x20, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x20, 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20,
- 0x6B, 0x65, 0x79, 0x73, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x75, 0x73, 0x65, 0x20, 0x69, 0x6E, 0x20,
- 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22,
- 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B,
- 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F,
- 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C,
- 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x22, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4D, 0x75, 0x6C, 0x74, 0x69,
- 0x73, 0x69, 0x67, 0x53, 0x69, 0x67, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20,
- 0x22, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x53, 0x69, 0x67, 0x20, 0x69, 0x73, 0x20,
- 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68,
- 0x61, 0x74, 0x20, 0x68, 0x6F, 0x6C, 0x64, 0x73, 0x20, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x70, 0x6C,
- 0x65, 0x20, 0x53, 0x75, 0x62, 0x73, 0x69, 0x67, 0x73, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63,
- 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65,
- 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x53, 0x75, 0x62, 0x73, 0x69, 0x67, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66,
- 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E,
- 0x73, 0x2F, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x53, 0x75, 0x62, 0x73, 0x69, 0x67,
- 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6F, 0x6C, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A,
- 0x20, 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x56, 0x65, 0x72,
- 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65,
- 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38,
- 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68,
- 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F,
- 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x63, 0x72, 0x79, 0x70,
- 0x74, 0x6F, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x53, 0x75, 0x62, 0x73, 0x69, 0x67, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69,
- 0x67, 0x53, 0x75, 0x62, 0x73, 0x69, 0x67, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x73, 0x74, 0x72,
- 0x75, 0x63, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x6F, 0x6C, 0x64, 0x73, 0x20, 0x61,
- 0x20, 0x70, 0x61, 0x69, 0x72, 0x20, 0x6F, 0x66, 0x20, 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20,
- 0x6B, 0x65, 0x79, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72,
- 0x65, 0x73, 0x5C, 0x6E, 0x73, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x20, 0x6D,
- 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x65, 0x6D, 0x70, 0x74, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A,
- 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F,
- 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x4B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22,
- 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x50, 0x75,
- 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69, 0x67,
- 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69,
- 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x53, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D,
- 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75,
- 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67,
- 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x63, 0x72, 0x79, 0x70, 0x74,
- 0x6F, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x50,
- 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E,
- 0x22, 0x3A, 0x20, 0x22, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x69,
- 0x73, 0x20, 0x61, 0x6E, 0x20, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x65, 0x64, 0x20, 0x65, 0x64,
- 0x32, 0x35, 0x35, 0x31, 0x39, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20,
- 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x65,
- 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79,
- 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x50, 0x75,
- 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A,
- 0x20, 0x22, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x20, 0x69, 0x73, 0x20, 0x61,
- 0x6E, 0x20, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x65, 0x64, 0x20, 0x65, 0x64, 0x32, 0x35, 0x35,
- 0x31, 0x39, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64,
- 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x65, 0x64, 0x32, 0x35, 0x35,
- 0x31, 0x39, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x52, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65,
- 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65,
- 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22,
- 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C,
- 0x65, 0x74, 0x52, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20,
- 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x72, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x60, 0x22, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F,
- 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70,
- 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61,
- 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54,
- 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49,
- 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6C, 0x65,
- 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65,
- 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61,
- 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72,
- 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C,
- 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x52, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x57, 0x61, 0x6C,
- 0x6C, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F,
- 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77,
- 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x72, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x60, 0x22, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F,
- 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70,
- 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x69, 0x64,
+ 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x4C, 0x69, 0x73, 0x74,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54,
+ 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x6C, 0x69,
+ 0x73, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22,
+ 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C,
+ 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E,
0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49,
- 0x44, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x6E, 0x61,
- 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
- 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4E, 0x65, 0x77, 0x57, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61,
- 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73,
- 0x77, 0x6F, 0x72, 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49,
- 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E, 0x61,
- 0x6D, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48,
+ 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74,
+ 0x69, 0x73, 0x69, 0x67, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61,
+ 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E,
+ 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D,
+ 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F,
+ 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4C, 0x69, 0x73, 0x74,
+ 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A,
+ 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x47, 0x45,
+ 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66,
+ 0x6F, 0x72, 0x20, 0x60, 0x47, 0x45, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C,
+ 0x65, 0x74, 0x73, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79,
+ 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x47, 0x45, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65,
+ 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22,
0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C,
0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61,
0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69,
0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x52, 0x65, 0x6E, 0x65, 0x77, 0x57, 0x61, 0x6C, 0x6C, 0x65,
- 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64,
- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50,
- 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E,
- 0x65, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65,
- 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F,
- 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x72, 0x65,
- 0x6E, 0x65, 0x77, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79,
- 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73,
- 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65,
- 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
- 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74,
- 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65,
- 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C,
- 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E, 0x65, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x44, 0x65, 0x72, 0x69,
+ 0x76, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x4B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E,
+ 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x44, 0x65, 0x72, 0x69, 0x76, 0x61,
+ 0x74, 0x69, 0x6F, 0x6E, 0x4B, 0x65, 0x79, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20,
+ 0x74, 0x6F, 0x20, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x20, 0x65, 0x64, 0x32, 0x35, 0x35, 0x31,
+ 0x39, 0x20, 0x6B, 0x65, 0x79, 0x73, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x75, 0x73, 0x65, 0x20, 0x69,
+ 0x6E, 0x20, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79,
+ 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22,
+ 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A,
+ 0x20, 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61,
0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E,
0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D,
- 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F,
- 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E,
- 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22,
- 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50,
- 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x54, 0x72, 0x61, 0x6E, 0x73,
- 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D,
- 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x60, 0x22, 0x2C, 0x0A,
+ 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x22,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4D, 0x75, 0x6C,
+ 0x74, 0x69, 0x73, 0x69, 0x67, 0x53, 0x69, 0x67, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22,
+ 0x3A, 0x20, 0x22, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x53, 0x69, 0x67, 0x20, 0x69,
+ 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x6F, 0x6C, 0x64, 0x73, 0x20, 0x6D, 0x75, 0x6C, 0x74, 0x69,
+ 0x70, 0x6C, 0x65, 0x20, 0x53, 0x75, 0x62, 0x73, 0x69, 0x67, 0x73, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A,
+ 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F,
+ 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x75, 0x62, 0x73, 0x69, 0x67, 0x73, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72,
+ 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69,
+ 0x6F, 0x6E, 0x73, 0x2F, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x53, 0x75, 0x62, 0x73,
+ 0x69, 0x67, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6F, 0x6C, 0x64, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74,
+ 0x22, 0x3A, 0x20, 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x56,
+ 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E,
+ 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x75, 0x69, 0x6E,
+ 0x74, 0x38, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
+ 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69,
+ 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E,
+ 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x63, 0x72,
+ 0x79, 0x70, 0x74, 0x6F, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x53, 0x75, 0x62, 0x73, 0x69, 0x67,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x4D, 0x75, 0x6C, 0x74, 0x69,
+ 0x73, 0x69, 0x67, 0x53, 0x75, 0x62, 0x73, 0x69, 0x67, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x73,
+ 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x6F, 0x6C, 0x64, 0x73,
+ 0x20, 0x61, 0x20, 0x70, 0x61, 0x69, 0x72, 0x20, 0x6F, 0x66, 0x20, 0x70, 0x75, 0x62, 0x6C, 0x69,
+ 0x63, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x61, 0x74,
+ 0x75, 0x72, 0x65, 0x73, 0x5C, 0x6E, 0x73, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
+ 0x20, 0x6D, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x65, 0x6D, 0x70, 0x74, 0x79, 0x22, 0x2C, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F,
0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70,
0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6C, 0x5F, 0x6D,
- 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A,
+ 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F,
+ 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x53,
+ 0x69, 0x67, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69,
+ 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x53, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72,
+ 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
+ 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74,
+ 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64,
+ 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x63, 0x72, 0x79,
+ 0x70, 0x74, 0x6F, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
+ 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79,
+ 0x20, 0x69, 0x73, 0x20, 0x61, 0x6E, 0x20, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x65, 0x64, 0x20,
+ 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4B, 0x65,
+ 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22,
+ 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73,
+ 0x2F, 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4B,
+ 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E,
+ 0x22, 0x3A, 0x20, 0x22, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x20, 0x69, 0x73,
+ 0x20, 0x61, 0x6E, 0x20, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x65, 0x64, 0x20, 0x65, 0x64, 0x32,
+ 0x35, 0x35, 0x31, 0x39, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x2C, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23,
- 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x4D, 0x75, 0x6C,
- 0x74, 0x69, 0x73, 0x69, 0x67, 0x53, 0x69, 0x67, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x75,
- 0x62, 0x6C, 0x69, 0x63, 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22,
- 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x50, 0x75,
- 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x69, 0x67,
- 0x6E, 0x65, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66,
- 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x22,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E,
- 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D,
- 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E,
- 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E,
- 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F,
- 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
+ 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x65, 0x64, 0x32,
+ 0x35, 0x35, 0x31, 0x39, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x52, 0x65, 0x6C, 0x65, 0x61,
+ 0x73, 0x65, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F,
+ 0x6B, 0x65, 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F,
+ 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61,
+ 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F,
+ 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x72, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x60, 0x22,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F,
- 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D,
- 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53,
- 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63,
- 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61,
- 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E,
- 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D,
- 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F,
- 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E,
- 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20,
- 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73,
- 0x69, 0x67, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76,
- 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x70,
- 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74,
- 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x61,
- 0x74, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F,
- 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E,
- 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x22, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6C, 0x5F, 0x6D, 0x75, 0x6C, 0x74,
- 0x69, 0x73, 0x69, 0x67, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65,
- 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73,
- 0x69, 0x67, 0x53, 0x69, 0x67, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x75, 0x62, 0x6C, 0x69,
- 0x63, 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64,
- 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x50, 0x75, 0x62, 0x6C, 0x69,
- 0x63, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74,
- 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61,
- 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64,
- 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C,
- 0x6C, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x3A, 0x20, 0x7B,
+ 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77,
- 0x6F, 0x72, 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
- 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56,
- 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x50, 0x72, 0x6F,
- 0x67, 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61,
- 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E,
- 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D,
- 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F,
- 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E,
- 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F,
- 0x53, 0x54, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76,
- 0x31, 0x2F, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x60, 0x22,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C,
+ 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41,
+ 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65,
+ 0x6C, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61,
+ 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D,
+ 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67,
+ 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64,
+ 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x52, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x57,
+ 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54,
+ 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31,
+ 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x72, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x60, 0x22,
0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
- 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
- 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F,
+ 0x69, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
+ 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
+ 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65,
+ 0x74, 0x49, 0x44, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F,
+ 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69,
+ 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x4E, 0x65, 0x77,
+ 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22,
+ 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
+ 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D,
+ 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x50, 0x61,
+ 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41,
+ 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65,
+ 0x6E, 0x61, 0x6D, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F,
+ 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F,
+ 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F,
+ 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x52, 0x65, 0x6E, 0x65, 0x77, 0x57, 0x61, 0x6C,
+ 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22,
+ 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52,
+ 0x65, 0x6E, 0x65, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60,
+ 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F,
+ 0x72, 0x65, 0x6E, 0x65, 0x77, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69,
+ 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F,
+ 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E,
+ 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
+ 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C,
+ 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61,
+ 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57,
+ 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E, 0x65, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D,
+ 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75,
+ 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67,
+ 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F,
+ 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69,
+ 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69,
+ 0x67, 0x6E, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56,
+ 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x54, 0x72, 0x61,
+ 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31,
+ 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x60, 0x22,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6C,
+ 0x5F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20,
+ 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x4D,
+ 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x53, 0x69, 0x67, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A,
+ 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F,
+ 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73,
+ 0x69, 0x67, 0x6E, 0x65, 0x72, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64,
+ 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x44, 0x69, 0x67, 0x65, 0x73,
+ 0x74, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
+ 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F,
+ 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E,
+ 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68,
+ 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65,
+ 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65,
+ 0x74, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22,
- 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x50,
- 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72,
+ 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
+ 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50,
+ 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x54, 0x72, 0x61, 0x6E, 0x73,
+ 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D,
+ 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75,
+ 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67,
+ 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F,
+ 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69,
+ 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69,
+ 0x67, 0x6E, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69,
+ 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22,
+ 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74,
+ 0x69, 0x73, 0x69, 0x67, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20,
+ 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x73, 0x69, 0x67,
+ 0x6E, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63,
+ 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65,
+ 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
+ 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x64, 0x61, 0x74, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69,
+ 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
+ 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D,
+ 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6C, 0x5F, 0x6D, 0x75,
+ 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F,
+ 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x4D, 0x75, 0x6C, 0x74,
+ 0x69, 0x73, 0x69, 0x67, 0x53, 0x69, 0x67, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x75, 0x62,
+ 0x6C, 0x69, 0x63, 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23,
+ 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x50, 0x75, 0x62,
+ 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C,
0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22,
0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
@@ -2752,490 +2705,537 @@ func init() {
0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50,
- 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x53, 0x69,
- 0x67, 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C,
- 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61,
- 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69,
- 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61,
- 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
- 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54,
- 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x52,
+ 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x50,
+ 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D,
+ 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75,
+ 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67,
+ 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F,
+ 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69,
+ 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69,
+ 0x67, 0x6E, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31,
+ 0x50, 0x4F, 0x53, 0x54, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20,
- 0x2F, 0x76, 0x31, 0x2F, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x2F,
- 0x73, 0x69, 0x67, 0x6E, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
- 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65,
- 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70,
- 0x75, 0x62, 0x6C, 0x69, 0x63, 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20,
- 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x50,
- 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x72,
- 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
- 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x42, 0x61, 0x73, 0x65, 0x36, 0x34, 0x20, 0x65,
- 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x6F, 0x66, 0x20, 0x6D, 0x73, 0x67, 0x70, 0x61,
- 0x63, 0x6B, 0x20, 0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x6F, 0x66, 0x20, 0x61,
- 0x20, 0x60, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x60, 0x20, 0x6F,
- 0x62, 0x6A, 0x65, 0x63, 0x74, 0x5C, 0x6E, 0x4E, 0x6F, 0x74, 0x65, 0x3A, 0x20, 0x53, 0x44, 0x4B,
- 0x20, 0x61, 0x6E, 0x64, 0x20, 0x67, 0x6F, 0x61, 0x6C, 0x20, 0x75, 0x73, 0x75, 0x61, 0x6C, 0x6C,
- 0x79, 0x20, 0x67, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x60, 0x53, 0x69, 0x67, 0x6E,
- 0x65, 0x64, 0x54, 0x78, 0x6E, 0x60, 0x20, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x73, 0x5C, 0x6E,
- 0x69, 0x6E, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2C, 0x20, 0x74, 0x68,
- 0x65, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x60, 0x74, 0x78, 0x6E, 0x60, 0x20, 0x2F, 0x20,
- 0x60, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x60, 0x20, 0x6F, 0x66,
- 0x20, 0x74, 0x68, 0x65, 0x5C, 0x6E, 0x67, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20,
- 0x60, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x54, 0x78, 0x6E, 0x60, 0x20, 0x6F, 0x62, 0x6A, 0x65,
- 0x63, 0x74, 0x20, 0x6E, 0x65, 0x65, 0x64, 0x73, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x65, 0x20, 0x75,
- 0x73, 0x65, 0x64, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x2F, 0x76, 0x31, 0x2F, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x2F, 0x73, 0x69, 0x67, 0x6E,
+ 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65,
+ 0x73, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
+ 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
+ 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x64, 0x64, 0x72, 0x65,
+ 0x73, 0x73, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A,
+ 0x20, 0x22, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20,
+ 0x22, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61,
+ 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65,
+ 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72,
- 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61,
- 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F,
- 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61,
- 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22,
- 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54,
- 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74,
- 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64,
- 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67,
+ 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74,
+ 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
+ 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x50,
+ 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22,
+ 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D,
+ 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F,
+ 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F,
+ 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F,
+ 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E, 0x54, 0x72, 0x61, 0x6E,
+ 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A,
+ 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F,
0x53, 0x54, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67,
- 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53,
+ 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74,
+ 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22,
+ 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73,
+ 0x2F, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72,
+ 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x42, 0x61, 0x73, 0x65, 0x36, 0x34,
+ 0x20, 0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x6F, 0x66, 0x20, 0x6D, 0x73, 0x67,
+ 0x70, 0x61, 0x63, 0x6B, 0x20, 0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x6F, 0x66,
+ 0x20, 0x61, 0x20, 0x60, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x60,
+ 0x20, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x5C, 0x6E, 0x4E, 0x6F, 0x74, 0x65, 0x3A, 0x20, 0x53,
+ 0x44, 0x4B, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x67, 0x6F, 0x61, 0x6C, 0x20, 0x75, 0x73, 0x75, 0x61,
+ 0x6C, 0x6C, 0x79, 0x20, 0x67, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x60, 0x53, 0x69,
+ 0x67, 0x6E, 0x65, 0x64, 0x54, 0x78, 0x6E, 0x60, 0x20, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x73,
+ 0x5C, 0x6E, 0x69, 0x6E, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2C, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x60, 0x74, 0x78, 0x6E, 0x60, 0x20,
+ 0x2F, 0x20, 0x60, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x60, 0x20,
+ 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x5C, 0x6E, 0x67, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x74, 0x65,
+ 0x64, 0x20, 0x60, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x54, 0x78, 0x6E, 0x60, 0x20, 0x6F, 0x62,
+ 0x6A, 0x65, 0x63, 0x74, 0x20, 0x6E, 0x65, 0x65, 0x64, 0x73, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x65,
+ 0x20, 0x75, 0x73, 0x65, 0x64, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E,
+ 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66,
+ 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D,
+ 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74,
+ 0x69, 0x6F, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F,
+ 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D,
+ 0x65, 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C,
+ 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C,
+ 0x65, 0x74, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6F,
+ 0x72, 0x64, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
+ 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31,
+ 0x50, 0x4F, 0x53, 0x54, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53,
+ 0x69, 0x67, 0x6E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61,
+ 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72,
+ 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C,
+ 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x20, 0x53, 0x69, 0x67,
+ 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x72, 0x79, 0x70,
+ 0x74, 0x6F, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x61, 0x74,
+ 0x75, 0x72, 0x65, 0x2E, 0x20, 0x49, 0x74, 0x20, 0x70, 0x72, 0x6F, 0x76, 0x65, 0x73, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x77, 0x61,
+ 0x73, 0x5C, 0x6E, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x61,
+ 0x20, 0x68, 0x6F, 0x6C, 0x64, 0x65, 0x72, 0x20, 0x6F, 0x66, 0x20, 0x61, 0x20, 0x63, 0x72, 0x79,
+ 0x70, 0x74, 0x6F, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x73, 0x65, 0x63, 0x72, 0x65,
+ 0x74, 0x2E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66,
+ 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E,
+ 0x73, 0x2F, 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x53, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75,
+ 0x72, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x54, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20,
+ 0x22, 0x54, 0x78, 0x54, 0x79, 0x70, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x79, 0x70, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73,
+ 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6E, 0x20, 0x74,
+ 0x6F, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6C, 0x65, 0x64, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74,
+ 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
+ 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69,
+ 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E,
+ 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x70, 0x72,
+ 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64,
+ 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x56, 0x65,
+ 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72,
+ 0x20, 0x60, 0x47, 0x45, 0x54, 0x20, 0x2F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x60,
+ 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
+ 0x20, 0x22, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A,
0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67,
0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E,
0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62,
0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x61,
- 0x74, 0x75, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6F,
- 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72,
- 0x65, 0x2E, 0x20, 0x49, 0x74, 0x20, 0x70, 0x72, 0x6F, 0x76, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61,
- 0x74, 0x20, 0x61, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x77, 0x61, 0x73, 0x5C,
- 0x6E, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x61, 0x20, 0x68,
- 0x6F, 0x6C, 0x64, 0x65, 0x72, 0x20, 0x6F, 0x66, 0x20, 0x61, 0x20, 0x63, 0x72, 0x79, 0x70, 0x74,
- 0x6F, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x2E,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A,
- 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F,
- 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x53, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65,
- 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x54, 0x78,
- 0x54, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x54,
- 0x78, 0x54, 0x79, 0x70, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x79, 0x70,
- 0x65, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63,
- 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6E, 0x20, 0x74, 0x6F, 0x20,
- 0x74, 0x68, 0x65, 0x20, 0x6C, 0x65, 0x64, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69,
- 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68,
- 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F,
- 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x70, 0x72, 0x6F, 0x74,
- 0x6F, 0x63, 0x6F, 0x6C, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73,
- 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x56, 0x65, 0x72, 0x73,
- 0x69, 0x6F, 0x6E, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74,
- 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60,
- 0x47, 0x45, 0x54, 0x20, 0x2F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x60, 0x22, 0x2C,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x52, 0x65, 0x73,
+ 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22,
+ 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
+ 0x20, 0x74, 0x6F, 0x20, 0x60, 0x47, 0x45, 0x54, 0x20, 0x2F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F,
+ 0x6E, 0x73, 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x56, 0x65,
+ 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72,
- 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F,
- 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B,
- 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6F,
- 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64,
- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x56, 0x65,
- 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x69,
- 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74,
- 0x6F, 0x20, 0x60, 0x47, 0x45, 0x54, 0x20, 0x2F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73,
- 0x60, 0x5C, 0x6E, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x6C, 0x79, 0x3A, 0x56, 0x65, 0x72, 0x73,
- 0x69, 0x6F, 0x6E, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62,
- 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72,
- 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79,
- 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D,
- 0x65, 0x22, 0x3A, 0x20, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61,
- 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E,
- 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D,
- 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F,
- 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C,
- 0x65, 0x74, 0x49, 0x6E, 0x66, 0x6F, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
- 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53,
- 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x66, 0x6F, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F,
- 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x69, 0x6E, 0x66, 0x6F, 0x60, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x62,
- 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x72,
- 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68, 0x61, 0x6E,
- 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20,
- 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F,
- 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78,
- 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56,
- 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x66, 0x6F, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22,
- 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72,
- 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F,
- 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B,
- 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74,
- 0x65, 0x4B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x75,
- 0x69, 0x6E, 0x74, 0x38, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61,
- 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D,
- 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67,
- 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x22, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x64, 0x32, 0x35, 0x35, 0x31,
- 0x39, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72,
- 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65,
- 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61,
- 0x74, 0x22, 0x3A, 0x20, 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68,
- 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F,
- 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x63, 0x72, 0x79, 0x70,
- 0x74, 0x6F, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x53, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65,
- 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
- 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x43, 0x6C, 0x61, 0x73,
- 0x73, 0x69, 0x63, 0x61, 0x6C, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
- 0x20, 0x2A, 0x2F, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65,
- 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61,
- 0x74, 0x22, 0x3A, 0x20, 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F,
- 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68,
- 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F,
- 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x63, 0x72, 0x79, 0x70,
- 0x74, 0x6F, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
- 0x20, 0x22, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x61, 0x6C, 0x6C, 0x65,
- 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E,
- 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20,
- 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74,
- 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D,
- 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24,
- 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74,
- 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61,
- 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F,
- 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64,
- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65,
- 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x44, 0x45, 0x4C, 0x45, 0x54,
- 0x45, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22,
- 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50,
- 0x49, 0x56, 0x31, 0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70,
- 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65,
- 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
- 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F,
- 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F,
- 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x64, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22,
- 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65,
- 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F,
- 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x4D, 0x75,
- 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
+ 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E,
+ 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x22,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D,
+ 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75,
+ 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67,
+ 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F,
+ 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69,
+ 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x57, 0x61,
+ 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x66, 0x6F, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22,
+ 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72,
+ 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50,
+ 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x66, 0x6F, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76,
+ 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x69, 0x6E, 0x66, 0x6F, 0x60, 0x22, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
+ 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x5F, 0x68,
+ 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22,
+ 0x3A, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65,
+ 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x41, 0x50,
+ 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x66,
+ 0x6F, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A,
+ 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67,
+ 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E,
+ 0x64, 0x2F, 0x64, 0x61, 0x65, 0x6D, 0x6F, 0x6E, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x6C, 0x69, 0x62,
+ 0x2F, 0x6B, 0x6D, 0x64, 0x61, 0x70, 0x69, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x50, 0x72, 0x69, 0x76,
+ 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A,
+ 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65,
+ 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20,
+ 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63,
+ 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63,
+ 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61,
+ 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x22, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x64, 0x32, 0x35,
+ 0x35, 0x31, 0x39, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x4B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22,
+ 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69,
+ 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65,
+ 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72,
+ 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
+ 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69,
+ 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E,
+ 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x63, 0x72,
+ 0x79, 0x70, 0x74, 0x6F, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x53, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75,
+ 0x72, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79,
+ 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x43, 0x6C,
+ 0x61, 0x73, 0x73, 0x69, 0x63, 0x61, 0x6C, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72,
+ 0x65, 0x73, 0x20, 0x2A, 0x2F, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69,
+ 0x74, 0x65, 0x6D, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65,
+ 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x66, 0x6F, 0x72,
+ 0x6D, 0x61, 0x74, 0x22, 0x3A, 0x20, 0x22, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D,
+ 0x67, 0x6F, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x67, 0x69,
+ 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E,
+ 0x64, 0x2F, 0x67, 0x6F, 0x2D, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2F, 0x63, 0x72,
+ 0x79, 0x70, 0x74, 0x6F, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x7D, 0x2C,
+ 0x0A, 0x20, 0x20, 0x22, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x73, 0x22, 0x3A, 0x20,
+ 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x61, 0x6C,
+ 0x6C, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
+ 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74,
+ 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C,
+ 0x65, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68,
+ 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E,
+ 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54,
+ 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73,
+ 0x20, 0x20, 0x20, 0x22, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73,
0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22,
- 0x52, 0x65, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54,
- 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x2F, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x60,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61,
- 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72,
- 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69,
- 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79,
- 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72,
- 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
- 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F,
- 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x61, 0x73, 0x74, 0x65,
- 0x72, 0x2D, 0x6B, 0x65, 0x79, 0x2F, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x60, 0x22, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22,
- 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73,
- 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72,
+ 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x44, 0x45, 0x4C,
+ 0x45, 0x54, 0x45, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x60, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A,
+ 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F,
+ 0x41, 0x50, 0x49, 0x56, 0x31, 0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x4B, 0x65, 0x79, 0x52, 0x65,
+ 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x44, 0x65, 0x6C, 0x65,
+ 0x74, 0x65, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
+ 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73,
+ 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76,
+ 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x64, 0x65, 0x6C, 0x65, 0x74,
+ 0x65, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D,
+ 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24,
+ 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74,
+ 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x44, 0x45, 0x4C, 0x45, 0x54, 0x45,
+ 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
+ 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x4B, 0x65, 0x79, 0x52,
+ 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A,
+ 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50,
+ 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x2F, 0x65, 0x78, 0x70, 0x6F,
+ 0x72, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68,
+ 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E,
+ 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54,
0x4B, 0x65, 0x79, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x4D, 0x75, 0x6C,
- 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
- 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
- 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75,
- 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x60, 0x22, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66,
- 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E,
- 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69,
- 0x73, 0x69, 0x67, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
- 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x47, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4B,
- 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F,
- 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F,
- 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x60, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22,
- 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65,
- 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F,
- 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x52,
- 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x49, 0x6D, 0x70,
- 0x6F, 0x72, 0x74, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x4D, 0x61, 0x73,
+ 0x74, 0x65, 0x72, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A,
+ 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
+ 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D,
+ 0x61, 0x73, 0x74, 0x65, 0x72, 0x2D, 0x6B, 0x65, 0x79, 0x2F, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74,
+ 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D,
+ 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24,
+ 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74,
+ 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x61,
+ 0x73, 0x74, 0x65, 0x72, 0x4B, 0x65, 0x79, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73,
+ 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x45, 0x78, 0x70, 0x6F, 0x72,
+ 0x74, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
+ 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70,
+ 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76,
+ 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x65, 0x78, 0x70, 0x6F, 0x72,
+ 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65,
+ 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69,
+ 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D,
+ 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73,
+ 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x47, 0x65, 0x6E, 0x65, 0x72,
+ 0x61, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A,
0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x70, 0x73, 0x6F, 0x6E, 0x73,
+ 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B,
- 0x65, 0x79, 0x2F, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22,
- 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50,
- 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74,
- 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x49, 0x6D,
- 0x70, 0x6F, 0x72, 0x74, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70,
- 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52,
- 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54,
- 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x69, 0x6D,
- 0x70, 0x6F, 0x72, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73,
- 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66,
- 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F,
- 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74,
- 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x49, 0x6E,
- 0x69, 0x74, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F,
- 0x6B, 0x65, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
- 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74,
- 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C,
- 0x65, 0x74, 0x2F, 0x69, 0x6E, 0x69, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F,
- 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56,
- 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x69, 0x74, 0x52,
- 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4C, 0x69, 0x73,
- 0x74, 0x4B, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
- 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
- 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6B, 0x65,
- 0x79, 0x2F, 0x6C, 0x69, 0x73, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64,
- 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31,
- 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F,
- 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4C, 0x69, 0x73, 0x74, 0x4D, 0x75, 0x6C,
- 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20,
- 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
- 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
- 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75,
- 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x6C, 0x69, 0x73, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A,
- 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F,
- 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69,
- 0x67, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x4C, 0x69, 0x73, 0x74, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x73, 0x52, 0x65,
- 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20,
- 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x47, 0x45,
- 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x73, 0x60, 0x22, 0x2C,
+ 0x65, 0x79, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68,
+ 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E,
+ 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54,
+ 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x4B, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
+ 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73,
+ 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F,
+ 0x76, 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x2F, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x60, 0x22, 0x2C,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A,
0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66,
0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E,
- 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x47, 0x45, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74,
- 0x73, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x52,
- 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64,
+ 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x49, 0x6D,
+ 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x49, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67,
+ 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22,
+ 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60,
+ 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69,
+ 0x67, 0x2F, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23,
+ 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49,
+ 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x49, 0x6D,
+ 0x70, 0x6F, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x49, 0x6E, 0x69, 0x74, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64,
0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22,
0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72,
0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F,
- 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x72, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x60, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22,
- 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65,
- 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F,
- 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C,
- 0x65, 0x74, 0x52, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
- 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x52, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x57, 0x61, 0x6C,
- 0x6C, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
- 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74,
- 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C,
- 0x65, 0x74, 0x2F, 0x72, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22,
- 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50,
- 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E,
- 0x61, 0x6D, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20,
+ 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x69, 0x6E, 0x69, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A,
+ 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F,
+ 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49,
+ 0x6E, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x52, 0x65, 0x6E, 0x65, 0x77, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x48, 0x61, 0x6E, 0x64,
- 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22,
+ 0x22, 0x4C, 0x69, 0x73, 0x74, 0x4B, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
+ 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70,
+ 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76,
+ 0x31, 0x2F, 0x6B, 0x65, 0x79, 0x2F, 0x6C, 0x69, 0x73, 0x74, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20,
+ 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41,
+ 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4B, 0x65, 0x79, 0x4C, 0x69, 0x73, 0x74, 0x52,
+ 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4C, 0x69, 0x73,
+ 0x74, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
+ 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70,
+ 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76,
+ 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x6C, 0x69, 0x73, 0x74, 0x60,
+ 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61,
+ 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72,
+ 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69,
+ 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C,
+ 0x74, 0x69, 0x73, 0x69, 0x67, 0x4C, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
+ 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D,
+ 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x4C, 0x69, 0x73, 0x74, 0x57, 0x61, 0x6C, 0x6C, 0x65,
+ 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F,
+ 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F,
+ 0x20, 0x60, 0x47, 0x45, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74,
+ 0x73, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65,
+ 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69,
+ 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x47, 0x45, 0x54, 0x57, 0x61,
+ 0x6C, 0x6C, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x22, 0x52, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74,
+ 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F,
+ 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64,
+ 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65,
+ 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20,
+ 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x72, 0x65, 0x6C, 0x65, 0x61,
+ 0x73, 0x65, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68,
+ 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E,
+ 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54,
+ 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73,
+ 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x52, 0x65, 0x6E, 0x61, 0x6D,
+ 0x65, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22,
0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72,
0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
- 0x73, 0x65, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C,
- 0x6C, 0x65, 0x74, 0x2F, 0x72, 0x65, 0x6E, 0x65, 0x77, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22,
- 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50,
- 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x52, 0x65, 0x6E,
- 0x65, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x53, 0x69, 0x67, 0x6E, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70,
+ 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F,
+ 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x72, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x60, 0x22, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A,
+ 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66,
+ 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E,
+ 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65,
+ 0x74, 0x52, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x52, 0x65, 0x6E, 0x65, 0x77, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74,
+ 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F,
+ 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64,
+ 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65,
+ 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31,
+ 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x72, 0x65, 0x6E, 0x65, 0x77, 0x60, 0x22, 0x2C,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A,
+ 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66,
+ 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E,
+ 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65,
+ 0x74, 0x52, 0x65, 0x6E, 0x65, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67,
+ 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22,
+ 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60,
+ 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69,
+ 0x67, 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64,
+ 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31,
+ 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x54, 0x72, 0x61, 0x6E,
+ 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F,
+ 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E, 0x50, 0x72, 0x6F,
+ 0x67, 0x72, 0x61, 0x6D, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70,
0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52,
0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54,
0x20, 0x2F, 0x76, 0x31, 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x73, 0x69,
+ 0x67, 0x6E, 0x64, 0x61, 0x74, 0x61, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64,
+ 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31,
+ 0x50, 0x4F, 0x53, 0x54, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x50, 0x72, 0x6F, 0x67,
+ 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D,
+ 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22,
+ 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60,
+ 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x2F, 0x73, 0x69,
0x67, 0x6E, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68,
0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E,
0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54,
- 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74,
- 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D,
- 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
+ 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F,
+ 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E, 0x54, 0x72, 0x61,
+ 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65,
0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F,
0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31,
- 0x2F, 0x6D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x64, 0x61,
- 0x74, 0x61, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68,
- 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E,
- 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54,
- 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x73, 0x69, 0x67, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x53,
- 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x53, 0x69, 0x67, 0x6E, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x52, 0x65, 0x73, 0x70,
- 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52,
- 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54,
- 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x60, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22,
- 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65,
- 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F,
- 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x50, 0x72, 0x6F, 0x67,
- 0x72, 0x61, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x69, 0x67, 0x6E, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63,
- 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B,
+ 0x2F, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x73, 0x69, 0x67,
+ 0x6E, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65,
+ 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69,
+ 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x54,
+ 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65,
+ 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x56, 0x65, 0x72, 0x73,
+ 0x69, 0x6F, 0x6E, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20,
- 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x74, 0x72, 0x61,
- 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x73, 0x69, 0x67, 0x6E, 0x60, 0x22, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66,
- 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E,
- 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x54, 0x72, 0x61, 0x6E, 0x73,
- 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
- 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73,
- 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22,
- 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60,
- 0x47, 0x45, 0x54, 0x20, 0x2F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x60, 0x22, 0x2C,
- 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A,
- 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66,
- 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E,
- 0x73, 0x2F, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E,
- 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E,
- 0x66, 0x6F, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F,
- 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, 0x74, 0x6F,
- 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77, 0x61, 0x6C, 0x6C, 0x65,
- 0x74, 0x2F, 0x69, 0x6E, 0x66, 0x6F, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64,
- 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41, 0x50, 0x49, 0x56, 0x31,
- 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E, 0x66, 0x6F, 0x52, 0x65,
+ 0x74, 0x6F, 0x20, 0x60, 0x47, 0x45, 0x54, 0x20, 0x2F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E,
+ 0x73, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65,
+ 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
+ 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20, 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69,
+ 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x22, 0x73, 0x65,
- 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x44, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E,
- 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x61, 0x70, 0x69, 0x5F, 0x6B,
- 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x47, 0x65, 0x6E,
- 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x70, 0x61,
- 0x72, 0x61, 0x6D, 0x65, 0x74, 0x65, 0x72, 0x2E, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x76, 0x61,
- 0x6C, 0x75, 0x65, 0x20, 0x63, 0x61, 0x6E, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6F, 0x75, 0x6E, 0x64,
- 0x20, 0x69, 0x6E, 0x20, 0x60, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x2F, 0x64,
- 0x69, 0x72, 0x2F, 0x6B, 0x6D, 0x64, 0x2E, 0x74, 0x6F, 0x6B, 0x65, 0x6E, 0x60, 0x2E, 0x20, 0x45,
- 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x3A, 0x20, 0x27, 0x33,
- 0x33, 0x30, 0x62, 0x32, 0x65, 0x34, 0x66, 0x63, 0x39, 0x62, 0x32, 0x30, 0x66, 0x34, 0x66, 0x38,
- 0x39, 0x38, 0x31, 0x32, 0x63, 0x66, 0x38, 0x37, 0x66, 0x31, 0x64, 0x61, 0x62, 0x65, 0x62, 0x37,
- 0x31, 0x36, 0x64, 0x32, 0x33, 0x65, 0x33, 0x66, 0x31, 0x31, 0x61, 0x65, 0x63, 0x39, 0x37, 0x61,
- 0x36, 0x31, 0x66, 0x66, 0x35, 0x66, 0x37, 0x35, 0x30, 0x35, 0x36, 0x33, 0x62, 0x37, 0x38, 0x27,
- 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A,
- 0x20, 0x22, 0x61, 0x70, 0x69, 0x4B, 0x65, 0x79, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x22, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x58, 0x2D, 0x4B, 0x4D, 0x44, 0x2D,
- 0x41, 0x50, 0x49, 0x2D, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x22, 0x69, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22,
- 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x65, 0x78, 0x61, 0x6D, 0x70,
- 0x6C, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x33, 0x33, 0x30, 0x62, 0x32, 0x65, 0x34, 0x66, 0x63, 0x39,
- 0x62, 0x32, 0x30, 0x66, 0x34, 0x66, 0x38, 0x39, 0x38, 0x31, 0x32, 0x63, 0x66, 0x38, 0x37, 0x66,
- 0x31, 0x64, 0x61, 0x62, 0x65, 0x62, 0x37, 0x31, 0x36, 0x64, 0x32, 0x33, 0x65, 0x33, 0x66, 0x31,
- 0x31, 0x61, 0x65, 0x63, 0x39, 0x37, 0x61, 0x36, 0x31, 0x66, 0x66, 0x35, 0x66, 0x37, 0x35, 0x30,
- 0x35, 0x36, 0x33, 0x62, 0x37, 0x38, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20,
- 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x22, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x22, 0x3A,
- 0x20, 0x5B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
- 0x61, 0x70, 0x69, 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x5B, 0x5D, 0x0A, 0x20, 0x20, 0x20,
- 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x5D, 0x0A, 0x7D,
+ 0x20, 0x20, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x57, 0x61, 0x6C, 0x6C,
+ 0x65, 0x74, 0x49, 0x6E, 0x66, 0x6F, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x3A,
+ 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73,
+ 0x65, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x50, 0x4F, 0x53, 0x54, 0x20, 0x2F, 0x76, 0x31, 0x2F, 0x77,
+ 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x2F, 0x69, 0x6E, 0x66, 0x6F, 0x60, 0x22, 0x2C, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x22, 0x3A, 0x20, 0x7B, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x24, 0x72, 0x65, 0x66, 0x22, 0x3A, 0x20,
+ 0x22, 0x23, 0x2F, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2F, 0x41,
+ 0x50, 0x49, 0x56, 0x31, 0x50, 0x4F, 0x53, 0x54, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x49, 0x6E,
+ 0x66, 0x6F, 0x52, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20,
+ 0x20, 0x22, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x44, 0x65, 0x66, 0x69, 0x6E, 0x69,
+ 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x22, 0x61,
+ 0x70, 0x69, 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x20,
+ 0x22, 0x47, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65,
+ 0x72, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x65, 0x74, 0x65, 0x72, 0x2E, 0x20, 0x54, 0x68, 0x69,
+ 0x73, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x63, 0x61, 0x6E, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6F, 0x75, 0x6E, 0x64, 0x20, 0x69, 0x6E, 0x20, 0x60, 0x2F, 0x6B, 0x6D, 0x64, 0x2F, 0x64, 0x61,
+ 0x74, 0x61, 0x2F, 0x64, 0x69, 0x72, 0x2F, 0x6B, 0x6D, 0x64, 0x2E, 0x74, 0x6F, 0x6B, 0x65, 0x6E,
+ 0x60, 0x2E, 0x20, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65,
+ 0x3A, 0x20, 0x27, 0x33, 0x33, 0x30, 0x62, 0x32, 0x65, 0x34, 0x66, 0x63, 0x39, 0x62, 0x32, 0x30,
+ 0x66, 0x34, 0x66, 0x38, 0x39, 0x38, 0x31, 0x32, 0x63, 0x66, 0x38, 0x37, 0x66, 0x31, 0x64, 0x61,
+ 0x62, 0x65, 0x62, 0x37, 0x31, 0x36, 0x64, 0x32, 0x33, 0x65, 0x33, 0x66, 0x31, 0x31, 0x61, 0x65,
+ 0x63, 0x39, 0x37, 0x61, 0x36, 0x31, 0x66, 0x66, 0x35, 0x66, 0x37, 0x35, 0x30, 0x35, 0x36, 0x33,
+ 0x62, 0x37, 0x38, 0x27, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x79,
+ 0x70, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x61, 0x70, 0x69, 0x4B, 0x65, 0x79, 0x22, 0x2C, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x58, 0x2D,
+ 0x4B, 0x4D, 0x44, 0x2D, 0x41, 0x50, 0x49, 0x2D, 0x54, 0x6F, 0x6B, 0x65, 0x6E, 0x22, 0x2C, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x6E, 0x22, 0x3A, 0x20, 0x22, 0x68, 0x65, 0x61,
+ 0x64, 0x65, 0x72, 0x22, 0x2C, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x78, 0x2D, 0x65,
+ 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x22, 0x3A, 0x20, 0x22, 0x33, 0x33, 0x30, 0x62, 0x32, 0x65,
+ 0x34, 0x66, 0x63, 0x39, 0x62, 0x32, 0x30, 0x66, 0x34, 0x66, 0x38, 0x39, 0x38, 0x31, 0x32, 0x63,
+ 0x66, 0x38, 0x37, 0x66, 0x31, 0x64, 0x61, 0x62, 0x65, 0x62, 0x37, 0x31, 0x36, 0x64, 0x32, 0x33,
+ 0x65, 0x33, 0x66, 0x31, 0x31, 0x61, 0x65, 0x63, 0x39, 0x37, 0x61, 0x36, 0x31, 0x66, 0x66, 0x35,
+ 0x66, 0x37, 0x35, 0x30, 0x35, 0x36, 0x33, 0x62, 0x37, 0x38, 0x22, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x7D, 0x0A, 0x20, 0x20, 0x7D, 0x2C, 0x0A, 0x20, 0x20, 0x22, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69,
+ 0x74, 0x79, 0x22, 0x3A, 0x20, 0x5B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x22, 0x61, 0x70, 0x69, 0x5F, 0x6B, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x5B, 0x5D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7D, 0x0A, 0x20, 0x20, 0x5D, 0x0A, 0x7D,
})
}
diff --git a/daemon/kmd/lib/kmdapi/responses.go b/daemon/kmd/lib/kmdapi/responses.go
index dee75b8a2..464bc7dde 100644
--- a/daemon/kmd/lib/kmdapi/responses.go
+++ b/daemon/kmd/lib/kmdapi/responses.go
@@ -159,42 +159,42 @@ type walletInfoResponse struct {
Body *APIV1POSTWalletInfoResponse
}
-// APIV1POSTMasterKeyExportResponse is the reponse to `POST /v1/master-key/export`
+// APIV1POSTMasterKeyExportResponse is the response to `POST /v1/master-key/export`
// friendly:ExportMasterKeyResponse
type APIV1POSTMasterKeyExportResponse struct {
APIV1ResponseEnvelope
MasterDerivationKey APIV1MasterDerivationKey `json:"master_derivation_key"`
}
-// Reponse to `POST /v1/master-key/export`
+// Response to `POST /v1/master-key/export`
// swagger:response ExportMasterKeyResponse
type exportMasterKeyResponse struct {
// in:body
Body *APIV1POSTMasterKeyExportResponse
}
-// APIV1POSTKeyImportResponse is the repsonse to `POST /v1/key/import`
+// APIV1POSTKeyImportResponse is the response to `POST /v1/key/import`
// friendly:ImportKeyResponse
type APIV1POSTKeyImportResponse struct {
APIV1ResponseEnvelope
Address string `json:"address"`
}
-// Repsonse to `POST /v1/key/import`
+// Response to `POST /v1/key/import`
// swagger:response ImportKeyResponse
type importKeyResponse struct {
// in:body
Body *APIV1POSTKeyImportResponse
}
-// APIV1POSTKeyExportResponse is the reponse to `POST /v1/key/export`
+// APIV1POSTKeyExportResponse is the response to `POST /v1/key/export`
// friendly:ExportKeyResponse
type APIV1POSTKeyExportResponse struct {
APIV1ResponseEnvelope
PrivateKey APIV1PrivateKey `json:"private_key"`
}
-// Reponse to `POST /v1/key/export`
+// Response to `POST /v1/key/export`
// swagger:response ExportKeyResponse
type exportKeyResponse struct {
// in:body
@@ -242,7 +242,7 @@ type listKeysResponse struct {
Body *APIV1POSTKeyListResponse
}
-// APIV1POSTTransactionSignResponse is the repsonse to `POST /v1/transaction/sign`
+// APIV1POSTTransactionSignResponse is the response to `POST /v1/transaction/sign`
// friendly:SignTransactionResponse
type APIV1POSTTransactionSignResponse struct {
APIV1ResponseEnvelope
@@ -258,7 +258,7 @@ type signTransactionResponse struct {
Body *APIV1POSTTransactionSignResponse
}
-// APIV1POSTProgramSignResponse is the repsonse to `POST /v1/data/sign`
+// APIV1POSTProgramSignResponse is the response to `POST /v1/data/sign`
// friendly:SignProgramResponse
type APIV1POSTProgramSignResponse struct {
APIV1ResponseEnvelope
diff --git a/data/basics/userBalance.go b/data/basics/userBalance.go
index a70405469..d80aef813 100644
--- a/data/basics/userBalance.go
+++ b/data/basics/userBalance.go
@@ -34,7 +34,7 @@ const (
Offline Status = iota
// Online indicates that the associated account participates in the consensus and receive rewards.
Online
- // NotParticipating indicates that the associated account neither participates in the consensus, nor recieves rewards.
+ // NotParticipating indicates that the associated account neither participates in the consensus, nor receives rewards.
// Accounts that are marked as NotParticipating cannot change their status, but can receive and send Algos to other accounts.
// Two special accounts that are defined as NotParticipating are the incentive pool (also know as rewards pool) and the fee sink.
// These two accounts also have additional Algo transfer restrictions.
diff --git a/data/bookkeeping/genesis.go b/data/bookkeeping/genesis.go
index 8a2984daf..f8ab7ff97 100644
--- a/data/bookkeeping/genesis.go
+++ b/data/bookkeeping/genesis.go
@@ -68,6 +68,13 @@ type Genesis struct {
// Arbitrary genesis comment string - will be excluded from file if empty
Comment string `codec:"comment"`
+
+ // DevMode defines whether this network operates in a developer mode or not. Developer mode networks
+ // are a single node network, that operates without the agreement service being active. In liue of the
+ // agreement service, a new block is generated each time a node receives a transaction group. The
+ // default value for this field is "false", which makes this field empty from it's encoding, and
+ // therefore backward compatible.
+ DevMode bool `codec:"devmode"`
}
// LoadGenesisFromFile attempts to load a Genesis structure from a (presumably) genesis.json file.
diff --git a/data/bookkeeping/msgp_gen.go b/data/bookkeeping/msgp_gen.go
index 616e2587d..8b88b8fbe 100644
--- a/data/bookkeeping/msgp_gen.go
+++ b/data/bookkeeping/msgp_gen.go
@@ -1664,8 +1664,8 @@ func (z *CompactCertState) MsgIsZero() bool {
func (z *Genesis) MarshalMsg(b []byte) (o []byte) {
o = msgp.Require(b, z.Msgsize())
// omitempty: check for empty values
- zb0002Len := uint32(8)
- var zb0002Mask uint16 /* 9 bits */
+ zb0002Len := uint32(9)
+ var zb0002Mask uint16 /* 10 bits */
if len((*z).Allocation) == 0 {
zb0002Len--
zb0002Mask |= 0x2
@@ -1674,30 +1674,34 @@ func (z *Genesis) MarshalMsg(b []byte) (o []byte) {
zb0002Len--
zb0002Mask |= 0x4
}
- if (*z).FeeSink == "" {
+ if (*z).DevMode == false {
zb0002Len--
zb0002Mask |= 0x8
}
- if (*z).SchemaID == "" {
+ if (*z).FeeSink == "" {
zb0002Len--
zb0002Mask |= 0x10
}
- if (*z).Network.MsgIsZero() {
+ if (*z).SchemaID == "" {
zb0002Len--
zb0002Mask |= 0x20
}
- if (*z).Proto.MsgIsZero() {
+ if (*z).Network.MsgIsZero() {
zb0002Len--
zb0002Mask |= 0x40
}
- if (*z).RewardsPool == "" {
+ if (*z).Proto.MsgIsZero() {
zb0002Len--
zb0002Mask |= 0x80
}
- if (*z).Timestamp == 0 {
+ if (*z).RewardsPool == "" {
zb0002Len--
zb0002Mask |= 0x100
}
+ if (*z).Timestamp == 0 {
+ zb0002Len--
+ zb0002Mask |= 0x200
+ }
// variable map header, size zb0002Len
o = append(o, 0x80|uint8(zb0002Len))
if zb0002Len != 0 {
@@ -1719,31 +1723,36 @@ func (z *Genesis) MarshalMsg(b []byte) (o []byte) {
o = msgp.AppendString(o, (*z).Comment)
}
if (zb0002Mask & 0x8) == 0 { // if not empty
+ // string "devmode"
+ o = append(o, 0xa7, 0x64, 0x65, 0x76, 0x6d, 0x6f, 0x64, 0x65)
+ o = msgp.AppendBool(o, (*z).DevMode)
+ }
+ if (zb0002Mask & 0x10) == 0 { // if not empty
// string "fees"
o = append(o, 0xa4, 0x66, 0x65, 0x65, 0x73)
o = msgp.AppendString(o, (*z).FeeSink)
}
- if (zb0002Mask & 0x10) == 0 { // if not empty
+ if (zb0002Mask & 0x20) == 0 { // if not empty
// string "id"
o = append(o, 0xa2, 0x69, 0x64)
o = msgp.AppendString(o, (*z).SchemaID)
}
- if (zb0002Mask & 0x20) == 0 { // if not empty
+ if (zb0002Mask & 0x40) == 0 { // if not empty
// string "network"
o = append(o, 0xa7, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b)
o = (*z).Network.MarshalMsg(o)
}
- if (zb0002Mask & 0x40) == 0 { // if not empty
+ if (zb0002Mask & 0x80) == 0 { // if not empty
// string "proto"
o = append(o, 0xa5, 0x70, 0x72, 0x6f, 0x74, 0x6f)
o = (*z).Proto.MarshalMsg(o)
}
- if (zb0002Mask & 0x80) == 0 { // if not empty
+ if (zb0002Mask & 0x100) == 0 { // if not empty
// string "rwd"
o = append(o, 0xa3, 0x72, 0x77, 0x64)
o = msgp.AppendString(o, (*z).RewardsPool)
}
- if (zb0002Mask & 0x100) == 0 { // if not empty
+ if (zb0002Mask & 0x200) == 0 { // if not empty
// string "timestamp"
o = append(o, 0xa9, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70)
o = msgp.AppendInt64(o, (*z).Timestamp)
@@ -1856,6 +1865,14 @@ func (z *Genesis) UnmarshalMsg(bts []byte) (o []byte, err error) {
}
}
if zb0002 > 0 {
+ zb0002--
+ (*z).DevMode, bts, err = msgp.ReadBoolBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "DevMode")
+ return
+ }
+ }
+ if zb0002 > 0 {
err = msgp.ErrTooManyArrayFields(zb0002)
if err != nil {
err = msgp.WrapError(err, "struct-from-array")
@@ -1947,6 +1964,12 @@ func (z *Genesis) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "Comment")
return
}
+ case "devmode":
+ (*z).DevMode, bts, err = msgp.ReadBoolBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err, "DevMode")
+ return
+ }
default:
err = msgp.ErrNoField(string(field))
if err != nil {
@@ -1971,13 +1994,13 @@ func (z *Genesis) Msgsize() (s int) {
for zb0001 := range (*z).Allocation {
s += (*z).Allocation[zb0001].Msgsize()
}
- s += 4 + msgp.StringPrefixSize + len((*z).RewardsPool) + 5 + msgp.StringPrefixSize + len((*z).FeeSink) + 10 + msgp.Int64Size + 8 + msgp.StringPrefixSize + len((*z).Comment)
+ s += 4 + msgp.StringPrefixSize + len((*z).RewardsPool) + 5 + msgp.StringPrefixSize + len((*z).FeeSink) + 10 + msgp.Int64Size + 8 + msgp.StringPrefixSize + len((*z).Comment) + 8 + msgp.BoolSize
return
}
// MsgIsZero returns whether this is a zero value
func (z *Genesis) MsgIsZero() bool {
- return ((*z).SchemaID == "") && ((*z).Network.MsgIsZero()) && ((*z).Proto.MsgIsZero()) && (len((*z).Allocation) == 0) && ((*z).RewardsPool == "") && ((*z).FeeSink == "") && ((*z).Timestamp == 0) && ((*z).Comment == "")
+ return ((*z).SchemaID == "") && ((*z).Network.MsgIsZero()) && ((*z).Proto.MsgIsZero()) && (len((*z).Allocation) == 0) && ((*z).RewardsPool == "") && ((*z).FeeSink == "") && ((*z).Timestamp == 0) && ((*z).Comment == "") && ((*z).DevMode == false)
}
// MarshalMsg implements msgp.Marshaler
diff --git a/data/pools/transactionPool.go b/data/pools/transactionPool.go
index c44d127d0..3d7125f5e 100644
--- a/data/pools/transactionPool.go
+++ b/data/pools/transactionPool.go
@@ -48,7 +48,7 @@ import (
// TransactionPool.AssembleBlock constructs a valid block for
// proposal given a deadline.
type TransactionPool struct {
- // feePerByte is stored at the begining of this struct to ensure it has a 64 bit aligned address. This is needed as it's being used
+ // feePerByte is stored at the beginning of this struct to ensure it has a 64 bit aligned address. This is needed as it's being used
// with atomic operations which require 64 bit alignment on arm.
feePerByte uint64
@@ -116,7 +116,7 @@ func MakeTransactionPool(ledger *ledger.Ledger, cfg config.Local, log logging.Lo
// poolAsmResults is used to syncronize the state of the block assembly process. The structure reading/writing is syncronized
// via the pool.assemblyMu lock.
type poolAsmResults struct {
- // the ok variable indicates whther the assembly for the block roundStartedEvaluating was complete ( i.e. ok == true ) or
+ // the ok variable indicates whether the assembly for the block roundStartedEvaluating was complete ( i.e. ok == true ) or
// whether it's still in-progress.
ok bool
blk *ledger.ValidatedBlock
@@ -126,7 +126,7 @@ type poolAsmResults struct {
// which round we started evaluating, but not a measure to whether the evaluation is complete.
roundStartedEvaluating basics.Round
// assemblyCompletedOrAbandoned is *not* protected via the pool.assemblyMu lock and should be accessed only from the OnNewBlock goroutine.
- // it's equivilent to the "ok" variable, and used for avoiding taking the lock.
+ // it's equivalent to the "ok" variable, and used for avoiding taking the lock.
assemblyCompletedOrAbandoned bool
}
@@ -484,7 +484,6 @@ func (pool *TransactionPool) OnNewBlock(block bookkeeping.Block, delta ledgercor
pool.mu.Lock()
defer pool.mu.Unlock()
defer pool.cond.Broadcast()
-
if pool.pendingBlockEvaluator == nil || block.Round() >= pool.pendingBlockEvaluator.Round() {
// Adjust the pool fee threshold. The rules are:
// - If there was less than one full block in the pool, reduce
@@ -865,7 +864,7 @@ func (pool *TransactionPool) AssembleBlock(round basics.Round, deadline time.Tim
return nil, fmt.Errorf("AssemblyBlock: encountered error for round %d: %v", round, pool.assemblyResults.err)
}
if pool.assemblyResults.roundStartedEvaluating > round {
- // this scenario should not happen unless the txpool is receiving the new blocks via OnNewBlocks
+ // this scenario should not happen unless the txpool is receiving the new blocks via OnNewBlock
// with "jumps" between consecutive blocks ( which is why it's a warning )
// The "normal" usecase is evaluated on the top of the function.
pool.log.Warnf("AssembleBlock: requested round is behind transaction pool round %d < %d", round, pool.assemblyResults.roundStartedEvaluating)
@@ -900,3 +899,17 @@ func (pool *TransactionPool) assembleEmptyBlock(round basics.Round) (assembled *
}
return blockEval.GenerateBlock()
}
+
+// 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()
+ defer pool.mu.Unlock()
+
+ // drop the current block evaluator and start with a new one.
+ pool.recomputeBlockEvaluator(make(map[transactions.Txid]basics.Round), 0)
+
+ // The above was already pregenerating the entire block,
+ // so there won't be any waiting on this call.
+ assembled, err = pool.AssembleBlock(pool.pendingBlockEvaluator.Round(), time.Now().Add(config.ProposalAssemblyTime))
+ return
+}
diff --git a/data/transactions/logic/README.md b/data/transactions/logic/README.md
index 7075d6249..02ca1cfdc 100644
--- a/data/transactions/logic/README.md
+++ b/data/transactions/logic/README.md
@@ -80,7 +80,7 @@ An application transaction must indicate the action to be taken following the ex
Most operations work with only one type of argument, uint64 or bytes, and panic if the wrong type value is on the stack.
-Many instructions accept values to designate Accounts, Assets, or Applications. Beginning with TEAL v4, these values may always be given as an _offset_ in the corresponding Txn fields (Txn.Accounts, Txn.ForeignAssets, Txn.ForeignApps) _or_ as the value itself (a bytes address for Accounts, or a uint64 ID). The values, however, must still be present in the Txn fields. Before TEAL v4, most opcodes required the use of an offset, except for reading account local values of assets or applications, which accepted the IDs directly and did not require the ID to be present in they corresponding _Foreign_ array. (Note that beginning with TEAL v4, those ID are required to be present in their corresponding _Foreign_ array.) See individual opcodes for details. In the case of account offsets or application offsets, 0 is specially defined to Txn.Sender or the ID of the current application, respectively.
+Many instructions accept values to designate Accounts, Assets, or Applications. Beginning with TEAL v4, these values may always be given as an _offset_ in the corresponding Txn fields (Txn.Accounts, Txn.ForeignAssets, Txn.ForeignApps) _or_ as the value itself (a bytes address for Accounts, or a uint64 ID). The values, however, must still be present in the Txn fields. Before TEAL v4, most opcodes required the use of an offset, except for reading account local values of assets or applications, which accepted the IDs directly and did not require the ID to be present in they corresponding _Foreign_ array. (Note that beginning with TEAL v4, those IDs are required to be present in their corresponding _Foreign_ array.) See individual opcodes for details. In the case of account offsets or application offsets, 0 is specially defined to Txn.Sender or the ID of the current application, respectively.
Many programs need only a few dozen instructions. The instruction set has some optimization built in. `intc`, `bytec`, and `arg` take an immediate value byte, making a 2-byte op to load a value onto the stack, but they also have single byte versions for loading the most common constant values. Any program will benefit from having a few common values loaded with a smaller one byte opcode. Cryptographic hashes and `ed25519verify` are single byte opcodes with powerful libraries behind them. These operations still take more time than other ops (and this is reflected in the cost of each op and the cost limit of a program) but are efficient in compiled code space.
@@ -96,7 +96,7 @@ For one-argument ops, `X` is the last element on the stack, which is typically r
For two-argument ops, `A` is the penultimate element on the stack and `B` is the top of the stack. These typically result in popping A and B from the stack and pushing the result.
-For three-argument ops, `A` is the element two below the top, `B` is the penultimate stack element and `C` is the top of the stack. These operatiosn typically pop A, B, and C from the stack and push the result.
+For three-argument ops, `A` is the element two below the top, `B` is the penultimate stack element and `C` is the top of the stack. These operations typically pop A, B, and C from the stack and push the result.
| Op | Description |
| --- | --- |
@@ -106,7 +106,7 @@ For three-argument ops, `A` is the element two below the top, `B` is the penulti
| `ed25519verify` | for (data A, signature B, pubkey C) verify the signature of ("ProgData" \|\| program_hash \|\| data) against the pubkey => {0 or 1} |
| `+` | A plus B. Panic on overflow. |
| `-` | A minus B. Panic if B > A. |
-| `/` | A divided by B. Panic if B == 0. |
+| `/` | A divided by B (truncated division). Panic if B == 0. |
| `*` | A times B. Panic on overflow. |
| `<` | A less than B => {0 or 1} |
| `>` | A greater than B => {0 or 1} |
@@ -139,8 +139,6 @@ For three-argument ops, `A` is the element two below the top, `B` is the penulti
| `getbyte` | pop a byte-array A and integer B. Extract the Bth byte of A and push it as an integer |
| `setbyte` | pop a byte-array A, integer B, and small integer C (between 0..255). Set the Bth byte of A to C, and push the result |
| `concat` | pop two byte-arrays A and B and join them, push the result |
-| `substring s e` | pop a byte-array A. For immediate values in 0..255 S and E: extract a range of bytes from A starting at S up to but not including E, push the substring result. If E < S, or either is larger than the array length, the program fails |
-| `substring3` | pop a byte-array A and two integers B and C. Extract a range of bytes from A starting at B up to but not including C, push the substring result. If C < B, or either is larger than the array length, the program fails |
These opcodes take byte-array values that are interpreted as
big-endian unsigned integers. For mathematical operators, the
@@ -158,7 +156,7 @@ bytes on outputs.
| --- | --- |
| `b+` | A plus B, where A and B are byte-arrays interpreted as big-endian unsigned integers |
| `b-` | A minus B, where A and B are byte-arrays interpreted as big-endian unsigned integers. Panic on underflow. |
-| `b/` | A divided by B, where A and B are byte-arrays interpreted as big-endian unsigned integers. Panic if B is zero. |
+| `b/` | A divided by B (truncated division), where A and B are byte-arrays interpreted as big-endian unsigned integers. Panic if B is zero. |
| `b*` | A times B, where A and B are byte-arrays interpreted as big-endian unsigned integers. |
| `b<` | A is less than B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1} |
| `b>` | A is greater than B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1} |
@@ -233,17 +231,17 @@ Some of these have immediate data in the byte or bytes after the opcode.
| 2 | FirstValid | uint64 | round number |
| 3 | FirstValidTime | uint64 | Causes program to fail; reserved for future use |
| 4 | LastValid | uint64 | round number |
-| 5 | Note | []byte | |
-| 6 | Lease | []byte | |
+| 5 | Note | []byte | Any data up to 1024 bytes |
+| 6 | Lease | []byte | 32 byte lease value |
| 7 | Receiver | []byte | 32 byte address |
| 8 | Amount | uint64 | micro-Algos |
| 9 | CloseRemainderTo | []byte | 32 byte address |
| 10 | VotePK | []byte | 32 byte address |
| 11 | SelectionPK | []byte | 32 byte address |
-| 12 | VoteFirst | uint64 | |
-| 13 | VoteLast | uint64 | |
-| 14 | VoteKeyDilution | uint64 | |
-| 15 | Type | []byte | |
+| 12 | VoteFirst | uint64 | The first round that the participation key is valid. |
+| 13 | VoteLast | uint64 | The last round that the participation key is valid. |
+| 14 | VoteKeyDilution | uint64 | Dilution for the 2-level participation key |
+| 15 | Type | []byte | Transaction type as bytes |
| 16 | TypeEnum | uint64 | See table below |
| 17 | XferAsset | uint64 | Asset ID |
| 18 | AssetAmount | uint64 | value in Asset's units |
@@ -309,7 +307,7 @@ Global fields are fields that are common to all the transactions in the group. I
**Asset Fields**
-Asset fields include `AssetHolding` and `AssetParam` fields that are used in `asset_read_*` opcodes
+Asset fields include `AssetHolding` and `AssetParam` fields that are used in the `asset_holding_get` and `asset_params_get` opcodes.
| Index | Name | Type | Notes |
| --- | --- | --- | --- |
@@ -330,6 +328,23 @@ Asset fields include `AssetHolding` and `AssetParam` fields that are used in `as
| 8 | AssetReserve | []byte | Reserve address |
| 9 | AssetFreeze | []byte | Freeze address |
| 10 | AssetClawback | []byte | Clawback address |
+| 11 | AssetCreator | []byte | Creator address |
+
+
+**App Fields**
+
+App fields used in the `app_params_get` opcode.
+
+| Index | Name | Type | Notes |
+| --- | --- | --- | --- |
+| 0 | AppApprovalProgram | []byte | Bytecode of Approval Program |
+| 1 | AppClearStateProgram | []byte | Bytecode of Clear State Program |
+| 2 | AppGlobalNumUint | uint64 | Number of uint64 values allowed in Global State |
+| 3 | AppGlobalNumByteSlice | uint64 | Number of byte array values allowed in Global State |
+| 4 | AppLocalNumUint | uint64 | Number of uint64 values allowed in Local State |
+| 5 | AppLocalNumByteSlice | uint64 | Number of byte array values allowed in Local State |
+| 6 | AppExtraProgramPages | uint64 | Number of Extra Program Pages of code space |
+| 7 | AppCreator | []byte | Creator address |
### Flow Control
@@ -368,6 +383,7 @@ Asset fields include `AssetHolding` and `AssetParam` fields that are used in `as
| `app_global_del` | delete key A from a global state of the current application |
| `asset_holding_get i` | read from account A and asset B holding field X (imm arg) => {0 or 1 (top), value} |
| `asset_params_get i` | read from asset A params field X (imm arg) => {0 or 1 (top), value} |
+| `app_params_get i` | read from app A params field X (imm arg) => {0 or 1 (top), value} |
# Assembler Syntax
@@ -400,7 +416,7 @@ byte "string literal"
`int` constants may be `0x` prefixed for hex, `0` prefixed for octal, or decimal numbers.
-`intcblock` may be explictly assembled. It will conflict with the assembler gathering `int` pseudo-ops into a `intcblock` program prefix, but may be used if code only has explicit `intc` references. `intcblock` should be followed by space separated int constants all on one line.
+`intcblock` may be explicitly assembled. It will conflict with the assembler gathering `int` pseudo-ops into a `intcblock` program prefix, but may be used if code only has explicit `intc` references. `intcblock` should be followed by space separated int constants all on one line.
`bytecblock` may be explicitly assembled. It will conflict with the assembler if there are any `byte` pseudo-ops but may be used if only explicit `bytec` references are used. `bytecblock` should be followed with byte constants all on one line, either 'encoding value' pairs (`b64 AAA...`) or 0x prefix or function-style values (`base64(...)`) or string literal values.
diff --git a/data/transactions/logic/README_in.md b/data/transactions/logic/README_in.md
index 05f697164..8f62938f4 100644
--- a/data/transactions/logic/README_in.md
+++ b/data/transactions/logic/README_in.md
@@ -122,12 +122,18 @@ Global fields are fields that are common to all the transactions in the group. I
**Asset Fields**
-Asset fields include `AssetHolding` and `AssetParam` fields that are used in `asset_read_*` opcodes
+Asset fields include `AssetHolding` and `AssetParam` fields that are used in the `asset_holding_get` and `asset_params_get` opcodes.
@@ asset_holding_fields.md @@
@@ asset_params_fields.md @@
+**App Fields**
+
+App fields used in the `app_params_get` opcode.
+
+@@ app_params_fields.md @@
+
### Flow Control
@@ Flow_Control.md @@
@@ -167,7 +173,7 @@ byte "string literal"
`int` constants may be `0x` prefixed for hex, `0` prefixed for octal, or decimal numbers.
-`intcblock` may be explictly assembled. It will conflict with the assembler gathering `int` pseudo-ops into a `intcblock` program prefix, but may be used if code only has explicit `intc` references. `intcblock` should be followed by space separated int constants all on one line.
+`intcblock` may be explicitly assembled. It will conflict with the assembler gathering `int` pseudo-ops into a `intcblock` program prefix, but may be used if code only has explicit `intc` references. `intcblock` should be followed by space separated int constants all on one line.
`bytecblock` may be explicitly assembled. It will conflict with the assembler if there are any `byte` pseudo-ops but may be used if only explicit `bytec` references are used. `bytecblock` should be followed with byte constants all on one line, either 'encoding value' pairs (`b64 AAA...`) or 0x prefix or function-style values (`base64(...)`) or string literal values.
diff --git a/data/transactions/logic/TEAL_opcodes.md b/data/transactions/logic/TEAL_opcodes.md
index aabe6306e..0aa9c4e8f 100644
--- a/data/transactions/logic/TEAL_opcodes.md
+++ b/data/transactions/logic/TEAL_opcodes.md
@@ -18,7 +18,7 @@ Ops have a 'cost' of 1 unless otherwise specified.
- SHA256 hash of value X, yields [32]byte
- **Cost**:
- 7 (LogicSigVersion = 1)
- - 35 (2 <= LogicSigVersion <= 4)
+ - 35 (2 <= LogicSigVersion <= 5)
## keccak256
@@ -28,7 +28,7 @@ Ops have a 'cost' of 1 unless otherwise specified.
- Keccak256 hash of value X, yields [32]byte
- **Cost**:
- 26 (LogicSigVersion = 1)
- - 130 (2 <= LogicSigVersion <= 4)
+ - 130 (2 <= LogicSigVersion <= 5)
## sha512_256
@@ -38,7 +38,7 @@ Ops have a 'cost' of 1 unless otherwise specified.
- SHA512_256 hash of value X, yields [32]byte
- **Cost**:
- 9 (LogicSigVersion = 1)
- - 45 (2 <= LogicSigVersion <= 4)
+ - 45 (2 <= LogicSigVersion <= 5)
## ed25519verify
@@ -72,7 +72,7 @@ Overflow is an error condition which halts execution and fails the transaction.
- Opcode: 0x0a
- Pops: *... stack*, {uint64 A}, {uint64 B}
- Pushes: uint64
-- A divided by B. Panic if B == 0.
+- A divided by B (truncated division). Panic if B == 0.
`divmodw` is available to divide the two-element values produced by `mulw` and `addw`.
@@ -374,17 +374,17 @@ Overflow is an error condition which halts execution and fails the transaction.
| 2 | FirstValid | uint64 | round number |
| 3 | FirstValidTime | uint64 | Causes program to fail; reserved for future use |
| 4 | LastValid | uint64 | round number |
-| 5 | Note | []byte | |
-| 6 | Lease | []byte | |
+| 5 | Note | []byte | Any data up to 1024 bytes |
+| 6 | Lease | []byte | 32 byte lease value |
| 7 | Receiver | []byte | 32 byte address |
| 8 | Amount | uint64 | micro-Algos |
| 9 | CloseRemainderTo | []byte | 32 byte address |
| 10 | VotePK | []byte | 32 byte address |
| 11 | SelectionPK | []byte | 32 byte address |
-| 12 | VoteFirst | uint64 | |
-| 13 | VoteLast | uint64 | |
-| 14 | VoteKeyDilution | uint64 | |
-| 15 | Type | []byte | |
+| 12 | VoteFirst | uint64 | The first round that the participation key is valid. |
+| 13 | VoteLast | uint64 | The last round that the participation key is valid. |
+| 14 | VoteKeyDilution | uint64 | Dilution for the 2-level participation key |
+| 15 | Type | []byte | Transaction type as bytes |
| 16 | TypeEnum | uint64 | See table below |
| 17 | XferAsset | uint64 | Asset ID |
| 18 | AssetAmount | uint64 | value in Asset's units |
@@ -547,7 +547,7 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
## gaid t
-- Opcode: 0x3c
+- Opcode: 0x3c {uint8 transaction group index}
- Pops: _None_
- Pushes: uint64
- push the ID of the asset or application created in the Tth transaction of the current group
@@ -722,6 +722,46 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- pop a byte-array A, integer B, and small integer C (between 0..255). Set the Bth byte of A to C, and push the result
- LogicSigVersion >= 3
+## extract s l
+
+- Opcode: 0x57 {uint8 start position} {uint8 length}
+- Pops: *... stack*, []byte
+- Pushes: []byte
+- pop a byte-array A. For immediate values in 0..255 S and L: extract a range of bytes from A starting at S up to but not including S+L, push the substring result. If L is 0, then extract to the end of the string. If S or S+L is larger than the array length, the program fails
+- LogicSigVersion >= 5
+
+## extract3
+
+- Opcode: 0x58
+- Pops: *... stack*, {[]byte A}, {uint64 B}, {uint64 C}
+- Pushes: []byte
+- pop a byte-array A and two integers B and C. Extract a range of bytes from A starting at B up to but not including B+C, push the substring result. If B or B+C is larger than the array length, the program fails
+- LogicSigVersion >= 5
+
+## extract16bits
+
+- Opcode: 0x59
+- Pops: *... stack*, {[]byte A}, {uint64 B}
+- Pushes: uint64
+- pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+2, convert bytes as big endian and push the uint64 result. If B or B+2 is larger than the array length, the program fails
+- LogicSigVersion >= 5
+
+## extract32bits
+
+- Opcode: 0x5a
+- Pops: *... stack*, {[]byte A}, {uint64 B}
+- Pushes: uint64
+- pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+4, convert bytes as big endian and push the uint64 result. If B or B+4 is larger than the array length, the program fails
+- LogicSigVersion >= 5
+
+## extract64bits
+
+- Opcode: 0x5b
+- Pops: *... stack*, {[]byte A}, {uint64 B}
+- Pushes: uint64
+- pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+8, convert bytes as big endian and push the uint64 result. If B or B+8 is larger than the array length, the program fails
+- LogicSigVersion >= 5
+
## balance
- Opcode: 0x60
@@ -877,10 +917,36 @@ params: Txn.Accounts offset (or, since v4, an account address that appears in Tx
| 8 | AssetReserve | []byte | Reserve address |
| 9 | AssetFreeze | []byte | Freeze address |
| 10 | AssetClawback | []byte | Clawback address |
+| 11 | AssetCreator | []byte | Creator address |
params: Before v4, Txn.ForeignAssets offset. Since v4, Txn.ForeignAssets offset or an asset id that appears in Txn.ForeignAssets. Return: did_exist flag (1 if exist and 0 otherwise), value.
+## app_params_get i
+
+- Opcode: 0x72 {uint8 app params field index}
+- Pops: *... stack*, uint64
+- Pushes: *... stack*, any, uint64
+- read from app A params field X (imm arg) => {0 or 1 (top), value}
+- LogicSigVersion >= 5
+- Mode: Application
+
+`app_params_get` Fields:
+
+| Index | Name | Type | Notes |
+| --- | --- | --- | --- |
+| 0 | AppApprovalProgram | []byte | Bytecode of Approval Program |
+| 1 | AppClearStateProgram | []byte | Bytecode of Clear State Program |
+| 2 | AppGlobalNumUint | uint64 | Number of uint64 values allowed in Global State |
+| 3 | AppGlobalNumByteSlice | uint64 | Number of byte array values allowed in Global State |
+| 4 | AppLocalNumUint | uint64 | Number of uint64 values allowed in Local State |
+| 5 | AppLocalNumByteSlice | uint64 | Number of byte array values allowed in Local State |
+| 6 | AppExtraProgramPages | uint64 | Number of Extra Program Pages of code space |
+| 7 | AppCreator | []byte | Creator address |
+
+
+params: Txn.ForeignApps offset or an app id that appears in Txn.ForeignApps. Return: did_exist flag (1 if exist and 0 otherwise), value.
+
## min_balance
- Opcode: 0x78
@@ -914,7 +980,7 @@ pushint args are not added to the intcblock during assembly processes
## callsub target
-- Opcode: 0x88
+- Opcode: 0x88 {int16 branch offset, big endian}
- Pops: _None_
- Pushes: _None_
- branch unconditionally to TARGET, saving the next instruction on the call stack
@@ -1007,7 +1073,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xa2
- Pops: *... stack*, {[]byte A}, {[]byte B}
- Pushes: []byte
-- A divided by B, where A and B are byte-arrays interpreted as big-endian unsigned integers. Panic if B is zero.
+- A divided by B (truncated division), where A and B are byte-arrays interpreted as big-endian unsigned integers. Panic if B is zero.
- **Cost**: 20
- LogicSigVersion >= 4
diff --git a/data/transactions/logic/assembler.go b/data/transactions/logic/assembler.go
index d4b1193e2..231867d29 100644
--- a/data/transactions/logic/assembler.go
+++ b/data/transactions/logic/assembler.go
@@ -19,6 +19,7 @@ package logic
import (
"bufio"
"bytes"
+ "crypto/sha512"
"encoding/base32"
"encoding/base64"
"encoding/binary"
@@ -280,6 +281,8 @@ func (ops *OpStream) ReferToLabel(pc int, label string) {
ops.labelReferences = append(ops.labelReferences, labelReference{ops.sourceLine, pc, label})
}
+type opTypeFunc func(ops *OpStream, immediates []string) (StackTypes, StackTypes)
+
// returns allows opcodes like `txn` to be specific about their return
// value types, based on the field requested, rather than use Any as
// specified by opSpec.
@@ -444,11 +447,11 @@ func assembleIntC(ops *OpStream, spec *OpSpec, args []string) error {
}
func assembleByteC(ops *OpStream, spec *OpSpec, args []string) error {
if len(args) != 1 {
- ops.error("bytec operation needs one argument")
+ return ops.error("bytec operation needs one argument")
}
constIndex, err := strconv.ParseUint(args[0], 0, 64)
if err != nil {
- ops.error(err)
+ return ops.error(err)
}
ops.Bytec(uint(constIndex))
return nil
@@ -456,11 +459,11 @@ func assembleByteC(ops *OpStream, spec *OpSpec, args []string) error {
func asmPushInt(ops *OpStream, spec *OpSpec, args []string) error {
if len(args) != 1 {
- ops.errorf("%s needs one argument", spec.Name)
+ return ops.errorf("%s needs one argument", spec.Name)
}
val, err := strconv.ParseUint(args[0], 0, 64)
if err != nil {
- ops.error(err)
+ return ops.error(err)
}
ops.pending.WriteByte(spec.Opcode)
var scratch [binary.MaxVarintLen64]byte
@@ -470,7 +473,7 @@ func asmPushInt(ops *OpStream, spec *OpSpec, args []string) error {
}
func asmPushBytes(ops *OpStream, spec *OpSpec, args []string) error {
if len(args) != 1 {
- ops.errorf("%s needs one argument", spec.Name)
+ return ops.errorf("%s needs one argument", spec.Name)
}
val, _, err := parseBinaryArgs(args)
if err != nil {
@@ -643,6 +646,24 @@ func assembleByte(ops *OpStream, spec *OpSpec, args []string) error {
return nil
}
+// method "add(uint64,uint64)uint64"
+func assembleMethod(ops *OpStream, spec *OpSpec, args []string) error {
+ if len(args) == 0 {
+ return ops.error("method requires a literal argument")
+ }
+ arg := args[0]
+ if len(arg) > 1 && arg[0] == '"' && arg[len(arg)-1] == '"' {
+ val, err := parseStringLiteral(arg)
+ if err != nil {
+ return ops.error(err)
+ }
+ hash := sha512.Sum512_256(val)
+ ops.ByteLiteral(hash[0:4])
+ return nil
+ }
+ return ops.error("Unable to parse method signature")
+}
+
func assembleIntCBlock(ops *OpStream, spec *OpSpec, args []string) error {
ops.pending.WriteByte(spec.Opcode)
var scratch [binary.MaxVarintLen64]byte
@@ -961,11 +982,11 @@ func assembleGtxnsa(ops *OpStream, spec *OpSpec, args []string) error {
func assembleGlobal(ops *OpStream, spec *OpSpec, args []string) error {
if len(args) != 1 {
- return ops.error("global expects one argument")
+ return ops.errorf("%s expects one argument", spec.Name)
}
fs, ok := globalFieldSpecByName[args[0]]
if !ok {
- return ops.errorf("global unknown field: %#v", args[0])
+ return ops.errorf("%s unknown field: %#v", spec.Name, args[0])
}
if fs.version > ops.Version {
// no return here. we may as well continue to maintain typestack
@@ -982,11 +1003,11 @@ func assembleGlobal(ops *OpStream, spec *OpSpec, args []string) error {
func assembleAssetHolding(ops *OpStream, spec *OpSpec, args []string) error {
if len(args) != 1 {
- return ops.error("asset_holding_get expects one argument")
+ return ops.errorf("%s expects one argument", spec.Name)
}
val, ok := assetHoldingFields[args[0]]
if !ok {
- return ops.errorf("asset_holding_get unknown arg: %#v", args[0])
+ return ops.errorf("%s unknown arg: %#v", spec.Name, args[0])
}
ops.pending.WriteByte(spec.Opcode)
ops.pending.WriteByte(uint8(val))
@@ -996,11 +1017,11 @@ func assembleAssetHolding(ops *OpStream, spec *OpSpec, args []string) error {
func assembleAssetParams(ops *OpStream, spec *OpSpec, args []string) error {
if len(args) != 1 {
- return ops.error("asset_params_get expects one argument")
+ return ops.errorf("%s expects one argument", spec.Name)
}
val, ok := assetParamsFields[args[0]]
if !ok {
- return ops.errorf("asset_params_get unknown arg: %#v", args[0])
+ return ops.errorf("%s unknown arg: %#v", spec.Name, args[0])
}
ops.pending.WriteByte(spec.Opcode)
ops.pending.WriteByte(uint8(val))
@@ -1008,6 +1029,20 @@ func assembleAssetParams(ops *OpStream, spec *OpSpec, args []string) error {
return nil
}
+func assembleAppParams(ops *OpStream, spec *OpSpec, args []string) error {
+ if len(args) != 1 {
+ return ops.errorf("%s expects one argument", spec.Name)
+ }
+ val, ok := appParamsFields[args[0]]
+ if !ok {
+ return ops.errorf("%s unknown arg: %#v", spec.Name, args[0])
+ }
+ ops.pending.WriteByte(spec.Opcode)
+ ops.pending.WriteByte(uint8(val))
+ ops.returns(AppParamsFieldTypes[val], StackUint64)
+ return nil
+}
+
type assembleFunc func(*OpStream, *OpSpec, []string) error
// Basic assembly. Any extra bytes of opcode are encoded as byte immediates.
@@ -1029,13 +1064,52 @@ func asmDefault(ops *OpStream, spec *OpSpec, args []string) error {
return nil
}
+func typeSwap(ops *OpStream, args []string) (StackTypes, StackTypes) {
+ topTwo := oneAny.plus(oneAny)
+ top := len(ops.typeStack) - 1
+ if top >= 0 {
+ topTwo[1] = ops.typeStack[top]
+ if top >= 1 {
+ topTwo[0] = ops.typeStack[top-1]
+ }
+ }
+ reversed := StackTypes{topTwo[1], topTwo[0]}
+ return topTwo, reversed
+}
+
+func typeDig(ops *OpStream, args []string) (StackTypes, StackTypes) {
+ if len(args) == 0 {
+ return oneAny, oneAny
+ }
+ n, err := strconv.ParseUint(args[0], 0, 64)
+ if err != nil {
+ return oneAny, oneAny
+ }
+ depth := int(n) + 1
+ anys := make(StackTypes, depth)
+ for i := range anys {
+ anys[i] = StackAny
+ }
+ returns := anys.plus(oneAny)
+ idx := len(ops.typeStack) - depth
+ if idx >= 0 {
+ returns[len(returns)-1] = ops.typeStack[idx]
+ for i := idx + 1; i < len(ops.typeStack); i++ {
+ returns[i-idx-1] = ops.typeStack[i]
+ }
+ }
+ return anys, returns
+}
+
// keywords handle parsing and assembling special asm language constructs like 'addr'
// We use OpSpec here, but somewhat degenerate, since they don't have opcodes or eval functions
var keywords = map[string]OpSpec{
- "int": {0, "int", nil, assembleInt, nil, nil, oneInt, 1, modeAny, opDetails{1, 2, nil, nil}},
- "byte": {0, "byte", nil, assembleByte, nil, nil, oneBytes, 1, modeAny, opDetails{1, 2, nil, nil}},
+ "int": {0, "int", nil, assembleInt, nil, nil, oneInt, 1, modeAny, opDetails{1, 2, nil, nil, nil}},
+ "byte": {0, "byte", nil, assembleByte, nil, nil, oneBytes, 1, modeAny, opDetails{1, 2, nil, nil, nil}},
// parse basics.Address, actually just another []byte constant
- "addr": {0, "addr", nil, assembleAddr, nil, nil, oneBytes, 1, modeAny, opDetails{1, 2, nil, nil}},
+ "addr": {0, "addr", nil, assembleAddr, nil, nil, oneBytes, 1, modeAny, opDetails{1, 2, nil, nil, nil}},
+ // take a signature, hash it, and take first 4 bytes, actually just another []byte constant
+ "method": {0, "method", nil, assembleMethod, nil, nil, oneBytes, 1, modeAny, opDetails{1, 2, nil, nil, nil}},
}
type lineError struct {
@@ -1145,35 +1219,45 @@ func (ops *OpStream) trace(format string, args ...interface{}) {
}
// checks (and pops) arg types from arg type stack
-func (ops *OpStream) checkArgs(spec OpSpec) {
- firstPop := true
- for i := len(spec.Args) - 1; i >= 0; i-- {
- argType := spec.Args[i]
- stype := ops.tpop()
- if firstPop {
- firstPop = false
- ops.trace("pops(%s", argType.String())
+func (ops *OpStream) checkStack(args StackTypes, returns StackTypes, instruction []string) {
+ argcount := len(args)
+ if argcount > len(ops.typeStack) {
+ err := fmt.Errorf("%s expects %d stack arguments but stack height is %d", strings.Join(instruction, " "), argcount, len(ops.typeStack))
+ if len(ops.labelReferences) > 0 {
+ ops.warnf("%w; but branches have happened and assembler does not precisely track the stack in this case", err)
} else {
- ops.trace(", %s", argType.String())
+ ops.error(err)
}
- if !typecheck(argType, stype) {
- err := fmt.Errorf("%s arg %d wanted type %s got %s", spec.Name, i, argType.String(), stype.String())
- if len(ops.labelReferences) > 0 {
- ops.warnf("%w; but branches have happened and assembler does not precisely track types in this case", err)
+ } else {
+ firstPop := true
+ for i := argcount - 1; i >= 0; i-- {
+ argType := args[i]
+ stype := ops.tpop()
+ if firstPop {
+ firstPop = false
+ ops.trace("pops(%s", argType.String())
} else {
- ops.error(err)
+ ops.trace(", %s", argType.String())
+ }
+ if !typecheck(argType, stype) {
+ err := fmt.Errorf("%s arg %d wanted type %s got %s", strings.Join(instruction, " "), i, argType.String(), stype.String())
+ if len(ops.labelReferences) > 0 {
+ ops.warnf("%w; but branches have happened and assembler does not precisely track types in this case", err)
+ } else {
+ ops.error(err)
+ }
}
}
- }
- if !firstPop {
- ops.trace(")")
+ if !firstPop {
+ ops.trace(")")
+ }
}
- if len(spec.Returns) > 0 {
- ops.tpusha(spec.Returns)
- ops.trace(" pushes(%s", spec.Returns[0].String())
- if len(spec.Returns) > 1 {
- for _, rt := range spec.Returns[1:] {
+ if len(returns) > 0 {
+ ops.tpusha(returns)
+ ops.trace(" pushes(%s", returns[0].String())
+ if len(returns) > 1 {
+ for _, rt := range returns[1:] {
ops.trace(", %s", rt.String())
}
}
@@ -1228,6 +1312,9 @@ func (ops *OpStream) assemble(fin io.Reader) error {
spec, ok := OpsByName[ops.Version][opstring]
if !ok {
spec, ok = keywords[opstring]
+ if spec.Version > 1 && spec.Version > ops.Version {
+ ok = false
+ }
}
if ok {
ops.trace("%3d: %s\t", ops.sourceLine, opstring)
@@ -1235,13 +1322,20 @@ func (ops *OpStream) assemble(fin io.Reader) error {
if spec.Modes == runModeApplication {
ops.HasStatefulOps = true
}
- ops.checkArgs(spec)
+ args, returns := spec.Args, spec.Returns
+ if spec.Details.typeFunc != nil {
+ args, returns = spec.Details.typeFunc(ops, fields[1:])
+ }
+ ops.checkStack(args, returns, fields)
spec.asm(ops, &spec, fields[1:])
ops.trace("\n")
continue
}
// unknown opcode, let's report a good error if version problem
spec, ok = OpsByName[AssemblerMaxVersion][opstring]
+ if !ok {
+ spec, ok = keywords[opstring]
+ }
if ok {
ops.errorf("%s opcode was introduced in TEAL v%d", opstring, spec.Version)
} else {
@@ -2134,7 +2228,7 @@ func disGlobal(dis *disassembleState, spec *OpSpec) (string, error) {
if int(garg) >= len(GlobalFieldNames) {
return "", fmt.Errorf("invalid global arg index %d at pc=%d", garg, dis.pc)
}
- return fmt.Sprintf("global %s", GlobalFieldNames[garg]), nil
+ return fmt.Sprintf("%s %s", spec.Name, GlobalFieldNames[garg]), nil
}
func disBranch(dis *disassembleState, spec *OpSpec) (string, error) {
@@ -2176,7 +2270,7 @@ func disAssetHolding(dis *disassembleState, spec *OpSpec) (string, error) {
if int(arg) >= len(AssetHoldingFieldNames) {
return "", fmt.Errorf("invalid asset holding arg index %d at pc=%d", arg, dis.pc)
}
- return fmt.Sprintf("asset_holding_get %s", AssetHoldingFieldNames[arg]), nil
+ return fmt.Sprintf("%s %s", spec.Name, AssetHoldingFieldNames[arg]), nil
}
func disAssetParams(dis *disassembleState, spec *OpSpec) (string, error) {
@@ -2190,7 +2284,21 @@ func disAssetParams(dis *disassembleState, spec *OpSpec) (string, error) {
if int(arg) >= len(AssetParamsFieldNames) {
return "", fmt.Errorf("invalid asset params arg index %d at pc=%d", arg, dis.pc)
}
- return fmt.Sprintf("asset_params_get %s", AssetParamsFieldNames[arg]), nil
+ return fmt.Sprintf("%s %s", spec.Name, AssetParamsFieldNames[arg]), nil
+}
+
+func disAppParams(dis *disassembleState, spec *OpSpec) (string, error) {
+ lastIdx := dis.pc + 1
+ if len(dis.program) <= lastIdx {
+ missing := lastIdx - len(dis.program) + 1
+ return "", fmt.Errorf("unexpected %s opcode end: missing %d bytes", spec.Name, missing)
+ }
+ dis.nextpc = dis.pc + 2
+ arg := dis.program[dis.pc+1]
+ if int(arg) >= len(AppParamsFieldNames) {
+ return "", fmt.Errorf("invalid app params arg index %d at pc=%d", arg, dis.pc)
+ }
+ return fmt.Sprintf("%s %s", spec.Name, AppParamsFieldNames[arg]), nil
}
type disInfo struct {
diff --git a/data/transactions/logic/assembler_test.go b/data/transactions/logic/assembler_test.go
index 26eaab927..3dbeaf20c 100644
--- a/data/transactions/logic/assembler_test.go
+++ b/data/transactions/logic/assembler_test.go
@@ -289,6 +289,22 @@ gload 0 0
gloads 0
gaid 0
gaids
+int 100
+`
+
+const v5Nonsense = `
+app_params_get AppExtraProgramPages
+byte 0x0123456789abcd
+extract 0 8
+int 0
+int 8
+extract3
+int 0
+extract64bits
+int 0
+extract32bits
+int 0
+extract16bits
`
var nonsense = map[uint64]string{
@@ -296,13 +312,15 @@ var nonsense = map[uint64]string{
2: v1Nonsense + v2Nonsense,
3: v1Nonsense + v2Nonsense + v3Nonsense,
4: v1Nonsense + v2Nonsense + v3Nonsense + v4Nonsense,
+ 5: v1Nonsense + v2Nonsense + v3Nonsense + v4Nonsense + v5Nonsense,
}
var compiled = map[uint64]string{
1: "012008b7a60cf8acd19181cf959a12f8acd19181cf951af8acd19181cf15f8acd191810f01020026050212340c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d024242047465737400320032013202320328292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e0102222324252104082209240a220b230c240d250e230f23102311231223132314181b1c2b1716154000032903494",
2: "022008b7a60cf8acd19181cf959a12f8acd19181cf951af8acd19181cf15f8acd191810f01020026050212340c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d024242047465737400320032013202320328292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e0102222324252104082209240a220b230c240d250e230f23102311231223132314181b1c2b171615400003290349483403350222231d4a484848482a50512a63222352410003420000432105602105612105270463484821052b62482b642b65484821052b2106662b21056721072b682b692107210570004848210771004848361c0037001a0031183119311b311d311e311f3120210721051e312131223123312431253126312731283129312a312b312c312d312e312f",
3: "032008b7a60cf8acd19181cf959a12f8acd19181cf951af8acd19181cf15f8acd191810f01020026050212340c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d024242047465737400320032013202320328292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e0102222324252104082209240a220b230c240d250e230f23102311231223132314181b1c2b171615400003290349483403350222231d4a484848482a50512a63222352410003420000432105602105612105270463484821052b62482b642b65484821052b2106662b21056721072b682b692107210570004848210771004848361c0037001a0031183119311b311d311e311f3120210721051e312131223123312431253126312731283129312a312b312c312d312e312f4478222105531421055427042106552105082106564c4d4b02210538212106391c0081e80780046a6f686e",
- 4: "042004010200b7a60c26040242420c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f23102311231223132314181b1c28171615400003290349483403350222231d4a484848482a50512a632223524100034200004322602261222b634848222862482864286548482228236628226724286828692422700048482471004848361c0037001a0031183119311b311d311e311f312024221e312131223123312431253126312731283129312a312b312c312d312e312f44782522531422542b2355220823564c4d4b0222382123391c0081e80780046a6f686e2281d00f24231f880003420001892223902291922394239593a0a1a2a3a4a5a6a7a8a9aaabacadae23af3a00003b003c003d",
+ 4: "042004010200b7a60c26040242420c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f23102311231223132314181b1c28171615400003290349483403350222231d4a484848482a50512a632223524100034200004322602261222b634848222862482864286548482228236628226724286828692422700048482471004848361c0037001a0031183119311b311d311e311f312024221e312131223123312431253126312731283129312a312b312c312d312e312f44782522531422542b2355220823564c4d4b0222382123391c0081e80780046a6f686e2281d00f24231f880003420001892223902291922394239593a0a1a2a3a4a5a6a7a8a9aaabacadae23af3a00003b003c003d8164",
+ 5: "052004010200b7a60c26040242420c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f23102311231223132314181b1c28171615400003290349483403350222231d4a484848482a50512a632223524100034200004322602261222b634848222862482864286548482228236628226724286828692422700048482471004848361c0037001a0031183119311b311d311e311f312024221e312131223123312431253126312731283129312a312b312c312d312e312f44782522531422542b2355220823564c4d4b0222382123391c0081e80780046a6f686e2281d00f24231f880003420001892223902291922394239593a0a1a2a3a4a5a6a7a8a9aaabacadae23af3a00003b003c003d8164720680070123456789abcd57000824810858245b245a2459",
}
func pseudoOp(opcode string) bool {
@@ -379,7 +397,8 @@ type expect struct {
s string
}
-func testMatch(t *testing.T, actual, expected string) {
+func testMatch(t testing.TB, actual, expected string) {
+ t.Helper()
if strings.HasPrefix(expected, "...") && strings.HasSuffix(expected, "...") {
require.Contains(t, actual, expected[3:len(expected)-3])
} else if strings.HasPrefix(expected, "...") {
@@ -391,7 +410,8 @@ func testMatch(t *testing.T, actual, expected string) {
}
}
-func testProg(t *testing.T, source string, ver uint64, expected ...expect) *OpStream {
+func testProg(t testing.TB, source string, ver uint64, expected ...expect) *OpStream {
+ t.Helper()
program := strings.ReplaceAll(source, ";", "\n")
ops, err := AssembleStringWithVersion(program, ver)
if len(expected) == 0 {
@@ -1324,6 +1344,22 @@ func TestConstantDisassembly(t *testing.T) {
}
+func TestConstantArgs(t *testing.T) {
+ t.Parallel()
+ for v := uint64(1); v <= AssemblerMaxVersion; v++ {
+ testProg(t, "int", v, expect{1, "int needs one argument"})
+ testProg(t, "intc", v, expect{1, "intc operation needs one argument"})
+ testProg(t, "byte", v, expect{1, "byte operation needs byte literal argument"})
+ testProg(t, "bytec", v, expect{1, "bytec operation needs one argument"})
+ testProg(t, "addr", v, expect{1, "addr operation needs one argument"})
+ }
+ for v := uint64(3); v <= AssemblerMaxVersion; v++ {
+ testProg(t, "pushint", v, expect{1, "pushint needs one argument"})
+ testProg(t, "pushbytes", v, expect{1, "pushbytes needs one argument"})
+ }
+
+}
+
func TestAssembleDisassembleErrors(t *testing.T) {
t.Parallel()
@@ -1477,16 +1513,16 @@ func TestAssembleAsset(t *testing.T) {
introduction := OpsByName[LogicVersion]["asset_holding_get"].Version
for v := introduction; v <= AssemblerMaxVersion; v++ {
testProg(t, "asset_holding_get ABC 1", v,
- expect{1, "asset_holding_get arg 1..."})
+ expect{1, "asset_holding_get ABC 1 expects 2 stack arguments..."})
testProg(t, "int 1; asset_holding_get ABC 1", v,
- expect{2, "asset_holding_get arg 0..."})
+ expect{2, "asset_holding_get ABC 1 expects 2 stack arguments..."})
testProg(t, "int 1; int 1; asset_holding_get ABC 1", v,
expect{3, "asset_holding_get expects one argument"})
testProg(t, "int 1; int 1; asset_holding_get ABC", v,
expect{3, "asset_holding_get unknown arg: \"ABC\""})
testProg(t, "byte 0x1234; asset_params_get ABC 1", v,
- expect{2, "asset_params_get arg 0 wanted type uint64..."})
+ expect{2, "asset_params_get ABC 1 arg 0 wanted type uint64..."})
testLine(t, "asset_params_get ABC 1", v, "asset_params_get expects one argument")
testLine(t, "asset_params_get ABC", v, "asset_params_get unknown arg: \"ABC\"")
@@ -2014,3 +2050,31 @@ flip: // [x]
require.NoError(t, err)
require.Empty(t, ops.Warnings)
}
+
+func TestSwapTypeCheck(t *testing.T) {
+ t.Parallel()
+ /* reconfirm that we detect this type error */
+ testProg(t, "int 1; byte 0x1234; +", AssemblerMaxVersion, expect{3, "+ arg 1..."})
+ /* despite swap, we track types */
+ testProg(t, "int 1; byte 0x1234; swap; +", AssemblerMaxVersion, expect{4, "+ arg 0..."})
+ testProg(t, "byte 0x1234; int 1; swap; +", AssemblerMaxVersion, expect{4, "+ arg 1..."})
+}
+
+func TestDigAsm(t *testing.T) {
+ t.Parallel()
+ testProg(t, "int 1; dig; +", AssemblerMaxVersion, expect{2, "dig expects 1 immediate..."})
+ testProg(t, "int 1; dig junk; +", AssemblerMaxVersion, expect{2, "...invalid syntax..."})
+
+ testProg(t, "int 1; byte 0x1234; int 2; dig 2; +", AssemblerMaxVersion)
+ testProg(t, "byte 0x32; byte 0x1234; int 2; dig 2; +", AssemblerMaxVersion,
+ expect{5, "+ arg 1..."})
+ testProg(t, "byte 0x32; byte 0x1234; int 2; dig 3; +", AssemblerMaxVersion,
+ expect{4, "dig 3 expects 4..."})
+ testProg(t, "int 1; byte 0x1234; int 2; dig 12; +", AssemblerMaxVersion,
+ expect{4, "dig 12 expects 13..."})
+
+ // Confirm that digging something out does not ruin our knowledge about the types in the middle
+ testProg(t, "int 1; byte 0x1234; byte 0x1234; dig 2; dig 3; +; pop; +", AssemblerMaxVersion,
+ expect{6, "+ arg 1..."})
+
+}
diff --git a/data/transactions/logic/doc.go b/data/transactions/logic/doc.go
index c2ab47cb3..c474ced80 100644
--- a/data/transactions/logic/doc.go
+++ b/data/transactions/logic/doc.go
@@ -24,91 +24,97 @@ import (
// short description of every op
var opDocByName = map[string]string{
- "err": "Error. Panic immediately. This is primarily a fencepost against accidental zero bytes getting compiled into programs.",
- "sha256": "SHA256 hash of value X, yields [32]byte",
- "keccak256": "Keccak256 hash of value X, yields [32]byte",
- "sha512_256": "SHA512_256 hash of value X, yields [32]byte",
- "ed25519verify": "for (data A, signature B, pubkey C) verify the signature of (\"ProgData\" || program_hash || data) against the pubkey => {0 or 1}",
- "+": "A plus B. Panic on overflow.",
- "-": "A minus B. Panic if B > A.",
- "/": "A divided by B. Panic if B == 0.",
- "*": "A times B. Panic on overflow.",
- "<": "A less than B => {0 or 1}",
- ">": "A greater than B => {0 or 1}",
- "<=": "A less than or equal to B => {0 or 1}",
- ">=": "A greater than or equal to B => {0 or 1}",
- "&&": "A is not zero and B is not zero => {0 or 1}",
- "||": "A is not zero or B is not zero => {0 or 1}",
- "==": "A is equal to B => {0 or 1}",
- "!=": "A is not equal to B => {0 or 1}",
- "!": "X == 0 yields 1; else 0",
- "len": "yields length of byte value X",
- "itob": "converts uint64 X to big endian bytes",
- "btoi": "converts bytes X as big endian to uint64",
- "%": "A modulo B. Panic if B == 0.",
- "|": "A bitwise-or B",
- "&": "A bitwise-and B",
- "^": "A bitwise-xor B",
- "~": "bitwise invert value X",
- "shl": "A times 2^B, modulo 2^64",
- "shr": "A divided by 2^B",
- "sqrt": "The largest integer B such that B^2 <= X",
- "bitlen": "The highest set bit in X. If X is a byte-array, it is interpreted as a big-endian unsigned integer. bitlen of 0 is 0, bitlen of 8 is 4",
- "exp": "A raised to the Bth power. Panic if A == B == 0 and on overflow",
- "expw": "A raised to the Bth power as a 128-bit long result as low (top) and high uint64 values on the stack. Panic if A == B == 0 or if the results exceeds 2^128-1",
- "mulw": "A times B out to 128-bit long result as low (top) and high uint64 values on the stack",
- "addw": "A plus B out to 128-bit long result as sum (top) and carry-bit uint64 values on the stack",
- "divmodw": "Pop four uint64 values. The deepest two are interpreted as a uint128 dividend (deepest value is high word), the top two are interpreted as a uint128 divisor. Four uint64 values are pushed to the stack. The deepest two are the quotient (deeper value is the high uint64). The top two are the remainder, low bits on top.",
- "intcblock": "prepare block of uint64 constants for use by intc",
- "intc": "push Ith constant from intcblock to stack",
- "intc_0": "push constant 0 from intcblock to stack",
- "intc_1": "push constant 1 from intcblock to stack",
- "intc_2": "push constant 2 from intcblock to stack",
- "intc_3": "push constant 3 from intcblock to stack",
- "pushint": "push immediate UINT to the stack as an integer",
- "bytecblock": "prepare block of byte-array constants for use by bytec",
- "bytec": "push Ith constant from bytecblock to stack",
- "bytec_0": "push constant 0 from bytecblock to stack",
- "bytec_1": "push constant 1 from bytecblock to stack",
- "bytec_2": "push constant 2 from bytecblock to stack",
- "bytec_3": "push constant 3 from bytecblock to stack",
- "pushbytes": "push the following program bytes to the stack",
- "bzero": "push a byte-array of length X, containing all zero bytes",
- "arg": "push Nth LogicSig argument to stack",
- "arg_0": "push LogicSig argument 0 to stack",
- "arg_1": "push LogicSig argument 1 to stack",
- "arg_2": "push LogicSig argument 2 to stack",
- "arg_3": "push LogicSig argument 3 to stack",
- "txn": "push field F of current transaction to stack",
- "gtxn": "push field F of the Tth transaction in the current group",
- "gtxns": "push field F of the Xth transaction in the current group",
- "txna": "push Ith value of the array field F of the current transaction",
- "gtxna": "push Ith value of the array field F from the Tth transaction in the current group",
- "gtxnsa": "push Ith value of the array field F from the Xth transaction in the current group",
- "global": "push value from globals to stack",
- "load": "copy a value from scratch space to the stack",
- "store": "pop a value from the stack and store to scratch space",
- "gload": "push Ith scratch space index of the Tth transaction in the current group",
- "gloads": "push Ith scratch space index of the Xth transaction in the current group",
- "gaid": "push the ID of the asset or application created in the Tth transaction of the current group",
- "gaids": "push the ID of the asset or application created in the Xth transaction of the current group",
- "bnz": "branch to TARGET if value X is not zero",
- "bz": "branch to TARGET if value X is zero",
- "b": "branch unconditionally to TARGET",
- "return": "use last value on stack as success value; end",
- "pop": "discard value X from stack",
- "dup": "duplicate last value on stack",
- "dup2": "duplicate two last values on stack: A, B -> A, B, A, B",
- "dig": "push the Nth value from the top of the stack. dig 0 is equivalent to dup",
- "swap": "swaps two last values on stack: A, B -> B, A",
- "select": "selects one of two values based on top-of-stack: A, B, C -> (if C != 0 then B else A)",
- "concat": "pop two byte-arrays A and B and join them, push the result",
- "substring": "pop a byte-array A. For immediate values in 0..255 S and E: extract a range of bytes from A starting at S up to but not including E, push the substring result. If E < S, or either is larger than the array length, the program fails",
- "substring3": "pop a byte-array A and two integers B and C. Extract a range of bytes from A starting at B up to but not including C, push the substring result. If C < B, or either is larger than the array length, the program fails",
- "getbit": "pop a target A (integer or byte-array), and index B. Push the Bth bit of A.",
- "setbit": "pop a target A, index B, and bit C. Set the Bth bit of A to C, and push the result",
- "getbyte": "pop a byte-array A and integer B. Extract the Bth byte of A and push it as an integer",
- "setbyte": "pop a byte-array A, integer B, and small integer C (between 0..255). Set the Bth byte of A to C, and push the result",
+ "err": "Error. Panic immediately. This is primarily a fencepost against accidental zero bytes getting compiled into programs.",
+ "sha256": "SHA256 hash of value X, yields [32]byte",
+ "keccak256": "Keccak256 hash of value X, yields [32]byte",
+ "sha512_256": "SHA512_256 hash of value X, yields [32]byte",
+ "ed25519verify": "for (data A, signature B, pubkey C) verify the signature of (\"ProgData\" || program_hash || data) against the pubkey => {0 or 1}",
+ "+": "A plus B. Panic on overflow.",
+ "-": "A minus B. Panic if B > A.",
+ "/": "A divided by B (truncated division). Panic if B == 0.",
+ "*": "A times B. Panic on overflow.",
+ "<": "A less than B => {0 or 1}",
+ ">": "A greater than B => {0 or 1}",
+ "<=": "A less than or equal to B => {0 or 1}",
+ ">=": "A greater than or equal to B => {0 or 1}",
+ "&&": "A is not zero and B is not zero => {0 or 1}",
+ "||": "A is not zero or B is not zero => {0 or 1}",
+ "==": "A is equal to B => {0 or 1}",
+ "!=": "A is not equal to B => {0 or 1}",
+ "!": "X == 0 yields 1; else 0",
+ "len": "yields length of byte value X",
+ "itob": "converts uint64 X to big endian bytes",
+ "btoi": "converts bytes X as big endian to uint64",
+ "%": "A modulo B. Panic if B == 0.",
+ "|": "A bitwise-or B",
+ "&": "A bitwise-and B",
+ "^": "A bitwise-xor B",
+ "~": "bitwise invert value X",
+ "shl": "A times 2^B, modulo 2^64",
+ "shr": "A divided by 2^B",
+ "sqrt": "The largest integer B such that B^2 <= X",
+ "bitlen": "The highest set bit in X. If X is a byte-array, it is interpreted as a big-endian unsigned integer. bitlen of 0 is 0, bitlen of 8 is 4",
+ "exp": "A raised to the Bth power. Panic if A == B == 0 and on overflow",
+ "expw": "A raised to the Bth power as a 128-bit long result as low (top) and high uint64 values on the stack. Panic if A == B == 0 or if the results exceeds 2^128-1",
+ "mulw": "A times B out to 128-bit long result as low (top) and high uint64 values on the stack",
+ "addw": "A plus B out to 128-bit long result as sum (top) and carry-bit uint64 values on the stack",
+ "divmodw": "Pop four uint64 values. The deepest two are interpreted as a uint128 dividend (deepest value is high word), the top two are interpreted as a uint128 divisor. Four uint64 values are pushed to the stack. The deepest two are the quotient (deeper value is the high uint64). The top two are the remainder, low bits on top.",
+ "intcblock": "prepare block of uint64 constants for use by intc",
+ "intc": "push Ith constant from intcblock to stack",
+ "intc_0": "push constant 0 from intcblock to stack",
+ "intc_1": "push constant 1 from intcblock to stack",
+ "intc_2": "push constant 2 from intcblock to stack",
+ "intc_3": "push constant 3 from intcblock to stack",
+ "pushint": "push immediate UINT to the stack as an integer",
+ "bytecblock": "prepare block of byte-array constants for use by bytec",
+ "bytec": "push Ith constant from bytecblock to stack",
+ "bytec_0": "push constant 0 from bytecblock to stack",
+ "bytec_1": "push constant 1 from bytecblock to stack",
+ "bytec_2": "push constant 2 from bytecblock to stack",
+ "bytec_3": "push constant 3 from bytecblock to stack",
+ "pushbytes": "push the following program bytes to the stack",
+ "bzero": "push a byte-array of length X, containing all zero bytes",
+ "arg": "push Nth LogicSig argument to stack",
+ "arg_0": "push LogicSig argument 0 to stack",
+ "arg_1": "push LogicSig argument 1 to stack",
+ "arg_2": "push LogicSig argument 2 to stack",
+ "arg_3": "push LogicSig argument 3 to stack",
+ "txn": "push field F of current transaction to stack",
+ "gtxn": "push field F of the Tth transaction in the current group",
+ "gtxns": "push field F of the Xth transaction in the current group",
+ "txna": "push Ith value of the array field F of the current transaction",
+ "gtxna": "push Ith value of the array field F from the Tth transaction in the current group",
+ "gtxnsa": "push Ith value of the array field F from the Xth transaction in the current group",
+ "global": "push value from globals to stack",
+ "load": "copy a value from scratch space to the stack",
+ "store": "pop a value from the stack and store to scratch space",
+ "gload": "push Ith scratch space index of the Tth transaction in the current group",
+ "gloads": "push Ith scratch space index of the Xth transaction in the current group",
+ "gaid": "push the ID of the asset or application created in the Tth transaction of the current group",
+ "gaids": "push the ID of the asset or application created in the Xth transaction of the current group",
+ "bnz": "branch to TARGET if value X is not zero",
+ "bz": "branch to TARGET if value X is zero",
+ "b": "branch unconditionally to TARGET",
+ "return": "use last value on stack as success value; end",
+ "pop": "discard value X from stack",
+ "dup": "duplicate last value on stack",
+ "dup2": "duplicate two last values on stack: A, B -> A, B, A, B",
+ "dig": "push the Nth value from the top of the stack. dig 0 is equivalent to dup",
+ "swap": "swaps two last values on stack: A, B -> B, A",
+ "select": "selects one of two values based on top-of-stack: A, B, C -> (if C != 0 then B else A)",
+ "concat": "pop two byte-arrays A and B and join them, push the result",
+ "substring": "pop a byte-array A. For immediate values in 0..255 S and E: extract a range of bytes from A starting at S up to but not including E, push the substring result. If E < S, or either is larger than the array length, the program fails",
+ "substring3": "pop a byte-array A and two integers B and C. Extract a range of bytes from A starting at B up to but not including C, push the substring result. If C < B, or either is larger than the array length, the program fails",
+ "getbit": "pop a target A (integer or byte-array), and index B. Push the Bth bit of A.",
+ "setbit": "pop a target A, index B, and bit C. Set the Bth bit of A to C, and push the result",
+ "getbyte": "pop a byte-array A and integer B. Extract the Bth byte of A and push it as an integer",
+ "setbyte": "pop a byte-array A, integer B, and small integer C (between 0..255). Set the Bth byte of A to C, and push the result",
+ "extract": "pop a byte-array A. For immediate values in 0..255 S and L: extract a range of bytes from A starting at S up to but not including S+L, push the substring result. If L is 0, then extract to the end of the string. If S or S+L is larger than the array length, the program fails",
+ "extract3": "pop a byte-array A and two integers B and C. Extract a range of bytes from A starting at B up to but not including B+C, push the substring result. If B or B+C is larger than the array length, the program fails",
+ "extract16bits": "pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+2, convert bytes as big endian and push the uint64 result. If B or B+2 is larger than the array length, the program fails",
+ "extract32bits": "pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+4, convert bytes as big endian and push the uint64 result. If B or B+4 is larger than the array length, the program fails",
+ "extract64bits": "pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+8, convert bytes as big endian and push the uint64 result. If B or B+8 is larger than the array length, the program fails",
+
"balance": "get balance for account A, in microalgos. The balance is observed after the effects of previous transactions in the group, and after the fee for the current transaction is deducted.",
"min_balance": "get minimum required balance for account A, in microalgos. Required balance is affected by [ASA](https://developer.algorand.org/docs/features/asa/#assets-overview) and [App](https://developer.algorand.org/docs/features/asc1/stateful/#minimum-balance-requirement-for-a-smart-contract) usage. When creating or opting into an app, the minimum balance grows before the app code runs, therefore the increase is visible there. When deleting or closing out, the minimum balance decreases after the app executes.",
"app_opted_in": "check if account A opted in for the application B => {0 or 1}",
@@ -122,13 +128,14 @@ var opDocByName = map[string]string{
"app_global_del": "delete key A from a global state of the current application",
"asset_holding_get": "read from account A and asset B holding field X (imm arg) => {0 or 1 (top), value}",
"asset_params_get": "read from asset A params field X (imm arg) => {0 or 1 (top), value}",
+ "app_params_get": "read from app A params field X (imm arg) => {0 or 1 (top), value}",
"assert": "immediately fail unless value X is a non-zero number",
"callsub": "branch unconditionally to TARGET, saving the next instruction on the call stack",
"retsub": "pop the top instruction from the call stack and branch to it",
"b+": "A plus B, where A and B are byte-arrays interpreted as big-endian unsigned integers",
"b-": "A minus B, where A and B are byte-arrays interpreted as big-endian unsigned integers. Panic on underflow.",
- "b/": "A divided by B, where A and B are byte-arrays interpreted as big-endian unsigned integers. Panic if B is zero.",
+ "b/": "A divided by B (truncated division), where A and B are byte-arrays interpreted as big-endian unsigned integers. Panic if B is zero.",
"b*": "A times B, where A and B are byte-arrays interpreted as big-endian unsigned integers.",
"b<": "A is less than B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1}",
"b>": "A is greater than B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1}",
@@ -166,14 +173,18 @@ var opcodeImmediateNotes = map[string]string{
"bnz": "{int16 branch offset, big endian}",
"bz": "{int16 branch offset, big endian}",
"b": "{int16 branch offset, big endian}",
+ "callsub": "{int16 branch offset, big endian}",
"load": "{uint8 position in scratch space to load from}",
"store": "{uint8 position in scratch space to store to}",
"gload": "{uint8 transaction group index} {uint8 position in scratch space to load from}",
"gloads": "{uint8 position in scratch space to load from}",
+ "gaid": "{uint8 transaction group index}",
"substring": "{uint8 start position} {uint8 end position}",
+ "extract": "{uint8 start position} {uint8 length}",
"dig": "{uint8 depth}",
"asset_holding_get": "{uint8 asset holding field index}",
"asset_params_get": "{uint8 asset params field index}",
+ "app_params_get": "{uint8 app params field index}",
}
// OpImmediateNote returns a short string about immediate data which follows the op byte
@@ -220,6 +231,7 @@ var opDocExtras = map[string]string{
"app_global_del": "params: state key.\n\nDeleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)",
"asset_holding_get": "params: Txn.Accounts offset (or, since v4, an account address that appears in Txn.Accounts or is Txn.Sender), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if exist and 0 otherwise), value.",
"asset_params_get": "params: Before v4, Txn.ForeignAssets offset. Since v4, Txn.ForeignAssets offset or an asset id that appears in Txn.ForeignAssets. Return: did_exist flag (1 if exist and 0 otherwise), value.",
+ "app_params_get": "params: Txn.ForeignApps offset or an app id that appears in Txn.ForeignApps. Return: did_exist flag (1 if exist and 0 otherwise), value.",
}
// OpDocExtra returns extra documentation text about an op
@@ -229,12 +241,13 @@ func OpDocExtra(opName string) string {
// OpGroups is groupings of ops for documentation purposes.
var OpGroups = map[string][]string{
- "Arithmetic": {"sha256", "keccak256", "sha512_256", "ed25519verify", "+", "-", "/", "*", "<", ">", "<=", ">=", "&&", "||", "shl", "shr", "sqrt", "bitlen", "exp", "==", "!=", "!", "len", "itob", "btoi", "%", "|", "&", "^", "~", "mulw", "addw", "divmodw", "expw", "getbit", "setbit", "getbyte", "setbyte", "concat", "substring", "substring3"},
+ "Arithmetic": {"sha256", "keccak256", "sha512_256", "ed25519verify", "+", "-", "/", "*", "<", ">", "<=", ">=", "&&", "||", "shl", "shr", "sqrt", "bitlen", "exp", "==", "!=", "!", "len", "itob", "btoi", "%", "|", "&", "^", "~", "mulw", "addw", "divmodw", "expw", "getbit", "setbit", "getbyte", "setbyte", "concat"},
+ "Byte Array Slicing": {"substring", "substring3", "extract", "extract3", "extract16bits", "extract32bits", "extract64bits"},
"Byteslice Arithmetic": {"b+", "b-", "b/", "b*", "b<", "b>", "b<=", "b>=", "b==", "b!=", "b%"},
"Byteslice Logic": {"b|", "b&", "b^", "b~"},
"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", "txn", "gtxn", "txna", "gtxna", "gtxns", "gtxnsa", "global", "load", "store", "gload", "gloads", "gaid", "gaids"},
"Flow Control": {"err", "bnz", "bz", "b", "return", "pop", "dup", "dup2", "dig", "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"},
+ "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"},
}
// OpCost indicates the cost of an operation over the range of
@@ -302,18 +315,22 @@ func OnCompletionDescription(value uint64) string {
const OnCompletionPreamble = "An application transaction must indicate the action to be taken following the execution of its approvalProgram or clearStateProgram. The constants below describe the available actions."
var txnFieldDocs = map[string]string{
- "Sender": "32 byte address",
- "Fee": "micro-Algos",
- "FirstValid": "round number",
- "FirstValidTime": "Causes program to fail; reserved for future use",
- "LastValid": "round number",
- "Receiver": "32 byte address",
- "Amount": "micro-Algos",
- "CloseRemainderTo": "32 byte address",
- "VotePK": "32 byte address",
- "SelectionPK": "32 byte address",
- //"VoteFirst": "",
- //"VoteLast": "",
+ "Sender": "32 byte address",
+ "Fee": "micro-Algos",
+ "FirstValid": "round number",
+ "FirstValidTime": "Causes program to fail; reserved for future use",
+ "LastValid": "round number",
+ "Note": "Any data up to 1024 bytes",
+ "Lease": "32 byte lease value",
+ "Receiver": "32 byte address",
+ "Amount": "micro-Algos",
+ "CloseRemainderTo": "32 byte address",
+ "VotePK": "32 byte address",
+ "SelectionPK": "32 byte address",
+ "VoteFirst": "The first round that the participation key is valid.",
+ "VoteLast": "The last round that the participation key is valid.",
+ "VoteKeyDilution": "Dilution for the 2-level participation key",
+ "Type": "Transaction type as bytes",
"TypeEnum": "See table below",
"XferAsset": "Asset ID",
"AssetAmount": "value in Asset's units",
@@ -422,4 +439,17 @@ var AssetParamsFieldDocs = map[string]string{
"AssetReserve": "Reserve address",
"AssetFreeze": "Freeze address",
"AssetClawback": "Clawback address",
+ "AssetCreator": "Creator address",
+}
+
+// AppParamsFieldDocs are notes on fields available in `app_params_get`
+var AppParamsFieldDocs = map[string]string{
+ "AppApprovalProgram": "Bytecode of Approval Program",
+ "AppClearStateProgram": "Bytecode of Clear State Program",
+ "AppGlobalNumUint": "Number of uint64 values allowed in Global State",
+ "AppGlobalNumByteSlice": "Number of byte array values allowed in Global State",
+ "AppLocalNumUint": "Number of uint64 values allowed in Local State",
+ "AppLocalNumByteSlice": "Number of byte array values allowed in Local State",
+ "AppExtraProgramPages": "Number of Extra Program Pages of code space",
+ "AppCreator": "Creator address",
}
diff --git a/data/transactions/logic/doc_test.go b/data/transactions/logic/doc_test.go
index bd5e59cc7..625783993 100644
--- a/data/transactions/logic/doc_test.go
+++ b/data/transactions/logic/doc_test.go
@@ -17,6 +17,7 @@
package logic
import (
+ "strings"
"testing"
"github.com/stretchr/testify/require"
@@ -39,6 +40,14 @@ func TestOpDocs(t *testing.T) {
t.Errorf("error: doc for op %#v missing from opDocByName", op)
}
}
+
+ require.Len(t, txnFieldDocs, len(TxnFieldNames))
+ require.Len(t, onCompletionDescriptions, len(OnCompletionNames))
+ require.Len(t, globalFieldDocs, len(GlobalFieldNames))
+ require.Len(t, AssetHoldingFieldDocs, len(AssetHoldingFieldNames))
+ require.Len(t, AssetParamsFieldDocs, len(AssetParamsFieldNames))
+ require.Len(t, AppParamsFieldDocs, len(AppParamsFieldNames))
+ require.Len(t, TypeNameDescriptions, len(TxnTypeNames))
}
func TestOpGroupCoverage(t *testing.T) {
@@ -77,6 +86,19 @@ func TestOpImmediateNote(t *testing.T) {
require.Empty(t, xd)
}
+func TestAllImmediatesDocumented(t *testing.T) {
+ for _, op := range OpSpecs {
+ count := len(op.Details.Immediates)
+ note := OpImmediateNote(op.Name)
+ if count == 1 && op.Details.Immediates[0].kind >= immBytes {
+ // More elaborate than can be checked by easy count.
+ require.NotEmpty(t, note)
+ continue
+ }
+ require.Equal(t, count, strings.Count(note, "{"), "%s immediates doc is wrong", op.Name)
+ }
+}
+
func TestOpDocExtra(t *testing.T) {
xd := OpDocExtra("bnz")
require.NotEmpty(t, xd)
diff --git a/data/transactions/logic/eval.go b/data/transactions/logic/eval.go
index 21ba35162..a0b0593cc 100644
--- a/data/transactions/logic/eval.go
+++ b/data/transactions/logic/eval.go
@@ -143,7 +143,8 @@ type LedgerForLogic interface {
LatestTimestamp() int64
AssetHolding(addr basics.Address, assetIdx basics.AssetIndex) (basics.AssetHolding, error)
- AssetParams(aidx basics.AssetIndex) (basics.AssetParams, error)
+ AssetParams(aidx basics.AssetIndex) (basics.AssetParams, basics.Address, error)
+ AppParams(aidx basics.AppIndex) (basics.AppParams, basics.Address, error)
ApplicationID() basics.AppIndex
CreatorAddress() basics.Address
OptedIn(addr basics.Address, appIdx basics.AppIndex) (bool, error)
@@ -345,7 +346,6 @@ func (pe PanicError) Error() string {
return fmt.Sprintf("panic in TEAL Eval: %v\n%s", pe.PanicValue, pe.StackTrace)
}
-var errLoopDetected = errors.New("loop detected")
var errLogicSigNotSupported = errors.New("LogicSig not supported")
var errTooManyArgs = errors.New("LogicSig has too many arguments")
@@ -782,7 +782,7 @@ func opAssert(cx *evalContext) {
cx.stack = cx.stack[:last]
return
}
- cx.err = errors.New("assert failed")
+ cx.err = fmt.Errorf("assert failed pc=%d", cx.pc)
}
func opSwap(cx *evalContext) {
@@ -1033,7 +1033,7 @@ func opEq(cx *evalContext) {
}
var cond bool
if ta == StackBytes {
- cond = bytes.Compare(cx.stack[prev].Bytes, cx.stack[last].Bytes) == 0
+ cond = bytes.Equal(cx.stack[prev].Bytes, cx.stack[last].Bytes)
} else {
cond = cx.stack[prev].Uint == cx.stack[last].Uint
}
@@ -1718,7 +1718,7 @@ func (cx *evalContext) assetHoldingEnumToValue(holding *basics.AssetHolding, fie
return
}
-func (cx *evalContext) assetParamsEnumToValue(params *basics.AssetParams, field uint64) (sv stackValue, err error) {
+func (cx *evalContext) assetParamsEnumToValue(params *basics.AssetParams, creator basics.Address, field uint64) (sv stackValue, err error) {
switch AssetParamsField(field) {
case AssetTotal:
sv.Uint = params.Total
@@ -1742,6 +1742,8 @@ func (cx *evalContext) assetParamsEnumToValue(params *basics.AssetParams, field
sv.Bytes = params.Freeze[:]
case AssetClawback:
sv.Bytes = params.Clawback[:]
+ case AssetCreator:
+ sv.Bytes = creator[:]
default:
err = fmt.Errorf("invalid asset params field %d", field)
return
@@ -1755,6 +1757,37 @@ func (cx *evalContext) assetParamsEnumToValue(params *basics.AssetParams, field
return
}
+func (cx *evalContext) appParamsEnumToValue(params *basics.AppParams, creator basics.Address, field uint64) (sv stackValue, err error) {
+ switch AppParamsField(field) {
+ case AppApprovalProgram:
+ sv.Bytes = params.ApprovalProgram[:]
+ case AppClearStateProgram:
+ sv.Bytes = params.ClearStateProgram[:]
+ case AppGlobalNumUint:
+ sv.Uint = params.GlobalStateSchema.NumUint
+ case AppGlobalNumByteSlice:
+ sv.Uint = params.GlobalStateSchema.NumByteSlice
+ case AppLocalNumUint:
+ sv.Uint = params.LocalStateSchema.NumUint
+ case AppLocalNumByteSlice:
+ sv.Uint = params.LocalStateSchema.NumByteSlice
+ case AppExtraProgramPages:
+ sv.Uint = uint64(params.ExtraProgramPages)
+ case AppCreator:
+ sv.Bytes = creator[:]
+ default:
+ err = fmt.Errorf("invalid app params field %d", field)
+ return
+ }
+
+ appParamsField := AppParamsField(field)
+ appParamsFieldType := AppParamsFieldTypes[appParamsField]
+ if !typecheck(appParamsFieldType, sv.argType()) {
+ err = fmt.Errorf("%s expected field type is %s but got %s", appParamsField.String(), appParamsFieldType.String(), sv.argType().String())
+ }
+ return
+}
+
// TxnFieldToTealValue is a thin wrapper for txnFieldToStack for external use
func TxnFieldToTealValue(txn *transactions.Transaction, groupIndex int, field TxnField, arrayFieldIdx uint64) (basics.TealValue, error) {
cx := evalContext{EvalParams: EvalParams{GroupIndex: groupIndex}}
@@ -2537,6 +2570,77 @@ func opSetByte(cx *evalContext) {
cx.stack = cx.stack[:prev]
}
+func opExtractImpl(x []byte, start, length int) (out []byte, err error) {
+ out = x
+ end := start + length
+ if start > len(x) || end > len(x) {
+ err = errors.New("extract range beyond length of string")
+ return
+ }
+ out = x[start:end]
+ return
+}
+
+func opExtract(cx *evalContext) {
+ last := len(cx.stack) - 1
+ startIdx := cx.program[cx.pc+1]
+ lengthIdx := cx.program[cx.pc+2]
+ // Shortcut: if length is 0, take bytes from start index to the end
+ length := int(lengthIdx)
+ if length == 0 {
+ length = len(cx.stack[last].Bytes) - int(startIdx)
+ }
+ cx.stack[last].Bytes, cx.err = opExtractImpl(cx.stack[last].Bytes, int(startIdx), length)
+}
+
+func opExtract3(cx *evalContext) {
+ last := len(cx.stack) - 1 // length
+ prev := last - 1 // start
+ byteArrayIdx := prev - 1 // bytes
+ startIdx := cx.stack[prev].Uint
+ lengthIdx := cx.stack[last].Uint
+ if startIdx > math.MaxInt32 || lengthIdx > math.MaxInt32 {
+ cx.err = errors.New("extract range beyond length of string")
+ return
+ }
+ cx.stack[byteArrayIdx].Bytes, cx.err = opExtractImpl(cx.stack[byteArrayIdx].Bytes, int(startIdx), int(lengthIdx))
+ cx.stack = cx.stack[:prev]
+}
+
+// We convert the bytes manually here because we need to accept "short" byte arrays.
+// A single byte is a legal uint64 decoded this way.
+func convertBytesToInt(x []byte) (out uint64) {
+ out = uint64(0)
+ for _, b := range x {
+ out = out << 8
+ out = out | (uint64(b) & 0x0ff)
+ }
+ return
+}
+
+func opExtractNBytes(cx *evalContext, n int) {
+ last := len(cx.stack) - 1 // start
+ prev := last - 1 // bytes
+ startIdx := cx.stack[last].Uint
+ cx.stack[prev].Bytes, cx.err = opExtractImpl(cx.stack[prev].Bytes, int(startIdx), n) // extract n bytes
+
+ cx.stack[prev].Uint = convertBytesToInt(cx.stack[prev].Bytes)
+ cx.stack[prev].Bytes = nil
+ cx.stack = cx.stack[:last]
+}
+
+func opExtract16Bits(cx *evalContext) {
+ opExtractNBytes(cx, 2) // extract 2 bytes
+}
+
+func opExtract32Bits(cx *evalContext) {
+ opExtractNBytes(cx, 4) // extract 4 bytes
+}
+
+func opExtract64Bits(cx *evalContext) {
+ opExtractNBytes(cx, 8) // extract 8 bytes
+}
+
func accountReference(cx *evalContext, account stackValue) (basics.Address, uint64, error) {
if account.argType() == StackUint64 {
addr, err := cx.Txn.Txn.AddressByIndex(account.Uint, cx.Txn.Txn.Sender)
@@ -2974,10 +3078,42 @@ func opAssetParamsGet(cx *evalContext) {
var exist uint64 = 0
var value stackValue
- if params, err := cx.Ledger.AssetParams(asset); err == nil {
+ if params, creator, err := cx.Ledger.AssetParams(asset); err == nil {
+ // params exist, read the value
+ exist = 1
+ value, err = cx.assetParamsEnumToValue(&params, creator, paramIdx)
+ if err != nil {
+ cx.err = err
+ return
+ }
+ }
+
+ cx.stack[last] = value
+ cx.stack = append(cx.stack, stackValue{Uint: exist})
+}
+
+func opAppParamsGet(cx *evalContext) {
+ last := len(cx.stack) - 1 // app
+
+ if cx.Ledger == nil {
+ cx.err = fmt.Errorf("ledger not available")
+ return
+ }
+
+ paramIdx := uint64(cx.program[cx.pc+1])
+
+ app, err := appReference(cx, cx.stack[last].Uint, true)
+ if err != nil {
+ cx.err = err
+ return
+ }
+
+ var exist uint64 = 0
+ var value stackValue
+ if params, creator, err := cx.Ledger.AppParams(app); err == nil {
// params exist, read the value
exist = 1
- value, err = cx.assetParamsEnumToValue(&params, paramIdx)
+ value, err = cx.appParamsEnumToValue(&params, creator, paramIdx)
if err != nil {
cx.err = err
return
diff --git a/data/transactions/logic/evalStateful_test.go b/data/transactions/logic/evalStateful_test.go
index 64bbe39b4..59fe92d9c 100644
--- a/data/transactions/logic/evalStateful_test.go
+++ b/data/transactions/logic/evalStateful_test.go
@@ -35,31 +35,42 @@ type balanceRecord struct {
addr basics.Address
balance uint64
locals map[basics.AppIndex]basics.TealKeyValue
- holdings map[uint64]basics.AssetHolding
+ holdings map[basics.AssetIndex]basics.AssetHolding
mods map[basics.AppIndex]map[string]basics.ValueDelta
}
-// In our test ledger, we don't store the AppParams with its creator,
-// so we need to carry the creator arround with the params,
+// In our test ledger, we don't store the creatables with their
+// creators, so we need to carry the creator around with them.
type appParams struct {
basics.AppParams
Creator basics.Address
}
+type asaParams struct {
+ basics.AssetParams
+ Creator basics.Address
+}
+
type testLedger struct {
balances map[basics.Address]balanceRecord
applications map[basics.AppIndex]appParams
- assets map[basics.AssetIndex]basics.AssetParams
+ assets map[basics.AssetIndex]asaParams
trackedCreatables map[int]basics.CreatableIndex
appID basics.AppIndex
creatorAddr basics.Address
mods map[basics.AppIndex]map[string]basics.ValueDelta
}
-func makeSchemas(li uint64, lb uint64, gi uint64, gb uint64) basics.StateSchemas {
- return basics.StateSchemas{
- LocalStateSchema: basics.StateSchema{NumUint: li, NumByteSlice: lb},
- GlobalStateSchema: basics.StateSchema{NumUint: gi, NumByteSlice: gb},
+func makeApp(li uint64, lb uint64, gi uint64, gb uint64) basics.AppParams {
+ return basics.AppParams{
+ ApprovalProgram: []byte{},
+ ClearStateProgram: []byte{},
+ GlobalState: map[string]basics.TealValue{},
+ StateSchemas: basics.StateSchemas{
+ LocalStateSchema: basics.StateSchema{NumUint: li, NumByteSlice: lb},
+ GlobalStateSchema: basics.StateSchema{NumUint: gi, NumByteSlice: gb},
+ },
+ ExtraProgramPages: 0,
}
}
@@ -68,20 +79,29 @@ func makeBalanceRecord(addr basics.Address, balance uint64) balanceRecord {
addr: addr,
balance: balance,
locals: make(map[basics.AppIndex]basics.TealKeyValue),
- holdings: make(map[uint64]basics.AssetHolding),
+ holdings: make(map[basics.AssetIndex]basics.AssetHolding),
mods: make(map[basics.AppIndex]map[string]basics.ValueDelta),
}
return br
}
+func makeSampleEnv() (EvalParams, *testLedger) {
+ txn := makeSampleTxn()
+ ep := defaultEvalParams(nil, &txn)
+ ep.TxnGroup = makeSampleTxnGroup(txn)
+ ledger := makeTestLedger(map[basics.Address]uint64{})
+ ep.Ledger = ledger
+ return ep, ledger
+}
+
func makeTestLedger(balances map[basics.Address]uint64) *testLedger {
l := new(testLedger)
l.balances = make(map[basics.Address]balanceRecord)
for addr, balance := range balances {
- l.balances[addr] = makeBalanceRecord(addr, balance)
+ l.newAccount(addr, balance)
}
l.applications = make(map[basics.AppIndex]appParams)
- l.assets = make(map[basics.AssetIndex]basics.AssetParams)
+ l.assets = make(map[basics.AssetIndex]asaParams)
l.trackedCreatables = make(map[int]basics.CreatableIndex)
l.mods = make(map[basics.AppIndex]map[string]basics.ValueDelta)
return l
@@ -95,28 +115,39 @@ func (l *testLedger) reset() {
}
}
-func (l *testLedger) newApp(addr basics.Address, appID basics.AppIndex, schemas basics.StateSchemas) {
+func (l *testLedger) newAccount(addr basics.Address, balance uint64) {
+ l.balances[addr] = makeBalanceRecord(addr, balance)
+}
+
+func (l *testLedger) newApp(creator basics.Address, appID basics.AppIndex, params basics.AppParams) {
l.appID = appID
- appIdx := appID
- l.applications[appIdx] = appParams{
- Creator: addr,
- AppParams: basics.AppParams{
- StateSchemas: schemas,
- GlobalState: make(basics.TealKeyValue),
- },
+ params = params.Clone()
+ if params.GlobalState == nil {
+ params.GlobalState = make(basics.TealKeyValue)
}
- br, ok := l.balances[addr]
+ l.applications[appID] = appParams{
+ Creator: creator,
+ AppParams: params.Clone(),
+ }
+ br, ok := l.balances[creator]
if !ok {
- br = makeBalanceRecord(addr, 0)
+ br = makeBalanceRecord(creator, 0)
}
- br.locals[appIdx] = make(map[string]basics.TealValue)
- l.balances[addr] = br
+ br.locals[appID] = make(map[string]basics.TealValue)
+ l.balances[creator] = br
}
-func (l *testLedger) newAsset(creator basics.Address, assetID uint64, params basics.AssetParams) {
- l.assets[basics.AssetIndex(assetID)] = params
- // We're not simulating details of ReserveAddress yet.
- l.setHolding(creator, assetID, params.Total, params.DefaultFrozen)
+func (l *testLedger) newAsset(creator basics.Address, assetID basics.AssetIndex, params basics.AssetParams) {
+ l.assets[assetID] = asaParams{
+ Creator: creator,
+ AssetParams: params,
+ }
+ br, ok := l.balances[creator]
+ if !ok {
+ br = makeBalanceRecord(creator, 0)
+ }
+ br.holdings[assetID] = basics.AssetHolding{Amount: params.Total, Frozen: params.DefaultFrozen}
+ l.balances[creator] = br
}
func (l *testLedger) setHolding(addr basics.Address, assetID uint64, amount uint64, frozen bool) {
@@ -124,7 +155,7 @@ func (l *testLedger) setHolding(addr basics.Address, assetID uint64, amount uint
if !ok {
br = makeBalanceRecord(addr, 0)
}
- br.holdings[assetID] = basics.AssetHolding{Amount: amount, Frozen: frozen}
+ br.holdings[basics.AssetIndex(assetID)] = basics.AssetHolding{Amount: amount, Frozen: frozen}
l.balances[addr] = br
}
@@ -369,7 +400,7 @@ func (l *testLedger) GetCreatableID(groupIdx int) basics.CreatableIndex {
func (l *testLedger) AssetHolding(addr basics.Address, assetID basics.AssetIndex) (basics.AssetHolding, error) {
if br, ok := l.balances[addr]; ok {
- if asset, ok := br.holdings[uint64(assetID)]; ok {
+ if asset, ok := br.holdings[assetID]; ok {
return asset, nil
}
return basics.AssetHolding{}, fmt.Errorf("No asset for account")
@@ -377,11 +408,18 @@ func (l *testLedger) AssetHolding(addr basics.Address, assetID basics.AssetIndex
return basics.AssetHolding{}, fmt.Errorf("no such address")
}
-func (l *testLedger) AssetParams(assetID basics.AssetIndex) (basics.AssetParams, error) {
+func (l *testLedger) AssetParams(assetID basics.AssetIndex) (basics.AssetParams, basics.Address, error) {
if asset, ok := l.assets[assetID]; ok {
- return asset, nil
+ return asset.AssetParams, asset.Creator, nil
}
- return basics.AssetParams{}, fmt.Errorf("no such asset")
+ return basics.AssetParams{}, basics.Address{}, fmt.Errorf("no such asset")
+}
+
+func (l *testLedger) AppParams(appID basics.AppIndex) (basics.AppParams, basics.Address, error) {
+ if app, ok := l.applications[appID]; ok {
+ return app.AppParams, app.Creator, nil
+ }
+ return basics.AppParams{}, basics.Address{}, fmt.Errorf("no such app")
}
func (l *testLedger) ApplicationID() basics.AppIndex {
@@ -596,7 +634,7 @@ pop
txn.Txn.Sender: 1,
},
)
- ledger.newApp(txn.Txn.Sender, 100, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
ledger.balances[txn.Txn.Sender].locals[100]["ALGO"] = algoValue
ledger.newAsset(txn.Txn.Sender, 5, params)
@@ -647,10 +685,9 @@ pop
"arg_3",
}
for _, source := range disallowed {
- ops, err := AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
+ ops := testProg(t, source, AssemblerMaxVersion)
ep := defaultEvalParams(nil, nil)
- err = CheckStateful(ops.Program, ep)
+ err := CheckStateful(ops.Program, ep)
require.Error(t, err)
_, err = EvalStateful(ops.Program, ep)
require.Error(t, err)
@@ -671,6 +708,7 @@ pop
"byte 0x01\napp_global_del",
"int 0\nint 0\nasset_holding_get AssetFrozen",
"int 0\nint 0\nasset_params_get AssetManager",
+ "int 0\nint 0\napp_params_get AppApprovalProgram",
}
for _, source := range statefulOpcodeCalls {
@@ -689,67 +727,31 @@ pop
require.True(t, modeAny.Any())
}
-func testStateful(t *testing.T, source string, ver uint64, ledger LedgerForLogic) (bool, error) {
- ops := testProg(t, source, ver)
-
- txn := makeSampleTxn()
- ep := defaultEvalParams(nil, &txn)
- ep.TxnGroup = makeSampleTxnGroup(txn)
- _, err := EvalStateful(ops.Program, ep)
- require.Error(t, err)
- require.Contains(t, err.Error(), "ledger not available")
-
- ep.Ledger = ledger
- return EvalStateful(ops.Program, ep)
-}
-
func TestBalance(t *testing.T) {
t.Parallel()
+ ep, ledger := makeSampleEnv()
text := "int 2; balance; int 177; =="
- tl := makeTestLedger(
- map[basics.Address]uint64{
- makeSampleTxn().Txn.Receiver: 177,
- },
- )
- _, err := testStateful(t, text, AssemblerMaxVersion, tl)
- require.Error(t, err)
- require.Contains(t, err.Error(), "invalid Account reference")
+ ledger.newAccount(ep.Txn.Txn.Receiver, 177)
+ testApp(t, text, ep, "invalid Account reference")
text = `int 1; balance; int 177; ==`
- pass, err := testStateful(t, text, AssemblerMaxVersion, tl)
- require.NoError(t, err)
- require.True(t, pass)
+ testApp(t, text, ep)
text = `txn Accounts 1; balance; int 177; ==;`
// won't assemble in old version teal
testProg(t, text, directRefEnabledVersion-1, expect{2, "balance arg 0 wanted type uint64..."})
// but legal after that
- pass, err = testStateful(t, text, directRefEnabledVersion, tl)
- require.NoError(t, err)
- require.True(t, pass)
+ testApp(t, text, ep)
text = "int 0; balance; int 13; =="
var addr basics.Address
copy(addr[:], []byte("aoeuiaoeuiaoeuiaoeuiaoeuiaoeui02"))
- tl = makeTestLedger(
- map[basics.Address]uint64{
- addr: 13,
- },
- )
- pass, err = testStateful(t, text, AssemblerMaxVersion, tl)
- require.Error(t, err)
- require.Contains(t, err.Error(), "failed to fetch balance")
- require.False(t, pass)
+ ledger.newAccount(addr, 13)
+ testApp(t, text, ep, "failed to fetch balance")
- tl = makeTestLedger(
- map[basics.Address]uint64{
- makeSampleTxn().Txn.Sender: 13,
- },
- )
- pass, err = testStateful(t, text, AssemblerMaxVersion, tl)
- require.NoError(t, err)
- require.True(t, pass)
+ ledger.newAccount(ep.Txn.Txn.Sender, 13)
+ testApp(t, text, ep)
}
func testApp(t *testing.T, program string, ep EvalParams, problems ...string) basics.EvalDelta {
@@ -793,28 +795,17 @@ func testApp(t *testing.T, program string, ep EvalParams, problems ...string) ba
func TestMinBalance(t *testing.T) {
t.Parallel()
- txn := makeSampleTxn()
- txgroup := makeSampleTxnGroup(txn)
- ep := defaultEvalParams(nil, nil)
- ep.Txn = &txn
- ep.TxnGroup = txgroup
+ ep, ledger := makeSampleEnv()
- testApp(t, "int 0; min_balance; int 1001; ==", ep, "ledger not available")
-
- ledger := makeTestLedger(
- map[basics.Address]uint64{
- txn.Txn.Sender: 234, // min_balance 0 is Sender
- txn.Txn.Receiver: 123, // Accounts[0] has been packed with the Receiver
- },
- )
- ep.Ledger = ledger
+ ledger.newAccount(ep.Txn.Txn.Sender, 234)
+ ledger.newAccount(ep.Txn.Txn.Receiver, 123)
testApp(t, "int 0; min_balance; int 1001; ==", ep)
// Sender makes an asset, min balance goes up
- ledger.newAsset(txn.Txn.Sender, 7, basics.AssetParams{Total: 1000})
+ ledger.newAsset(ep.Txn.Txn.Sender, 7, basics.AssetParams{Total: 1000})
testApp(t, "int 0; min_balance; int 2002; ==", ep)
- schemas := makeSchemas(1, 2, 3, 4)
- ledger.newApp(txn.Txn.Sender, 77, schemas)
+ schemas := makeApp(1, 2, 3, 4)
+ ledger.newApp(ep.Txn.Txn.Sender, 77, schemas)
// create + optin + 10 schema base + 4 ints + 6 bytes (local
// and global count b/c newApp opts the creator in)
minb := 2*1002 + 10*1003 + 4*1004 + 6*1005
@@ -832,7 +823,7 @@ func TestMinBalance(t *testing.T) {
testProg(t, "txn Accounts 1; min_balance; int 1001; ==", directRefEnabledVersion)
testApp(t, "txn Accounts 1; min_balance; int 1001; ==", ep) // 1 == Accounts[0]
// Receiver opts in
- ledger.setHolding(txn.Txn.Receiver, 7, 1, true)
+ ledger.setHolding(ep.Txn.Txn.Receiver, 7, 1, true)
testApp(t, "int 1; min_balance; int 2002; ==", ep) // 1 == Accounts[0]
testApp(t, "int 2; min_balance; int 1001; ==", ep, "invalid Account reference 2")
@@ -871,7 +862,7 @@ func TestAppCheckOptedIn(t *testing.T) {
testApp(t, "int 0; int 100; app_opted_in; int 0; ==", now)
// Receiver opted in
- ledger.newApp(txn.Txn.Receiver, 100, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Receiver, 100, basics.AppParams{})
testApp(t, "int 1; int 100; app_opted_in; int 1; ==", now)
testApp(t, "int 1; int 2; app_opted_in; int 1; ==", now)
testApp(t, "int 1; int 2; app_opted_in; int 0; ==", pre) // in pre, int 2 is an actual app id
@@ -880,7 +871,7 @@ func TestAppCheckOptedIn(t *testing.T) {
expect{3, "app_opted_in arg 0 wanted type uint64..."})
// Sender opted in
- ledger.newApp(txn.Txn.Sender, 100, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
testApp(t, "int 0; int 100; app_opted_in; int 1; ==", now)
}
@@ -937,11 +928,11 @@ int 1`
testApp(t, text, now, "no app for account")
// Make a different app (not 100)
- ledger.newApp(txn.Txn.Receiver, 9999, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Receiver, 9999, basics.AppParams{})
testApp(t, text, now, "no app for account")
// create the app and check the value from ApplicationArgs[0] (protocol.PaymentTx) does not exist
- ledger.newApp(txn.Txn.Receiver, 100, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Receiver, 100, basics.AppParams{})
testApp(t, text, now)
text = `int 1 // account idx
@@ -971,7 +962,7 @@ byte 0x414c474f
"no such address")
// check special case account idx == 0 => sender
- ledger.newApp(txn.Txn.Sender, 100, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
text = `int 0 // account idx
int 100 // app id
txn ApplicationArgs 0
@@ -989,8 +980,8 @@ byte 0x414c474f
"invalid Account reference")
// check reading state of other app
- ledger.newApp(txn.Txn.Sender, 56, makeSchemas(0, 0, 0, 0))
- ledger.newApp(txn.Txn.Sender, 100, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Sender, 56, basics.AppParams{})
+ ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
text = `int 0 // account idx
int 56 // app id
txn ApplicationArgs 0
@@ -1081,7 +1072,7 @@ byte 0x414c474f
testApp(t, text, now, "no such app")
// create the app and check the value from ApplicationArgs[0] (protocol.PaymentTx) does not exist
- ledger.newApp(txn.Txn.Sender, 100, makeSchemas(0, 0, 0, 1))
+ ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
testApp(t, text, now, "err opcode")
@@ -1227,6 +1218,12 @@ bnz ok
error:
err
ok:
+int 0//params
+asset_params_get AssetCreator
+pop
+txn Sender
+==
+assert
int 1
`
@@ -1263,7 +1260,7 @@ func TestAssets(t *testing.T) {
// it wasn't legal to use a direct ref for account
testProg(t, `byte "aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00"; int 54; asset_holding_get AssetBalance`,
- directRefEnabledVersion-1, expect{3, "asset_holding_get arg 0 wanted type uint64..."})
+ directRefEnabledVersion-1, expect{3, "asset_holding_get AssetBalance arg 0 wanted type uint64..."})
// but it is now (empty asset yields 0,0 on stack)
testApp(t, `byte "aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00"; int 55; asset_holding_get AssetBalance; ==`, now)
// This is receiver, who is in Assets array
@@ -1306,7 +1303,7 @@ func TestAssets(t *testing.T) {
testApp(t, strings.Replace(assetsTestProgram, "int 55", "int 0", -1), now)
// but old code cannot
- testProg(t, strings.Replace(assetsTestProgram, "int 0//account", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00\"", -1), directRefEnabledVersion-1, expect{3, "asset_holding_get arg 0 wanted type uint64..."})
+ testProg(t, strings.Replace(assetsTestProgram, "int 0//account", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00\"", -1), directRefEnabledVersion-1, expect{3, "asset_holding_get AssetBalance arg 0 wanted type uint64..."})
testApp(t, strings.Replace(assetsTestProgram, "int 0//params", "int 55", -1), pre, "invalid Asset ref")
testApp(t, strings.Replace(assetsTestProgram, "int 55", "int 0", -1), pre, "err opcode")
@@ -1416,6 +1413,20 @@ intc_1
testApp(t, source, now, "cannot compare ([]byte to uint64)")
}
+func TestAppParams(t *testing.T) {
+ t.Parallel()
+ ep, ledger := makeSampleEnv()
+ ledger.newAccount(ep.Txn.Txn.Sender, 1)
+ ledger.newApp(ep.Txn.Txn.Sender, 100, basics.AppParams{})
+
+ /* app id is in ForeignApps, but does not exist */
+ source := "int 56; app_params_get AppExtraProgramPages; int 0; ==; assert; int 0; =="
+ testApp(t, source, ep)
+ /* app id is in ForeignApps, but has zero ExtraProgramPages */
+ source = "int 100; app_params_get AppExtraProgramPages; int 1; ==; assert; int 0; =="
+ testApp(t, source, ep)
+}
+
func TestAppLocalReadWriteDeleteErrors(t *testing.T) {
t.Parallel()
@@ -1506,7 +1517,7 @@ intc_1
require.Error(t, err)
require.Contains(t, err.Error(), "no app for account")
- ledger.newApp(txn.Txn.Sender, 100, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
if name == "read" {
_, err = EvalStateful(ops.Program, ep)
@@ -1546,7 +1557,7 @@ func TestAppLocalStateReadWrite(t *testing.T) {
},
)
ep.Ledger = ledger
- ledger.newApp(txn.Txn.Sender, 100, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
// write int and bytes values
source := `int 0 // account
@@ -1865,7 +1876,7 @@ int 1
require.Error(t, err)
require.Contains(t, err.Error(), "no such app")
- ledger.newApp(txn.Txn.Sender, 100, makeSchemas(0, 0, 1, 0))
+ ledger.newApp(txn.Txn.Sender, 100, makeApp(0, 0, 1, 0))
// a special test for read
if name == "read" {
@@ -1960,7 +1971,7 @@ int 0x77
},
)
ep.Ledger = ledger
- ledger.newApp(txn.Txn.Sender, 100, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
ops, err := AssembleStringWithVersion(source, AssemblerMaxVersion)
require.NoError(t, err)
@@ -2133,14 +2144,14 @@ byte "myval"
},
)
ep.Ledger = ledger
- ledger.newApp(txn.Txn.Sender, 100, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
delta := testApp(t, source, ep, "no such app")
require.Empty(t, delta.GlobalDelta)
require.Empty(t, delta.LocalDeltas)
- ledger.newApp(txn.Txn.Receiver, 101, makeSchemas(0, 0, 0, 0))
- ledger.newApp(txn.Txn.Receiver, 100, makeSchemas(0, 0, 0, 0)) // this keeps current app id = 100
+ ledger.newApp(txn.Txn.Receiver, 101, basics.AppParams{})
+ ledger.newApp(txn.Txn.Receiver, 100, basics.AppParams{}) // this keeps current app id = 100
algoValue := basics.TealValue{Type: basics.TealBytesType, Bytes: "myval"}
ledger.applications[101].GlobalState["mykey"] = algoValue
@@ -2177,7 +2188,7 @@ int 7
},
)
ep.Ledger = ledger
- ledger.newApp(txn.Txn.Sender, 100, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
delta := testApp(t, source, ep)
require.Empty(t, delta.LocalDeltas)
@@ -2222,7 +2233,7 @@ int 1
},
)
ep.Ledger = ledger
- ledger.newApp(txn.Txn.Sender, 100, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
delta := testApp(t, source, ep)
require.Len(t, delta.GlobalDelta, 2)
@@ -2385,7 +2396,7 @@ int 1
},
)
ep.Ledger = ledger
- ledger.newApp(txn.Txn.Sender, 100, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
ledger.balances[txn.Txn.Receiver] = makeBalanceRecord(txn.Txn.Receiver, 1)
ledger.balances[txn.Txn.Receiver].locals[100] = make(basics.TealKeyValue)
@@ -2687,7 +2698,7 @@ func TestReturnTypes(t *testing.T) {
Clawback: txn.Txn.Receiver,
}
ledger.newAsset(txn.Txn.Sender, 1, params)
- ledger.newApp(txn.Txn.Sender, 1, makeSchemas(0, 0, 0, 0))
+ ledger.newApp(txn.Txn.Sender, 1, basics.AppParams{})
ledger.setTrackedCreatable(0, basics.CreatableLocator{Index: 1})
ledger.balances[txn.Txn.Receiver] = makeBalanceRecord(txn.Txn.Receiver, 1)
ledger.balances[txn.Txn.Receiver].locals[1] = make(basics.TealKeyValue)
@@ -2729,6 +2740,8 @@ func TestReturnTypes(t *testing.T) {
"gtxnsa": "gtxnsa ApplicationArgs 0",
"pushint": "pushint 7272",
"pushbytes": `pushbytes "jojogoodgorilla"`,
+ "app_params_get": "app_params_get AppGlobalNumUint",
+ "extract": "extract 0 2",
}
byName := OpsByName[LogicVersion]
@@ -2777,89 +2790,38 @@ func TestReturnTypes(t *testing.T) {
}
func TestRound(t *testing.T) {
- source := `global Round
-int 1
->=
-`
- ledger := makeTestLedger(
- map[basics.Address]uint64{},
- )
- ops, err := AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
-
- ep := defaultEvalParams(nil, nil)
- err = CheckStateful(ops.Program, ep)
- require.NoError(t, err)
- _, err = EvalStateful(ops.Program, ep)
- require.Error(t, err)
- require.Contains(t, err.Error(), "ledger not available")
-
- pass, err := Eval(ops.Program, ep)
- require.Error(t, err)
- require.Contains(t, err.Error(), "not allowed in current mode")
- require.False(t, pass)
-
- ep.Ledger = ledger
- pass, err = EvalStateful(ops.Program, ep)
- require.NoError(t, err)
- require.True(t, pass)
+ t.Parallel()
+ ep, _ := makeSampleEnv()
+ source := "global Round; int 1; >="
+ testApp(t, source, ep)
}
func TestLatestTimestamp(t *testing.T) {
- source := `global LatestTimestamp
-int 1
->=
-`
- ledger := makeTestLedger(
- map[basics.Address]uint64{},
- )
- ops, err := AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
-
- ep := defaultEvalParams(nil, nil)
- err = CheckStateful(ops.Program, ep)
- require.NoError(t, err)
- _, err = EvalStateful(ops.Program, ep)
- require.Error(t, err)
- require.Contains(t, err.Error(), "ledger not available")
-
- pass, err := Eval(ops.Program, ep)
- require.Error(t, err)
- require.Contains(t, err.Error(), "not allowed in current mode")
- require.False(t, pass)
-
- ep.Ledger = ledger
- pass, err = EvalStateful(ops.Program, ep)
- require.NoError(t, err)
- require.True(t, pass)
+ t.Parallel()
+ ep, _ := makeSampleEnv()
+ source := "global LatestTimestamp; int 1; >="
+ testApp(t, source, ep)
}
func TestCurrentApplicationID(t *testing.T) {
- source := `global CurrentApplicationID
-int 42
-==
-`
- ledger := makeTestLedger(
- map[basics.Address]uint64{},
- )
+ t.Parallel()
+ ep, ledger := makeSampleEnv()
ledger.appID = basics.AppIndex(42)
- ops, err := AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
+ source := "global CurrentApplicationID; int 42; =="
+ testApp(t, source, ep)
+}
- ep := defaultEvalParams(nil, nil)
- err = CheckStateful(ops.Program, ep)
- require.NoError(t, err)
- _, err = EvalStateful(ops.Program, ep)
- require.Error(t, err)
- require.Contains(t, err.Error(), "ledger not available")
+func TestAppLoop(t *testing.T) {
+ t.Parallel()
+ ep, _ := makeSampleEnv()
- pass, err := Eval(ops.Program, ep)
- require.Error(t, err)
- require.Contains(t, err.Error(), "not allowed in current mode")
- require.False(t, pass)
+ stateful := "global CurrentApplicationID; pop;"
- ep.Ledger = ledger
- pass, err = EvalStateful(ops.Program, ep)
- require.NoError(t, err)
- require.True(t, pass)
+ // Double until > 10. Should be 16
+ testApp(t, stateful+"int 1; loop: int 2; *; dup; int 10; <; bnz loop; int 16; ==", ep)
+
+ testApp(t, stateful+"int 1; loop: int 2; *; dup; int 10; <; bnz loop; int 16; ==", ep)
+
+ // Infinite loop because multiply by one instead of two
+ testApp(t, stateful+"int 1; loop:; int 1; *; dup; int 10; <; bnz loop; int 16; ==", ep, "dynamic cost")
}
diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go
index 8a37d1eb0..c1b291b77 100644
--- a/data/transactions/logic/eval_test.go
+++ b/data/transactions/logic/eval_test.go
@@ -910,6 +910,10 @@ const globalV4TestProgram = globalV3TestProgram + `
// No new globals in v4
`
+const globalV5TestProgram = globalV4TestProgram + `
+// No new globals in v5
+`
+
func TestGlobal(t *testing.T) {
t.Parallel()
type desc struct {
@@ -933,6 +937,10 @@ func TestGlobal(t *testing.T) {
CreatorAddress, globalV4TestProgram,
EvalStateful, CheckStateful,
},
+ 5: {
+ CreatorAddress, globalV5TestProgram,
+ EvalStateful, CheckStateful,
+ },
}
ledger := makeTestLedger(nil)
ledger.appID = 42
@@ -940,6 +948,8 @@ func TestGlobal(t *testing.T) {
require.NoError(t, err)
ledger.creatorAddr = addr
for v := uint64(0); v <= AssemblerMaxVersion; v++ {
+ _, ok := tests[v]
+ require.True(t, ok)
t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) {
last := tests[v].lastField
testProgram := tests[v].program
@@ -2019,6 +2029,74 @@ substring 2 99
len`, 2)
}
+func TestExtractOp(t *testing.T) {
+ t.Parallel()
+ testAccepts(t, "byte 0x123456789abc; extract 1 2; byte 0x3456; ==", 5)
+ testAccepts(t, "byte 0x123456789abc; extract 0 6; byte 0x123456789abc; ==", 5)
+ testAccepts(t, "byte 0x123456789abc; extract 3 0; byte 0x789abc; ==", 5)
+ testAccepts(t, "byte 0x123456789abc; extract 6 0; len; int 0; ==", 5)
+ testAccepts(t, "byte 0x123456789abcaa; extract 0 6; byte 0x123456789abcaa; !=", 5)
+
+ testAccepts(t, "byte 0x123456789abc; int 5; int 1; extract3; byte 0xbc; ==", 5)
+
+ testAccepts(t, "byte 0x123456789abcdef0; int 1; extract16bits; int 0x3456; ==", 5)
+ testAccepts(t, "byte 0x123456789abcdef0; int 1; extract32bits; int 0x3456789a; ==", 5)
+ testAccepts(t, "byte 0x123456789abcdef0; int 0; extract64bits; int 0x123456789abcdef0; ==", 5)
+ testAccepts(t, "byte 0x123456789abcdef0; int 0; extract64bits; int 0x123456789abcdef; !=", 5)
+}
+
+func TestExtractFlop(t *testing.T) {
+ t.Parallel()
+ // fails in compiler
+ testProg(t, `byte 0xf000000000000000
+ extract
+ len`, 5, expect{2, "extract expects 2 immediate arguments"})
+
+ testProg(t, `byte 0xf000000000000000
+ extract 1
+ len`, 5, expect{2, "extract expects 2 immediate arguments"})
+
+ // fails at runtime
+ err := testPanics(t, `byte 0xf000000000000000
+ extract 1 8
+ len`, 5)
+ require.Contains(t, err.Error(), "extract range beyond length of string")
+
+ err = testPanics(t, `byte 0xf000000000000000
+ extract 9 0
+ len`, 5)
+ require.Contains(t, err.Error(), "extract range beyond length of string")
+
+ err = testPanics(t, `byte 0xf000000000000000
+ int 4
+ int 0xFFFFFFFFFFFFFFFE
+ extract3
+ len`, 5)
+ require.Contains(t, err.Error(), "extract range beyond length of string")
+
+ err = testPanics(t, `byte 0xf000000000000000
+ int 100
+ int 2
+ extract3
+ len`, 5)
+ require.Contains(t, err.Error(), "extract range beyond length of string")
+
+ err = testPanics(t, `byte 0xf000000000000000
+ int 55
+ extract16bits`, 5)
+ require.Contains(t, err.Error(), "extract range beyond length of string")
+
+ err = testPanics(t, `byte 0xf000000000000000
+ int 9
+ extract32bits`, 5)
+ require.Contains(t, err.Error(), "extract range beyond length of string")
+
+ err = testPanics(t, `byte 0xf000000000000000
+ int 1
+ extract64bits`, 5)
+ require.Contains(t, err.Error(), "extract range beyond length of string")
+}
+
func TestLoadStore(t *testing.T) {
t.Parallel()
testAccepts(t, `int 37
@@ -3258,6 +3336,7 @@ func benchmarkOperation(b *testing.B, prefix string, operation string, suffix st
source := prefix + ";" + strings.Repeat(operation+";", 2000) + ";" + suffix
source = strings.ReplaceAll(source, ";", "\n")
ops, err := AssembleStringWithVersion(source, AssemblerMaxVersion)
+ require.NoError(b, err)
err = Check(ops.Program, defaultEvalParams(nil, nil))
require.NoError(b, err)
evalLoop(b, runs, ops.Program)
@@ -3964,6 +4043,7 @@ func obfuscate(program string) string {
type evalTester func(pass bool, err error) bool
func testEvaluation(t *testing.T, program string, introduced uint64, tester evalTester) error {
+ t.Helper()
var outer error
for v := uint64(1); v <= AssemblerMaxVersion; v++ {
t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) {
@@ -4094,6 +4174,14 @@ func TestBytes(t *testing.T) {
testAccepts(t, `byte "jo"; byte "hn"; concat; dup; int 2; int 105; setbyte; pop; byte "john"; ==`, 3)
}
+func TestMethod(t *testing.T) {
+ t.Parallel()
+ // Although 'method' is new around the time of v5, it is a
+ // pseudo-op, so it's ok to use it earlier, as it compiles to
+ // existing opcodes.
+ testAccepts(t, "method \"add(uint64,uint64)uint128\"; byte 0x8aa3b61f; ==", 1)
+}
+
func TestSwap(t *testing.T) {
t.Parallel()
testAccepts(t, "int 1; byte 0x1234; swap; int 1; ==; assert; byte 0x1234; ==", 3)
@@ -4113,7 +4201,7 @@ func TestSelect(t *testing.T) {
func TestDig(t *testing.T) {
t.Parallel()
testAccepts(t, "int 3; int 2; int 1; dig 1; int 2; ==; return", 3)
- testPanics(t, "int 3; int 2; int 1; dig 11; int 2; ==; return", 3)
+ testPanics(t, obfuscate("int 3; int 2; int 1; dig 11; int 2; ==; return"), 3)
}
func TestPush(t *testing.T) {
diff --git a/data/transactions/logic/fields.go b/data/transactions/logic/fields.go
index 3d27ca241..9bc37547c 100644
--- a/data/transactions/logic/fields.go
+++ b/data/transactions/logic/fields.go
@@ -23,7 +23,7 @@ import (
"github.com/algorand/go-algorand/protocol"
)
-//go:generate stringer -type=TxnField,GlobalField,AssetParamsField,AssetHoldingField,OnCompletionConstType -output=fields_string.go
+//go:generate stringer -type=TxnField,GlobalField,AssetParamsField,AppParamsField,AssetHoldingField,OnCompletionConstType -output=fields_string.go
// TxnField is an enum type for `txn` and `gtxn`
type TxnField int
@@ -236,7 +236,7 @@ var txnFieldSpecs = []txnFieldSpec{
// TxnaFieldNames are arguments to the 'txna' opcode
// It is a subset of txn transaction fields so initialized here in-place
-var TxnaFieldNames = []string{ApplicationArgs.String(), Accounts.String()}
+var TxnaFieldNames = []string{ApplicationArgs.String(), Accounts.String(), Assets.String(), Applications.String()}
// TxnaFieldTypes is StackBytes or StackUint64 parallel to TxnFieldNames
var TxnaFieldTypes = []StackType{
@@ -425,10 +425,14 @@ const (
AssetFreeze
// AssetClawback AssetParams.Clawback
AssetClawback
+
+ // AssetCreator is not *in* the Params, but it is uniquely determined.
+ AssetCreator
+
invalidAssetParamsField
)
-// AssetParamsFieldNames are arguments to the 'asset_holding_get' opcode
+// AssetParamsFieldNames are arguments to the 'asset_params_get' opcode
var AssetParamsFieldNames []string
type assetParamsFieldType struct {
@@ -448,6 +452,7 @@ var assetParamsFieldTypeList = []assetParamsFieldType{
{AssetReserve, StackBytes},
{AssetFreeze, StackBytes},
{AssetClawback, StackBytes},
+ {AssetCreator, StackBytes},
}
// AssetParamsFieldTypes is StackUint64 StackBytes in parallel with AssetParamsFieldNames
@@ -455,6 +460,55 @@ var AssetParamsFieldTypes []StackType
var assetParamsFields map[string]uint64
+// AppParamsField is an enum for `app_params_get` opcode
+type AppParamsField int
+
+const (
+ // AppApprovalProgram AppParams.ApprovalProgram
+ AppApprovalProgram AppParamsField = iota
+ // AppClearStateProgram AppParams.ClearStateProgram
+ AppClearStateProgram
+ // AppGlobalNumUint AppParams.StateSchemas.GlobalStateSchema.NumUint
+ AppGlobalNumUint
+ // AppGlobalNumByteSlice AppParams.StateSchemas.GlobalStateSchema.NumByteSlice
+ AppGlobalNumByteSlice
+ // AppLocalNumUint AppParams.StateSchemas.LocalStateSchema.NumUint
+ AppLocalNumUint
+ // AppLocalNumByteSlice AppParams.StateSchemas.LocalStateSchema.NumByteSlice
+ AppLocalNumByteSlice
+ // AppExtraProgramPages AppParams.ExtraProgramPages
+ AppExtraProgramPages
+
+ // AppCreator is not *in* the Params, but it is uniquely determined.
+ AppCreator
+
+ invalidAppParamsField
+)
+
+// AppParamsFieldNames are arguments to the 'app_params_get' opcode
+var AppParamsFieldNames []string
+
+type appParamsFieldType struct {
+ field AppParamsField
+ ftype StackType
+}
+
+var appParamsFieldTypeList = []appParamsFieldType{
+ {AppApprovalProgram, StackBytes},
+ {AppClearStateProgram, StackBytes},
+ {AppGlobalNumUint, StackUint64},
+ {AppGlobalNumByteSlice, StackUint64},
+ {AppLocalNumUint, StackUint64},
+ {AppLocalNumByteSlice, StackUint64},
+ {AppExtraProgramPages, StackUint64},
+ {AppCreator, StackBytes},
+}
+
+// AppParamsFieldTypes is StackUint64 StackBytes in parallel with AppParamsFieldNames
+var AppParamsFieldTypes []StackType
+
+var appParamsFields map[string]uint64
+
func init() {
TxnFieldNames = make([]string, int(invalidTxnField))
for fi := Sender; fi < invalidTxnField; fi++ {
@@ -515,6 +569,19 @@ func init() {
assetParamsFields[fn] = uint64(i)
}
+ AppParamsFieldNames = make([]string, int(invalidAppParamsField))
+ for i := AppApprovalProgram; i < invalidAppParamsField; i++ {
+ AppParamsFieldNames[int(i)] = i.String()
+ }
+ AppParamsFieldTypes = make([]StackType, len(AppParamsFieldNames))
+ for _, ft := range appParamsFieldTypeList {
+ AppParamsFieldTypes[int(ft.field)] = ft.ftype
+ }
+ appParamsFields = make(map[string]uint64)
+ for i, fn := range AppParamsFieldNames {
+ appParamsFields[fn] = uint64(i)
+ }
+
txnTypeIndexes = make(map[string]uint64, len(TxnTypeNames))
for i, tt := range TxnTypeNames {
txnTypeIndexes[tt] = uint64(i)
diff --git a/data/transactions/logic/fields_string.go b/data/transactions/logic/fields_string.go
index e56dd872f..c3fa22576 100644
--- a/data/transactions/logic/fields_string.go
+++ b/data/transactions/logic/fields_string.go
@@ -1,4 +1,4 @@
-// Code generated by "stringer -type=TxnField,GlobalField,AssetParamsField,AssetHoldingField,OnCompletionConstType -output=fields_string.go"; DO NOT EDIT.
+// Code generated by "stringer -type=TxnField,GlobalField,AssetParamsField,AppParamsField,AssetHoldingField,OnCompletionConstType -output=fields_string.go"; DO NOT EDIT.
package logic
@@ -120,12 +120,13 @@ func _() {
_ = x[AssetReserve-8]
_ = x[AssetFreeze-9]
_ = x[AssetClawback-10]
- _ = x[invalidAssetParamsField-11]
+ _ = x[AssetCreator-11]
+ _ = x[invalidAssetParamsField-12]
}
-const _AssetParamsField_name = "AssetTotalAssetDecimalsAssetDefaultFrozenAssetUnitNameAssetNameAssetURLAssetMetadataHashAssetManagerAssetReserveAssetFreezeAssetClawbackinvalidAssetParamsField"
+const _AssetParamsField_name = "AssetTotalAssetDecimalsAssetDefaultFrozenAssetUnitNameAssetNameAssetURLAssetMetadataHashAssetManagerAssetReserveAssetFreezeAssetClawbackAssetCreatorinvalidAssetParamsField"
-var _AssetParamsField_index = [...]uint8{0, 10, 23, 41, 54, 63, 71, 88, 100, 112, 123, 136, 159}
+var _AssetParamsField_index = [...]uint8{0, 10, 23, 41, 54, 63, 71, 88, 100, 112, 123, 136, 148, 171}
func (i AssetParamsField) String() string {
if i < 0 || i >= AssetParamsField(len(_AssetParamsField_index)-1) {
@@ -137,6 +138,31 @@ func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
+ _ = x[AppApprovalProgram-0]
+ _ = x[AppClearStateProgram-1]
+ _ = x[AppGlobalNumUint-2]
+ _ = x[AppGlobalNumByteSlice-3]
+ _ = x[AppLocalNumUint-4]
+ _ = x[AppLocalNumByteSlice-5]
+ _ = x[AppExtraProgramPages-6]
+ _ = x[AppCreator-7]
+ _ = x[invalidAppParamsField-8]
+}
+
+const _AppParamsField_name = "AppApprovalProgramAppClearStateProgramAppGlobalNumUintAppGlobalNumByteSliceAppLocalNumUintAppLocalNumByteSliceAppExtraProgramPagesAppCreatorinvalidAppParamsField"
+
+var _AppParamsField_index = [...]uint8{0, 18, 38, 54, 75, 90, 110, 130, 140, 161}
+
+func (i AppParamsField) String() string {
+ if i < 0 || i >= AppParamsField(len(_AppParamsField_index)-1) {
+ return "AppParamsField(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _AppParamsField_name[_AppParamsField_index[i]:_AppParamsField_index[i+1]]
+}
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
_ = x[AssetBalance-0]
_ = x[AssetFrozen-1]
_ = x[invalidAssetHoldingField-2]
diff --git a/data/transactions/logic/fields_test.go b/data/transactions/logic/fields_test.go
new file mode 100644
index 000000000..bab2418a6
--- /dev/null
+++ b/data/transactions/logic/fields_test.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 logic
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestArrayFields(t *testing.T) {
+ require.Equal(t, len(TxnaFieldNames), len(TxnaFieldTypes))
+ require.Equal(t, len(txnaFieldSpecByField), len(TxnaFieldTypes))
+}
diff --git a/data/transactions/logic/opcodes.go b/data/transactions/logic/opcodes.go
index bd06eb374..50698e7b6 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 = 4
+const LogicVersion = 5
// rekeyingEnabledVersion is the version of TEAL where RekeyTo functionality
// was enabled. This is important to remember so that old TEAL accounts cannot
@@ -49,27 +49,32 @@ type opDetails struct {
Size int
checkFunc opCheckFunc
Immediates []immediate
+ typeFunc opTypeFunc
}
-var opDefault = opDetails{1, 1, nil, nil}
-var opBranch = opDetails{1, 3, checkBranch, []immediate{{"target", immLabel}}}
+var opDefault = opDetails{1, 1, nil, nil, nil}
+var opBranch = opDetails{1, 3, checkBranch, []immediate{{"target", immLabel}}, nil}
func costly(cost int) opDetails {
- return opDetails{cost, 1, nil, nil}
+ return opDetails{cost, 1, nil, nil, nil}
}
-func immediates(name string, rest ...string) opDetails {
- num := 1 + len(rest)
- immediates := make([]immediate, num)
- immediates[0] = immediate{name, immByte}
- for i, n := range rest {
- immediates[i+1] = immediate{n, immByte}
+func immediates(names ...string) opDetails {
+ immediates := make([]immediate, len(names))
+ for i, name := range names {
+ immediates[i] = immediate{name, immByte}
}
- return opDetails{1, 1 + num, nil, immediates}
+ return opDetails{1, 1 + len(immediates), nil, immediates, nil}
+}
+
+func stacky(typer opTypeFunc, imms ...string) opDetails {
+ d := immediates(imms...)
+ d.typeFunc = typer
+ return d
}
func varies(checker opCheckFunc, name string, kind immKind) opDetails {
- return opDetails{1, 0, checker, []immediate{{name, kind}}}
+ return opDetails{1, 0, checker, []immediate{{name, kind}}, nil}
}
// immType describes the immediate arguments to an opcode
@@ -211,8 +216,8 @@ var OpSpecs = []OpSpec{
{0x4a, "dup2", opDup2, asmDefault, disDefault, twoAny, twoAny.plus(twoAny), 2, modeAny, opDefault},
// There must be at least one thing on the stack for dig, but
// it would be nice if we did better checking than that.
- {0x4b, "dig", opDig, asmDefault, disDefault, oneAny, twoAny, 3, modeAny, immediates("n")},
- {0x4c, "swap", opSwap, asmDefault, disDefault, twoAny, twoAny, 3, modeAny, opDefault},
+ {0x4b, "dig", opDig, asmDefault, disDefault, oneAny, twoAny, 3, modeAny, stacky(typeDig, "n")},
+ {0x4c, "swap", opSwap, asmDefault, disDefault, twoAny, twoAny, 3, modeAny, stacky(typeSwap)},
{0x4d, "select", opSelect, asmDefault, disDefault, twoAny.plus(oneInt), oneAny, 3, modeAny, opDefault},
{0x50, "concat", opConcat, asmDefault, disDefault, twoBytes, oneBytes, 2, modeAny, opDefault},
@@ -222,6 +227,11 @@ var OpSpecs = []OpSpec{
{0x54, "setbit", opSetBit, asmDefault, disDefault, anyIntInt, oneAny, 3, modeAny, opDefault},
{0x55, "getbyte", opGetByte, asmDefault, disDefault, byteInt, oneInt, 3, modeAny, opDefault},
{0x56, "setbyte", opSetByte, asmDefault, disDefault, byteIntInt, oneBytes, 3, modeAny, opDefault},
+ {0x57, "extract", opExtract, asmDefault, disDefault, oneBytes, oneBytes, 5, modeAny, immediates("s", "l")},
+ {0x58, "extract3", opExtract3, asmDefault, disDefault, byteIntInt, oneBytes, 5, modeAny, opDefault},
+ {0x59, "extract16bits", opExtract16Bits, asmDefault, disDefault, byteInt, oneInt, 5, modeAny, opDefault},
+ {0x5a, "extract32bits", opExtract32Bits, asmDefault, disDefault, byteInt, oneInt, 5, modeAny, opDefault},
+ {0x5b, "extract64bits", opExtract64Bits, asmDefault, disDefault, byteInt, oneInt, 5, modeAny, opDefault},
{0x60, "balance", opBalance, asmDefault, disDefault, oneInt, oneInt, 2, runModeApplication, opDefault},
{0x60, "balance", opBalance, asmDefault, disDefault, oneAny, oneInt, directRefEnabledVersion, runModeApplication, opDefault},
@@ -243,6 +253,7 @@ var OpSpecs = []OpSpec{
{0x70, "asset_holding_get", opAssetHoldingGet, assembleAssetHolding, disAssetHolding, twoInts, oneAny.plus(oneInt), 2, runModeApplication, immediates("i")},
{0x70, "asset_holding_get", opAssetHoldingGet, assembleAssetHolding, disAssetHolding, oneAny.plus(oneInt), oneAny.plus(oneInt), directRefEnabledVersion, runModeApplication, immediates("i")},
{0x71, "asset_params_get", opAssetParamsGet, assembleAssetParams, disAssetParams, oneInt, oneAny.plus(oneInt), 2, runModeApplication, immediates("i")},
+ {0x72, "app_params_get", opAppParamsGet, assembleAppParams, disAppParams, oneInt, oneAny.plus(oneInt), 5, runModeApplication, immediates("i")},
{0x78, "min_balance", opMinBalance, asmDefault, disDefault, oneInt, oneInt, 3, runModeApplication, opDefault},
{0x78, "min_balance", opMinBalance, asmDefault, disDefault, oneAny, oneInt, directRefEnabledVersion, runModeApplication, opDefault},
diff --git a/data/transactions/verify/txn.go b/data/transactions/verify/txn.go
index 6009f200c..cab9a98e3 100644
--- a/data/transactions/verify/txn.go
+++ b/data/transactions/verify/txn.go
@@ -46,7 +46,7 @@ const txnPerWorksetThreshold = 32
// When the PaysetGroups is generating worksets, it enqueues up to concurrentWorksets entries to the execution pool. This serves several
// purposes :
-// - if the verification task need to be aborted, there are only concurrentWorksets entries that are currently redundent on the execution pool queue.
+// - if the verification task need to be aborted, there are only concurrentWorksets entries that are currently redundant on the execution pool queue.
// - that number of concurrent tasks would not get beyond the capacity of the execution pool back buffer.
// - if we were to "redundently" execute all these during context cancelation, we would spent at most 2ms * 16 = 32ms time.
// - it allows us to linearly scan the input, and process elements only once we're going to queue them into the pool.
@@ -137,7 +137,7 @@ func TxnGroup(stxs []transactions.SignedTxn, contextHdr bookkeeping.BlockHeader,
return
}
// feesPaid may have saturated. That's ok. Since we know
- // feeNeeded did not overlfow, simple comparision tells us
+ // feeNeeded did not overlfow, simple comparison tells us
// feesPaid was enough.
if feesPaid < feeNeeded {
err = fmt.Errorf("txgroup had %d in fees, which is less than the minimum %d * %d",
diff --git a/data/transactions/verify/verifiedTxnCache.go b/data/transactions/verify/verifiedTxnCache.go
index 033f56fb2..44a230010 100644
--- a/data/transactions/verify/verifiedTxnCache.go
+++ b/data/transactions/verify/verifiedTxnCache.go
@@ -29,12 +29,12 @@ import (
const entriesPerBucket = 8179 // the default bucket size; a prime number could promote a lower hash collisions in case the hash function isn't perfect.
const maxPinnedEntries = 500000
-// VerifiedTxnCacheError helps to identifiy the errors of a cache error and diffrenciate these from a general verification errors.
+// VerifiedTxnCacheError helps to identify the errors of a cache error and diffrenciate these from a general verification errors.
type VerifiedTxnCacheError struct {
inner error
}
-// Unwrap provides accesss to the underlying error
+// Unwrap provides access to the underlying error
func (e *VerifiedTxnCacheError) Unwrap() error {
return e.inner
}
diff --git a/data/txHandler.go b/data/txHandler.go
index b0ec96485..fa8bf250b 100644
--- a/data/txHandler.go
+++ b/data/txHandler.go
@@ -257,7 +257,7 @@ func (handler *TxHandler) processIncomingTxn(rawmsg network.IncomingMessage) net
return network.OutgoingMessage{Action: network.Ignore}
}
-// checkAlreadyCommitted test to see if the given transaction ( in the txBacklogMsg ) was already commited, and
+// checkAlreadyCommitted test to see if the given transaction ( in the txBacklogMsg ) was already committed, and
// whether it would qualify as a candidate for the transaction pool.
//
// Note that this also checks the consistency of the transaction's group hash,
@@ -340,7 +340,7 @@ type solicitedTxHandler struct {
func (handler *solicitedTxHandler) Handle(txgroup []transactions.SignedTxn) error {
outmsg, _ := handler.txHandler.processDecoded(txgroup)
if outmsg.Action == network.Disconnect {
- return fmt.Errorf("invlid transaction")
+ return fmt.Errorf("invalid transaction")
}
return nil
}
diff --git a/debug/logfilter/main_test.go b/debug/logfilter/main_test.go
index 2697a88c0..963e28c34 100644
--- a/debug/logfilter/main_test.go
+++ b/debug/logfilter/main_test.go
@@ -29,7 +29,7 @@ import (
)
func TestLogFilterExamples(t *testing.T) {
- // iterate on all the example files in the local directroy.
+ // iterate on all the example files in the local directory.
exampleFiles := []string{}
filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
if err != nil {
diff --git a/docker/build/Dockerfile-deploy b/docker/build/Dockerfile-deploy
index dbc0c78bd..d8c4a38ee 100644
--- a/docker/build/Dockerfile-deploy
+++ b/docker/build/Dockerfile-deploy
@@ -1,4 +1,4 @@
-FROM ubuntu:18.04
+FROM --platform=linux/amd64 ubuntu:18.04
ARG GOLANG_VERSION
RUN apt-get update && apt-get install -y git libboost-all-dev wget sqlite3 autoconf jq bsdmainutils shellcheck
diff --git a/docker/releases/build_releases.sh b/docker/releases/build_releases.sh
index 33967d5fc..01d5f5372 100755
--- a/docker/releases/build_releases.sh
+++ b/docker/releases/build_releases.sh
@@ -27,9 +27,13 @@ DEPLOY=true
IMAGE_NAME=stable
NETWORK=mainnet
TAGNAME=latest
+CACHED=false
while [ "$1" != "" ]; do
case "$1" in
+ --cached)
+ CACHED=true
+ ;;
--name)
shift
IMAGE_NAME="${1-stable}"
@@ -53,50 +57,65 @@ while [ "$1" != "" ]; do
shift
done
-if [[ ! "$NETWORK" =~ ^mainnet$|^testnet$|^betanet$ ]]
-then
+# Set IMAGE_NAME to docker image name
+case $NETWORK in
+ mainnet)
+ IMAGE_NAME=stable
+ ;;
+ testnet)
+ IMAGE_NAME=testnet
+ ;;
+ betanet)
+ IMAGE_NAME=betanet
+ CHANNEL=beta
+ ;;
+ *)
echo "$RED_FG[$0]$END_FG_COLOR Network values must be either \`mainnet\`, \`testnet\` or \`betanet\`."
exit 1
-elif [ "$NETWORK" != "mainnet" ]
-then
- if [ "$NETWORK" == "betanet" ]
- then
- CHANNEL=beta
- fi
+ ;;
+esac
- IMAGE_NAME="$NETWORK"
- NETWORK="-g $NETWORK"
-fi
-
-build_image () {
- IFS='' read -r -d '' DOCKERFILE <<EOF
- FROM ubuntu
+IFS='' read -r -d '' DOCKERFILE <<EOF
+FROM ubuntu
- RUN apt-get update && apt-get install -y ca-certificates curl --no-install-recommends && \
- curl --silent -L https://github.com/algorand/go-algorand-doc/blob/master/downloads/installers/linux_amd64/install_master_linux-amd64.tar.gz?raw=true | tar xzf - && \
- ./update.sh -c $CHANNEL -n -p ~/node -d ~/node/data -i $NETWORK
- WORKDIR /root/node
+RUN apt-get update && apt-get install -y ca-certificates curl --no-install-recommends && \
+ curl --silent -L https://github.com/algorand/go-algorand-doc/blob/master/downloads/installers/linux_amd64/install_master_linux-amd64.tar.gz?raw=true | tar xzf - && \
+ ./update.sh -c $CHANNEL -n -p ~/node -d ~/node/data -i -g $NETWORK
+WORKDIR /root/node
EOF
- if ! echo "$DOCKERFILE" | docker build -t "algorand/$IMAGE_NAME:$TAGNAME" -
- then
- echo -e "\n$RED_FG[$0]$END_FG_COLOR The algorand/$IMAGE_NAME:$TAGNAME image could not be built."
- exit 1
- fi
-}
+# By default, we don't want to cache our docker build. However, we might want to
+# if running building and tagging back to back, like with mainnet and testnet.
+if ! $CACHED
+then
+ CACHED_ARG='--no-cache'
+fi
-build_image
+if ! echo "$DOCKERFILE" | docker build $CACHED_ARG -t "algorand/$IMAGE_NAME:$TAGNAME" -
+then
+ echo -e "\n$RED_FG[$0]$END_FG_COLOR The algorand/$IMAGE_NAME:$TAGNAME image could not be built."
+ exit 1
+fi
if $DEPLOY
then
if ! docker push "algorand/$IMAGE_NAME:$TAGNAME"
then
- echo -e "\n$RED_FG[$0]$END_FG_COLOR \`docker push\` failed."
+ echo -e "\n$RED_FG[$0]$END_FG_COLOR \`docker push\` of $IMAGE_NAME:$TAGNAME failed."
exit 1
fi
+ if [ "$TAGNAME" != 'latest' ]
+ then
+ # We built a new tag, so also tag this as latest.
+ docker tag algorand/$IMAGE_NAME:$TAGNAME algorand/$IMAGE_NAME:latest
+ if ! docker push algorand/$IMAGE_NAME:latest
+ then
+ echo -e "\n$RED_FG[$0]$END_FG_COLOR \`docker push\` of $IMAGE_NAME:latest failed."
+ fi
+ fi
+
echo -e "\n$GREEN_FG[$0]$END_FG_COLOR Successfully published to docker hub."
fi
-echo "$GREEN_FG[$0]$END_FG_COLOR Build completed with no failures."
-
+echo -e "\n$GREEN_FG[$0]$END_FG_COLOR Build completed with no failures."
diff --git a/gen/generate.go b/gen/generate.go
index 4c14f61f9..08c2e373c 100644
--- a/gen/generate.go
+++ b/gen/generate.go
@@ -149,11 +149,11 @@ func GenerateGenesisFiles(genesisData GenesisData, consensus config.ConsensusPro
return fmt.Errorf("couldn't make output directory '%s': %v", outDir, err.Error())
}
- return generateGenesisFiles(outDir, proto, consensusParams, genesisData.NetworkName, genesisData.VersionModifier, allocation, genesisData.FirstPartKeyRound, genesisData.LastPartKeyRound, genesisData.PartKeyDilution, genesisData.FeeSink, genesisData.RewardsPool, genesisData.Comment, verboseOut)
+ return generateGenesisFiles(outDir, proto, consensusParams, genesisData.NetworkName, genesisData.VersionModifier, allocation, genesisData.FirstPartKeyRound, genesisData.LastPartKeyRound, genesisData.PartKeyDilution, genesisData.FeeSink, genesisData.RewardsPool, genesisData.Comment, genesisData.DevMode, verboseOut)
}
func generateGenesisFiles(outDir string, protoVersion protocol.ConsensusVersion, protoParams config.ConsensusParams, netName string, schemaVersionModifier string,
- allocation []genesisAllocation, firstWalletValid uint64, lastWalletValid uint64, partKeyDilution uint64, feeSink, rewardsPool basics.Address, comment string, verboseOut io.Writer) (err error) {
+ allocation []genesisAllocation, firstWalletValid uint64, lastWalletValid uint64, partKeyDilution uint64, feeSink, rewardsPool basics.Address, comment string, devmode bool, verboseOut io.Writer) (err error) {
genesisAddrs := make(map[string]basics.Address)
records := make(map[string]basics.AccountData)
@@ -352,6 +352,7 @@ func generateGenesisFiles(outDir string, protoVersion protocol.ConsensusVersion,
FeeSink: feeSink.String(),
RewardsPool: rewardsPool.String(),
Comment: comment,
+ DevMode: devmode,
}
for _, wallet := range allocation {
diff --git a/gen/walletData.go b/gen/walletData.go
index 798de92cb..15cfd1f1d 100644
--- a/gen/walletData.go
+++ b/gen/walletData.go
@@ -49,6 +49,7 @@ type GenesisData struct {
Wallets []WalletData
FeeSink basics.Address
RewardsPool basics.Address
+ DevMode bool
Comment string
}
diff --git a/installer/external/node_exporter-stable-darwin-arm64.tar.gz b/installer/external/node_exporter-stable-darwin-arm64.tar.gz
new file mode 100644
index 000000000..56d41a144
--- /dev/null
+++ b/installer/external/node_exporter-stable-darwin-arm64.tar.gz
Binary files differ
diff --git a/installer/rpm/algorand/0dnf-algorand-hourly.cron b/installer/rpm/algorand/0dnf-algorand-hourly.cron
new file mode 100755
index 000000000..53287c8e3
--- /dev/null
+++ b/installer/rpm/algorand/0dnf-algorand-hourly.cron
@@ -0,0 +1,2 @@
+#!/bin/bash
+exec /usr/bin/dnf-automatic /etc/dnf/dnf-cron-algorand.conf
diff --git a/installer/rpm/algorand/0yum-algorand-hourly.cron b/installer/rpm/algorand/0yum-algorand-hourly.cron
deleted file mode 100755
index 64cbaa816..000000000
--- a/installer/rpm/algorand/0yum-algorand-hourly.cron
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-exec /usr/sbin/yum-cron /etc/yum/yum-cron-algorand.conf
diff --git a/installer/rpm/algorand/algorand.spec b/installer/rpm/algorand/algorand.spec
index b45301bd1..c7cd519bb 100644
--- a/installer/rpm/algorand/algorand.spec
+++ b/installer/rpm/algorand/algorand.spec
@@ -4,7 +4,8 @@ Release: 1
Summary: Algorand node software
URL: https://www.algorand.com
License: AGPL-3+
-Requires: yum-cron
+Requires: dnf-automatic
+
Requires: systemd
Requires(pre): shadow-utils
@@ -42,16 +43,19 @@ install -m 644 ${REPO_DIR}/installer/algorand.service %{buildroot}/lib/systemd/s
install -m 644 ${REPO_DIR}/installer/algorand@.service %{buildroot}/lib/systemd/system/algorand@.service
mkdir -p %{buildroot}/etc/cron.hourly
-install -m 755 ${REPO_DIR}/installer/rpm/algorand/0yum-algorand-hourly.cron %{buildroot}/etc/cron.hourly/0yum-algorand-hourly.cron
+install -m 755 ${REPO_DIR}/installer/rpm/algorand/0dnf-algorand-hourly.cron %{buildroot}/etc/cron.hourly/0dnf-algorand-hourly.cron
+
+
+mkdir -p %{buildroot}/etc/dnf
+install -m 644 ${REPO_DIR}/installer/rpm/algorand/dnf-cron-algorand.conf %{buildroot}/etc/dnf/dnf-cron-algorand.conf
-mkdir -p %{buildroot}/etc/yum
-install -m 644 ${REPO_DIR}/installer/rpm/algorand/yum-cron-algorand.conf %{buildroot}/etc/yum/yum-cron-algorand.conf
mkdir -p %{buildroot}/etc/pki/rpm-gpg
install -m 644 ${REPO_DIR}/installer/rpm/RPM-GPG-KEY-Algorand %{buildroot}/etc/pki/rpm-gpg/RPM-GPG-KEY-Algorand
-mkdir -p %{buildroot}/usr/lib/algorand/yum.repos.d
-install -m 644 ${REPO_DIR}/installer/rpm/algorand/algorand.repo %{buildroot}/usr/lib/algorand/yum.repos.d/algorand.repo
+mkdir -p %{buildroot}/usr/lib/algorand/dnf.repos.d
+install -m 644 ${REPO_DIR}/installer/rpm/algorand/algorand.repo %{buildroot}/usr/lib/algorand/dnf.repos.d/algorand.repo
+
mkdir -p %{buildroot}/var/lib/algorand/genesis
if [ "%{RELEASE_GENESIS_PROCESS}" != "x" ]; then
@@ -88,10 +92,11 @@ fi
%endif
/lib/systemd/system/algorand.service
/lib/systemd/system/algorand@.service
-%config(noreplace) /etc/cron.hourly/0yum-algorand-hourly.cron
-%config(noreplace) /etc/yum/yum-cron-algorand.conf
+%config(noreplace) /etc/cron.hourly/0dnf-algorand-hourly.cron
+%config(noreplace) /etc/dnf/dnf-cron-algorand.conf
+
/etc/pki/rpm-gpg/RPM-GPG-KEY-Algorand
-/usr/lib/algorand/yum.repos.d/algorand.repo
+/usr/lib/algorand/dnf.repos.d/algorand.repo
%changelog
diff --git a/installer/rpm/algorand/yum-cron-algorand.conf b/installer/rpm/algorand/dnf-cron-algorand.conf
index b35acbeaf..53160c501 100644
--- a/installer/rpm/algorand/yum-cron-algorand.conf
+++ b/installer/rpm/algorand/dnf-cron-algorand.conf
@@ -72,7 +72,7 @@ reposdir = /usr/lib/algorand/yum.repos.d
# -4: critical
# -3: critical+errors
# -2: critical+errors+warnings (default)
-debuglevel = -2
+debuglevel = 2
# skip_broken = True
mdpolicy = group:main
diff --git a/ledger/accountdb.go b/ledger/accountdb.go
index 0dbb6509c..1a8b6f973 100644
--- a/ledger/accountdb.go
+++ b/ledger/accountdb.go
@@ -137,7 +137,7 @@ type persistedAccountData struct {
round basics.Round
}
-// compactAccountDeltas and accountDelta is an extention to ledgercore.AccountDeltas that is being used by the commitRound function for counting the
+// compactAccountDeltas and accountDelta is an extension to ledgercore.AccountDeltas that is being used by the commitRound function for counting the
// number of changes we've made per account. The ndeltas is used exclusively for consistency checking - making sure that
// all the pending changes were written and that there are no outstanding writes missing.
type compactAccountDeltas struct {
@@ -274,7 +274,7 @@ func (a *compactAccountDeltas) accountsLoadOld(tx *sql.Tx) (err error) {
}
a.updateOld(idx, *persistedAcctData)
} else {
- // to retain backward compatability, we will treat this condition as if we don't have the account.
+ // to retain backward compatibility, we will treat this condition as if we don't have the account.
a.updateOld(idx, persistedAccountData{addr: addr, rowid: rowid.Int64})
}
case sql.ErrNoRows:
@@ -1526,7 +1526,7 @@ type accountAddressHash struct {
}
// Next returns an array containing the account address and hash
-// the Next function works in multiple processing stages, where it first processs the current accounts and order them
+// the Next function works in multiple processing stages, where it first processes the current accounts and order them
// followed by returning the ordered accounts. In the first phase, it would return empty accountAddressHash array
// and sets the processedRecords to the number of accounts that were processed. On the second phase, the acct
// would contain valid data ( and optionally the account data as well, if was asked in makeOrderedAccountsIter) and
diff --git a/ledger/accountdb_test.go b/ledger/accountdb_test.go
index 3789ca393..414a6a78a 100644
--- a/ledger/accountdb_test.go
+++ b/ledger/accountdb_test.go
@@ -97,7 +97,7 @@ func randomFullAccountData(rewardsLevel, lastCreatableID uint64) (basics.Account
data.AssetParams[basics.AssetIndex(lastCreatableID)] = ap
}
}
- if 1 == (crypto.RandUint64() % 2) {
+ if 1 == (crypto.RandUint64()%2) && lastCreatableID > 0 {
// if account owns assets
data.Assets = make(map[basics.AssetIndex]basics.AssetHolding)
ownedAssetsCount := crypto.RandUint64()%20 + 1
@@ -113,7 +113,7 @@ func randomFullAccountData(rewardsLevel, lastCreatableID uint64) (basics.Account
crypto.RandBytes(data.AuthAddr[:])
}
- if 1 == (crypto.RandUint64() % 3) {
+ if 1 == (crypto.RandUint64()%3) && lastCreatableID > 0 {
data.AppLocalStates = make(map[basics.AppIndex]basics.AppLocalState)
appStatesCount := crypto.RandUint64()%20 + 1
for i := uint64(0); i < appStatesCount; i++ {
diff --git a/ledger/acctupdates.go b/ledger/acctupdates.go
index 932e4ed3d..9a82a8524 100644
--- a/ledger/acctupdates.go
+++ b/ledger/acctupdates.go
@@ -71,7 +71,7 @@ var trieCachedNodesCount = 9000
var merkleCommitterNodesPerPage = int64(116)
// baseAccountsPendingAccountsBufferSize defines the size of the base account pending accounts buffer size.
-// At the begining of a new round, the entries from this buffer are being flushed into the base accounts map.
+// At the beginning of a new round, the entries from this buffer are being flushed into the base accounts map.
const baseAccountsPendingAccountsBufferSize = 100000
// baseAccountsPendingAccountsWarnThreshold defines the threshold at which the lruAccounts would generate a warning
@@ -131,7 +131,7 @@ type accountUpdates struct {
// initProto specifies the initial consensus parameters at the genesis block.
initProto config.ConsensusParams
- // dbDirectory is the directory where the ledger and block sql file resides as well as the parent directroy for the catchup files to be generated
+ // dbDirectory is the directory where the ledger and block sql file resides as well as the parent directory for the catchup files to be generated
dbDirectory string
// catchpointInterval is the configured interval at which the accountUpdates would generate catchpoint labels and catchpoint files.
@@ -1067,7 +1067,7 @@ func (au *accountUpdates) initializeCaches(lastBalancesRound, lastestBlockRound,
// are we too far behind ? ( taking into consideration the catchpoint writing, which can stall the writing for quite a bit )
if roundsBehind > initializeCachesRoundFlushInterval+basics.Round(au.catchpointInterval) {
- // we're unable to persist changes. This is unexpected, but there is no point in keep trying batching additional changes since any futher changes
+ // we're unable to persist changes. This is unexpected, but there is no point in keep trying batching additional changes since any further changes
// would just accumulate in memory.
close(blockEvalFailed)
au.log.Errorf("initializeCaches was unable to fill up the account caches accounts round = %d, block round = %d. See above error for more details.", au.dbRound, blk.Round())
diff --git a/ledger/acctupdates_test.go b/ledger/acctupdates_test.go
index 8671ff487..925c3ce0e 100644
--- a/ledger/acctupdates_test.go
+++ b/ledger/acctupdates_test.go
@@ -577,7 +577,7 @@ func BenchmarkBalancesChanges(b *testing.B) {
}
func BenchmarkCalibrateNodesPerPage(b *testing.B) {
- b.Skip("This benchmark was used to tune up the NodesPerPage; it's not really usefull otherwise")
+ b.Skip("This benchmark was used to tune up the NodesPerPage; it's not really useful otherwise")
defaultNodesPerPage := merkleCommitterNodesPerPage
for nodesPerPage := 32; nodesPerPage < 300; nodesPerPage++ {
b.Run(fmt.Sprintf("Test_merkleCommitterNodesPerPage_%d", nodesPerPage), func(b *testing.B) {
@@ -589,7 +589,7 @@ func BenchmarkCalibrateNodesPerPage(b *testing.B) {
}
func BenchmarkCalibrateCacheNodeSize(b *testing.B) {
- //b.Skip("This benchmark was used to tune up the trieCachedNodesCount; it's not really usefull otherwise")
+ //b.Skip("This benchmark was used to tune up the trieCachedNodesCount; it's not really useful otherwise")
defaultTrieCachedNodesCount := trieCachedNodesCount
for cacheSize := 3000; cacheSize < 50000; cacheSize += 1000 {
b.Run(fmt.Sprintf("Test_cacheSize_%d", cacheSize), func(b *testing.B) {
@@ -601,7 +601,7 @@ func BenchmarkCalibrateCacheNodeSize(b *testing.B) {
}
// TestLargeAccountCountCatchpointGeneration creates a ledger containing a large set of accounts ( i.e. 100K accounts )
-// and attempts to have the accountUpdates create the associated catchpoint. It's designed precisly around setting an
+// and attempts to have the accountUpdates create the associated catchpoint. It's designed precisely around setting an
// environment which would quickly ( i.e. after 32 rounds ) would start producing catchpoints.
func TestLargeAccountCountCatchpointGeneration(t *testing.T) {
if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
@@ -1048,7 +1048,7 @@ func TestListCreatables(t *testing.T) {
// ******* All results are obtained from the cache. Empty database *******
// ******* No deletes *******
- // get random data. Inital batch, no deletes
+ // get random data. Initial batch, no deletes
ctbsList, randomCtbs := randomCreatables(numElementsPerSegement)
expectedDbImage := make(map[basics.CreatableIndex]ledgercore.ModifiedCreatable)
ctbsWithDeletes := randomCreatableSampling(1, ctbsList, randomCtbs,
@@ -1750,7 +1750,7 @@ func TestSplittingConsensusVersionCommits(t *testing.T) {
}
// TestSplittingConsensusVersionCommitsBoundry tests the a sequence of commits that spans over multiple consensus versions works correctly, and
-// in particular, complements TestSplittingConsensusVersionCommits by testing the commit boundry.
+// in particular, complements TestSplittingConsensusVersionCommits by testing the commit boundary.
func TestSplittingConsensusVersionCommitsBoundry(t *testing.T) {
initProtocolVersion := protocol.ConsensusV20
initialProtoParams := config.Consensus[initProtocolVersion]
diff --git a/ledger/applications.go b/ledger/applications.go
index 6e1674624..e03604a59 100644
--- a/ledger/applications.go
+++ b/ledger/applications.go
@@ -106,32 +106,60 @@ func (al *logicLedger) AssetHolding(addr basics.Address, assetIdx basics.AssetIn
return holding, nil
}
-func (al *logicLedger) AssetParams(assetIdx basics.AssetIndex) (basics.AssetParams, error) {
+func (al *logicLedger) AssetParams(assetIdx basics.AssetIndex) (basics.AssetParams, basics.Address, error) {
// Find asset creator
creator, ok, err := al.cow.GetCreator(basics.CreatableIndex(assetIdx), basics.AssetCreatable)
if err != nil {
- return basics.AssetParams{}, err
+ return basics.AssetParams{}, creator, err
}
// Ensure asset exists
if !ok {
- return basics.AssetParams{}, fmt.Errorf("asset %d does not exist", assetIdx)
+ return basics.AssetParams{}, creator, fmt.Errorf("asset %d does not exist", assetIdx)
}
// Fetch the requested balance record
record, err := al.cow.Get(creator, false)
if err != nil {
- return basics.AssetParams{}, err
+ return basics.AssetParams{}, creator, err
}
// Ensure account created the requested asset
params, ok := record.AssetParams[assetIdx]
if !ok {
err = fmt.Errorf("account %s has not created asset %d", creator, assetIdx)
- return basics.AssetParams{}, err
+ return basics.AssetParams{}, creator, err
}
- return params, nil
+ return params, creator, nil
+}
+
+func (al *logicLedger) AppParams(appIdx basics.AppIndex) (basics.AppParams, basics.Address, error) {
+ // Find app creator
+ creator, ok, err := al.cow.GetCreator(basics.CreatableIndex(appIdx), basics.AppCreatable)
+ if err != nil {
+ return basics.AppParams{}, creator, err
+ }
+
+ // Ensure app exists
+ if !ok {
+ return basics.AppParams{}, creator, fmt.Errorf("app %d does not exist", appIdx)
+ }
+
+ // Fetch the requested balance record
+ record, err := al.cow.Get(creator, false)
+ if err != nil {
+ return basics.AppParams{}, creator, err
+ }
+
+ // Ensure account created the requested app
+ params, ok := record.AppParams[appIdx]
+ if !ok {
+ err = fmt.Errorf("account %s has not created app %d", creator, appIdx)
+ return basics.AppParams{}, creator, err
+ }
+
+ return params, creator, nil
}
func (al *logicLedger) Round() basics.Round {
diff --git a/ledger/applications_test.go b/ledger/applications_test.go
index 403084d02..5d1ec743a 100644
--- a/ledger/applications_test.go
+++ b/ledger/applications_test.go
@@ -220,15 +220,16 @@ func TestLogicLedgerAsset(t *testing.T) {
a.NoError(err)
a.NotNil(l)
- _, err = l.AssetParams(basics.AssetIndex(aidx))
+ _, _, err = l.AssetParams(basics.AssetIndex(aidx))
a.Error(err)
a.Contains(err.Error(), fmt.Sprintf("asset %d does not exist", aidx))
c.brs = map[basics.Address]basics.AccountData{
addr1: {AssetParams: map[basics.AssetIndex]basics.AssetParams{assetIdx: {Total: 1000}}},
}
- ap, err := l.AssetParams(assetIdx)
+ ap, creator, err := l.AssetParams(assetIdx)
a.NoError(err)
+ a.Equal(addr1, creator)
a.Equal(uint64(1000), ap.Total)
_, err = l.AssetHolding(addr1, assetIdx)
diff --git a/ledger/blockqueue_test.go b/ledger/blockqueue_test.go
new file mode 100644
index 000000000..93bafc322
--- /dev/null
+++ b/ledger/blockqueue_test.go
@@ -0,0 +1,96 @@
+// 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 ledger
+
+import (
+ "errors"
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/agreement"
+ "github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/bookkeeping"
+ "github.com/algorand/go-algorand/ledger/ledgercore"
+ "github.com/algorand/go-algorand/logging"
+ "github.com/algorand/go-algorand/protocol"
+)
+
+func TestPutBlockTooOld(t *testing.T) {
+ genesisInitState, _, _ := genesis(10)
+
+ dbName := fmt.Sprintf("%s.%d", t.Name(), crypto.RandUint64())
+ const inMem = true
+ cfg := config.GetDefaultLocal()
+ cfg.Archival = true
+ l, err := OpenLedger(logging.Base(), dbName, inMem, genesisInitState, cfg)
+ require.NoError(t, err)
+ defer l.Close()
+
+ blk := bookkeeping.Block{}
+ var cert agreement.Certificate
+ err = l.blockQ.putBlock(blk, cert) // try putBlock for a block in a previous round
+
+ expectedErr := &ledgercore.BlockInLedgerError{}
+ require.True(t, errors.As(err, expectedErr))
+
+ blkent := randomBlock(1)
+ blk = blkent.block
+ cert = blkent.cert
+ err = l.blockQ.putBlock(blk, cert) // add block for round 1 to blockQueue
+ require.NoError(t, err)
+
+ err = l.blockQ.putBlock(blk, cert) // try adding same block again (should fail)
+ require.True(t, errors.As(err, expectedErr))
+}
+
+// TestGetEncodedBlockCert tests getEncodedBlockCert with valid and invalid round numbers.
+func TestGetEncodedBlockCert(t *testing.T) {
+ genesisInitState, _, _ := genesis(10)
+
+ const inMem = true
+ cfg := config.GetDefaultLocal()
+ l, err := OpenLedger(logging.Base(), t.Name(), inMem, genesisInitState, cfg)
+ require.NoError(t, err)
+ defer l.Close()
+
+ blkent := randomBlock(1)
+ blk := blkent.block
+ cert := blkent.cert
+ err = l.blockQ.putBlock(blk, cert)
+ require.NoError(t, err)
+
+ var blkBytes []byte
+ var certBytes []byte
+
+ blkBytes, certBytes, err = l.blockQ.getEncodedBlockCert(0)
+ require.Equal(t, protocol.Encode(&genesisInitState.Block), blkBytes)
+ require.Equal(t, protocol.Encode(&agreement.Certificate{}), certBytes)
+ require.NoError(t, err)
+
+ blkBytes, certBytes, err = l.blockQ.getEncodedBlockCert(1)
+ require.Equal(t, protocol.Encode(&blk), blkBytes)
+ require.Equal(t, protocol.Encode(&cert), certBytes)
+ require.NoError(t, err)
+
+ _, _, err = l.blockQ.getEncodedBlockCert(100) // should not be entry for this round
+
+ expectedErr := &ledgercore.ErrNoEntry{}
+ require.True(t, errors.As(err, expectedErr))
+}
diff --git a/ledger/catchpointwriter.go b/ledger/catchpointwriter.go
index f919fa695..26fa65f71 100644
--- a/ledger/catchpointwriter.go
+++ b/ledger/catchpointwriter.go
@@ -44,7 +44,7 @@ const (
catchpointFileVersion = uint64(0200)
)
-// catchpointWriter is the struct managing the persistance of accounts data into the catchpoint file.
+// catchpointWriter is the struct managing the persistence of accounts data into the catchpoint file.
// it's designed to work in a step fashion : a caller will call the WriteStep method in a loop until
// the writing is complete. It might take multiple steps until the operation is over, and the caller
// has the option of throttling the CPU utilization in between the calls.
diff --git a/ledger/cow.go b/ledger/cow.go
index d0422f0a2..ba17dafc5 100644
--- a/ledger/cow.go
+++ b/ledger/cow.go
@@ -220,7 +220,9 @@ func (cb *roundCowState) trackCreatable(creatableIndex basics.CreatableIndex) {
func (cb *roundCowState) addTx(txn transactions.Transaction, txid transactions.Txid) {
cb.mods.Txids[txid] = txn.LastValid
- cb.mods.Txleases[ledgercore.Txlease{Sender: txn.Sender, Lease: txn.Lease}] = txn.LastValid
+ if txn.Lease != [32]byte{} {
+ cb.mods.Txleases[ledgercore.Txlease{Sender: txn.Sender, Lease: txn.Lease}] = txn.LastValid
+ }
}
func (cb *roundCowState) setCompactCertNext(rnd basics.Round) {
diff --git a/ledger/eval.go b/ledger/eval.go
index e8da2c740..3b1968a74 100644
--- a/ledger/eval.go
+++ b/ledger/eval.go
@@ -1240,7 +1240,7 @@ transactionGroupLoop:
}
}
- // Finally, procees any pending end-of-block state changes
+ // Finally, proceeds any pending end-of-block state changes
err = eval.endOfBlock()
if err != nil {
return ledgercore.StateDelta{}, err
diff --git a/ledger/ledger.go b/ledger/ledger.go
index 50718bb26..42c878834 100644
--- a/ledger/ledger.go
+++ b/ledger/ledger.go
@@ -279,22 +279,22 @@ func openLedgerDB(dbPathPrefix string, dbMem bool) (trackerDBs db.Pair, blockDBs
return
}
-// setSynchronousMode sets the writing database connections syncronous mode to the specified mode
+// setSynchronousMode sets the writing database connections synchronous mode to the specified mode
func (l *Ledger) setSynchronousMode(ctx context.Context, synchronousMode db.SynchronousMode) {
if synchronousMode < db.SynchronousModeOff || synchronousMode > db.SynchronousModeExtra {
- l.log.Warnf("ledger.setSynchronousMode unable to set syncronous mode : requested value %d is invalid", synchronousMode)
+ l.log.Warnf("ledger.setSynchronousMode unable to set synchronous mode : requested value %d is invalid", synchronousMode)
return
}
err := l.blockDBs.Wdb.SetSynchronousMode(ctx, synchronousMode, synchronousMode >= db.SynchronousModeFull)
if err != nil {
- l.log.Warnf("ledger.setSynchronousMode unable to set syncronous mode on blocks db: %v", err)
+ l.log.Warnf("ledger.setSynchronousMode unable to set synchronous mode on blocks db: %v", err)
return
}
err = l.trackerDBs.Wdb.SetSynchronousMode(ctx, synchronousMode, synchronousMode >= db.SynchronousModeFull)
if err != nil {
- l.log.Warnf("ledger.setSynchronousMode unable to set syncronous mode on trackers db: %v", err)
+ l.log.Warnf("ledger.setSynchronousMode unable to set synchronous mode on trackers db: %v", err)
return
}
}
@@ -477,14 +477,6 @@ func (l *Ledger) CheckDup(currentProto config.ConsensusParams, current basics.Ro
return l.txTail.checkDup(currentProto, current, firstValid, lastValid, txid, txl.Txlease)
}
-// GetRoundTxIds returns a map of the transactions ids that we have for the given round
-// this function is currently not being used, but remains here as it might be useful in the future.
-func (l *Ledger) GetRoundTxIds(rnd basics.Round) (txMap map[transactions.Txid]bool) {
- l.trackerMu.RLock()
- defer l.trackerMu.RUnlock()
- return l.txTail.getRoundTxIds(rnd)
-}
-
// Latest returns the latest known block round added to the ledger.
func (l *Ledger) Latest() basics.Round {
return l.blockQ.latest()
diff --git a/ledger/ledger_test.go b/ledger/ledger_test.go
index 03153210b..0e2249456 100644
--- a/ledger/ledger_test.go
+++ b/ledger/ledger_test.go
@@ -1550,7 +1550,7 @@ func TestListAssetsAndApplications(t *testing.T) {
// ******* All results are obtained from the cache. Empty database *******
// ******* No deletes *******
- // get random data. Inital batch, no deletes
+ // get random data. Initial batch, no deletes
randomCtbs, maxAsset, maxApp, err := generateCreatables(numElementsPerSegement)
require.NoError(t, err)
diff --git a/ledger/lruaccts.go b/ledger/lruaccts.go
index c1cf8dd94..2544ff3a7 100644
--- a/ledger/lruaccts.go
+++ b/ledger/lruaccts.go
@@ -17,21 +17,19 @@
package ledger
import (
- "container/list"
-
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/logging"
)
// lruAccounts provides a storage class for the most recently used accounts data.
-// It doesn't have any syncronization primitive on it's own and require to be
+// It doesn't have any synchronization primitive on it's own and require to be
// syncronized by the caller.
type lruAccounts struct {
// accountsList contain the list of persistedAccountData, where the front ones are the most "fresh"
// and the ones on the back are the oldest.
- accountsList *list.List
+ accountsList *persistedAccountDataList
// accounts provides fast access to the various elements in the list by using the account address
- accounts map[basics.Address]*list.Element
+ accounts map[basics.Address]*persistedAccountDataListNode
// pendingAccounts are used as a way to avoid taking a write-lock. When the caller needs to "materialize" these,
// it would call flushPendingWrites and these would be merged into the accounts/accountsList
pendingAccounts chan persistedAccountData
@@ -44,8 +42,8 @@ type lruAccounts struct {
// init initializes the lruAccounts for use.
// thread locking semantics : write lock
func (m *lruAccounts) init(log logging.Logger, pendingWrites int, pendingWritesWarnThreshold int) {
- m.accountsList = list.New()
- m.accounts = make(map[basics.Address]*list.Element)
+ m.accountsList = newPersistedAccountList().allocateFreeNodes(pendingWrites)
+ m.accounts = make(map[basics.Address]*persistedAccountDataListNode, pendingWrites)
m.pendingAccounts = make(chan persistedAccountData, pendingWrites)
m.log = log
m.pendingWritesWarnThreshold = pendingWritesWarnThreshold
@@ -55,7 +53,7 @@ func (m *lruAccounts) init(log logging.Logger, pendingWrites int, pendingWritesW
// thread locking semantics : read lock
func (m *lruAccounts) read(addr basics.Address) (data persistedAccountData, has bool) {
if el := m.accounts[addr]; el != nil {
- return el.Value.(persistedAccountData), true
+ return *el.Value, true
}
return persistedAccountData{}, false
}
@@ -96,15 +94,14 @@ func (m *lruAccounts) writePending(acct persistedAccountData) {
func (m *lruAccounts) write(acctData persistedAccountData) {
if el := m.accounts[acctData.addr]; el != nil {
// already exists; is it a newer ?
- existing := el.Value.(persistedAccountData)
- if existing.before(&acctData) {
+ if el.Value.before(&acctData) {
// we update with a newer version.
- el.Value = acctData
+ el.Value = &acctData
}
- m.accountsList.MoveToFront(el)
+ m.accountsList.moveToFront(el)
} else {
// new entry.
- m.accounts[acctData.addr] = m.accountsList.PushFront(acctData)
+ m.accounts[acctData.addr] = m.accountsList.pushFront(&acctData)
}
}
@@ -116,9 +113,9 @@ func (m *lruAccounts) prune(newSize int) (removed int) {
if len(m.accounts) <= newSize {
break
}
- back := m.accountsList.Back()
- delete(m.accounts, back.Value.(persistedAccountData).addr)
- m.accountsList.Remove(back)
+ back := m.accountsList.back()
+ delete(m.accounts, back.Value.addr)
+ m.accountsList.remove(back)
removed++
}
return
diff --git a/ledger/lruaccts_test.go b/ledger/lruaccts_test.go
index 0e093fdf4..4080cd3a3 100644
--- a/ledger/lruaccts_test.go
+++ b/ledger/lruaccts_test.go
@@ -17,6 +17,7 @@
package ledger
import (
+ "encoding/binary"
"testing"
"time"
@@ -43,7 +44,7 @@ func TestBasicLRUAccounts(t *testing.T) {
baseAcct.write(acct)
}
- // verify that all these accounts are truely there.
+ // verify that all these accounts are truly there.
for i := 0; i < accountsNum; i++ {
addr := basics.Address(crypto.Hash([]byte{byte(i)}))
acct, has := baseAcct.read(addr)
@@ -176,7 +177,7 @@ func TestLRUAccountsOmittedPendingWrites(t *testing.T) {
baseAcct.flushPendingWrites()
- // verify that all these accounts are truely there.
+ // verify that all these accounts are truly there.
for i := 0; i < pendingWritesBuffer; i++ {
addr := basics.Address(crypto.Hash([]byte{byte(i)}))
acct, has := baseAcct.read(addr)
@@ -195,3 +196,53 @@ func TestLRUAccountsOmittedPendingWrites(t *testing.T) {
require.Equal(t, persistedAccountData{}, acct)
}
}
+
+func BenchmarkLRUAccountsWrite(b *testing.B) {
+ numTestAccounts := 5000
+ // there are 2500 accounts that overlap
+ fillerAccounts := generatePersistedAccountData(0, 97500)
+ accounts := generatePersistedAccountData(97500-numTestAccounts/2, 97500+numTestAccounts/2)
+
+ benchLruWrite(b, fillerAccounts, accounts)
+}
+
+func benchLruWrite(b *testing.B, fillerAccounts []persistedAccountData, accounts []persistedAccountData) {
+ b.ResetTimer()
+ b.StopTimer()
+ var baseAcct lruAccounts
+ // setting up the baseAccts with a predefined cache size
+ baseAcct.init(logging.TestingLog(b), baseAccountsPendingAccountsBufferSize, baseAccountsPendingAccountsWarnThreshold)
+ for i := 0; i < b.N; i++ {
+ baseAcct = fillLRUAccounts(baseAcct, fillerAccounts)
+
+ b.StartTimer()
+ fillLRUAccounts(baseAcct, accounts)
+ b.StopTimer()
+ baseAcct.prune(0)
+ }
+}
+
+func fillLRUAccounts(baseAcct lruAccounts, fillerAccounts []persistedAccountData) lruAccounts {
+ for _, account := range fillerAccounts {
+ baseAcct.write(account)
+ }
+ return baseAcct
+}
+
+func generatePersistedAccountData(startRound, endRound int) []persistedAccountData {
+ accounts := make([]persistedAccountData, endRound-startRound)
+ buffer := make([]byte, 4)
+
+ for i := startRound; i < endRound; i++ {
+ binary.BigEndian.PutUint32(buffer, uint32(i))
+ digest := crypto.Hash(buffer)
+
+ accounts[i-startRound] = persistedAccountData{
+ addr: basics.Address(digest),
+ round: basics.Round(i + startRound),
+ rowid: int64(i),
+ accountData: basics.AccountData{MicroAlgos: basics.MicroAlgos{Raw: uint64(i)}},
+ }
+ }
+ return accounts
+}
diff --git a/ledger/onlineacct.go b/ledger/onlineacct.go
index 2c8bf5bfa..687f0c595 100644
--- a/ledger/onlineacct.go
+++ b/ledger/onlineacct.go
@@ -84,6 +84,7 @@ func (h *onlineTopHeap) Push(x interface{}) {
// Pop implements heap.Interface
func (h *onlineTopHeap) Pop() interface{} {
res := h.accts[len(h.accts)-1]
+ h.accts[len(h.accts)-1] = nil
h.accts = h.accts[:len(h.accts)-1]
return res
}
diff --git a/ledger/onlineacct_test.go b/ledger/onlineacct_test.go
new file mode 100644
index 000000000..cd7eb4230
--- /dev/null
+++ b/ledger/onlineacct_test.go
@@ -0,0 +1,138 @@
+// 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 ledger
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/basics"
+)
+
+func TestOnlineTopHeap_Less(t *testing.T) {
+ h := onlineTopHeap{
+ accts: []*onlineAccount{
+ {
+ Address: basics.Address{},
+ NormalizedOnlineBalance: 0,
+ },
+ {
+ Address: basics.Address{},
+ NormalizedOnlineBalance: 1,
+ },
+ {
+ Address: basics.Address(crypto.Hash([]byte("address"))),
+ NormalizedOnlineBalance: 0,
+ },
+ },
+ }
+
+ require.True(t, h.Less(1, 0))
+ require.True(t, h.Less(1, 2))
+ require.True(t, h.Less(2, 0))
+
+ require.False(t, h.Less(0, 1))
+ require.False(t, h.Less(0, 2))
+ require.False(t, h.Less(2, 1))
+}
+
+func TestOnlineTopHeap_Swap(t *testing.T) {
+ h := onlineTopHeap{
+ accts: []*onlineAccount{
+ {
+ Address: basics.Address{},
+ NormalizedOnlineBalance: 0,
+ },
+ {
+ Address: basics.Address{},
+ NormalizedOnlineBalance: 1,
+ },
+ {
+ Address: basics.Address(crypto.Hash([]byte("address"))),
+ NormalizedOnlineBalance: 0,
+ },
+ },
+ }
+
+ acct0 := h.accts[0]
+ acct2 := h.accts[2]
+
+ h.Swap(0, 2)
+
+ require.Equal(t, acct0, h.accts[2])
+ require.Equal(t, acct2, h.accts[0])
+}
+
+func TestOnlineTopHeap_Push(t *testing.T) {
+ h := onlineTopHeap{
+ accts: []*onlineAccount{
+ {
+ Address: basics.Address{},
+ NormalizedOnlineBalance: 0,
+ },
+ {
+ Address: basics.Address{},
+ NormalizedOnlineBalance: 1,
+ },
+ },
+ }
+
+ acct0 := h.accts[0]
+ acct1 := h.accts[1]
+ acct2 := &onlineAccount{
+ Address: basics.Address(crypto.Hash([]byte("address"))),
+ NormalizedOnlineBalance: 0,
+ }
+
+ h.Push(acct2)
+
+ require.Equal(t, 3, h.Len())
+ require.Equal(t, acct0, h.accts[0])
+ require.Equal(t, acct1, h.accts[1])
+ require.Equal(t, acct2, h.accts[2])
+}
+
+func TestOnlineTopHeap_Pop(t *testing.T) {
+ h := onlineTopHeap{
+ accts: []*onlineAccount{
+ {
+ Address: basics.Address{},
+ NormalizedOnlineBalance: 0,
+ },
+ {
+ Address: basics.Address{},
+ NormalizedOnlineBalance: 1,
+ },
+ {
+ Address: basics.Address(crypto.Hash([]byte("address"))),
+ NormalizedOnlineBalance: 0,
+ },
+ },
+ }
+
+ originalAccounts := h.accts
+
+ h.Pop()
+
+ require.Equal(t, 2, h.Len())
+ require.Equal(t, 3, cap(h.accts))
+ require.Equal(t, originalAccounts[0], h.accts[0])
+ require.Equal(t, originalAccounts[1], h.accts[1])
+ require.Nil(t, originalAccounts[2])
+}
diff --git a/ledger/persistedaccts_list.go b/ledger/persistedaccts_list.go
new file mode 100644
index 000000000..ae84e6f02
--- /dev/null
+++ b/ledger/persistedaccts_list.go
@@ -0,0 +1,144 @@
+// 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 ledger
+
+// persistedAccountDataList represents a doubly linked list.
+// must initiate with newPersistedAccountList.
+type persistedAccountDataList struct {
+ root persistedAccountDataListNode // sentinel list element, only &root, root.prev, and root.next are used
+ freeList *persistedAccountDataListNode // preallocated nodes location
+}
+
+type persistedAccountDataListNode struct {
+ // Next and previous pointers in the doubly-linked list of elements.
+ // To simplify the implementation, internally a list l is implemented
+ // as a ring, such that &l.root is both the next element of the last
+ // list element (l.Back()) and the previous element of the first list
+ // element (l.Front()).
+ next, prev *persistedAccountDataListNode
+
+ Value *persistedAccountData
+}
+
+func newPersistedAccountList() *persistedAccountDataList {
+ l := new(persistedAccountDataList)
+ l.root.next = &l.root
+ l.root.prev = &l.root
+ // used as a helper but does not store value
+ l.freeList = new(persistedAccountDataListNode)
+
+ return l
+}
+
+func (l *persistedAccountDataList) inserNodeToFreeList(otherNode *persistedAccountDataListNode) {
+ otherNode.next = l.freeList.next
+ otherNode.prev = nil
+ otherNode.Value = nil
+
+ l.freeList.next = otherNode
+}
+
+func (l *persistedAccountDataList) getNewNode() *persistedAccountDataListNode {
+ if l.freeList.next == nil {
+ return new(persistedAccountDataListNode)
+ }
+ newNode := l.freeList.next
+ l.freeList.next = newNode.next
+
+ return newNode
+}
+
+func (l *persistedAccountDataList) allocateFreeNodes(numAllocs int) *persistedAccountDataList {
+ if l.freeList == nil {
+ return l
+ }
+ for i := 0; i < numAllocs; i++ {
+ l.inserNodeToFreeList(new(persistedAccountDataListNode))
+ }
+
+ return l
+}
+
+func isEmpty(list *persistedAccountDataList) bool {
+ // assumes we are inserting correctly to the list - using pushFront.
+ return list.root.next == &list.root
+}
+
+// Back returns the last element of list l or nil if the list is empty.
+func (l *persistedAccountDataList) back() *persistedAccountDataListNode {
+ if isEmpty(l) {
+ return nil
+ }
+ return l.root.prev
+}
+
+// remove removes e from l if e is an element of list l.
+// It returns the element value e.Value.
+// The element must not be nil.
+func (l *persistedAccountDataList) remove(e *persistedAccountDataListNode) {
+ e.prev.next = e.next
+ e.next.prev = e.prev
+ e.next = nil // avoid memory leaks
+ e.prev = nil // avoid memory leaks
+
+ l.inserNodeToFreeList(e)
+}
+
+// pushFront inserts a new element e with value v at the front of list l and returns e.
+func (l *persistedAccountDataList) pushFront(v *persistedAccountData) *persistedAccountDataListNode {
+ newNode := l.getNewNode()
+ newNode.Value = v
+ return l.insertValue(newNode, &l.root)
+}
+
+// insertValue inserts e after at, increments l.len, and returns e.
+func (l *persistedAccountDataList) insertValue(newNode *persistedAccountDataListNode, at *persistedAccountDataListNode) *persistedAccountDataListNode {
+ n := at.next
+ at.next = newNode
+ newNode.prev = at
+ newNode.next = n
+ n.prev = newNode
+
+ return newNode
+}
+
+// moveToFront moves element e to the front of list l.
+// If e is not an element of l, the list is not modified.
+// The element must not be nil.
+func (l *persistedAccountDataList) moveToFront(e *persistedAccountDataListNode) {
+ if l.root.next == e {
+ return
+ }
+ l.move(e, &l.root)
+}
+
+// move moves e to next to at and returns e.
+func (l *persistedAccountDataList) move(e, at *persistedAccountDataListNode) *persistedAccountDataListNode {
+ if e == at {
+ return e
+ }
+ e.prev.next = e.next
+ e.next.prev = e.prev
+
+ n := at.next
+ at.next = e
+ e.prev = at
+ e.next = n
+ n.prev = e
+
+ return e
+}
diff --git a/ledger/persistedaccts_list_test.go b/ledger/persistedaccts_list_test.go
new file mode 100644
index 000000000..14860d27d
--- /dev/null
+++ b/ledger/persistedaccts_list_test.go
@@ -0,0 +1,211 @@
+// 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 ledger
+
+import (
+ "github.com/algorand/go-algorand/data/basics"
+ "testing"
+)
+
+func checkLen(list *persistedAccountDataList) int {
+ if isEmpty(list) {
+ return 0
+ }
+ return countListSize(&list.root)
+}
+
+func countListSize(head *persistedAccountDataListNode) (counter int) {
+ for i := head.next; i != head && i != nil; i = i.next {
+ counter++
+ }
+ return counter
+}
+
+func TestRemoveFromList(t *testing.T) {
+ l := newPersistedAccountList()
+ e1 := l.pushFront(&persistedAccountData{addr: basics.Address{1}})
+ e2 := l.pushFront(&persistedAccountData{addr: basics.Address{2}})
+ e3 := l.pushFront(&persistedAccountData{addr: basics.Address{3}})
+ checkListPointers(t, l, []*persistedAccountDataListNode{e3, e2, e1})
+
+ l.remove(e2)
+ checkListPointers(t, l, []*persistedAccountDataListNode{e3, e1})
+ l.remove(e3)
+ checkListPointers(t, l, []*persistedAccountDataListNode{e1})
+}
+
+func TestAddingNewNodeWithAllocatedFreeList(t *testing.T) {
+ l := newPersistedAccountList().allocateFreeNodes(10)
+ checkListPointers(t, l, []*persistedAccountDataListNode{})
+ if countListSize(l.freeList) != 10 {
+ t.Errorf("free list did not allocate nodes")
+ return
+ }
+ // test elements
+ e1 := l.pushFront(&persistedAccountData{addr: basics.Address{1}})
+ checkListPointers(t, l, []*persistedAccountDataListNode{e1})
+
+ if countListSize(l.freeList) != 9 {
+ t.Errorf("free list did not provide a node on new list entry")
+ return
+ }
+}
+
+func checkListLen(t *testing.T, l *persistedAccountDataList, len int) bool {
+ if n := checkLen(l); n != len {
+ t.Errorf("l.Len() = %d, want %d", n, len)
+ return true
+ }
+ return false
+}
+
+// inspect that the list seems like the array
+func checkListPointers(t *testing.T, l *persistedAccountDataList, es []*persistedAccountDataListNode) {
+ root := &l.root
+
+ if failed := checkListLen(t, l, len(es)); failed {
+ return
+ }
+
+ if failed := zeroListInspection(t, l, es, root); failed {
+ return
+ }
+
+ // len(es) > 0
+ pointerInspection(t, es, root)
+}
+
+func zeroListInspection(t *testing.T, l *persistedAccountDataList, es []*persistedAccountDataListNode, root *persistedAccountDataListNode) bool {
+ // zero length lists must be the zero value or properly initialized (sentinel circle)
+ if len(es) == 0 {
+ if l.root.next != nil && l.root.next != root || l.root.prev != nil && l.root.prev != root {
+ t.Errorf("l.root.next = %p, l.root.prev = %p; both should both be nil or %p", l.root.next, l.root.prev, root)
+ }
+ return true
+ }
+ return false
+}
+
+func pointerInspection(t *testing.T, es []*persistedAccountDataListNode, root *persistedAccountDataListNode) {
+ // check internal and external prev/next connections
+ for i, e := range es {
+ prev := root
+ if i > 0 {
+ prev = es[i-1]
+ }
+ if p := e.prev; p != prev {
+ t.Errorf("elt[%d](%p).prev = %p, want %p", i, e, p, prev)
+ }
+
+ next := root
+ if i < len(es)-1 {
+ next = es[i+1]
+ }
+ if n := e.next; n != next {
+ t.Errorf("elt[%d](%p).next = %p, want %p", i, e, n, next)
+ }
+ }
+}
+
+func TestMultielementListPositioning(t *testing.T) {
+ l := newPersistedAccountList()
+ checkListPointers(t, l, []*persistedAccountDataListNode{})
+ // test elements
+ e2 := l.pushFront(&persistedAccountData{addr: basics.Address{2}})
+ e1 := l.pushFront(&persistedAccountData{addr: basics.Address{1}})
+ e3 := l.pushFront(&persistedAccountData{addr: basics.Address{3}})
+ e4 := l.pushFront(&persistedAccountData{addr: basics.Address{4}})
+ e5 := l.pushFront(&persistedAccountData{addr: basics.Address{5}})
+
+ checkListPointers(t, l, []*persistedAccountDataListNode{e5, e4, e3, e1, e2})
+
+ l.move(e4, e1)
+ checkListPointers(t, l, []*persistedAccountDataListNode{e5, e3, e1, e4, e2})
+
+ l.remove(e5)
+ checkListPointers(t, l, []*persistedAccountDataListNode{e3, e1, e4, e2})
+
+ l.move(e1, e4) // swap in middle
+ checkListPointers(t, l, []*persistedAccountDataListNode{e3, e4, e1, e2})
+
+ l.moveToFront(e4)
+ checkListPointers(t, l, []*persistedAccountDataListNode{e4, e3, e1, e2})
+
+ l.remove(e2)
+ checkListPointers(t, l, []*persistedAccountDataListNode{e4, e3, e1})
+
+ l.moveToFront(e3) // move from middle
+ checkListPointers(t, l, []*persistedAccountDataListNode{e3, e4, e1})
+
+ l.moveToFront(e1) // move from end
+ checkListPointers(t, l, []*persistedAccountDataListNode{e1, e3, e4})
+
+ l.moveToFront(e1) // no movement
+ checkListPointers(t, l, []*persistedAccountDataListNode{e1, e3, e4})
+
+ e2 = l.pushFront(&persistedAccountData{addr: basics.Address{2}})
+ checkListPointers(t, l, []*persistedAccountDataListNode{e2, e1, e3, e4})
+
+ l.remove(e3) // removing from middle
+ checkListPointers(t, l, []*persistedAccountDataListNode{e2, e1, e4})
+
+ l.remove(e4) // removing from end
+ checkListPointers(t, l, []*persistedAccountDataListNode{e2, e1})
+
+ l.move(e2, e1) // swapping between two elements
+ checkListPointers(t, l, []*persistedAccountDataListNode{e1, e2})
+
+ l.remove(e1) // removing front
+ checkListPointers(t, l, []*persistedAccountDataListNode{e2})
+
+ l.move(e2, l.back()) // swapping element with itself.
+ checkListPointers(t, l, []*persistedAccountDataListNode{e2})
+
+ l.remove(e2) // remove last one
+ checkListPointers(t, l, []*persistedAccountDataListNode{})
+}
+
+func TestSingleElementListPositioning(t *testing.T) {
+ l := newPersistedAccountList()
+ checkListPointers(t, l, []*persistedAccountDataListNode{})
+ e := l.pushFront(&persistedAccountData{addr: basics.Address{1}})
+ checkListPointers(t, l, []*persistedAccountDataListNode{e})
+ l.moveToFront(e)
+ checkListPointers(t, l, []*persistedAccountDataListNode{e})
+ l.remove(e)
+ checkListPointers(t, l, []*persistedAccountDataListNode{})
+}
+
+func TestRemovedNodeShouldBeMovedToFreeList(t *testing.T) {
+ l := newPersistedAccountList()
+ e1 := l.pushFront(&persistedAccountData{addr: basics.Address{1}})
+ e2 := l.pushFront(&persistedAccountData{addr: basics.Address{2}})
+
+ checkListPointers(t, l, []*persistedAccountDataListNode{e2, e1})
+
+ e := l.back()
+ l.remove(e)
+
+ for i := l.freeList.next; i != nil; i = i.next {
+ if i == e {
+ // stopping the tst with good results:
+ return
+ }
+ }
+ t.Error("expected the removed node to appear at the freelist")
+
+}
diff --git a/ledger/roundlru.go b/ledger/roundlru.go
index 9c837ede3..615dd164a 100644
--- a/ledger/roundlru.go
+++ b/ledger/roundlru.go
@@ -121,7 +121,7 @@ func (hlc *heapLRUCache) inc() {
}
}
func (hlc *heapLRUCache) reIndex() {
- if hlc.entries.heap != nil || len(hlc.entries.heap) == 0 {
+ if len(hlc.entries.heap) == 0 {
return
}
minprio := hlc.entries.heap[0].useIndex
diff --git a/ledger/roundlru_test.go b/ledger/roundlru_test.go
index 806c2728f..6d2c4317b 100644
--- a/ledger/roundlru_test.go
+++ b/ledger/roundlru_test.go
@@ -19,6 +19,8 @@ package ledger
import (
"testing"
+ "github.com/stretchr/testify/require"
+
"github.com/algorand/go-algorand/data/basics"
)
@@ -59,3 +61,30 @@ func TestRoundLRUBasic(t *testing.T) {
getNone(t, &cache, 2)
getNone(t, &cache, 4)
}
+
+func TestRoundLRUReIndex(t *testing.T) {
+ cache := heapLRUCache{
+ entries: lruHeap{
+ heap: []lruEntry{
+ {
+ useIndex: MaxInt - 2,
+ },
+ {
+ useIndex: MaxInt - 1,
+ },
+ {
+ useIndex: MaxInt - 3,
+ },
+ },
+ },
+ maxEntries: 3,
+ nextUseIndex: MaxInt - 1,
+ }
+
+ cache.inc()
+
+ require.Equal(t, 3, cache.nextUseIndex)
+ require.Equal(t, 1, cache.entries.heap[0].useIndex)
+ require.Equal(t, 2, cache.entries.heap[1].useIndex)
+ require.Equal(t, 0, cache.entries.heap[2].useIndex)
+}
diff --git a/ledger/txtail.go b/ledger/txtail.go
index 6f6c08c91..68cc0f5ed 100644
--- a/ledger/txtail.go
+++ b/ledger/txtail.go
@@ -26,8 +26,9 @@ import (
"github.com/algorand/go-algorand/ledger/ledgercore"
)
+const initialLastValidArrayLen = 256
+
type roundTxMembers struct {
- txids map[transactions.Txid]basics.Round
txleases map[ledgercore.Txlease]basics.Round // map of transaction lease to when it expires
proto config.ConsensusParams
}
@@ -60,6 +61,13 @@ func (t *txTail) loadFromDisk(l ledgerForTracker) error {
t.lastValid = make(map[basics.Round]map[transactions.Txid]struct{})
t.recent = make(map[basics.Round]roundTxMembers)
+
+ // the roundsLastValids is a temporary map used during the execution of
+ // loadFromDisk, allowing us to construct the lastValid maps in their
+ // optimal size. This would ensure that upon startup, we don't preallocate
+ // more memory than we truly need.
+ roundsLastValids := make(map[basics.Round][]transactions.Txid)
+
for ; old <= latest; old++ {
blk, err := l.Block(old)
if err != nil {
@@ -71,19 +79,44 @@ func (t *txTail) loadFromDisk(l ledgerForTracker) error {
return err
}
+ consensusParams := config.Consensus[blk.CurrentProtocol]
t.recent[old] = roundTxMembers{
- txids: make(map[transactions.Txid]basics.Round),
- txleases: make(map[ledgercore.Txlease]basics.Round),
- proto: config.Consensus[blk.CurrentProtocol],
+ txleases: make(map[ledgercore.Txlease]basics.Round, len(payset)),
+ proto: consensusParams,
}
+
for _, txad := range payset {
tx := txad.SignedTxn
- t.recent[old].txids[tx.ID()] = tx.Txn.LastValid
- t.recent[old].txleases[ledgercore.Txlease{Sender: tx.Txn.Sender, Lease: tx.Txn.Lease}] = tx.Txn.LastValid
- t.putLV(tx.Txn.LastValid, tx.ID())
+ if consensusParams.SupportTransactionLeases && (tx.Txn.Lease != [32]byte{}) {
+ t.recent[old].txleases[ledgercore.Txlease{Sender: tx.Txn.Sender, Lease: tx.Txn.Lease}] = tx.Txn.LastValid
+ }
+ if tx.Txn.LastValid > t.lowWaterMark {
+ list := roundsLastValids[tx.Txn.LastValid]
+ // if the list reached capacity, resize.
+ if len(list) == cap(list) {
+ var newList []transactions.Txid
+ if cap(list) == 0 {
+ newList = make([]transactions.Txid, 0, initialLastValidArrayLen)
+ } else {
+ newList = make([]transactions.Txid, len(list), len(list)*2)
+ }
+ copy(newList[:], list[:])
+ list = newList
+ }
+ list = append(list, tx.ID())
+ roundsLastValids[tx.Txn.LastValid] = list
+ }
}
}
+ // add all the entries in roundsLastValids to their corresponding map entry in t.lastValid
+ for lastValid, list := range roundsLastValids {
+ lastValueMap := make(map[transactions.Txid]struct{}, len(list))
+ for _, id := range list {
+ lastValueMap[id] = struct{}{}
+ }
+ t.lastValid[lastValid] = lastValueMap
+ }
return nil
}
@@ -93,13 +126,12 @@ func (t *txTail) close() {
func (t *txTail) newBlock(blk bookkeeping.Block, delta ledgercore.StateDelta) {
rnd := blk.Round()
- if t.recent[rnd].txids != nil {
+ if _, has := t.recent[rnd]; has {
// Repeat, ignore
return
}
t.recent[rnd] = roundTxMembers{
- txids: delta.Txids,
txleases: delta.Txleases,
proto: config.Consensus[blk.CurrentProtocol],
}
@@ -162,15 +194,6 @@ func (t *txTail) checkDup(proto config.ConsensusParams, current basics.Round, fi
return nil
}
-func (t *txTail) getRoundTxIds(rnd basics.Round) (txMap map[transactions.Txid]bool) {
- rndtxs := t.recent[rnd].txids
- txMap = make(map[transactions.Txid]bool, len(rndtxs))
- for txid := range rndtxs {
- txMap[txid] = true
- }
- return
-}
-
func (t *txTail) putLV(lastValid basics.Round, id transactions.Txid) {
if _, ok := t.lastValid[lastValid]; !ok {
t.lastValid[lastValid] = make(map[transactions.Txid]struct{})
diff --git a/ledger/txtail_test.go b/ledger/txtail_test.go
index c314f3856..cefebedae 100644
--- a/ledger/txtail_test.go
+++ b/ledger/txtail_test.go
@@ -93,3 +93,98 @@ func TestTxTailCheckdup(t *testing.T) {
}
}
}
+
+type txTailTestLedger struct {
+ Ledger
+}
+
+const testTxTailValidityRange = 200
+const testTxTailTxnPerRound = 150
+
+func (t *txTailTestLedger) Latest() basics.Round {
+ return basics.Round(config.Consensus[protocol.ConsensusCurrentVersion].MaxTxnLife + 10)
+}
+
+func (t *txTailTestLedger) BlockHdr(r basics.Round) (bookkeeping.BlockHeader, error) {
+ return bookkeeping.BlockHeader{
+ UpgradeState: bookkeeping.UpgradeState{
+ CurrentProtocol: protocol.ConsensusCurrentVersion,
+ },
+ }, nil
+}
+
+func (t *txTailTestLedger) Block(r basics.Round) (bookkeeping.Block, error) {
+ blk := bookkeeping.Block{
+ BlockHeader: bookkeeping.BlockHeader{
+ UpgradeState: bookkeeping.UpgradeState{
+ CurrentProtocol: protocol.ConsensusCurrentVersion,
+ },
+ Round: r,
+ },
+ Payset: make(transactions.Payset, testTxTailTxnPerRound),
+ }
+ for i := range blk.Payset {
+ blk.Payset[i] = makeTxTailTestTransaction(r, i)
+ }
+
+ return blk, nil
+}
+func makeTxTailTestTransaction(r basics.Round, txnIdx int) (txn transactions.SignedTxnInBlock) {
+ txn.Txn.FirstValid = r
+ txn.Txn.LastValid = r + testTxTailValidityRange
+ if txnIdx%5 == 0 {
+ digest := crypto.Hash([]byte{byte(r), byte(r >> 8), byte(r >> 16), byte(r >> 24), byte(r >> 32), byte(r >> 40), byte(r >> 48), byte(r >> 56)})
+ copy(txn.Txn.Lease[:], digest[:])
+ }
+ // use 7 different senders.
+ sender := uint64((int(r) + txnIdx) % 7)
+ senderDigest := crypto.Hash([]byte{byte(sender), byte(sender >> 8), byte(sender >> 16), byte(sender >> 24), byte(sender >> 32), byte(sender >> 40), byte(sender >> 48), byte(sender >> 56)})
+ copy(txn.Txn.Sender[:], senderDigest[:])
+ return txn
+}
+
+func TestTxTailLoadFromDisk(t *testing.T) {
+ var ledger txTailTestLedger
+ txtail := txTail{}
+
+ err := txtail.loadFromDisk(&ledger)
+ require.NoError(t, err)
+ require.Equal(t, int(config.Consensus[protocol.ConsensusCurrentVersion].MaxTxnLife), len(txtail.recent))
+ require.Equal(t, testTxTailValidityRange, len(txtail.lastValid))
+ require.Equal(t, ledger.Latest(), txtail.lowWaterMark)
+
+ // do some fuzz testing for leases -
+ for i := 0; i < 5000; i++ {
+ r := basics.Round(crypto.RandUint64() % uint64(ledger.Latest()))
+ txIdx := int(crypto.RandUint64() % uint64(len(txtail.recent)))
+ txn := makeTxTailTestTransaction(r, txIdx)
+ if txn.Txn.Lease != [32]byte{} {
+ // transaction has a lease
+ txl := ledgercore.Txlease{Sender: txn.Txn.Sender, Lease: txn.Txn.Lease}
+ dupResult := txtail.checkDup(
+ config.Consensus[protocol.ConsensusCurrentVersion], ledger.Latest(),
+ txn.Txn.FirstValid, txn.Txn.LastValid, txn.Txn.ID(),
+ txl)
+ if r >= ledger.Latest()-testTxTailValidityRange {
+ require.Equal(t, ledgercore.MakeLeaseInLedgerError(txn.Txn.ID(), txl), dupResult)
+ } else {
+ require.Equal(t, &txtailMissingRound{round: txn.Txn.LastValid}, dupResult)
+ }
+ } else {
+ // transaction has no lease
+ dupResult := txtail.checkDup(
+ config.Consensus[protocol.ConsensusCurrentVersion], ledger.Latest(),
+ txn.Txn.FirstValid, txn.Txn.LastValid, txn.Txn.ID(),
+ ledgercore.Txlease{})
+ if r >= ledger.Latest()-testTxTailValidityRange {
+ if txn.Txn.LastValid > ledger.Latest() {
+ require.Equal(t, &ledgercore.TransactionInLedgerError{Txid: txn.Txn.ID()}, dupResult)
+ } else {
+ require.Nil(t, dupResult)
+ }
+ } else {
+ require.Equal(t, &txtailMissingRound{round: txn.Txn.LastValid}, dupResult)
+ }
+ }
+ }
+}
diff --git a/libgoal/libgoal.go b/libgoal/libgoal.go
index d09cbf7e7..87cfcbaa6 100644
--- a/libgoal/libgoal.go
+++ b/libgoal/libgoal.go
@@ -382,7 +382,7 @@ func (c *Client) GenerateAddress(walletHandle []byte) (string, error) {
return resp.Address, nil
}
-// CreateMultisigAccount takes a wallet handle, a list of (nonmultisig) addresses, and a threshold and creates (and returns) a multisig adress
+// CreateMultisigAccount takes a wallet handle, a list of (nonmultisig) addresses, and a threshold and creates (and returns) a multisig address
// TODO: Should these be raw public keys instead of addresses so users can't shoot themselves in the foot by passing in a multisig addr? Probably will become irrelevant after CSID changes.
func (c *Client) CreateMultisigAccount(walletHandle []byte, threshold uint8, addrs []string) (string, error) {
// convert the addresses into public keys
@@ -687,8 +687,33 @@ func (c *Client) AssetInformation(index uint64) (resp v1.AssetParams, err error)
// AssetInformationV2 takes an asset's index and returns its information
func (c *Client) AssetInformationV2(index uint64) (resp generatedV2.Asset, err error) {
algod, err := c.ensureAlgodClient()
- if err == nil {
- resp, err = algod.AssetInformationV2(index)
+ if err != nil {
+ return
+ }
+ resp, err = algod.AssetInformationV2(index)
+ if err != nil {
+ return generatedV2.Asset{}, err
+ }
+
+ byteLen := func(p *[]byte) int {
+ if p == nil {
+ return 0
+ }
+ return len(*p)
+ }
+
+ // these conversions are in case the strings are not a UTF-8 printable
+ if byteLen(resp.Params.NameB64) > 0 {
+ resp.Params.Name = new(string)
+ *resp.Params.Name = string(*resp.Params.NameB64)
+ }
+ if byteLen(resp.Params.UnitNameB64) > 0 {
+ resp.Params.UnitName = new(string)
+ *resp.Params.UnitName = string(*resp.Params.UnitNameB64)
+ }
+ if byteLen(resp.Params.UrlB64) > 0 {
+ resp.Params.Url = new(string)
+ *resp.Params.Url = string(*resp.Params.UrlB64)
}
return
}
diff --git a/logging/telemetry.go b/logging/telemetry.go
index 7258b9ca6..e231a51e9 100644
--- a/logging/telemetry.go
+++ b/logging/telemetry.go
@@ -93,24 +93,42 @@ func makeTelemetryState(cfg TelemetryConfig, hookFactory hookFactory) (*telemetr
func ReadTelemetryConfigOrDefault(dataDir string, genesisID string) (cfg TelemetryConfig, err error) {
err = nil
dataDirProvided := dataDir != ""
+ var configPath string
+
+ // If we have a data directory, then load the config
if dataDirProvided {
- configPath := filepath.Join(dataDir, TelemetryConfigFilename)
+ configPath = filepath.Join(dataDir, TelemetryConfigFilename)
+ // Load the config, if the GUID is there then we are all set
+ // However if it isn't there then we must create it, save the file and load it.
cfg, err = LoadTelemetryConfig(configPath)
}
+
+ // We couldn't load the telemetry config for some reason
+ // If the reason is because the directory doesn't exist or we didn't provide a data directory then...
if (err != nil && os.IsNotExist(err)) || !dataDirProvided {
- var configPath string
+
configPath, err = config.GetConfigFilePath(TelemetryConfigFilename)
if err != nil {
+ // In this case we don't know what to do since we couldn't
+ // create the directory. Just create an ephemeral config.
cfg = createTelemetryConfig()
return
}
+
+ // Load the telemetry from the default config path
cfg, err = LoadTelemetryConfig(configPath)
}
+
+ // If there was some error loading the configuration from the config path...
if err != nil {
+ // Create an ephemeral config
cfg = createTelemetryConfig()
+
+ // If the error was that the the config wasn't there then it wasn't really an error
if os.IsNotExist(err) {
err = nil
} else {
+ // The error was actually due to a malformed config file...just return
return
}
}
@@ -134,9 +152,20 @@ func EnsureTelemetryConfig(dataDir *string, genesisID string) (TelemetryConfig,
// EnsureTelemetryConfigCreated is the same as EnsureTelemetryConfig but it also returns a bool indicating
// whether EnsureTelemetryConfig had to create the config.
func EnsureTelemetryConfigCreated(dataDir *string, genesisID string) (TelemetryConfig, bool, error) {
+ /*
+ Our logic should be as follows:
+ - We first look inside the provided data-directory. If a config file is there, load it
+ and return it
+ - Otherwise, look in the global directory. If a config file is there, load it and return it.
+ - Otherwise, if a data-directory was provided then save the config file there.
+ - Otherwise, save the config file in the global directory
+
+ */
+
configPath := ""
var cfg TelemetryConfig
var err error
+
if dataDir != nil && *dataDir != "" {
configPath = filepath.Join(*dataDir, TelemetryConfigFilename)
cfg, err = LoadTelemetryConfig(configPath)
@@ -149,6 +178,8 @@ func EnsureTelemetryConfigCreated(dataDir *string, genesisID string) (TelemetryC
configPath, err = config.GetConfigFilePath(TelemetryConfigFilename)
if err != nil {
cfg := createTelemetryConfig()
+ // Since GetConfigFilePath failed, there is no chance that we
+ // can save the next config files
return cfg, true, err
}
cfg, err = LoadTelemetryConfig(configPath)
@@ -158,6 +189,23 @@ func EnsureTelemetryConfigCreated(dataDir *string, genesisID string) (TelemetryC
err = nil
created = true
cfg = createTelemetryConfig()
+
+ if dataDir != nil && *dataDir != "" {
+
+ /*
+ There could be a scenario where a data directory was supplied that doesn't exist.
+ In that case, we don't want to create the directory, just save in the global one
+ */
+
+ // If the directory exists...
+ if _, err := os.Stat(*dataDir); err == nil {
+
+ // Remember, if we had a data directory supplied we want to save the config there
+ configPath = filepath.Join(*dataDir, TelemetryConfigFilename)
+ }
+
+ }
+
cfg.FilePath = configPath // Initialize our desired cfg.FilePath
// There was no config file, create it.
diff --git a/logging/telemetryConfig.go b/logging/telemetryConfig.go
index 0e3818c44..32aede9f4 100644
--- a/logging/telemetryConfig.go
+++ b/logging/telemetryConfig.go
@@ -33,6 +33,9 @@ import (
// TelemetryConfigFilename default file name for telemetry config "logging.config"
var TelemetryConfigFilename = "logging.config"
+var defaultTelemetryUsername = "telemetry-v9"
+var defaultTelemetryPassword = "oq%$FA1TOJ!yYeMEcJ7D688eEOE#MGCu"
+
const hostnameLength = 255
// TelemetryOverride Determines whether an override value is set and what it's value is.
@@ -65,8 +68,8 @@ func createTelemetryConfig() TelemetryConfig {
MinLogLevel: logrus.WarnLevel,
ReportHistoryLevel: logrus.WarnLevel,
// These credentials are here intentionally. Not a bug.
- UserName: "telemetry-v9",
- Password: "oq%$FA1TOJ!yYeMEcJ7D688eEOE#MGCu",
+ UserName: defaultTelemetryUsername,
+ Password: defaultTelemetryPassword,
}
}
@@ -89,6 +92,14 @@ func (cfg TelemetryConfig) Save(configPath string) error {
marshaledConfig.MinLogLevel = uint32(cfg.MinLogLevel)
marshaledConfig.ReportHistoryLevel = uint32(cfg.ReportHistoryLevel)
+ // If the configuration contains both default username and password for the telemetry
+ // server then we just want to substitute a blank string
+ if marshaledConfig.TelemetryConfig.UserName == defaultTelemetryUsername &&
+ marshaledConfig.TelemetryConfig.Password == defaultTelemetryPassword {
+ marshaledConfig.TelemetryConfig.UserName = ""
+ marshaledConfig.TelemetryConfig.Password = ""
+ }
+
enc := json.NewEncoder(f)
err = enc.Encode(marshaledConfig)
return err
@@ -127,6 +138,7 @@ func SanitizeTelemetryString(input string, maxParts int) string {
return input
}
+// Returns err if os.Open fails or if config is mal-formed
func loadTelemetryConfig(path string) (TelemetryConfig, error) {
f, err := os.Open(path)
if err != nil {
@@ -143,6 +155,11 @@ func loadTelemetryConfig(path string) (TelemetryConfig, error) {
cfg.ReportHistoryLevel = logrus.Level(marshaledConfig.ReportHistoryLevel)
cfg.FilePath = path
+ if cfg.UserName == "" && cfg.Password == "" {
+ cfg.UserName = defaultTelemetryUsername
+ cfg.Password = defaultTelemetryPassword
+ }
+
// Sanitize user-defined name.
if len(cfg.Name) > 0 {
cfg.Name = SanitizeTelemetryString(cfg.Name, 1)
diff --git a/logging/telemetryConfig_test.go b/logging/telemetryConfig_test.go
index 362ecd657..6e040d146 100644
--- a/logging/telemetryConfig_test.go
+++ b/logging/telemetryConfig_test.go
@@ -17,6 +17,7 @@
package logging
import (
+ "encoding/json"
"io/ioutil"
"os"
"path/filepath"
@@ -34,8 +35,8 @@ func Test_loadTelemetryConfig(t *testing.T) {
MinLogLevel: 4,
ReportHistoryLevel: 4,
// These credentials are here intentionally. Not a bug.
- UserName: "telemetry-v9",
- Password: "oq%$FA1TOJ!yYeMEcJ7D688eEOE#MGCu",
+ UserName: defaultTelemetryUsername,
+ Password: defaultTelemetryPassword,
}
a := require.New(t)
@@ -119,3 +120,54 @@ func TestLoadTelemetryConfig(t *testing.T) {
require.Equal(t, createTelemetryConfig().Password, tc.Password)
}
+
+func TestLoadTelemetryConfigBlankUsernamePassword(t *testing.T) {
+
+ testLoggingConfigFileName := "../test/testdata/configs/logging/logging.config.test2"
+ tc, err := loadTelemetryConfig(testLoggingConfigFileName)
+ require.NoError(t, err)
+ // make sure the user name was loaded from the specified file
+ require.Equal(t, defaultTelemetryUsername, tc.UserName)
+ // ensure we know how to default correctly if some of the fields in the configuration field aren't specified.
+ require.Equal(t, defaultTelemetryPassword, tc.Password)
+}
+
+func TestSaveTelemetryConfigBlankUsernamePassword(t *testing.T) {
+
+ testDir := os.Getenv("TESTDIR")
+
+ if testDir == "" {
+ testDir, _ = ioutil.TempDir("", "tmp")
+ }
+
+ a := require.New(t)
+
+ configsPath := filepath.Join(testDir, "logging.config")
+
+ config := createTelemetryConfig()
+
+ // Ensure that config has default username and password
+ config.UserName = defaultTelemetryUsername
+ config.Password = defaultTelemetryPassword
+
+ err := config.Save(configsPath)
+ a.NoError(err)
+
+ f, err := os.Open(configsPath)
+ a.NoError(err)
+ defer f.Close()
+
+ var cfg TelemetryConfig
+
+ var marshaledConfig MarshalingTelemetryConfig
+ marshaledConfig.TelemetryConfig = createTelemetryConfig()
+
+ dec := json.NewDecoder(f)
+ err = dec.Decode(&marshaledConfig)
+ a.NoError(err)
+
+ cfg = marshaledConfig.TelemetryConfig
+ a.Equal(cfg.UserName, "")
+ a.Equal(cfg.Password, "")
+
+}
diff --git a/logging/telemetryhook.go b/logging/telemetryhook.go
index 5c5484fc1..146843492 100644
--- a/logging/telemetryhook.go
+++ b/logging/telemetryhook.go
@@ -33,7 +33,7 @@ func createAsyncHook(wrappedHook logrus.Hook, channelDepth uint, maxQueueDepth i
}
func createAsyncHookLevels(wrappedHook logrus.Hook, channelDepth uint, maxQueueDepth int, levels []logrus.Level) *asyncTelemetryHook {
- // one time check to see if the wrappedHook is ready (true for mocked telemetry)
+ // needed by 'makeTelemetryTestFixtureWithConfig' to mark ready in unit tests.
tfh, ok := wrappedHook.(*telemetryFilteredHook)
ready := ok && tfh.wrappedHook != nil
diff --git a/logging/telemetryhook_test.go b/logging/telemetryhook_test.go
index d596519e7..c60275f95 100644
--- a/logging/telemetryhook_test.go
+++ b/logging/telemetryhook_test.go
@@ -21,7 +21,6 @@ import (
"os"
"path/filepath"
"testing"
- "time"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
@@ -170,19 +169,17 @@ func TestSaveLoadConfig(t *testing.T) {
os.RemoveAll(configDir)
}
-func TestAsyncTelemetryHook_Close(t *testing.T) {
- t.Skip("We no longer ensure 100% delivery. To not block, we drop messages when they come in faster than the network sends them.")
- a := require.New(t)
- t.Parallel()
-
+func TestAsyncTelemetryHook_CloseDrop(t *testing.T) {
const entryCount = 100
+ filling := make(chan struct{})
+
testHook := makeMockTelemetryHook(logrus.DebugLevel)
testHook.cb = func(entry *logrus.Entry) {
- // Inject a delay to ensure we buffer entries
- time.Sleep(1 * time.Millisecond)
+ <-filling // Block while filling
}
hook := createAsyncHook(&testHook, 4, entryCount)
+ hook.ready = true
for i := 0; i < entryCount; i++ {
entry := logrus.Entry{
Level: logrus.ErrorLevel,
@@ -190,16 +187,14 @@ func TestAsyncTelemetryHook_Close(t *testing.T) {
hook.Fire(&entry)
}
+ close(filling)
hook.Close()
- a.Equal(entryCount, len(testHook.entries()))
+ // To not block, we drop messages when they come in faster than the network sends them.
+ require.Less(t, len(testHook.entries()), entryCount)
}
func TestAsyncTelemetryHook_QueueDepth(t *testing.T) {
- t.Skip("flakey test can fail on slow test systems")
- a := require.New(t)
- t.Parallel()
-
const entryCount = 100
const maxDepth = 10
@@ -211,6 +206,7 @@ func TestAsyncTelemetryHook_QueueDepth(t *testing.T) {
}
hook := createAsyncHook(&testHook, entryCount, maxDepth)
+ hook.ready = true
for i := 0; i < entryCount; i++ {
entry := logrus.Entry{
Level: logrus.ErrorLevel,
@@ -221,5 +217,5 @@ func TestAsyncTelemetryHook_QueueDepth(t *testing.T) {
close(filling)
hook.Close()
- a.Equal(maxDepth, len(testHook.entries()))
+ require.Equal(t, maxDepth, len(testHook.entries()))
}
diff --git a/netdeploy/network.go b/netdeploy/network.go
index 3295f5116..6cc052f52 100644
--- a/netdeploy/network.go
+++ b/netdeploy/network.go
@@ -41,11 +41,11 @@ const maxGetRelayAddressRetry = 50
// NetworkCfg contains the persisted configuration of the deployed network
type NetworkCfg struct {
- Name string
+ Name string `json:"Name,omitempty"`
// RelayDirs are directories where relays live (where we check for connection IP:Port)
// They are stored relative to root dir (e.g. "Primary")
- RelayDirs []string
- TemplateFile string // Template file used to create the network
+ RelayDirs []string `json:"RelayDirs,omitempty"`
+ TemplateFile string `json:"TemplateFile,omitempty"` // Template file used to create the network
}
// Network represents an instance of a deployed network
@@ -139,7 +139,14 @@ func (n Network) Name() string {
// PrimaryDataDir returns the primary data directory for the network
func (n Network) PrimaryDataDir() string {
- return n.getNodeFullPath(n.cfg.RelayDirs[0])
+ if !n.gen.DevMode || len(n.cfg.RelayDirs) > 0 {
+ return n.getNodeFullPath(n.cfg.RelayDirs[0])
+ }
+ // for devmode, there should be only a single node, so pick it up.
+ for nodeName := range n.nodeDirs {
+ return n.getNodeFullPath(nodeName)
+ }
+ panic(fmt.Errorf("neither relay directories nor node directories are defined for the network"))
}
// NodeDataDirs returns an array of node data directories (not the relays)
diff --git a/network/connPerfMon.go b/network/connPerfMon.go
index 79a1bf564..b81867722 100644
--- a/network/connPerfMon.go
+++ b/network/connPerfMon.go
@@ -58,7 +58,7 @@ type pmMessage struct {
type pmPeerStatistics struct {
peer Peer // the peer interface
peerDelay int64 // the peer avarage relative message delay
- peerFirstMessage float32 // what precentage of the messages were delivered by this peer before any other peer
+ peerFirstMessage float32 // what percentage of the messages were delivered by this peer before any other peer
}
// pmStatistics is the resulting datastructure of the performance analysis.
@@ -88,7 +88,7 @@ type connectionPerformanceMonitor struct {
connectionDelay map[Peer]int64 // contains the total delay we've sustained by each peer when we're in stages pmStagePresync-pmStageStopping and the average delay after that. ( in nano seconds )
firstMessageCount map[Peer]int64 // maps the peers to their accumulated first messages ( the number of times a message seen coming from this peer first )
msgCount int64 // total number of messages that we've accumulated.
- accumulationTime int64 // the duration of which we're going to accumulate messages. This will get randomized to prevent cross-node syncronization.
+ accumulationTime int64 // the duration of which we're going to accumulate messages. This will get randomized to prevent cross-node synchronization.
}
// makeConnectionPerformanceMonitor creates a new performance monitor instance, that is configured for monitoring the given message tags.
@@ -369,7 +369,7 @@ func (pm *connectionPerformanceMonitor) accumulateMessage(msg *IncomingMessage,
}
// we already seen this digest
// make sure we're only moving forward in time. This could be caused when
- // we have lock contension.
+ // we have lock contention.
pendingMsg.peerMsgTime[msg.Sender] = msg.Received
if msg.Received < pendingMsg.firstPeerTime {
pendingMsg.firstPeerTime = msg.Received
diff --git a/network/netprio.go b/network/netprio.go
index eb64142a8..fc7e82302 100644
--- a/network/netprio.go
+++ b/network/netprio.go
@@ -18,6 +18,7 @@ package network
import (
"container/heap"
+ "sync/atomic"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/protocol"
@@ -125,6 +126,7 @@ func (pt *prioTracker) setPriority(peer *wsPeer, addr basics.Address, weight uin
peer.prioAddress = addr
peer.prioWeight = weight
heap.Fix(peersHeap{wn}, peer.peerIndex)
+ atomic.AddInt32(&wn.peersChangeCounter, 1)
}
func (pt *prioTracker) removePeer(peer *wsPeer) {
diff --git a/network/phonebook.go b/network/phonebook.go
index a02bb48af..ea08d1bba 100644
--- a/network/phonebook.go
+++ b/network/phonebook.go
@@ -216,7 +216,7 @@ func (e *phonebookImpl) GetConnectionWaitTime(addr string) (addrInPhonebook bool
if !addrInPhonebook {
// The addr is not in this phonebook.
// Will find the addr in a different phonebook.
- return addrInPhonebook, 0 /* not unsed */, curTime /* not unsed */
+ return addrInPhonebook, 0 /* not used */, curTime /* not used */
}
var timeSince time.Duration
@@ -237,7 +237,7 @@ func (e *phonebookImpl) GetConnectionWaitTime(addr string) (addrInPhonebook bool
numElts := len(e.data[addr].recentConnectionTimes)
if uint(numElts) >= e.connectionsRateLimitingCount {
return addrInPhonebook, /* true */
- (e.connectionsRateLimitingWindow - timeSince), curTime /* not unsed */
+ (e.connectionsRateLimitingWindow - timeSince), curTime /* not used */
}
// Else, there is space in connectionsRateLimitingCount. The
diff --git a/network/requestLogger.go b/network/requestLogger.go
index d8f960a08..7b4d9c014 100644
--- a/network/requestLogger.go
+++ b/network/requestLogger.go
@@ -30,7 +30,7 @@ import (
// RequestLogger is a middleware helps logging all the incoming http requests.
// The intended use is to place it at the bottom of the http processing. It will capture the status codes
-// set by the upsteam handlers and write the request info/response to the logger.
+// set by the upstream handlers and write the request info/response to the logger.
type RequestLogger struct {
downsteamHandler http.Handler
trackingWritersPool sync.Pool
diff --git a/network/requestTracker.go b/network/requestTracker.go
index 91660eee5..0fade36e3 100644
--- a/network/requestTracker.go
+++ b/network/requestTracker.go
@@ -142,7 +142,7 @@ func (ard *hostIncomingRequests) add(trackerRequest *TrackerRequest) {
return
}
-// countConnections counts the number of connection that we have that occured after the provided specified time
+// countConnections counts the number of connection that we have that occurred after the provided specified time
func (ard *hostIncomingRequests) countConnections(rateLimitingWindowStartTime time.Time) (count uint) {
i := ard.findTimestampIndex(rateLimitingWindowStartTime)
return uint(len(ard.requests) - i + len(ard.additionalHostRequests))
diff --git a/network/wsNetwork.go b/network/wsNetwork.go
index f6ad3e401..0a0006531 100644
--- a/network/wsNetwork.go
+++ b/network/wsNetwork.go
@@ -371,7 +371,7 @@ type WebsocketNetwork struct {
// connPerfMonitor is used on outgoing connections to measure their relative message timing
connPerfMonitor *connectionPerformanceMonitor
- // lastNetworkAdvanceMu syncronized teh access to lastNetworkAdvance
+ // lastNetworkAdvanceMu syncronized the access to lastNetworkAdvance
lastNetworkAdvanceMu deadlock.Mutex
// lastNetworkAdvance contains the last timestamp where the agreement protocol was able to make a notable progress.
@@ -402,6 +402,12 @@ type WebsocketNetwork struct {
// that messagesOfInterestEnc does not change once it is set during
// network start.
messagesOfInterestMu deadlock.Mutex
+
+ // peersConnectivityCheckTicker is the timer for testing that all the connected peers
+ // are still transmitting or receiving information. The channel produced by this ticker
+ // is consumed by any of the messageHandlerThread(s). The ticker itself is created during
+ // Start(), and being shut down when Stop() is called.
+ peersConnectivityCheckTicker *time.Ticker
}
type broadcastRequest struct {
@@ -429,7 +435,7 @@ func (wn *WebsocketNetwork) Address() (string, bool) {
}
// PublicAddress what we tell other nodes to connect to.
-// Might be different than our locally percieved network address due to NAT/etc.
+// Might be different than our locally perceived network address due to NAT/etc.
// Returns config "PublicAddress" if available, otherwise local addr.
func (wn *WebsocketNetwork) PublicAddress() string {
if len(wn.config.PublicAddress) > 0 {
@@ -789,9 +795,15 @@ func (wn *WebsocketNetwork) Start() {
wn.wg.Add(1)
go wn.pingThread()
}
+ // we shouldn't have any ticker here.. but in case we do - just stop it.
+ if wn.peersConnectivityCheckTicker != nil {
+ wn.peersConnectivityCheckTicker.Stop()
+ }
+ wn.peersConnectivityCheckTicker = time.NewTicker(connectionActivityMonitorInterval)
for i := 0; i < incomingThreads; i++ {
wn.wg.Add(1)
- go wn.messageHandlerThread()
+ // We pass the peersConnectivityCheckTicker.C here so that we don't need to syncronize the access to the ticker's data structure.
+ go wn.messageHandlerThread(wn.peersConnectivityCheckTicker.C)
}
wn.wg.Add(1)
go wn.broadcastThread()
@@ -832,6 +844,12 @@ func (wn *WebsocketNetwork) innerStop() {
func (wn *WebsocketNetwork) Stop() {
wn.handlers.ClearHandlers([]Tag{})
+ // if we have a working ticker, just stop it and clear it out. The access to this variable is safe since the Start()/Stop() are synced by the
+ // caller, and the WebsocketNetwork doesn't access wn.peersConnectivityCheckTicker directly.
+ if wn.peersConnectivityCheckTicker != nil {
+ wn.peersConnectivityCheckTicker.Stop()
+ wn.peersConnectivityCheckTicker = nil
+ }
wn.innerStop()
var listenAddr string
if wn.listener != nil {
@@ -1126,10 +1144,9 @@ func (wn *WebsocketNetwork) ServeHTTP(response http.ResponseWriter, request *htt
incomingPeers.Set(float64(wn.numIncomingPeers()), nil)
}
-func (wn *WebsocketNetwork) messageHandlerThread() {
+func (wn *WebsocketNetwork) messageHandlerThread(peersConnectivityCheckCh <-chan time.Time) {
defer wn.wg.Done()
- inactivityCheckTicker := time.NewTicker(connectionActivityMonitorInterval)
- defer inactivityCheckTicker.Stop()
+
for {
select {
case <-wn.ctx.Done():
@@ -1172,7 +1189,7 @@ func (wn *WebsocketNetwork) messageHandlerThread() {
}
default:
}
- case <-inactivityCheckTicker.C:
+ case <-peersConnectivityCheckCh:
// go over the peers and ensure we have some type of communication going on.
wn.checkPeersConnectivity()
}
@@ -1346,7 +1363,7 @@ func (wn *WebsocketNetwork) peerSnapshot(dest []*wsPeer) ([]*wsPeer, int32) {
// clear out the unused portion of the peers array to allow the GC to cleanup unused peers.
remainderPeers := dest[len(wn.peers):cap(dest)]
for i := range remainderPeers {
- // we want to delete only up to the first nil peer, since we're always writing to this array from the begining to the end
+ // we want to delete only up to the first nil peer, since we're always writing to this array from the beginning to the end
if remainderPeers[i] == nil {
break
}
@@ -1854,7 +1871,7 @@ var SupportedProtocolVersions = []string{"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 Introducted topic key/data pairs and enabled services over the gossip connections
+ * 2.1 Introduced topic key/data pairs and enabled services over the gossip connections
*/
const ProtocolVersion = "2.1"
@@ -1894,18 +1911,35 @@ var errBcastInvalidArray = errors.New("invalid broadcast array")
var errBcastQFull = errors.New("broadcast queue full")
-// HostColonPortPattern matches "^[^:]+:\\d+$" e.g. "foo.com.:1234"
-var HostColonPortPattern = regexp.MustCompile("^[^:]+:\\d+$")
+var errURLNoHost = errors.New("could not parse a host from url")
+
+// HostColonPortPattern matches "^[-a-zA-Z0-9.]+:\\d+$" e.g. "foo.com.:1234"
+var HostColonPortPattern = regexp.MustCompile("^[-a-zA-Z0-9.]+:\\d+$")
// ParseHostOrURL handles "host:port" or a full URL.
// Standard library net/url.Parse chokes on "host:port".
func ParseHostOrURL(addr string) (*url.URL, error) {
- var parsedURL *url.URL
+ // If the entire addr is "host:port" grab that right away.
+ // Don't try url.Parse() because that will grab "host:" as if it were "scheme:"
if HostColonPortPattern.MatchString(addr) {
- parsedURL = &url.URL{Scheme: "http", Host: addr}
- return parsedURL, nil
+ return &url.URL{Scheme: "http", Host: addr}, nil
+ }
+ parsed, err := url.Parse(addr)
+ if err == nil {
+ if parsed.Host == "" {
+ return nil, errURLNoHost
+ }
+ return parsed, nil
+ }
+ if strings.HasPrefix(addr, "http:") || strings.HasPrefix(addr, "https:") || strings.HasPrefix(addr, "ws:") || strings.HasPrefix(addr, "wss:") || strings.HasPrefix(addr, "://") || strings.HasPrefix(addr, "//") {
+ return parsed, err
+ }
+ // This turns "[::]:4601" into "http://[::]:4601" which url.Parse can do
+ parsed, e2 := url.Parse("http://" + addr)
+ if e2 == nil {
+ return parsed, nil
}
- return url.Parse(addr)
+ return parsed, err /* return original err, not our prefix altered try */
}
// addrToGossipAddr parses host:port or a URL and returns the URL to the websocket interface at that address.
@@ -1923,7 +1957,7 @@ func (wn *WebsocketNetwork) addrToGossipAddr(addr string) (string, error) {
return parsedURL.String(), nil
}
-// tryConnectReserveAddr synchronously checks that addr is not already being connected to, returns (websocket URL or "", true if connection may procede)
+// tryConnectReserveAddr synchronously checks that addr is not already being connected to, returns (websocket URL or "", true if connection may proceed)
func (wn *WebsocketNetwork) tryConnectReserveAddr(addr string) (gossipAddr string, ok bool) {
wn.tryConnectLock.Lock()
defer wn.tryConnectLock.Unlock()
@@ -1949,7 +1983,7 @@ func (wn *WebsocketNetwork) tryConnectReserveAddr(addr string) (gossipAddr strin
return gossipAddr, true
}
-// tryConnectReleaseAddr should be called when connection succedes and becomes a peer or fails and is no longer being attempted
+// tryConnectReleaseAddr should be called when connection succeeds and becomes a peer or fails and is no longer being attempted
func (wn *WebsocketNetwork) tryConnectReleaseAddr(addr, gossipAddr string) {
wn.tryConnectLock.Lock()
defer wn.tryConnectLock.Unlock()
@@ -2001,7 +2035,7 @@ func (wn *WebsocketNetwork) tryConnect(addr, gossipAddr string) {
for _, supportedProtocolVersion := range SupportedProtocolVersions {
requestHeader.Add(ProtocolAcceptVersionHeader, supportedProtocolVersion)
}
- // for backward compatability, include the ProtocolVersion header as well.
+ // for backward compatibility, include the ProtocolVersion header as well.
requestHeader.Set(ProtocolVersionHeader, ProtocolVersion)
SetUserAgentHeader(requestHeader)
myInstanceName := wn.log.GetInstanceName()
diff --git a/network/wsNetwork_test.go b/network/wsNetwork_test.go
index 3ac4a86c8..0eef556b9 100644
--- a/network/wsNetwork_test.go
+++ b/network/wsNetwork_test.go
@@ -24,6 +24,7 @@ import (
"math/rand"
"net"
"net/http"
+ "net/url"
"os"
"runtime"
"sort"
@@ -887,12 +888,12 @@ func TestDupFilter(t *testing.T) {
waitReady(t, netC, readyTimeout.C)
t.Log("c ready")
- // TODO: this test has two halves that exercise inbound de-dup and outbound non-send due to received hash. But it doesn't properly _test_ them as it doesn't measure _why_ it receives each message exactly once. The second half below could actualy be because of the same inbound de-dup as this first half. You can see the actions of either in metrics.
+ // TODO: this test has two halves that exercise inbound de-dup and outbound non-send due to received hash. But it doesn't properly _test_ them as it doesn't measure _why_ it receives each message exactly once. The second half below could actually be because of the same inbound de-dup as this first half. You can see the actions of either in metrics.
// algod_network_duplicate_message_received_total{} 2
// algod_outgoing_network_message_filtered_out_total{} 2
// Maybe we should just .Set(0) those counters and use them in this test?
- // This exercizes inbound dup detection.
+ // This exercise inbound dup detection.
netA.Broadcast(context.Background(), protocol.AgreementVoteTag, msg, true, nil)
netA.Broadcast(context.Background(), protocol.AgreementVoteTag, msg, true, nil)
netA.Broadcast(context.Background(), protocol.AgreementVoteTag, msg, true, nil)
@@ -1127,6 +1128,7 @@ func TestWebsocketNetworkPrioLimit(t *testing.T) {
netB := makeTestWebsocketNode(t)
netB.SetPrioScheme(&prioB)
netB.config.GossipFanout = 1
+ netB.config.NetAddress = ""
netB.phonebook.ReplacePeerList([]string{addrA}, "default", PhoneBookEntryRelayRole)
netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: counterB}})
netB.Start()
@@ -1140,6 +1142,7 @@ func TestWebsocketNetworkPrioLimit(t *testing.T) {
netC := makeTestWebsocketNode(t)
netC.SetPrioScheme(&prioC)
netC.config.GossipFanout = 1
+ netC.config.NetAddress = ""
netC.phonebook.ReplacePeerList([]string{addrA}, "default", PhoneBookEntryRelayRole)
netC.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.TxnTag, MessageHandler: counterC}})
netC.Start()
@@ -1147,30 +1150,45 @@ func TestWebsocketNetworkPrioLimit(t *testing.T) {
// Wait for response messages to propagate from B+C to A
select {
- case <-netA.prioResponseChan:
+ case peer := <-netA.prioResponseChan:
+ netA.peersLock.RLock()
+ require.Subset(t, []uint64{prioB.prio, prioC.prio}, []uint64{peer.prioWeight})
+ netA.peersLock.RUnlock()
case <-time.After(time.Second):
t.Errorf("timeout on netA.prioResponseChan 1")
}
select {
- case <-netA.prioResponseChan:
+ case peer := <-netA.prioResponseChan:
+ netA.peersLock.RLock()
+ require.Subset(t, []uint64{prioB.prio, prioC.prio}, []uint64{peer.prioWeight})
+ netA.peersLock.RUnlock()
case <-time.After(time.Second):
t.Errorf("timeout on netA.prioResponseChan 2")
}
waitReady(t, netA, time.After(time.Second))
+ firstPeer := netA.peers[0]
netA.Broadcast(context.Background(), protocol.TxnTag, nil, true, nil)
+ failed := false
select {
case <-counterBdone:
case <-time.After(time.Second):
t.Errorf("timeout, B did not receive message")
+ failed = true
}
select {
case <-counterCdone:
t.Errorf("C received message")
+ failed = true
case <-time.After(time.Second):
}
+
+ if failed {
+ t.Errorf("NetA had the following two peers priorities : [0]:%s=%d [1]:%s=%d", netA.peers[0].rootURL, netA.peers[0].prioWeight, netA.peers[1].rootURL, netA.peers[1].prioWeight)
+ t.Errorf("first peer before broadcasting was %s", firstPeer.rootURL)
+ }
}
// Create many idle connections, to see if we have excessive CPU utilization.
@@ -1579,7 +1597,7 @@ func handleTopicRequest(msg IncomingMessage) (out OutgoingMessage) {
}
}
-// Set up two nodes, test topics send/recieve is working
+// Set up two nodes, test topics send/receive is working
func TestWebsocketNetworkTopicRoundtrip(t *testing.T) {
var topicMsgReqTag Tag = protocol.UniEnsBlockReqTag
netA := makeTestWebsocketNode(t)
@@ -1969,3 +1987,53 @@ func BenchmarkVariableTransactionMessageBlockSizes(t *testing.B) {
txnCount += txnCount/4 + 1
}
}
+
+type urlCase struct {
+ text string
+ out url.URL
+}
+
+func TestParseHostOrURL(t *testing.T) {
+ urlTestCases := []urlCase{
+ {"localhost:123", url.URL{Scheme: "http", Host: "localhost:123"}},
+ {"http://localhost:123", url.URL{Scheme: "http", Host: "localhost:123"}},
+ {"ws://localhost:9999", url.URL{Scheme: "ws", Host: "localhost:9999"}},
+ {"wss://localhost:443", url.URL{Scheme: "wss", Host: "localhost:443"}},
+ {"https://localhost:123", url.URL{Scheme: "https", Host: "localhost:123"}},
+ {"https://somewhere.tld", url.URL{Scheme: "https", Host: "somewhere.tld"}},
+ {"http://127.0.0.1:123", url.URL{Scheme: "http", Host: "127.0.0.1:123"}},
+ {"//somewhere.tld", url.URL{Scheme: "", Host: "somewhere.tld"}},
+ {"//somewhere.tld:4601", url.URL{Scheme: "", Host: "somewhere.tld:4601"}},
+ {"http://[::]:123", url.URL{Scheme: "http", Host: "[::]:123"}},
+ {"1.2.3.4:123", url.URL{Scheme: "http", Host: "1.2.3.4:123"}},
+ {"[::]:123", url.URL{Scheme: "http", Host: "[::]:123"}},
+ {"r2-devnet.devnet.algodev.network:4560", url.URL{Scheme: "http", Host: "r2-devnet.devnet.algodev.network:4560"}},
+ }
+ badUrls := []string{
+ "justahost",
+ "localhost:WAT",
+ "http://localhost:WAT",
+ "https://localhost:WAT",
+ "ws://localhost:WAT",
+ "wss://localhost:WAT",
+ "//localhost:WAT",
+ "://badaddress", // See rpcs/blockService_test.go TestRedirectFallbackEndpoints
+ "://localhost:1234",
+ }
+ for _, tc := range urlTestCases {
+ t.Run(tc.text, func(t *testing.T) {
+ v, err := ParseHostOrURL(tc.text)
+ require.NoError(t, err)
+ if tc.out != *v {
+ t.Errorf("url wanted %#v, got %#v", tc.out, v)
+ return
+ }
+ })
+ }
+ for _, addr := range badUrls {
+ t.Run(addr, func(t *testing.T) {
+ _, err := ParseHostOrURL(addr)
+ require.Error(t, err, "url should fail", addr)
+ })
+ }
+}
diff --git a/network/wsPeer.go b/network/wsPeer.go
index a3f248978..f9e5e1dc1 100644
--- a/network/wsPeer.go
+++ b/network/wsPeer.go
@@ -200,7 +200,7 @@ type wsPeer struct {
// responseChannelsMutex guards the operations of responseChannels
responseChannelsMutex deadlock.RWMutex
- // sendMessageTag is a map of allowed message to send to a peer. We don't use any syncronization on this map, and the
+ // sendMessageTag is a map of allowed message to send to a peer. We don't use any synchronization on this map, and the
// only gurentee is that it's being accessed only during startup and/or by the sending loop go routine.
sendMessageTag map[protocol.Tag]bool
@@ -579,7 +579,7 @@ func (wp *wsPeer) writeLoopSend(msgs sendMessages) disconnectReason {
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 recieve: %d > %d tag=%s", len(msg.data), maxMessageLength, string(msg.data[0:2]))
+ 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
return disconnectReasonNone
}
diff --git a/node/impls.go b/node/impls.go
index 4aafa0c1a..67f9963a0 100644
--- a/node/impls.go
+++ b/node/impls.go
@@ -108,7 +108,7 @@ func (l agreementLedger) EnsureDigest(cert agreement.Certificate, verifier *agre
// The channel send to UnmatchedPendingCertificates is guaranteed to be non-blocking since due to the fact that -
// 1. the channel capacity is 1
// 2. we just cleared a single item off this channel ( if there was any )
- // 3. the EnsureDigest method is being called with the agreeement service guarantee
+ // 3. the EnsureDigest method is being called with the agreement service guarantee
// 4. no other senders to this channel exists
l.UnmatchedPendingCertificates <- catchup.PendingUnmatchedCertificate{Cert: cert, VoteVerifier: verifier}
}
diff --git a/node/indexer/indexer_test.go b/node/indexer/indexer_test.go
index e6387dded..6be41dbbe 100644
--- a/node/indexer/indexer_test.go
+++ b/node/indexer/indexer_test.go
@@ -110,7 +110,7 @@ func (s *IndexSuite) TestIndexer_GetRoundsByAddress() {
}
func (s *IndexSuite) TestIndexer_DuplicateRounds() {
- // Get Transactions (we're guranteed to have more than one txn per address per block)
+ // Get Transactions (we're guaranteed to have more than one txn per address per block)
res, err := s.idx.GetRoundsByAddress(s.addrs[0].String(), 100)
diff --git a/node/node.go b/node/node.go
index f0ec9c67c..089a303e4 100644
--- a/node/node.go
+++ b/node/node.go
@@ -113,6 +113,7 @@ type AlgorandFullNode struct {
rootDir string
genesisID string
genesisHash crypto.Digest
+ devMode bool // is this node operates in a developer mode ? ( benign agreement, broadcasting transaction generates a new block )
log logging.Logger
@@ -164,6 +165,11 @@ func MakeFull(log logging.Logger, rootDir string, cfg config.Local, phonebookAdd
node.log = log.With("name", cfg.NetAddress)
node.genesisID = genesis.ID()
node.genesisHash = crypto.HashObj(genesis)
+ node.devMode = genesis.DevMode
+
+ if node.devMode {
+ cfg.DisableNetworking = true
+ }
// tie network, block fetcher, and agreement services together
p2pNode, err := network.NewWebsocketNetwork(node.log, node.config, phonebookAddresses, genesis.ID(), genesis.Network)
@@ -184,7 +190,7 @@ func MakeFull(log logging.Logger, rootDir string, cfg config.Local, phonebookAdd
// create initial ledger, if it doesn't exist
err = os.Mkdir(genesisDir, 0700)
if err != nil && !os.IsExist(err) {
- log.Errorf("Unable to create genesis directroy: %v", err)
+ log.Errorf("Unable to create genesis directory: %v", err)
return nil, err
}
var genalloc data.GenesisBalances
@@ -238,11 +244,16 @@ func MakeFull(log logging.Logger, rootDir string, cfg config.Local, phonebookAdd
blockValidator := blockValidatorImpl{l: node.ledger, verificationPool: node.highPriorityCryptoVerificationPool}
agreementLedger := makeAgreementLedger(node.ledger, node.net)
-
+ var agreementClock timers.Clock
+ if node.devMode {
+ agreementClock = timers.MakeFrozenClock()
+ } else {
+ agreementClock = timers.MakeMonotonicClock(time.Now())
+ }
agreementParameters := agreement.Parameters{
Logger: log,
Accessor: crashAccess,
- Clock: timers.MakeMonotonicClock(time.Now()),
+ Clock: agreementClock,
Local: node.config,
Network: gossip.WrapNetwork(node.net, log),
Ledger: agreementLedger,
@@ -462,10 +473,38 @@ func (node *AlgorandFullNode) Ledger() *data.Ledger {
return node.ledger
}
+// writeDevmodeBlock generates a new block for a devmode, and write it to the ledger.
+func (node *AlgorandFullNode) writeDevmodeBlock() (err error) {
+ var vb *ledger.ValidatedBlock
+ vb, err = node.transactionPool.AssembleDevModeBlock()
+ if err != nil || vb == nil {
+ return
+ }
+
+ // add the newly generated block to the ledger
+ err = node.ledger.AddValidatedBlock(*vb, agreement.Certificate{})
+ return err
+}
+
// BroadcastSignedTxGroup broadcasts a transaction group that has already been signed.
-func (node *AlgorandFullNode) BroadcastSignedTxGroup(txgroup []transactions.SignedTxn) error {
+func (node *AlgorandFullNode) BroadcastSignedTxGroup(txgroup []transactions.SignedTxn) (err error) {
+ // in developer mode, we need to take a lock, so that each new transaction group would truly
+ // render into a unique block.
+ if node.devMode {
+ node.mu.Lock()
+ defer func() {
+ // if we added the transaction successfully to the transaction pool, then
+ // attempt to generate a block and write it to the ledger.
+ if err == nil {
+ err = node.writeDevmodeBlock()
+ }
+ node.mu.Unlock()
+ }()
+ }
+
lastRound := node.ledger.Latest()
- b, err := node.ledger.BlockHdr(lastRound)
+ var b bookkeeping.BlockHeader
+ b, err = node.ledger.BlockHdr(lastRound)
if err != nil {
node.log.Errorf("could not get block header from last round %v: %v", lastRound, err)
return err
@@ -524,7 +563,7 @@ func (node *AlgorandFullNode) ListTxns(addr basics.Address, minRound basics.Roun
return result, nil
}
-// GetTransaction looks for the required txID within with a specific account withing a range of rounds (inclusive) and
+// GetTransaction looks for the required txID within with a specific account within a range of rounds (inclusive) and
// returns the SignedTxn and true iff it finds the transaction.
func (node *AlgorandFullNode) GetTransaction(addr basics.Address, txID transactions.Txid, minRound basics.Round, maxRound basics.Round) (TxnWithStatus, bool) {
// start with the most recent round, and work backwards:
diff --git a/node/node_test.go b/node/node_test.go
index 62cddbc5d..3fe3be4a9 100644
--- a/node/node_test.go
+++ b/node/node_test.go
@@ -467,7 +467,7 @@ type mismatchingDirectroyPermissionsLog struct {
func (m mismatchingDirectroyPermissionsLog) Errorf(fmts string, args ...interface{}) {
fmtStr := fmt.Sprintf(fmts, args...)
- require.Contains(m.t, fmtStr, "Unable to create genesis directroy")
+ require.Contains(m.t, fmtStr, "Unable to create genesis directory")
}
// TestMismatchingGenesisDirectoryPermissions tests to see that the os.MkDir check we have in MakeFull works as expected. It tests both the return error as well as the logged error.
diff --git a/nodecontrol/algodControl.go b/nodecontrol/algodControl.go
index 6ba5413bb..d6aed9f48 100644
--- a/nodecontrol/algodControl.go
+++ b/nodecontrol/algodControl.go
@@ -432,7 +432,7 @@ func (nc NodeController) SetConsensus(consensus config.ConsensusProtocols) error
return config.SaveConfigurableConsensus(nc.algodDataDir, consensus)
}
-// GetConsensus rebuild the consensus version from the data directroy
+// GetConsensus rebuild the consensus version from the data directory
func (nc NodeController) GetConsensus() (config.ConsensusProtocols, error) {
return config.PreloadConfigurableConsensusProtocols(nc.algodDataDir)
}
diff --git a/nodecontrol/nodeControlErrors.go b/nodecontrol/nodeControlErrors.go
index 9ebf1736f..74f62d14e 100644
--- a/nodecontrol/nodeControlErrors.go
+++ b/nodecontrol/nodeControlErrors.go
@@ -34,6 +34,6 @@ func (e *errAlgodExitedEarly) Error() string {
return fmt.Sprintf("node exited with an error code, check node.log for more details : %v", e.innerError)
}
-func (e *errAlgodExitedEarly) Unwrap(err error) error {
+func (e *errAlgodExitedEarly) Unwrap() error {
return e.innerError
}
diff --git a/protocol/codec_tester.go b/protocol/codec_tester.go
index 7a07b3580..66695910e 100644
--- a/protocol/codec_tester.go
+++ b/protocol/codec_tester.go
@@ -53,7 +53,6 @@ func RandomizeObject(template interface{}) (interface{}, error) {
if tt.Kind() != reflect.Ptr {
return nil, fmt.Errorf("RandomizeObject: must be ptr")
}
-
v := reflect.New(tt.Elem())
err := randomizeValue(v.Elem(), tt.String(), "")
return v.Interface(), err
@@ -90,28 +89,54 @@ func printWarning(warnMsg string) {
var testedDatatypesForAllocBound = map[string]bool{}
var testedDatatypesForAllocBoundMu = deadlock.Mutex{}
-func checkBoundsLimitingTag(val reflect.Value, datapath string, structTag string) (hasAllocBound bool) {
- if structTag == "" {
- return
- }
+func checkMsgpAllocBoundDirective(dataType reflect.Type) bool {
+ // does any of the go files in the package directory has the msgp:allocbound defined for that datatype ?
+ gopath := os.Getenv("GOPATH")
+ const repositoryRoot = "go-algorand/"
+ packageFilesPath := path.Join(gopath, "src", dataType.PkgPath())
+
+ if _, err := os.Stat(packageFilesPath); os.IsNotExist(err) {
+ // no such directory. Try to assemble the path based on the current working directory.
+ cwd, err := os.Getwd()
+ if err != nil {
+ return false
+ }
+ if cwdPaths := strings.SplitAfter(cwd, repositoryRoot); len(cwdPaths) == 2 {
+ cwd = cwdPaths[0]
+ } else {
+ return false
+ }
- testedDatatypesForAllocBoundMu.Lock()
- defer testedDatatypesForAllocBoundMu.Unlock()
- // make sure we test each datatype only once.
- if val.Type().Name() == "" {
- if testedDatatypesForAllocBound[datapath] {
- hasAllocBound = true
- return
+ relPkdPath := strings.SplitAfter(dataType.PkgPath(), repositoryRoot)
+ if len(relPkdPath) != 2 {
+ return false
}
- testedDatatypesForAllocBound[datapath] = true
- } else {
- if testedDatatypesForAllocBound[val.Type().Name()] {
- hasAllocBound = true
- return
+ packageFilesPath = path.Join(cwd, relPkdPath[1])
+ if _, err := os.Stat(packageFilesPath); os.IsNotExist(err) {
+ return false
}
- testedDatatypesForAllocBound[val.Type().Name()] = true
}
+ packageFiles := []string{}
+ filepath.Walk(packageFilesPath, func(path string, info os.FileInfo, err error) error {
+ if filepath.Ext(path) == ".go" {
+ packageFiles = append(packageFiles, path)
+ }
+ return nil
+ })
+ for _, packageFile := range packageFiles {
+ fileBytes, err := ioutil.ReadFile(packageFile)
+ if err != nil {
+ continue
+ }
+ if strings.Index(string(fileBytes), fmt.Sprintf("msgp:allocbound %s", dataType.Name())) != -1 {
+ // message pack alloc bound definition was found.
+ return true
+ }
+ }
+ return false
+}
+func checkBoundsLimitingTag(val reflect.Value, datapath string, structTag string) (hasAllocBound bool) {
var objType string
if val.Kind() == reflect.Slice {
objType = "slice"
@@ -119,41 +144,47 @@ func checkBoundsLimitingTag(val reflect.Value, datapath string, structTag string
objType = "map"
}
- tagsMap := parseStructTags(structTag)
+ if structTag != "" {
+ tagsMap := parseStructTags(structTag)
- if tagsMap["allocbound"] == "-" {
- printWarning(fmt.Sprintf("%s %s have an unbounded allocbound defined", objType, datapath))
- return
- }
- if _, have := tagsMap["allocbound"]; have {
- hasAllocBound = true
- return
- }
+ if tagsMap["allocbound"] == "-" {
+ printWarning(fmt.Sprintf("%s %s have an unbounded allocbound defined", objType, datapath))
+ return
+ }
- if val.Type().Name() != "" {
- // does any of the go files in the package directroy has the msgp:allocbound defined for that datatype ?
- gopath := os.Getenv("GOPATH")
- packageFilesPath := path.Join(gopath, "src", val.Type().PkgPath())
- packageFiles := []string{}
- filepath.Walk(packageFilesPath, func(path string, info os.FileInfo, err error) error {
- if filepath.Ext(path) == ".go" {
- packageFiles = append(packageFiles, path)
- }
- return nil
- })
- for _, packageFile := range packageFiles {
- fileBytes, err := ioutil.ReadFile(packageFile)
- if err != nil {
- continue
- }
- if strings.Index(string(fileBytes), fmt.Sprintf("msgp:allocbound %s", val.Type().Name())) != -1 {
- // message pack alloc bound definition was found.
- hasAllocBound = true
- return
+ if _, have := tagsMap["allocbound"]; have {
+ hasAllocBound = true
+ testedDatatypesForAllocBoundMu.Lock()
+ defer testedDatatypesForAllocBoundMu.Unlock()
+ if val.Type().Name() == "" {
+ testedDatatypesForAllocBound[datapath] = true
+ } else {
+ testedDatatypesForAllocBound[val.Type().Name()] = true
}
+ return
+ }
+ }
+ // no struct tag, or have a struct tag with no allocbound.
+ if val.Type().Name() != "" {
+ testedDatatypesForAllocBoundMu.Lock()
+ var exists bool
+ hasAllocBound, exists = testedDatatypesForAllocBound[val.Type().Name()]
+ testedDatatypesForAllocBoundMu.Unlock()
+ if !exists {
+ // does any of the go files in the package directory has the msgp:allocbound defined for that datatype ?
+ hasAllocBound = checkMsgpAllocBoundDirective(val.Type())
+ testedDatatypesForAllocBoundMu.Lock()
+ testedDatatypesForAllocBound[val.Type().Name()] = hasAllocBound
+ testedDatatypesForAllocBoundMu.Unlock()
+ return
+ } else if hasAllocBound {
+ return
}
}
- printWarning(fmt.Sprintf("%s %s does not have an allocbound defined - %s", objType, datapath, val.Type().PkgPath()))
+
+ if val.Type().Kind() == reflect.Slice || val.Type().Kind() == reflect.Map || val.Type().Kind() == reflect.Array {
+ printWarning(fmt.Sprintf("%s %s does not have an allocbound defined for %s %s", objType, datapath, val.Type().String(), val.Type().PkgPath()))
+ }
return
}
diff --git a/scripts/archtype.sh b/scripts/archtype.sh
index eb295acd3..6c7c6a8f2 100755
--- a/scripts/archtype.sh
+++ b/scripts/archtype.sh
@@ -8,7 +8,7 @@ elif [[ "${ARCH}" = "armv6l" ]]; then
echo "arm"
elif [[ "${ARCH}" = "armv7l" ]]; then
echo "arm"
-elif [[ "${ARCH}" = "aarch64" ]]; then
+elif [[ "${ARCH}" = "aarch64" ]] || [[ "${ARCH}" = "arm64" ]]; then
echo "arm64"
else
# Anything else needs to be specifically added...
diff --git a/scripts/build_packages.sh b/scripts/build_packages.sh
index bd2592f63..b434c485d 100755
--- a/scripts/build_packages.sh
+++ b/scripts/build_packages.sh
@@ -33,6 +33,7 @@ if [ "${CHANNEL}" = "" ]; then
fi
VARIATION_ARRAY=(${VARIATIONS})
+echo "Variation Array: ${VARIATION_ARRAY}"
# Set the TIMESTAMP to use for the genesis.json file - set here so all packages use the same number
TIMESTAMP=
diff --git a/scripts/buildhost/linux-arm.sh b/scripts/buildhost/linux-arm.sh
index f7b093155..4dbefa653 100755
--- a/scripts/buildhost/linux-arm.sh
+++ b/scripts/buildhost/linux-arm.sh
@@ -53,7 +53,7 @@ fi
scp -i key.pem -o "StrictHostKeyChecking no" ubuntu@$(cat instance):/home/ubuntu/armv6_stretch/id_rsa ./id_rsa
if [ "$?" != "0" ]; then
- exitWithError 1 "Unable to retreive RasPI credentials from EC2 instance at $(cat instance)"
+ exitWithError 1 "Unable to retrieve RasPI credentials from EC2 instance at $(cat instance)"
fi
echo "Waiting for RasPI SSH connection at $(cat instance)"
diff --git a/scripts/buildhost/run.sh b/scripts/buildhost/run.sh
index 5ac0e182f..26c08ca20 100755
--- a/scripts/buildhost/run.sh
+++ b/scripts/buildhost/run.sh
@@ -8,7 +8,7 @@
#
# Examples: scripts/buildhost/run.sh
#
-# Use the following travis varaibles:
+# Use the following travis variables:
# BUILD_REQUESTS_BUCKET
# BUILD_PULL_REQUESTS_BUCKET
# AWS_ACCESS_KEY_ID
diff --git a/scripts/buildtools/install_buildtools.sh b/scripts/buildtools/install_buildtools.sh
index 362e33fad..d6c0da388 100755
--- a/scripts/buildtools/install_buildtools.sh
+++ b/scripts/buildtools/install_buildtools.sh
@@ -36,6 +36,12 @@ while getopts ":o:h" opt; do
done
shift $((OPTIND -1))
+if [ "$#" -ne 0 ]; then
+ echo "Unexpected positional arguments passed to script: $@"
+ exit 1
+fi
+
+
SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
pushd .
cd ${SCRIPTPATH}
@@ -76,7 +82,7 @@ function install_go_module {
if [[ "${BUILDTOOLS_INSTALL}" != "ALL" ]]; then
install_go_module "${BUILDTOOLS_INSTALL}"
- return
+ exit 0
fi
install_go_module golang.org/x/lint golang.org/x/lint/golint
diff --git a/scripts/compute_package_name.sh b/scripts/compute_package_name.sh
index d3bfb28c5..7e53a1351 100755
--- a/scripts/compute_package_name.sh
+++ b/scripts/compute_package_name.sh
@@ -10,6 +10,10 @@
CHANNEL=${1:-stable}
NAME=${2:-algorand}
+if [ ! -z ${PACKAGE_NAME_EXTENSION} ]; then
+ NAME="${NAME}-${PACKAGE_NAME_EXTENSION}"
+fi
+
if [ "$CHANNEL" = beta ]; then
echo "$NAME-beta"
elif [ "$CHANNEL" = nightly ]; then
@@ -17,4 +21,3 @@ elif [ "$CHANNEL" = nightly ]; then
else
echo "$NAME"
fi
-
diff --git a/scripts/configure_dev-deps.sh b/scripts/configure_dev-deps.sh
index 26ef82d6b..4242d3d35 100755
--- a/scripts/configure_dev-deps.sh
+++ b/scripts/configure_dev-deps.sh
@@ -1,2 +1,2 @@
#!/usr/bin/env bash
-# this script file remained here for backward compatiblity until all the references for this file could be safely removed.
+# this script file remained here for backward compatibility until all the references for this file could be safely removed.
diff --git a/scripts/install_linux_deps.sh b/scripts/install_linux_deps.sh
index ec7151378..453bbaf70 100755
--- a/scripts/install_linux_deps.sh
+++ b/scripts/install_linux_deps.sh
@@ -6,9 +6,12 @@ DISTRIB=$ID
ARCH_DEPS="boost boost-libs expect jq autoconf shellcheck sqlite python-virtualenv"
UBUNTU_DEPS="libboost-all-dev expect jq autoconf shellcheck sqlite3 python3-venv"
+FEDORA_DEPS="boost-devel expect jq autoconf ShellCheck sqlite python-virtualenv"
if [ "${DISTRIB}" = "arch" ]; then
pacman -S --refresh --needed --noconfirm $ARCH_DEPS
+elif [ "${DISTRIB}" = "fedora" ]; then
+ dnf -y install $FEDORA_DEPS
else
apt-get update
apt-get -y install $UBUNTU_DEPS
diff --git a/scripts/release/mule/Makefile.mule b/scripts/release/mule/Makefile.mule
index 1b666f6ae..627e7fe21 100644
--- a/scripts/release/mule/Makefile.mule
+++ b/scripts/release/mule/Makefile.mule
@@ -47,9 +47,9 @@ mule-docker:
mule-package-%: PKG_TYPE=$*
mule-package-%:
- echo Building algorand package...
+ echo Building algorand package $(PKG_TYPE)...
scripts/release/mule/package/$(PKG_TYPE)/package.sh algorand
- echo Building algorand-devtools package...
+ echo Building algorand-devtools package $(PKG_TYPE)...
scripts/release/mule/package/$(PKG_TYPE)/package.sh algorand-devtools
mule-releases-page:
diff --git a/scripts/release/mule/deploy/docker/docker.sh b/scripts/release/mule/deploy/docker/docker.sh
index f0b0ffc50..c4125f041 100755
--- a/scripts/release/mule/deploy/docker/docker.sh
+++ b/scripts/release/mule/deploy/docker/docker.sh
@@ -6,7 +6,7 @@
# For betanet:
# ./docker.sh betanet
#
-set -ex
+set -e
if [ -z "$NETWORK" ] || [ -z "$VERSION" ]; then
echo "[$0] NETWORK=$NETWORK or VERSION=$VERSION is missing."
@@ -23,24 +23,14 @@ pushd docker/releases
if [ "$NETWORK" = mainnet ]
then
- # Build and push mainnet.
- ./build_releases.sh
+ # Build and push mainnet.
+ ./build_releases.sh --tagname "$VERSION"
- # Build and push testnet.
- ./build_releases.sh --network testnet
-
- if [ -z "$VERSION" ]
- then
- echo "[$0] No version specified."
- exit 1
- fi
-
- ./build_releases.sh --tagname "$VERSION"
+ # Build and push testnet.
+ ./build_releases.sh --tagname "$VERSION" --network testnet --cached
elif [ "$NETWORK" = betanet ]
then
- ./build_releases.sh --network betanet
- ./build_releases.sh --network betanet --tagname "$VERSION"
+ ./build_releases.sh --tagname "$VERSION" --network betanet
fi
popd
-
diff --git a/scripts/release/mule/deploy/releases_page/generate_releases_page.py b/scripts/release/mule/deploy/releases_page/generate_releases_page.py
index af5fbd865..88f70c638 100755
--- a/scripts/release/mule/deploy/releases_page/generate_releases_page.py
+++ b/scripts/release/mule/deploy/releases_page/generate_releases_page.py
@@ -136,7 +136,7 @@ def read_hashes(fin):
ob = {}
by_fname[fname] = ob
- # if 32 chars, it's md5; 64 is sha256, 128 is sha512. Asign to dict
+ # if 32 chars, it's md5; 64 is sha256, 128 is sha512. Assign to dict
# under those keys
if len(hashstr) == 32:
ob["md5"] = hashstr
diff --git a/scripts/release/mule/test/test.sh b/scripts/release/mule/test/test.sh
index 3fafe7c28..90a8998be 100755
--- a/scripts/release/mule/test/test.sh
+++ b/scripts/release/mule/test/test.sh
@@ -93,7 +93,7 @@ else
# We need to install this since it's not being installed by a package manager.
# Normally, this is installed for us b/c it's a dependency.
# See `./installer/rpm/algorand/algorand.spec`.
- yum install yum-cron -y
+ dnf install dnf-automatic -y
#
# Note that the RPM package DOES NOT have the CHANNEL in its filename (unlike DEB),
# instead it contains the package name.
diff --git a/scripts/release/test/util/test_package.sh b/scripts/release/test/util/test_package.sh
index 1106db0bc..397772c58 100755
--- a/scripts/release/test/util/test_package.sh
+++ b/scripts/release/test/util/test_package.sh
@@ -7,17 +7,9 @@ set -ex
. "${HOME}"/build_env
-# TODO: The following error happens on centos:8
-#
-# Error:
-# Problem: conflicting requests
-# - nothing provides yum-cron needed by algorand-2.0.4-1.x86_64
-# (try to add '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)
-# smoke_test.sh: line 47: algod: command not found
-
OS_LIST=(
centos:7
-# centos:8
+ centos:8
fedora:28
ubuntu:16.04
ubuntu:18.04
diff --git a/scripts/travis/after_build.sh b/scripts/travis/after_build.sh
index 79c414fab..f5d9ad915 100755
--- a/scripts/travis/after_build.sh
+++ b/scripts/travis/after_build.sh
@@ -8,18 +8,10 @@
#
# Examples: scripts/travis/after_build.sh
-SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
-OS=$("${SCRIPTPATH}/../ostype.sh")
-if [[ "${OS}" == "darwin" ]]; then
- # do not run these on darwin
- exit;
-fi;
-
if [ "${TRAVIS_EVENT_TYPE}" = "cron" ] || [[ "${TRAVIS_BRANCH}" =~ ^rel/ ]]; then
if [ "${BUILD_TYPE}" != "integration" ]; then
cd "$(dirname "$0")"/../.. || exit 1
make prof
- make cover
rm ./node/node.test
fi;
fi;
diff --git a/scripts/travis/build_test.sh b/scripts/travis/build_test.sh
index a52ce6478..54e95a503 100755
--- a/scripts/travis/build_test.sh
+++ b/scripts/travis/build_test.sh
@@ -15,10 +15,12 @@ SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
if [ "${USER}" = "travis" ]; then
# we're running on a travis machine
- "${SCRIPTPATH}/build.sh" --make_debug
- "${SCRIPTPATH}/travis_wait.sh" 90 "${SCRIPTPATH}/test.sh"
+ "${SCRIPTPATH}/travis_wait.sh" 30 "${SCRIPTPATH}/build.sh" --make_debug
+ # Need to call travis_retry first, if travis_wait calls travis_retry
+ # it doesn't show the output.
+ "${SCRIPTPATH}/travis_retry.sh" "${SCRIPTPATH}/travis_wait.sh" 90 "${SCRIPTPATH}/test.sh"
else
# we're running on an ephermal build machine
"${SCRIPTPATH}/build.sh" --make_debug
- "${SCRIPTPATH}/test.sh"
+ "${SCRIPTPATH}/travis_retry.sh" "${SCRIPTPATH}/test.sh"
fi
diff --git a/scripts/travis/codegen_verification.sh b/scripts/travis/codegen_verification.sh
index e354630f9..0f9f2b595 100755
--- a/scripts/travis/codegen_verification.sh
+++ b/scripts/travis/codegen_verification.sh
@@ -75,6 +75,9 @@ echo "Running fixcheck"
GOPATH=$(go env GOPATH)
"$GOPATH"/bin/algofix -error */
+echo "Updating TEAL Specs"
+make -C data/transactions/logic
+
echo Checking Enlistment...
if [[ -n $(git status --porcelain) ]]; then
echo Enlistment is dirty - did you forget to run make?
diff --git a/scripts/travis/external_build.sh b/scripts/travis/external_build.sh
index e6112dd20..7f2e07175 100755
--- a/scripts/travis/external_build.sh
+++ b/scripts/travis/external_build.sh
@@ -8,7 +8,7 @@
#
# Examples: scripts/travis/external_build.sh
#
-# Use the following travis varaibles:
+# Use the following travis variables:
# BUILD_TYPE
# TARGET_PLATFORM
# TRAVIS_BRANCH
diff --git a/scripts/travis/run_tests.sh b/scripts/travis/run_tests.sh
index 3acbe825c..0c6f278f4 100755
--- a/scripts/travis/run_tests.sh
+++ b/scripts/travis/run_tests.sh
@@ -2,9 +2,6 @@
set -e
-SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
-OS=$("${SCRIPTPATH}/../ostype.sh")
-
if [ "${BUILD_TYPE}" = "integration" ]; then
# Run short tests when doing pull requests; leave the long testing for nightly runs.
if [[ "${TRAVIS_BRANCH}" =~ ^rel/nightly ]]; then
@@ -15,13 +12,7 @@ if [ "${BUILD_TYPE}" = "integration" ]; then
export SHORTTEST
make integration
elif [ "${TRAVIS_EVENT_TYPE}" = "cron" ] || [[ "${TRAVIS_BRANCH}" =~ ^rel/ ]]; then
- if [[ "${OS}" != "darwin" ]]; then
- make fulltest -j2
- fi
+ make fulltest -j2
else
- if [[ "${OS}" != "darwin" ]]; then
- # setting it to 1 disable parallel making. This is done specicifically for travis, as travis seems to
- # have memory limitations and setting this to 1 could reduce the likelihood of hitting these.
- make shorttest -j1
- fi
+ make shorttest -j2
fi
diff --git a/scripts/travis/test.sh b/scripts/travis/test.sh
index 9958a0db7..011a970bd 100755
--- a/scripts/travis/test.sh
+++ b/scripts/travis/test.sh
@@ -15,7 +15,7 @@ chmod +x ~/gimme
eval "$(~/gimme "${GOLANG_VERSION}")"
# If this command fails the Makefile will select 'go test' instead.
-"${SCRIPTPATH}/../buildtools/install_buildtools.sh" "gotest.tools/gotestsum" || true
+"${SCRIPTPATH}/../buildtools/install_buildtools.sh" -o "gotest.tools/gotestsum" || true
if [ "${OS}-${ARCH}" = "linux-arm" ] || [ "${OS}-${ARCH}" = "windows-amd64" ]; then
# for arm, no tests need to be invoked.
diff --git a/scripts/travis/travis_retry.sh b/scripts/travis/travis_retry.sh
new file mode 100755
index 000000000..9270ccdd6
--- /dev/null
+++ b/scripts/travis/travis_retry.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+
+# https://github.com/travis-ci/travis-build/blob/master/lib/travis/build/bash/travis_retry.bash
+
+ANSI_RED="\033[31;1m"
+ANSI_RESET="\033[0m"
+
+travis_retry() {
+ local result=0
+ local count=1
+ while [[ "${count}" -le 3 ]]; do
+ [[ "${result}" -ne 0 ]] && {
+ echo -e "\\n${ANSI_RED}The command \"${*}\" failed. Retrying, ${count} of 3.${ANSI_RESET}\\n" >&2
+ }
+ # run the command in a way that doesn't disable setting `errexit`
+ "${@}"
+ result="${?}"
+ if [[ $result -eq 0 ]]; then break; fi
+ count="$((count + 1))"
+ sleep 1
+ done
+
+ [[ "${count}" -gt 3 ]] && {
+ echo -e "\\n${ANSI_RED}The command \"${*}\" failed 3 times.${ANSI_RESET}\\n" >&2
+ }
+
+ return "${result}"
+}
+
+travis_retry "$@"
diff --git a/scripts/travis/travis_wait.sh b/scripts/travis/travis_wait.sh
index 6dc7a8df9..902e9cd3f 100755
--- a/scripts/travis/travis_wait.sh
+++ b/scripts/travis/travis_wait.sh
@@ -69,4 +69,4 @@ travis_wait() {
return $result
}
-travis_wait $@ \ No newline at end of file
+travis_wait "$@"
diff --git a/test/commandandcontrol/cc_agent/main.go b/test/commandandcontrol/cc_agent/main.go
index 8fe4411b9..8e5ef9a3c 100644
--- a/test/commandandcontrol/cc_agent/main.go
+++ b/test/commandandcontrol/cc_agent/main.go
@@ -65,11 +65,11 @@ func checkFlags() (ok bool) {
ok = false
}
if len(*binDir) == 0 {
- log.Errorf("Use the -bindir flag to specifiy the location of the algod bin directory")
+ log.Errorf("Use the -bindir flag to specify the location of the algod bin directory")
ok = false
}
if len(*tempDir) == 0 {
- log.Errorf("Use the -tempdir flag to specifiy the location of the tmp directory directory")
+ log.Errorf("Use the -tempdir flag to specify the location of the tmp directory directory")
ok = false
}
return ok
diff --git a/test/e2e-go/cli/algoh/expect/algohExpectCommon.exp b/test/e2e-go/cli/algoh/expect/algohExpectCommon.exp
index 3e66dd918..be5888134 100644
--- a/test/e2e-go/cli/algoh/expect/algohExpectCommon.exp
+++ b/test/e2e-go/cli/algoh/expect/algohExpectCommon.exp
@@ -92,7 +92,7 @@ proc ::Algoh::StopNode { TEST_ALGO_DIR } {
puts "node stop with $TEST_ALGO_DIR"
spawn goal node stop -d $TEST_ALGO_DIR
expect {
- timeout { close; ::Algoh::Abort "Did not recieve appropriate message during node stop"}
+ timeout { close; ::Algoh::Abort "Did not receive appropriate message during node stop"}
"*The node was successfully stopped.*" {puts "Node stopped successfully"; close}
eof { catch wait result; if { [lindex $result 3] != 0 } { puts "Unable to stop node"; Algoh::Abort } }
diff --git a/test/e2e-go/cli/goal/expect/goalFormattingTest.exp b/test/e2e-go/cli/goal/expect/goalFormattingTest.exp
index 6f60d1061..054406479 100644
--- a/test/e2e-go/cli/goal/expect/goalFormattingTest.exp
+++ b/test/e2e-go/cli/goal/expect/goalFormattingTest.exp
@@ -12,7 +12,7 @@ if { [catch {
set TIME_STAMP [clock seconds]
- # generate invalid transaction file. ( we want to see that goal is ommitting the control characters when printing out the error message )
+ # generate invalid transaction file. ( we want to see that goal is omitting the control characters when printing out the error message )
exec echo {{ "\u001b[0G\u001b[0K\u001b[33munexpected_key\u001b[0m": 2 }} > $TEST_ALGO_DIR/tx.json
exec cat $TEST_ALGO_DIR/tx.json | msgpacktool -e -b32 > $TEST_ALGO_DIR/tx
exec rm $TEST_ALGO_DIR/tx.json
diff --git a/test/e2e-go/cli/goal/expect/goalNodeTest.exp b/test/e2e-go/cli/goal/expect/goalNodeTest.exp
index 7d4d70e92..deb0a5466 100644
--- a/test/e2e-go/cli/goal/expect/goalNodeTest.exp
+++ b/test/e2e-go/cli/goal/expect/goalNodeTest.exp
@@ -42,7 +42,7 @@ if { [catch {
-re "\\S+" { close; ::AlgorandGoal::Abort "Unexpected message for goal node start on a running node" }
eof {
if {$ALREADY_STARTED_MESSAGE_RECEIVED == 0} {
- { close; ::AlgorandGoal::Abort "eof recieved before the expected message "}
+ { close; ::AlgorandGoal::Abort "eof received before the expected message "}
}
}
}
diff --git a/test/e2e-go/cli/goal/expect/statefulTealCreateLargeAppTest.exp b/test/e2e-go/cli/goal/expect/statefulTealCreateLargeAppTest.exp
deleted file mode 100644
index afae71c1c..000000000
--- a/test/e2e-go/cli/goal/expect/statefulTealCreateLargeAppTest.exp
+++ /dev/null
@@ -1,143 +0,0 @@
-#!/usr/bin/expect -f
-#exp_internal 1
-set err 0
-log_user 1
-
-source goalExpectCommon.exp
-
-# put a TEAL program into f, with at least size and cost.
-
-set TEST_ALGO_DIR [lindex $argv 0]
-set TEST_DATA_DIR [lindex $argv 1]
-
-proc teal {f v size cost {prefix ""}} {
- set CHAN [open $f w]
- puts $CHAN "#pragma version $v\n"
- puts $CHAN $prefix
- for {set i 5} {$i < $size} {incr i 2} {
- puts $CHAN "int 1\npop\n"
- }
-
- if {$cost > [expr $size * 2]} {
- puts $CHAN "byte 0x1234\n"
- for {set i [expr $size * 2]} {$i < $cost} {incr i 130} {
- puts $CHAN "keccak256\n"
- }
- puts $CHAN "pop\n"
- }
- puts $CHAN "int 1\n"
- close $CHAN
-}
-
-
-if { [catch {
- source goalExpectCommon.exp
-
- puts "starting test"
-
- puts "TEST_ALGO_DIR: $TEST_ALGO_DIR"
- puts "TEST_DATA_DIR: $TEST_DATA_DIR"
-
-
- set timeout 60
- set TIME_STAMP [clock seconds]
-
- set TEST_ROOT_DIR $TEST_ALGO_DIR/root_$TIME_STAMP
- set TEST_PRIMARY_NODE_DIR $TEST_ROOT_DIR/Primary/
- set NETWORK_NAME test_net_expect_$TIME_STAMP
- set NETWORK_TEMPLATE "$TEST_DATA_DIR/nettemplates/TwoNodes50EachFuture.json"
-
-
- exec cp $TEST_DATA_DIR/../../installer/genesis/devnet/genesis.json $TEST_ALGO_DIR
-
- # Create network
- ::AlgorandGoal::CreateNetwork $NETWORK_NAME $NETWORK_TEMPLATE $TEST_ALGO_DIR $TEST_ROOT_DIR
-
- # Start network
- ::AlgorandGoal::StartNetwork $NETWORK_NAME $NETWORK_TEMPLATE $TEST_ROOT_DIR
-
- set PRIMARY_NODE_ADDRESS [ ::AlgorandGoal::GetAlgodNetworkAddress $TEST_PRIMARY_NODE_DIR ]
- puts "Primary Node Address: $PRIMARY_NODE_ADDRESS"
-
- set PRIMARY_WALLET_NAME unencrypted-default-wallet
-
- # Determine primary account
- set PRIMARY_ACCOUNT_ADDRESS [::AlgorandGoal::GetHighestFundedAccountForWallet $PRIMARY_WALLET_NAME $TEST_PRIMARY_NODE_DIR]
-
- # Check the balance of the primary account
- set PRIMARY_ACCOUNT_BALANCE [::AlgorandGoal::GetAccountBalance $PRIMARY_WALLET_NAME $PRIMARY_ACCOUNT_ADDRESS $TEST_PRIMARY_NODE_DIR]
- puts "Primary Account Balance: $PRIMARY_ACCOUNT_BALANCE"
-
- ::AlgorandGoal::WaitForRound 1 $TEST_PRIMARY_NODE_DIR
-
- # Create wallet #1
- set WALLET_1_NAME Wallet_1_$TIME_STAMP
- set WALLET_1_PASSWORD 1234
- set WALLET_1_PASSPHRASE [::AlgorandGoal::CreateWallet $WALLET_1_NAME $WALLET_1_PASSWORD $TEST_PRIMARY_NODE_DIR]
- puts "WALLET_1_PASSPHRASE: $WALLET_1_PASSPHRASE"
- ::AlgorandGoal::VerifyWallet $WALLET_1_NAME $TEST_PRIMARY_NODE_DIR
-
- # Associate a new account with the wallet
- set ACCOUNT_1_ADDRESS [::AlgorandGoal::CreateAccountForWallet $WALLET_1_NAME $WALLET_1_PASSWORD $TEST_PRIMARY_NODE_DIR]
- ::AlgorandGoal::VerifyAccount $WALLET_1_NAME $WALLET_1_PASSWORD $ACCOUNT_1_ADDRESS $TEST_PRIMARY_NODE_DIR
-
- # Transfer Algos from primary account to account 1
- set MIN_BALANCE 1000000
- set TRANSFER_AMOUNT [expr {1000 * $MIN_BALANCE}]
- set FEE_AMOUNT 1000
- set TRANSACTION_ID [::AlgorandGoal::AccountTransfer $PRIMARY_WALLET_NAME "" $PRIMARY_ACCOUNT_ADDRESS $TRANSFER_AMOUNT $ACCOUNT_1_ADDRESS $FEE_AMOUNT $TEST_PRIMARY_NODE_DIR ""]
-
- set GLOBAL_BYTE_SLICES 1
- set LOCAL_BYTE_SLICES 0
- set TEAL_PROGS_DIR "$TEST_DATA_DIR/../scripts/e2e_subs/tealprogs"
-
- # Create large teal programs
- teal "$TEST_ROOT_DIR/big-app.teal" 3 4090 1 "int 0\nbalance\npop\n"
- teal "$TEST_ROOT_DIR/big-app-v4.teal" 4 4090 1 "int 0\nbalance\npop\n"
-
- # Create a small program
- teal "$TEST_ROOT_DIR/sm-app.teal" 3 10 1 "int 0\nbalance\npop\n"
-
- # App create fails. Approval program too long
- spawn goal app create --creator $PRIMARY_ACCOUNT_ADDRESS --approval-prog ${TEST_ROOT_DIR}/big-app.teal --global-byteslices $GLOBAL_BYTE_SLICES --global-ints 0 --local-byteslices $LOCAL_BYTE_SLICES --local-ints 0 --app-arg "str:hello" --clear-prog ${TEST_ROOT_DIR}/big-app.teal -w $PRIMARY_WALLET_NAME -d $TEST_PRIMARY_NODE_DIR
- expect {
- timeout { puts timeout; ::AlgorandGoal::Abort "\n Failed to see expected output" }
- "approval program too long. max len 1024 bytes" {puts "received expected error"; close}
- eof { close; ::AlgorandGoal::Abort "did not receive expected error" }
- }
-
- # App create fails. Clear program too long
- spawn goal app create --creator $PRIMARY_ACCOUNT_ADDRESS --approval-prog ${TEST_ROOT_DIR}/sm-app.teal --global-byteslices $GLOBAL_BYTE_SLICES --global-ints 0 --local-byteslices $LOCAL_BYTE_SLICES --local-ints 0 --app-arg "str:hello" --clear-prog ${TEST_ROOT_DIR}/big-app.teal -w $PRIMARY_WALLET_NAME -d $TEST_PRIMARY_NODE_DIR
- expect {
- timeout { puts timeout; ::AlgorandGoal::Abort "\n Failed to see expected output" }
- "clear state program too long. max len 1024 bytes" {puts "received expected error"; close}
- eof { close; ::AlgorandGoal::Abort "did not receive expected error" }
- }
-
- # App create with extra pages, v3 teal
- spawn goal app create --creator $PRIMARY_ACCOUNT_ADDRESS --approval-prog ${TEST_ROOT_DIR}/big-app.teal --global-byteslices $GLOBAL_BYTE_SLICES --global-ints 0 --local-byteslices $LOCAL_BYTE_SLICES --local-ints 0 --app-arg "str:hello" --clear-prog ${TEST_ROOT_DIR}/big-app.teal --extra-pages 3 -w $PRIMARY_WALLET_NAME -d $TEST_PRIMARY_NODE_DIR
- expect {
- timeout { puts timeout; ::AlgorandGoal::Abort "\n Failed to see expected output" }
- "*pc=705 static cost budget of 700 exceeded" {puts "received expected message"; close}
- eof { close; ::AlgorandGoal::Abort "did not receive expected message" }
- }
-
- # App create with extra pages, v4 teal
- spawn goal app create --creator $PRIMARY_ACCOUNT_ADDRESS --approval-prog ${TEST_ROOT_DIR}/big-app-v4.teal --global-byteslices $GLOBAL_BYTE_SLICES --global-ints 0 --local-byteslices $LOCAL_BYTE_SLICES --local-ints 0 --app-arg "str:hello" --clear-prog ${TEST_ROOT_DIR}/big-app-v4.teal --extra-pages 3 -w $PRIMARY_WALLET_NAME -d $TEST_PRIMARY_NODE_DIR
- expect {
- timeout { puts timeout; ::AlgorandGoal::Abort "\n Failed to see expected output" }
- "*pc=704 dynamic cost budget of 700 exceeded, executing intc_1" {puts "received expected message"; close}
- eof { close; ::AlgorandGoal::Abort "did not receive expected message" }
- }
-
-
- # Shutdown the network
- ::AlgorandGoal::StopNetwork $NETWORK_NAME $TEST_ROOT_DIR
-
- puts "Goal Stateful Teal test Successful"
-
- exit 0
-
-} EXCEPTION ] } {
- ::AlgorandGoal::Abort "ERROR in statefulTealCreateAppTest: $EXCEPTION"
-}
diff --git a/test/e2e-go/features/catchup/catchpointCatchup_test.go b/test/e2e-go/features/catchup/catchpointCatchup_test.go
index 84b4e2f6c..6865bebfa 100644
--- a/test/e2e-go/features/catchup/catchpointCatchup_test.go
+++ b/test/e2e-go/features/catchup/catchpointCatchup_test.go
@@ -79,7 +79,6 @@ func (ec *nodeExitErrorCollector) Print() {
}
func TestBasicCatchpointCatchup(t *testing.T) {
- t.Skip("Temporarily disabling since they need work and shouldn't block releases")
if testing.Short() {
t.Skip()
}
@@ -92,7 +91,7 @@ func TestBasicCatchpointCatchup(t *testing.T) {
// Let it run for 37 rounds.
// create a web proxy, and connect it to the primary node, blocking all requests for round #1. ( and allowing everything else )
// start a secondary node, and instuct it to catchpoint catchup from the proxy. ( which would be for round 36 )
- // wait until the clone node cought up, skipping the "impossibe" hole of round #1.
+ // wait until the clone node cought up, skipping the "impossible" hole of round #1.
consensus := make(config.ConsensusProtocols)
const consensusCatchpointCatchupTestProtocol = protocol.ConsensusVersion("catchpointtestingprotocol")
@@ -119,9 +118,6 @@ func TestBasicCatchpointCatchup(t *testing.T) {
errorsCollector := nodeExitErrorCollector{t: fixtures.SynchronizedTest(t)}
defer errorsCollector.Print()
- // Give the second node (which starts up last) all the stake so that its proposal always has better credentials,
- // and so that its proposal isn't dropped. Otherwise the test burns 17s to recover. We don't care about stake
- // distribution for catchup so this is fine.
fixture.SetupNoStart(t, filepath.Join("nettemplates", "CatchpointCatchupTestNetwork.json"))
// Get primary node
@@ -217,8 +213,8 @@ func TestBasicCatchpointCatchup(t *testing.T) {
log.Infof("primary node latest catchpoint - %s!\n", *primaryNodeStatus.LastCatchpoint)
secondNodeRestClient.Catchup(*primaryNodeStatus.LastCatchpoint)
- currentRound = uint64(36)
- targetRound = uint64(37)
+ currentRound = primaryNodeStatus.LastRound
+ targetRound = currentRound + 1
log.Infof("Second node catching up to round 36")
for {
err = fixture.ClientWaitForRound(secondNodeRestClient, currentRound, 10*time.Second)
diff --git a/test/e2e-go/features/multisig/multisig_test.go b/test/e2e-go/features/multisig/multisig_test.go
index c24b4bc5f..8a086b89d 100644
--- a/test/e2e-go/features/multisig/multisig_test.go
+++ b/test/e2e-go/features/multisig/multisig_test.go
@@ -68,7 +68,7 @@ func TestBasicMultisig(t *testing.T) {
// fund account with enough Algos to allow for 3 transactions and still keep a minBalance in the account
amountToFund := 4*minAcctBalance + 3*minTxnFee
curStatus, err := client.Status()
- fixture.SendMoneyAndWait(curStatus.LastRound, amountToFund, minTxnFee, fundingAddr, multisigAddr)
+ fixture.SendMoneyAndWait(curStatus.LastRound, amountToFund, minTxnFee, fundingAddr, multisigAddr, "")
// try to transact with 1 of 3
amountToSend := minAcctBalance
unsignedTransaction, err := client.ConstructPayment(multisigAddr, addrs[0], minTxnFee, amountToSend, nil, "", [32]byte{}, 0, 0)
@@ -193,7 +193,7 @@ func TestDuplicateKeys(t *testing.T) {
amountToFund := 3 * minAcctBalance
txnFee := minTxnFee
curStatus, _ := client.Status()
- fixture.SendMoneyAndWait(curStatus.LastRound, amountToFund, txnFee, fundingAddr, multisigAddr)
+ fixture.SendMoneyAndWait(curStatus.LastRound, amountToFund, txnFee, fundingAddr, multisigAddr, "")
// try to transact with "1" signature (though, this is a signature from "every" member of the multisig)
amountToSend := minAcctBalance
unsignedTransaction, err := client.ConstructPayment(multisigAddr, addrs[0], txnFee, amountToSend, nil, "", [32]byte{}, 0, 0)
diff --git a/test/e2e-go/features/participation/onlineOfflineParticipation_test.go b/test/e2e-go/features/participation/onlineOfflineParticipation_test.go
index b6e3296ce..2c822f6f9 100644
--- a/test/e2e-go/features/participation/onlineOfflineParticipation_test.go
+++ b/test/e2e-go/features/participation/onlineOfflineParticipation_test.go
@@ -18,12 +18,16 @@ package participation
import (
"path/filepath"
+ "runtime"
"testing"
+ "time"
"github.com/stretchr/testify/require"
"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/test/e2e-go/globals"
"github.com/algorand/go-algorand/test/framework/fixtures"
)
@@ -95,20 +99,45 @@ func waitForAccountToProposeBlock(a *require.Assertions, fixture *fixtures.RestC
return false
}
+// TestNewAccountCanGoOnlineAndParticipate tests two behaviors:
+// - When the account does not have enough stake, or after receivning algos, but before the lookback rounds,
+// it should not be proposing blocks
+// - When the account balance receives enough stake, it should be proposing after lookback rounds
func TestNewAccountCanGoOnlineAndParticipate(t *testing.T) {
- /*if runtime.GOOS == "darwin" {
- t.Skip()
- }
if testing.Short() {
t.Skip()
- }*/
- t.Skip() // temporary disable the test since it's failing.
+ }
t.Parallel()
a := require.New(fixtures.SynchronizedTest(t))
+ // Make the seed lookback shorter, otherwise will wait for 320 rounds
+ consensus := make(config.ConsensusProtocols)
+ shortPartKeysProtocol := config.Consensus[protocol.ConsensusCurrentVersion]
+ shortPartKeysProtocol.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
+ shortPartKeysProtocol.SeedLookback = 2
+ shortPartKeysProtocol.SeedRefreshInterval = 8
+ if runtime.GOARCH == "amd64" {
+ // amd64 platforms are generally quite capable, so accelerate the round times to make the test run faster.
+ shortPartKeysProtocol.AgreementFilterTimeoutPeriod0 = 1 * time.Second
+ shortPartKeysProtocol.AgreementFilterTimeout = 1 * time.Second
+ }
+ consensus[protocol.ConsensusVersion("shortpartkeysprotocol")] = shortPartKeysProtocol
+
var fixture fixtures.RestClientFixture
- fixture.Setup(t, filepath.Join("nettemplates", "TwoNodesOneOnline.json"))
+ fixture.SetConsensus(consensus)
+ fixture.SetupNoStart(t, filepath.Join("nettemplates", "OneNode.json"))
+
+ // update the config file by setting the ParticipationKeysRefreshInterval to 5 second.
+ nodeDirectory, err := fixture.GetNodeDir("Primary")
+ a.NoError(err)
+ cfg, err := config.LoadConfigFromDisk(nodeDirectory)
+ a.NoError(err)
+ cfg.ParticipationKeysRefreshInterval = 5 * time.Second
+ cfg.SaveToDisk(nodeDirectory)
+
+ fixture.Start()
+
defer fixture.Shutdown()
client := fixture.LibGoalClient
@@ -129,7 +158,7 @@ func TestNewAccountCanGoOnlineAndParticipate(t *testing.T) {
transactionFee := minTxnFee
amountToSendInitial := 5 * minAcctBalance
- fixture.SendMoneyAndWait(initialRound, amountToSendInitial, transactionFee, richAccount, newAccount)
+ fixture.SendMoneyAndWait(initialRound, amountToSendInitial, transactionFee, richAccount, newAccount, "")
amt, err := client.GetBalance(newAccount)
a.NoError(err)
nodeStatus, err := client.Status()
@@ -145,7 +174,7 @@ func TestNewAccountCanGoOnlineAndParticipate(t *testing.T) {
a.NoError(err, "rest client should be able to add participation key to new account")
a.Equal(newAccount, partkeyResponse.Parent.String(), "partkey response should echo queried account")
// account uses part key to go online
- goOnlineTx, err := client.MakeUnsignedGoOnlineTx(newAccount, nil, 0, 0, transactionFee, [32]byte{})
+ goOnlineTx, err := client.MakeUnsignedGoOnlineTx(newAccount, &partkeyResponse, 0, 0, transactionFee, [32]byte{})
a.NoError(err, "should be able to make go online tx")
a.Equal(newAccount, goOnlineTx.Src().String(), "go online response should echo queried account")
onlineTxID, err := client.SignAndBroadcastTransaction(wh, nil, goOnlineTx)
@@ -159,35 +188,37 @@ func TestNewAccountCanGoOnlineAndParticipate(t *testing.T) {
newAccountStatus, err := client.AccountInformation(newAccount)
a.NoError(err, "client should be able to get information about new account")
a.Equal(basics.Online.String(), newAccountStatus.Status, "new account should be online")
- // account receives almost all of rich account's stake (minus enough to
- // keep it over MinBalance), so it will be selected for participation
+
+ // transfer the funds and close to the new account
amountToSend := richBalance - 3*transactionFee - amountToSendInitial - minAcctBalance
- fixture.SendMoneyAndWait(onlineRound, amountToSend, transactionFee, richAccount, newAccount)
+ txn := fixture.SendMoneyAndWait(onlineRound, amountToSend, transactionFee, richAccount, newAccount, newAccount)
+ fundedRound := txn.ConfirmedRound
nodeStatus, _ = client.Status()
- fundedRound := nodeStatus.LastRound
-
params, err := client.ConsensusParams(nodeStatus.LastRound)
a.NoError(err)
- lookbackRound := balanceRound(basics.Round(nodeStatus.LastRound), params)
- delta := int64(nodeStatus.LastRound) - int64(lookbackRound)
- a.True(delta > 0)
+ accountProposesStarting := balanceRoundOf(basics.Round(fundedRound), params)
// Need to wait for funding to take effect on selection, then we can see if we're participating
// Stop before the account should become eligible for selection so we can ensure it wasn't
- err = fixture.WaitForRoundWithTimeout(fundedRound + uint64(delta) - 1)
+ err = fixture.ClientWaitForRound(fixture.AlgodClient, uint64(accountProposesStarting-1),
+ time.Duration(uint64(globals.MaxTimePerRound)*uint64(accountProposesStarting-1)))
a.NoError(err)
- blockWasProposed := fixture.VerifyBlockProposed(newAccount, int(delta)-1)
- a.False(blockWasProposed, "account should not be selected until BalLookback (round %d) passes", int(delta)-1)
+ // Check if the account did not propose any blocks up to this round
+ blockWasProposed := fixture.VerifyBlockProposedRange(newAccount, int(accountProposesStarting)-1,
+ int(accountProposesStarting)-1)
+ a.False(blockWasProposed, "account should not be selected until BalLookback (round %d) passes", int(accountProposesStarting-1))
+
+ // Now wait until the round where the funded account will be used.
+ err = fixture.ClientWaitForRound(fixture.AlgodClient, uint64(accountProposesStarting), 10*globals.MaxTimePerRound)
+ a.NoError(err)
- // check that account starts participating after a while
- proposalWindow := 20 // arbitrary
- blockWasProposedByNewAccountRecently := waitForAccountToProposeBlock(a, &fixture, newAccount, proposalWindow)
+ blockWasProposedByNewAccountRecently := fixture.VerifyBlockProposedRange(newAccount, int(accountProposesStarting), 1)
a.True(blockWasProposedByNewAccountRecently, "newly online account should be proposing blocks")
}
-// helper copied from agreement/selector.go
-func balanceRound(r basics.Round, cparams config.ConsensusParams) basics.Round {
- return r.SubSaturate(basics.Round(2 * cparams.SeedRefreshInterval * cparams.SeedLookback))
+// Returns the earliest round which will have the balanceRound equal to r
+func balanceRoundOf(r basics.Round, cparams config.ConsensusParams) basics.Round {
+ return basics.Round(2*cparams.SeedRefreshInterval*cparams.SeedLookback) + r
}
diff --git a/test/e2e-go/features/participation/participationRewards_test.go b/test/e2e-go/features/participation/participationRewards_test.go
index 60d837ac7..be6d661cc 100644
--- a/test/e2e-go/features/participation/participationRewards_test.go
+++ b/test/e2e-go/features/participation/participationRewards_test.go
@@ -19,7 +19,6 @@ package participation
import (
"fmt"
"path/filepath"
- "runtime"
"testing"
"github.com/stretchr/testify/require"
@@ -132,9 +131,6 @@ func TestOnlineOfflineRewards(t *testing.T) {
}
func TestPartkeyOnlyRewards(t *testing.T) {
- if runtime.GOOS == "darwin" {
- t.Skip()
- }
if testing.Short() {
t.Skip()
}
@@ -335,7 +331,7 @@ func TestRewardRateRecalculation(t *testing.T) {
minFee, minBal, err := fixture.MinFeeAndBalance(curStatus.LastRound)
r.NoError(err)
deadline := curStatus.LastRound + uint64(5)
- fixture.SendMoneyAndWait(deadline, amountToSend, minFee, richAccount.Address, rewardsAccount)
+ fixture.SendMoneyAndWait(deadline, amountToSend, minFee, richAccount.Address, rewardsAccount, "")
blk, err := client.Block(curStatus.LastRound)
r.NoError(err)
@@ -361,7 +357,7 @@ func TestRewardRateRecalculation(t *testing.T) {
curStatus, err = client.Status()
r.NoError(err)
deadline = curStatus.LastRound + uint64(5)
- fixture.SendMoneyAndWait(deadline, amountToSend, minFee, richAccount.Address, rewardsAccount)
+ fixture.SendMoneyAndWait(deadline, amountToSend, minFee, richAccount.Address, rewardsAccount, "")
rewardRecalcRound = rewardRecalcRound + consensusParams.RewardsRateRefreshInterval
diff --git a/test/e2e-go/features/transactions/asset_test.go b/test/e2e-go/features/transactions/asset_test.go
index 4068bf03f..9606d3130 100644
--- a/test/e2e-go/features/transactions/asset_test.go
+++ b/test/e2e-go/features/transactions/asset_test.go
@@ -423,7 +423,7 @@ func TestAssetInformation(t *testing.T) {
a := require.New(fixtures.SynchronizedTest(t))
var fixture fixtures.RestClientFixture
- fixture.Setup(t, filepath.Join("nettemplates", "TwoNodes50EachFuture.json"))
+ fixture.Setup(t, filepath.Join("nettemplates", "TwoNodes50EachV24.json"))
defer fixture.Shutdown()
client := fixture.LibGoalClient
diff --git a/test/e2e-go/features/transactions/sendReceive_test.go b/test/e2e-go/features/transactions/sendReceive_test.go
index b91fe8b84..700e6215b 100644
--- a/test/e2e-go/features/transactions/sendReceive_test.go
+++ b/test/e2e-go/features/transactions/sendReceive_test.go
@@ -23,6 +23,7 @@ import (
"github.com/stretchr/testify/require"
+ v1 "github.com/algorand/go-algorand/daemon/algod/api/spec/v1"
"github.com/algorand/go-algorand/test/framework/fixtures"
)
@@ -47,6 +48,16 @@ func TestAccountsCanSendMoney(t *testing.T) {
testAccountsCanSendMoney(t, filepath.Join("nettemplates", "TwoNodes50Each.json"), numberOfSends)
}
+// this test checks that two accounts' balances stay up to date
+// as they send each other money many times
+func TestDevModeAccountsCanSendMoney(t *testing.T) {
+ numberOfSends := 25
+ if testing.Short() {
+ numberOfSends = 3
+ }
+ testAccountsCanSendMoney(t, filepath.Join("nettemplates", "DevModeNetwork.json"), numberOfSends)
+}
+
func testAccountsCanSendMoney(t *testing.T, templatePath string, numberOfSends int) {
t.Parallel()
a := require.New(fixtures.SynchronizedTest(t))
@@ -62,11 +73,17 @@ func testAccountsCanSendMoney(t *testing.T, templatePath string, numberOfSends i
pingAccount := pingAccountList[0].Address
pongClient := fixture.GetLibGoalClientForNamedNode("Node")
- wh, err := pongClient.GetUnencryptedWalletHandle()
- a.NoError(err)
- pongAccountList, err := pongClient.ListAddresses(wh)
+ pongAccounts, err := fixture.GetNodeWalletsSortedByBalance(pongClient.DataDir())
a.NoError(err)
- pongAccount := pongAccountList[0]
+ var pongAccount string
+ for _, acct := range pongAccounts {
+ if acct.Address == pingAccount {
+ continue
+ }
+ // we found an account.
+ pongAccount = acct.Address
+ break
+ }
pingBalance, err := c.GetBalance(pingAccount)
pongBalance, err := c.GetBalance(pongAccount)
@@ -87,6 +104,8 @@ func testAccountsCanSendMoney(t *testing.T, templatePath string, numberOfSends i
pongTxidsToAddresses := make(map[string]string)
pingTxidsToAddresses := make(map[string]string)
+ waitForTransaction := false
+
for i := 0; i < numberOfSends; i++ {
pongTx, err := pongClient.SendPaymentFromUnencryptedWallet(pongAccount, pingAccount, transactionFee, amountPongSendsPing, GenerateRandomBytes(8))
pongTxidsToAddresses[pongTx.ID().String()] = pongAccount
@@ -96,24 +115,38 @@ func testAccountsCanSendMoney(t *testing.T, templatePath string, numberOfSends i
a.NoError(err, "fixture should be able to send money (ping -> pong), error on send number %v", i)
expectedPingBalance = expectedPingBalance - transactionFee - amountPingSendsPong + amountPongSendsPing
expectedPongBalance = expectedPongBalance - transactionFee - amountPongSendsPing + amountPingSendsPong
- curStatus, _ := pongClient.Status()
- curRound := curStatus.LastRound
- err = fixture.WaitForRoundWithTimeout(curRound + uint64(1))
- a.NoError(err)
+
+ var pongTxInfo, pingTxInfo v1.Transaction
+ pongTxInfo, err = pingClient.PendingTransactionInformation(pongTx.ID().String())
+ if err == nil {
+ pingTxInfo, err = pingClient.PendingTransactionInformation(pingTx.ID().String())
+ }
+ waitForTransaction = err != nil || pongTxInfo.ConfirmedRound == 0 || pingTxInfo.ConfirmedRound == 0
+
+ if waitForTransaction {
+ curStatus, _ := pongClient.Status()
+ curRound := curStatus.LastRound
+ err = fixture.WaitForRoundWithTimeout(curRound + uint64(1))
+ a.NoError(err)
+ }
}
curStatus, _ := pongClient.Status()
curRound := curStatus.LastRound
- fixture.AlgodClient = fixture.GetAlgodClientForController(fixture.GetNodeControllerForDataDir(pongClient.DataDir()))
- fixture.WaitForAllTxnsToConfirm(curRound+uint64(5), pingTxidsToAddresses)
+ if waitForTransaction {
+ fixture.AlgodClient = fixture.GetAlgodClientForController(fixture.GetNodeControllerForDataDir(pongClient.DataDir()))
+ fixture.WaitForAllTxnsToConfirm(curRound+uint64(5), pingTxidsToAddresses)
+ }
pingBalance, _ = fixture.GetBalanceAndRound(pingAccount)
pongBalance, _ = fixture.GetBalanceAndRound(pongAccount)
a.True(expectedPingBalance <= pingBalance, "ping balance is different than expected.")
a.True(expectedPongBalance <= pongBalance, "pong balance is different than expected.")
- fixture.AlgodClient = fixture.GetAlgodClientForController(fixture.GetNodeControllerForDataDir(pingClient.DataDir()))
- fixture.WaitForAllTxnsToConfirm(curRound+uint64(5), pongTxidsToAddresses)
+ if waitForTransaction {
+ fixture.AlgodClient = fixture.GetAlgodClientForController(fixture.GetNodeControllerForDataDir(pingClient.DataDir()))
+ fixture.WaitForAllTxnsToConfirm(curRound+uint64(5), pongTxidsToAddresses)
+ }
pingBalance, _ = fixture.GetBalanceAndRound(pingAccount)
pongBalance, _ = fixture.GetBalanceAndRound(pongAccount)
diff --git a/test/e2e-go/features/transactions/transactionPool_test.go b/test/e2e-go/features/transactions/transactionPool_test.go
deleted file mode 100644
index a6d235b18..000000000
--- a/test/e2e-go/features/transactions/transactionPool_test.go
+++ /dev/null
@@ -1,169 +0,0 @@
-// 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 (
- "math/rand"
- "path/filepath"
- "testing"
-
- "github.com/stretchr/testify/require"
-
- "github.com/algorand/go-algorand/test/framework/fixtures"
-)
-
-func TestTransactionPoolOrderingAndClearing(t *testing.T) {
- t.Skip("test is flaky as of 2019-06-18")
- t.Parallel()
- r := require.New(fixtures.SynchronizedTest(t))
-
- var fixture fixtures.RestClientFixture
- fixture.Setup(t, filepath.Join("nettemplates", "TwoNodes50EachOneOnline.json"))
- defer fixture.Shutdown()
- c := fixture.LibGoalClient
-
- // stop the other node in this network so that no new blocks are produced
- otherNode, err := fixture.GetNodeController("Node")
- r.NoError(err, "should be able to get other node's controller")
- err = otherNode.StopAlgod()
- r.NoError(err, "should be able to stop other node")
- // get the round that the network was stopped on, it will be used when the network restarts
- curStatus, _ := c.Status()
- stoppedRound := curStatus.LastRound
-
- minTxnFee, minAcctBalance, err := fixture.MinFeeAndBalance(curStatus.LastRound)
- r.NoError(err)
-
- // put transactions in the pool - they cannot be removed from the pool while the node is stopped
- numTransactions := 25
- sourceAccount, err := fixture.GetRichestAccount()
- r.NoError(err, "should be able to get richest account")
- wh, err := c.GetUnencryptedWalletHandle()
- r.NoError(err, "should be able to get unencrypted wallet handle")
- fixedRandSeed := int64(0)
- rand.Seed(fixedRandSeed)
- var pendingTxids []string
- txidsAndAddressesForConfirmationChecking := make(map[string]string)
- for i := 0; i < numTransactions; i++ {
- newAccount, err := c.GenerateAddress(wh)
- r.NoError(err, "should be able to generate new address")
- txnFee := uint64(rand.Int()%10000) + minTxnFee
- tx, err := c.SendPaymentFromUnencryptedWallet(sourceAccount.Address, newAccount, txnFee, minAcctBalance, nil)
- r.NoError(err)
- fixture.AssertValidTxid(tx.ID().String())
- pendingTxids = append(pendingTxids, tx.ID().String())
- txidsAndAddressesForConfirmationChecking[tx.ID().String()] = sourceAccount.Address
- }
- // examine the pending pool
- pendingTxnsResponse, err := c.GetPendingTransactions(uint64(0)) // "0" == "give everything you know of"
- r.NoError(err, "should be able to get pending transactions")
- // verify len(pending) is correct
- r.Equal(uint64(numTransactions), pendingTxnsResponse.TotalTxns)
- // verify pending is sorted by priority
- // (which, since each txn is of equal length, is equivalent to fee)
- pendingTxns := pendingTxnsResponse.TruncatedTxns.Transactions
- r.Equal(uint64(len(pendingTxnsResponse.TruncatedTxns.Transactions)), pendingTxnsResponse.TotalTxns)
- last := pendingTxns[0].Fee
- for i := 0; i < numTransactions; i++ {
- r.False(last < pendingTxns[i].Fee)
- last = pendingTxns[i].Fee
- }
- // start the other node again
- _, err = fixture.StartNode(otherNode.GetDataDir())
- r.NoError(err)
- // wait for the pending transactions to be confirmed,
- // then demonstrate they ended up in the confirmed blocks
- timeoutRound := stoppedRound + uint64(5)
- fixture.WaitForAllTxnsToConfirm(timeoutRound, txidsAndAddressesForConfirmationChecking)
- latestStatus, err := c.Status()
- r.NoError(err)
- latestRound := latestStatus.LastRound
- var confirmedTransactions []string
- for i := stoppedRound; i < latestRound; i++ {
- block, err := c.Block(i)
- r.NoError(err)
- for _, tx := range block.Transactions.Transactions {
- confirmedTransactions = append(confirmedTransactions, tx.TxID)
- }
- }
- for _, confirmedTransaction := range confirmedTransactions {
- r.Contains(pendingTxids, confirmedTransaction)
- }
- // check the pending pool now and confirm it's empty
- pendingTxnsResponse, err = c.GetPendingTransactions(uint64(0))
- r.NoError(err, "should be able to get pending transactions")
- // verify len(pending) is correct
- r.Equal(uint64(0), pendingTxnsResponse.TotalTxns)
-
-}
-
-func TestTransactionPoolExponentialFees(t *testing.T) {
- t.Skip("new FIFO pool does not have exponential fee txn replacement")
-
- t.Parallel()
- r := require.New(fixtures.SynchronizedTest(t))
-
- var fixture fixtures.RestClientFixture
- fixture.Setup(t, filepath.Join("nettemplates", "TwoNodes50Each.json"))
- defer fixture.Shutdown()
- c := fixture.LibGoalClient
-
- // stop the other node in this network so that no new blocks are produced
- otherNode, err := fixture.GetNodeController("Node")
- r.NoError(err, "should be able to get other node's controller")
- err = otherNode.StopAlgod()
- r.NoError(err, "should be able to stop other node")
- // put transactions in the pool - they cannot be removed from the pool while the node is stopped
- transactionPoolSize := 50000
- sourceAccount, err := fixture.GetRichestAccount()
- r.NoError(err, "should be able to get richest account")
- wh, err := c.GetUnencryptedWalletHandle()
- r.NoError(err, "should be able to get unencrypted wallet handle")
-
- minTxnFee, minAcctBalance, err := fixture.CurrentMinFeeAndBalance()
- r.NoError(err)
-
- txnFee := minTxnFee
- for i := 0; i < transactionPoolSize; i++ {
- newAccount, err := c.GenerateAddress(wh)
- r.NoError(err, "should be able to generate new address")
- tx, err := c.SendPaymentFromUnencryptedWallet(sourceAccount.Address, newAccount, txnFee, minAcctBalance, nil)
- r.NoError(err, "got an error on number %d", i)
- fixture.AssertValidTxid(tx.ID().String())
- }
- // the transaction pool is now full.
- // it will take an exponentially-increasing fee to add more transactions.
- // try to add another one without increasing the fee to see an error.
- newAccount, err := c.GenerateAddress(wh)
- r.NoError(err, "should be able to generate new address")
- _, err = c.SendPaymentFromUnencryptedWallet(sourceAccount.Address, newAccount, txnFee, minAcctBalance, nil)
- r.Error(err, "should not be able to add a 50001th txn")
- // replace as many transactions as we can and see no error.
- // (will have to abort early, of course, because we cannot go all the way up to 2^50000 algos fee.)
- for i := 0; i < transactionPoolSize; i++ {
- txnFee = txnFee * 2
- // if the txnFee is "enormous", we're done checking
- if txnFee > (sourceAccount.Amount / 2) {
- break
- }
- newAccount, err := c.GenerateAddress(wh)
- r.NoError(err, "should be able to generate new address")
- tx, err := c.SendPaymentFromUnencryptedWallet(sourceAccount.Address, newAccount, txnFee, minAcctBalance, nil)
- r.NoError(err, "should be able to add exponentially-more-fee-paying transaction to pool")
- fixture.AssertValidTxid(tx.ID().String())
- }
-}
diff --git a/test/e2e-go/restAPI/restClient_test.go b/test/e2e-go/restAPI/restClient_test.go
index a53e808b8..d6e03a9a0 100644
--- a/test/e2e-go/restAPI/restClient_test.go
+++ b/test/e2e-go/restAPI/restClient_test.go
@@ -810,43 +810,3 @@ func TestClientTruncatesPendingTransactions(t *testing.T) {
}
a.True(len(txIDsSeen) == NumTxns-MaxTxns)
}
-
-func TestClientPrioritizesPendingTransactions(t *testing.T) {
- t.Skip("new FIFO pool does not have prioritization")
- a := require.New(fixtures.SynchronizedTest(t))
- var localFixture fixtures.RestClientFixture
- localFixture.Setup(t, filepath.Join("nettemplates", "TwoNodes50Each.json"))
- defer localFixture.Shutdown()
-
- testClient := localFixture.LibGoalClient
- wh, _ := testClient.GetUnencryptedWalletHandle()
- addresses, _ := testClient.ListAddresses(wh)
- fromAddress := addresses[0]
- toAddress, _ := testClient.GenerateAddress(wh)
- nc, _ := localFixture.GetNodeController("Node")
- err := nc.FullStop()
- a.NoError(err)
-
- minTxnFee, minAcctBalance, err := localFixture.CurrentMinFeeAndBalance()
- a.NoError(err)
-
- NumTxns := 5
- MaxTxns := 3
- for i := 0; i < NumTxns; i++ {
- toAddress2, _ := testClient.GenerateAddress(wh)
- _, err := testClient.SendPaymentFromUnencryptedWallet(fromAddress, toAddress2, minTxnFee, minAcctBalance, nil)
- a.NoError(err)
- }
-
- // Add a very high fee transaction. This should have first priority
- // (even if we don't know the encoding length of the underlying signed txn)
- txHigh, err := testClient.SendPaymentFromUnencryptedWallet(fromAddress, toAddress, minTxnFee*10, minAcctBalance, nil)
- a.NoError(err)
-
- statusResponse, err := testClient.GetPendingTransactions(uint64(MaxTxns))
- a.NoError(err)
- a.NotEmpty(statusResponse)
- a.True(int(statusResponse.TotalTxns) == NumTxns+1)
- a.True(len(statusResponse.TruncatedTxns.Transactions) == MaxTxns)
- a.True(statusResponse.TruncatedTxns.Transactions[0].TxID == txHigh.ID().String())
-}
diff --git a/test/framework/fixtures/expectFixture.go b/test/framework/fixtures/expectFixture.go
index 5d34b0c2c..602c6bbbf 100644
--- a/test/framework/fixtures/expectFixture.go
+++ b/test/framework/fixtures/expectFixture.go
@@ -110,7 +110,7 @@ func MakeExpectTest(t *testing.T) *ExpectFixture {
return ef
}
-// Run Process all expect script files with suffix Test.exp within the current directroy
+// Run Process all expect script files with suffix Test.exp within the current directory
func (ef *ExpectFixture) Run() {
for testName := range ef.expectFiles {
if match, _ := regexp.MatchString(ef.testFilter, testName); match {
diff --git a/test/framework/fixtures/restClientFixture.go b/test/framework/fixtures/restClientFixture.go
index a27a1a5b1..06a891b95 100644
--- a/test/framework/fixtures/restClientFixture.go
+++ b/test/framework/fixtures/restClientFixture.go
@@ -56,6 +56,12 @@ func (f *RestClientFixture) SetupShared(testName string, templateFile string) {
f.AlgodClient = f.GetAlgodClientForController(f.NC)
}
+// Start can be called to start the fixture's network if SetupNoStart() was used.
+func (f *RestClientFixture) Start() {
+ f.LibGoalFixture.Start()
+ f.AlgodClient = f.GetAlgodClientForController(f.NC)
+}
+
// GetAlgodClientForController returns a RestClient for the specified NodeController
func (f *RestClientFixture) GetAlgodClientForController(nc nodecontrol.NodeController) client.RestClient {
url, err := nc.ServerURL()
@@ -267,36 +273,33 @@ func (f *RestClientFixture) WaitForAllTxnsToConfirm(roundTimeout uint64, txidsAn
// SendMoneyAndWait uses the rest client to send money and WaitForTxnConfirmation to wait for the send to confirm
// it adds some extra error checking as well
-func (f *RestClientFixture) SendMoneyAndWait(curRound, amountToSend, transactionFee uint64, fromAccount, toAccount string) (fundingTxid string) {
+func (f *RestClientFixture) SendMoneyAndWait(curRound, amountToSend, transactionFee uint64, fromAccount, toAccount string, closeToAccount string) (txn v1.Transaction) {
client := f.LibGoalClient
wh, err := client.GetUnencryptedWalletHandle()
require.NoError(f.t, err, "client should be able to get unencrypted wallet handle")
- fundingTxid = f.SendMoneyAndWaitFromWallet(wh, nil, curRound, amountToSend, transactionFee, fromAccount, toAccount)
+ txn = f.SendMoneyAndWaitFromWallet(wh, nil, curRound, amountToSend, transactionFee, fromAccount, toAccount, closeToAccount)
return
}
// SendMoneyAndWaitFromWallet is as above, but for a specific wallet
-func (f *RestClientFixture) SendMoneyAndWaitFromWallet(walletHandle, walletPassword []byte, curRound, amountToSend, transactionFee uint64, fromAccount, toAccount string) (fundingTxid string) {
+func (f *RestClientFixture) SendMoneyAndWaitFromWallet(walletHandle, walletPassword []byte, curRound, amountToSend, transactionFee uint64, fromAccount, toAccount string, closeToAccount string) (txn v1.Transaction) {
client := f.LibGoalClient
- fundingTx, err := client.SendPaymentFromWallet(walletHandle, walletPassword, fromAccount, toAccount, transactionFee, amountToSend, nil, "", 0, 0)
+ fundingTx, err := client.SendPaymentFromWallet(walletHandle, walletPassword, fromAccount, toAccount, transactionFee, amountToSend, nil, closeToAccount, 0, 0)
require.NoError(f.t, err, "client should be able to send money from rich to poor account")
require.NotEmpty(f.t, fundingTx.ID().String(), "transaction ID should not be empty")
waitingDeadline := curRound + uint64(5)
- _, err = f.WaitForConfirmedTxn(waitingDeadline, fromAccount, fundingTx.ID().String())
+ txn, err = f.WaitForConfirmedTxn(waitingDeadline, fromAccount, fundingTx.ID().String())
require.NoError(f.t, err)
return
}
-// VerifyBlockProposed checks the last searchRange blocks to see if any blocks were proposed by address
-func (f *RestClientFixture) VerifyBlockProposed(account string, searchRange int) (blockWasProposed bool) {
+// VerifyBlockProposedRange checks the rounds starting at fromRounds and moving backwards checking countDownNumRounds rounds if any
+// blocks were proposed by address
+func (f *RestClientFixture) VerifyBlockProposedRange(account string, fromRound, countDownNumRounds int) (blockWasProposed bool) {
c := f.LibGoalClient
- currentRound, err := c.CurrentRound()
- if err != nil {
- require.NoError(f.t, err, "client failed to get the last round")
- }
- for i := 0; i < searchRange; i++ {
- block, err := c.Block(currentRound - uint64(i))
- require.NoError(f.t, err, "client failed to get block %d", currentRound-uint64(i))
+ for i := 0; i < countDownNumRounds; i++ {
+ block, err := c.Block(uint64(fromRound - i))
+ require.NoError(f.t, err, "client failed to get block %d", fromRound-i)
if block.Proposer == account {
blockWasProposed = true
break
@@ -305,6 +308,16 @@ func (f *RestClientFixture) VerifyBlockProposed(account string, searchRange int)
return
}
+// VerifyBlockProposed checks the last searchRange blocks to see if any blocks were proposed by address
+func (f *RestClientFixture) VerifyBlockProposed(account string, searchRange int) (blockWasProposed bool) {
+ c := f.LibGoalClient
+ currentRound, err := c.CurrentRound()
+ if err != nil {
+ require.NoError(f.t, err, "client failed to get the last round")
+ }
+ return f.VerifyBlockProposedRange(account, int(currentRound), int(searchRange))
+}
+
// GetBalancesOnSameRound gets the balances for the passed addresses, and keeps trying until the balances are all the same round
// if it can't get the balances for the same round within maxRetries retries, it will return the last balance seen for each acct
// it also returns whether it got balances all for the same round, and what the last queried round was
diff --git a/test/muleCI/mule.yaml b/test/muleCI/mule.yaml
index 57b6f338e..0ec2ac277 100644
--- a/test/muleCI/mule.yaml
+++ b/test/muleCI/mule.yaml
@@ -25,19 +25,6 @@ agents:
buildArgs:
- GOLANG_VERSION=`./scripts/get_golang_version.sh`
- ARCH=amd64
- - name: cicd.centos8.amd64
- dockerFilePath: docker/build/cicd.centos8.Dockerfile
- image: algorand/go-algorand-ci-linux-centos8
- version: scripts/configure_dev-deps.sh
- arch: amd64
- env:
- - TRAVIS_BRANCH=${GIT_BRANCH}
- - NETWORK=$NETWORK
- - VERSION=$VERSION
- - BUILD_NUMBER=$BUILD_NUMBER
- buildArgs:
- - GOLANG_VERSION=`./scripts/get_golang_version.sh`
- - ARCH=amd64
- name: cicd.ubuntu.arm64
dockerFilePath: docker/build/cicd.ubuntu.Dockerfile
image: algorand/go-algorand-ci-linux-ubuntu
@@ -112,21 +99,11 @@ tasks:
target: archive
- task: docker.Make
- name: archive.amd64.centos8
- agent: cicd.centos8.amd64
- target: archive
-
- - task: docker.Make
name: rpm.amd64
agent: cicd.centos.amd64
target: mule-package-rpm
- task: docker.Make
- name: rpm.amd64.centos8
- agent: cicd.centos8.amd64
- target: mule-package-rpm
-
- - task: docker.Make
name: deb.amd64
agent: cicd.ubuntu.amd64
target: mule-package-deb
@@ -230,13 +207,11 @@ jobs:
- stash.Unstash.linux-arm
- docker.Make.deb.amd64
- docker.Make.rpm.amd64
- - docker.Make.rpm.amd64.centos8
- stash.Stash.packages
archive-linux-amd64:
tasks:
- stash.Unstash.packages
- docker.Make.archive.amd64
- - docker.Make.archive.amd64.centos8
package-docker:
tasks:
- docker.Make.docker-image
diff --git a/test/netperf-go/puppeteer/main.go b/test/netperf-go/puppeteer/main.go
index f9e5d7ddf..37aa5eb55 100644
--- a/test/netperf-go/puppeteer/main.go
+++ b/test/netperf-go/puppeteer/main.go
@@ -43,7 +43,7 @@ func init() {
rootCmd.Flags().StringVarP(&deployFor, "for", "f", "", "Specify instance `for` tag")
rootCmd.MarkFlagRequired("for")
rootCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Verbosed output")
- rootCmd.Flags().StringVarP(&stageDir, "stageDir", "s", "", "staging directory for deployed networks (defaults to a temporary directroy)")
+ rootCmd.Flags().StringVarP(&stageDir, "stageDir", "s", "", "staging directory for deployed networks (defaults to a temporary directory)")
rootCmd.Flags().BoolVarP(&skipCleanup, "skipCleanup", "", false, "Skip clean up of the staging directory on exit")
rootCmd.Flags().BoolVarP(&skipReset, "skipReset", "", false, "Skip resetting of the staging directory during initialization")
diff --git a/test/scripts/e2e_client_runner.py b/test/scripts/e2e_client_runner.py
index e1f169b90..c225b9483 100755
--- a/test/scripts/e2e_client_runner.py
+++ b/test/scripts/e2e_client_runner.py
@@ -79,17 +79,17 @@ def create_kmd_config_with_unsafe_scrypt(working_dir):
with open(os.path.join(kmd_config_dir,"kmd_config.json.example")) as f:
kmd_conf_data = json.load(f)
if "drivers" not in kmd_conf_data:
- raise Exception("kmd_conf example does not contian drivers attribute")
+ raise Exception("kmd_conf example does not contain drivers attribute")
if "sqlite" not in kmd_conf_data["drivers"]:
- raise Exception("kmd_conf example does not contian sqlite attribute")
+ raise Exception("kmd_conf example does not contain sqlite attribute")
if "allow_unsafe_scrypt" not in kmd_conf_data["drivers"]["sqlite"]:
- raise Exception("kmd_conf example does not contian allow_unsafe_scrypt attribute")
+ raise Exception("kmd_conf example does not contain allow_unsafe_scrypt attribute")
if "scrypt" not in kmd_conf_data["drivers"]["sqlite"]:
- raise Exception("kmd_conf example does not contian scrypt attribute")
+ raise Exception("kmd_conf example does not contain scrypt attribute")
if "scrypt_n" not in kmd_conf_data["drivers"]["sqlite"]["scrypt"]:
- raise Exception("kmd_conf example does not contian scrypt_n attribute")
+ raise Exception("kmd_conf example does not contain scrypt_n attribute")
if "scrypt_r" not in kmd_conf_data["drivers"]["sqlite"]["scrypt"]:
- raise Exception("kmd_conf example does not contian scrypt_r attribute")
+ raise Exception("kmd_conf example does not contain scrypt_r attribute")
kmd_conf_data["drivers"]["sqlite"]["allow_unsafe_scrypt"] = True
kmd_conf_data["drivers"]["sqlite"]["scrypt"]["scrypt_n"] = 4096
diff --git a/test/scripts/e2e_subs/e2e-app-extra-pages.sh b/test/scripts/e2e_subs/e2e-app-extra-pages.sh
new file mode 100755
index 000000000..0fafa3256
--- /dev/null
+++ b/test/scripts/e2e_subs/e2e-app-extra-pages.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+date '+app-extra-pages-test start %Y%m%d_%H%M%S'
+
+set -e
+set -x
+set -o pipefail
+export SHELLOPTS
+
+WALLET=$1
+
+gcmd="goal -w ${WALLET}"
+
+ACCOUNT=$(${gcmd} account list|awk '{ print $3 }')
+
+function generate_teal() {
+ FILE=$1
+ VERSION=$2
+ SIZE=$3
+ COST=$4
+ PREFIX=$5
+
+ printf '#pragma version %d\n' $VERSION > "${FILE}"
+ printf "${PREFIX}\n" >> "${FILE}"
+
+ # i = 5; i <= SIZE - 1; i += 2
+ for i in $(seq 5 2 $(expr $SIZE - 1)); do
+ printf "int 1\npop\n" >> "${FILE}"
+ done
+
+ if [ "$COST" -gt "$(expr $SIZE '*' 2)" ]; then
+ # i = SIZE * 2; i <= COST - 1; i += 130
+ for i in $(seq $(expr $SIZE '*' 2) 130 $(expr $COST - 1)); do
+ printf "keccak256\n" >> "${FILE}"
+ done
+ printf "pop\n" >> "${FILE}"
+ fi
+
+ printf "int 1\n" >> "${FILE}"
+}
+
+BIG_TEAL_FILE="$TEMPDIR/big-app.teal"
+BIG_TEAL_V4_FILE="$TEMPDIR/big-app-v4.teal"
+SMALL_TEAL_FILE="$TEMPDIR/sm-app.teal"
+
+generate_teal "$BIG_TEAL_FILE" 3 4090 1 "int 0\nbalance\npop\n"
+generate_teal "$BIG_TEAL_V4_FILE" 4 4090 1 "int 0\nbalance\npop\n"
+generate_teal "$SMALL_TEAL_FILE" 3 10 1 "int 0\nbalance\npop\n"
+
+# App create fails. Approval program too long
+RES=$(${gcmd} app create --creator ${ACCOUNT} --approval-prog "${BIG_TEAL_FILE}" --clear-prog "${BIG_TEAL_FILE}" --global-byteslices 1 --global-ints 0 --local-byteslices 0 --local-ints 0 2>&1 || true)
+EXPERROR="approval program too long. max len 2048 bytes"
+if [[ $RES != *"${EXPERROR}"* ]]; then
+ date '+app-extra-pages-test FAIL the application creation should fail %Y%m%d_%H%M%S'
+ false
+fi
+
+# App create fails. Clear state program too long
+RES=$(${gcmd} app create --creator ${ACCOUNT} --approval-prog "${SMALL_TEAL_FILE}" --clear-prog "${BIG_TEAL_FILE}" --global-byteslices 1 --global-ints 0 --local-byteslices 0 --local-ints 0 2>&1 || true)
+EXPERROR="clear state program too long. max len 2048 bytes"
+if [[ $RES != *"${EXPERROR}"* ]]; then
+ date '+app-extra-pages-test FAIL the application creation should fail %Y%m%d_%H%M%S'
+ false
+fi
+
+# App create with extra pages, v3 teal
+RES=$(${gcmd} app create --creator ${ACCOUNT} --approval-prog "${BIG_TEAL_FILE}" --clear-prog "${BIG_TEAL_FILE}" --extra-pages 3 --global-byteslices 1 --global-ints 0 --local-byteslices 0 --local-ints 0 2>&1 || true)
+EXPERROR="pc=705 static cost budget of 700 exceeded"
+if [[ $RES != *"${EXPERROR}"* ]]; then
+ date '+app-extra-pages-test FAIL the application creation should fail %Y%m%d_%H%M%S'
+ false
+fi
+
+# App create with extra pages, v4 teal
+RES=$(${gcmd} app create --creator ${ACCOUNT} --approval-prog "${BIG_TEAL_V4_FILE}" --clear-prog "${BIG_TEAL_V4_FILE}" --extra-pages 3 --global-byteslices 1 --global-ints 0 --local-byteslices 0 --local-ints 0 2>&1 || true)
+EXPERROR="pc=704 dynamic cost budget of 700 exceeded, executing intc_0"
+if [[ $RES != *"${EXPERROR}"* ]]; then
+ date '+app-extra-pages-test FAIL the application creation should fail %Y%m%d_%H%M%S'
+ false
+fi
+
+# App create with extra pages, succeedd
+${gcmd} app create --creator ${ACCOUNT} --approval-prog "${SMALL_TEAL_FILE}" --clear-prog "${SMALL_TEAL_FILE}" --extra-pages 1 --global-byteslices 1 --global-ints 0 --local-byteslices 0 --local-ints 0
diff --git a/test/scripts/e2e_subs/rest-applications-endpoint.sh b/test/scripts/e2e_subs/rest-applications-endpoint.sh
index 6d66e5798..18337a7c5 100755
--- a/test/scripts/e2e_subs/rest-applications-endpoint.sh
+++ b/test/scripts/e2e_subs/rest-applications-endpoint.sh
@@ -11,7 +11,7 @@ date "+$0 start %Y%m%d_%H%M%S"
printf '#pragma version 2\nint 1' > "${TEMPDIR}/simple.teal"
APPID=$(${gcmd} app create --creator "${ACCOUNT}" --approval-prog "${TEMPDIR}/simple.teal" --clear-prog "${TEMPDIR}/simple.teal" --global-byteslices 0 --global-ints 2 --local-byteslices 0 --local-ints 0 | grep Created | awk '{ print $6 }')
-# Good request, non-existant app id
+# Good request, non-existent app id
call_and_verify "Should not find app." "/v2/applications/987654321" 404 'application does not exist'
# Good request
call_and_verify "Should contain app data." "/v2/applications/$APPID" 200 '"global-state-schema":{"num-byte-slice":0,"num-uint":2}'
diff --git a/test/scripts/e2e_subs/rest-assets-endpoint.sh b/test/scripts/e2e_subs/rest-assets-endpoint.sh
index fc6ca6e80..ddeeb2f71 100755
--- a/test/scripts/e2e_subs/rest-assets-endpoint.sh
+++ b/test/scripts/e2e_subs/rest-assets-endpoint.sh
@@ -7,17 +7,24 @@ source "$my_dir/rest.sh" "$@"
date "+$0 start %Y%m%d_%H%M%S"
-ASSET_ID=$(${gcmd} asset create --creator "${ACCOUNT}" --total 10000 --decimals 19 --name "spanish coin" --unitname "doubloon" | grep "Created asset with asset index" | rev | cut -d ' ' -f 1 | rev)
+ASSET_ID=$(${gcmd} asset create --creator "${ACCOUNT}" --total 10000 --decimals 19 --asseturl 'https://www.reddit.com/r/AlgorandOfficial/' --name "spanish coin" --unitname "doubloon" | grep "Created asset with asset index" | rev | cut -d ' ' -f 1 | rev)
-# Good request, non-existant asset id
+# Good request, non-existent asset id
call_and_verify "Should not find asset." "/v2/assets/987654321" 404 'asset does not exist'
# Good request
call_and_verify "Should contain asset data." "/v2/assets/$ASSET_ID" 200 '","decimals":19,"default-frozen":false,"freeze":"'
# Good request, pretty response
-call_and_verify "Should contain asset data." "/v2/assets/$ASSET_ID?pretty" 200 '
- "decimals": 19,
- "default-frozen": false,
- "freeze": "'
+call_and_verify "Should contain asset data." "/v2/assets/$ASSET_ID?pretty" 200 \
+ '"decimals": 19' \
+ '"default-frozen": false' \
+ '"name": "spanish coin"' \
+ '"name-b64": "c3BhbmlzaCBjb2lu"' \
+ '"total": 10000' \
+ '"unit-name": "doubloon"' \
+ '"unit-name-b64": "ZG91Ymxvb24="' \
+ '"url": "https://www.reddit.com/r/AlgorandOfficial/"'\
+ '"url-b64": "aHR0cHM6Ly93d3cucmVkZGl0LmNvbS9yL0FsZ29yYW5kT2ZmaWNpYWwv"'
+
# Some invalid path parameters
call_and_verify "Asset parameter parsing error 1." "/v2/assets/-2" 400 "Invalid format for parameter asset-id"
call_and_verify "Asset parameter parsing error 2." "/v2/assets/not-a-number" 400 "Invalid format for parameter asset-id"
diff --git a/test/scripts/e2e_subs/rest.sh b/test/scripts/e2e_subs/rest.sh
index 84b9ed570..fab6f1d51 100755
--- a/test/scripts/e2e_subs/rest.sh
+++ b/test/scripts/e2e_subs/rest.sh
@@ -54,22 +54,67 @@ function fail_and_exit {
# $1 - test description.
# $2 - query
# $3 - expected status code
-# $4 - substring that should be in the response
+# $4... - substring that should be in the response
function call_and_verify {
- local CODE
+ local DESCRIPTION="$1"
+ shift
+ local QUERY="$1"
+ shift
+ local EXPECTED_CODE="$1"
+ shift
+
+ echo "MATCHING $@"
+ curl_test "$DESCRIPTION" "$QUERY" "$EXPECTED_CODE" true "$@"
+}
+
+# CURL Test - query and veryify results
+# $1 - test description.
+# $2 - query
+# $3 - expected status code
+# $4 - match result
+# $5... - substring(s) that should be in the response
+function curl_test {
+ local DESCRIPTION="$1"
+ shift
+ local QUERY="$1"
+ shift
+ local EXPECTED_CODE="$1"
+ shift
+ local MATCH_RESULT="$1"
+ shift
+ local SUBSTRING
+
+ local START=$SECONDS
set +e
- CODE=$(call "$2" "${TEMPDIR}/curl_out.txt")
+ local CODE=$(call "$QUERY" "${TEMPDIR}/curl_out.txt")
if [[ $? != 0 ]]; then
- fail_and_exit "$1" "$2" "curl had a non-zero exit code."
+ cat $CURL_TEMPFILE
+ fail_and_exit "$DESCRIPTION" "$QUERY" "curl had a non-zero exit code."
fi
set -e
RES=$(cat "${TEMPDIR}/curl_out.txt")
- if [[ "$CODE" != "$3" ]]; then
- fail_and_exit "$1" "$2" "unexpected HTTP status code expected $3 (actual $CODE)"
- fi
- if [[ "$RES" != *"$4"* ]]; then
- fail_and_exit "$1" "$2" "unexpected response. should contain '$4', actual: $RES"
+ if [[ "$CODE" != "$EXPECTED_CODE" ]]; then
+ fail_and_exit "$DESCRIPTION" "$QUERY" "unexpected HTTP status code expected $EXPECTED_CODE (actual $CODE): $RES"
fi
+
+ #local ELAPSED=$(($SECONDS - $START))
+ #if [[ $ELAPSED -gt $MAX_TIME ]]; then
+ # fail_and_exit "$DESCRIPTION" "$QUERY" "query duration too long, $ELAPSED > $MAX_TIME"
+ #fi
+
+ # Check result substrings
+ for SUBSTRING in "$@"; do
+ echo "CHECKING '$SUBSTRING'"
+ if [[ $MATCH_RESULT = true ]]; then
+ if [[ "$RES" != *"$SUBSTRING"* ]]; then
+ fail_and_exit "$DESCRIPTION" "$QUERY" "unexpected response. should contain '$SUBSTRING', actual: $RES"
+ fi
+ else
+ if [[ "$RES" == *"$SUBSTRING"* ]]; then
+ fail_and_exit "$DESCRIPTION" "$QUERY" "unexpected response. should NOT contain '$SUBSTRING', actual: $RES"
+ fi
+ fi
+ done
}
diff --git a/test/scripts/e2e_subs/teal-app-params.sh b/test/scripts/e2e_subs/teal-app-params.sh
new file mode 100755
index 000000000..89b30d836
--- /dev/null
+++ b/test/scripts/e2e_subs/teal-app-params.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+filename=$(basename "$0")
+scriptname="${filename%.*}"
+date "+${scriptname} start %Y%m%d_%H%M%S"
+
+set -e
+set -x
+set -o pipefail
+export SHELLOPTS
+
+WALLET=$1
+
+TEAL=test/scripts/e2e_subs/tealprogs
+
+gcmd="goal -w ${WALLET}"
+
+ACCOUNT=$(${gcmd} account list|awk '{ print $3 }')
+
+APPID=$(${gcmd} app create --creator "$ACCOUNT" --approval-prog=${TEAL}/app-params.teal --clear-prog=${TEAL}/approve-all.teal --global-byteslices 1 --global-ints 2 --local-byteslices 3 --local-ints 4 --extra-pages 2 --app-arg "addr:$ACCOUNT" | grep Created | awk '{ print $6 }')
+
+ACCOUNTB=$(${gcmd} account new|awk '{ print $6 }')
+${gcmd} clerk send -f "$ACCOUNT" -t "$ACCOUNTB" -a 1000000
+
+# Now call from a different account
+${gcmd} app call --app-id="$APPID" --from="$ACCOUNTB" --app-arg "addr:$ACCOUNT"
+
+
+
+date "+${scriptname} OK %Y%m%d_%H%M%S"
diff --git a/test/scripts/e2e_subs/tealprogs/app-params.teal b/test/scripts/e2e_subs/tealprogs/app-params.teal
new file mode 100644
index 000000000..e8ee7052e
--- /dev/null
+++ b/test/scripts/e2e_subs/tealprogs/app-params.teal
@@ -0,0 +1,78 @@
+#pragma version 5
+ // This program checks its own app params, as set up in
+ // teal-app-params.sh, to confirm they all work.
+
+
+ // Check the creator is the address provided
+ int 0
+ app_params_get AppCreator
+ assert
+ txn ApplicationArgs 0
+ ==
+ assert
+
+
+ // Check this program is version 5
+ int 0
+ app_params_get AppApprovalProgram
+ assert
+ int 0
+ getbyte
+ int 5
+ ==
+ assert
+
+ // Check it's longer than 15 (don't want to try to check all the bytes)
+ int 0
+ app_params_get AppApprovalProgram
+ assert
+ len
+ int 15
+ >
+ assert
+
+
+ // Check the Clear State program precisely
+ int 0
+ app_params_get AppClearStateProgram
+ assert
+ byte 0x0220010122
+ ==
+ assert
+
+ int 0
+ app_params_get AppGlobalNumByteSlice
+ assert
+ int 1
+ ==
+ assert
+
+ int 0
+ app_params_get AppGlobalNumUint
+ assert
+ int 2
+ ==
+ assert
+
+ int 0
+ app_params_get AppLocalNumByteSlice
+ assert
+ int 3
+ ==
+ assert
+
+ int 0
+ app_params_get AppLocalNumUint
+ assert
+ int 4
+ ==
+ assert
+
+ int 0
+ app_params_get AppExtraProgramPages
+ assert
+ int 2
+ ==
+ assert
+
+ int 1
diff --git a/test/testdata/configs/logging/logging.config.test2 b/test/testdata/configs/logging/logging.config.test2
new file mode 100644
index 000000000..80e6588bd
--- /dev/null
+++ b/test/testdata/configs/logging/logging.config.test2
@@ -0,0 +1,4 @@
+{
+ "UserName": "",
+ "Password": ""
+}
diff --git a/test/testdata/nettemplates/DevModeNetwork.json b/test/testdata/nettemplates/DevModeNetwork.json
new file mode 100644
index 000000000..657498553
--- /dev/null
+++ b/test/testdata/nettemplates/DevModeNetwork.json
@@ -0,0 +1,34 @@
+{
+ "Genesis": {
+ "NetworkName": "devmodenet",
+ "Wallets": [
+ {
+ "Name": "Wallet1",
+ "Stake": 40,
+ "Online": true
+ },
+ {
+ "Name": "Wallet2",
+ "Stake": 40,
+ "Online": true
+ },
+ {
+ "Name": "Wallet3",
+ "Stake": 20,
+ "Online": true
+ }
+ ],
+ "DevMode": true
+ },
+ "Nodes": [
+ {
+ "Name": "Node",
+ "IsRelay": false,
+ "Wallets": [
+ { "Name": "Wallet1", "ParticipationOnly": false },
+ { "Name": "Wallet2", "ParticipationOnly": false },
+ { "Name": "Wallet3", "ParticipationOnly": false }
+ ]
+ }
+ ]
+}
diff --git a/test/testdata/nettemplates/TwoNodesOneOnline.json b/test/testdata/nettemplates/OneNode.json
index 4f5fa32a3..60b368989 100644
--- a/test/testdata/nettemplates/TwoNodesOneOnline.json
+++ b/test/testdata/nettemplates/OneNode.json
@@ -1,6 +1,7 @@
{
"Genesis": {
"NetworkName": "tbd",
+ "ConsensusProtocol": "shortpartkeysprotocol",
"Wallets": [
{
"Name": "Rich",
@@ -27,15 +28,10 @@
{ "Name": "Rich",
"ParticipationOnly": false },
{ "Name": "Partkey",
- "ParticipationOnly": true }
- ]
- },
- {
- "Name": "Node",
- "Wallets": [
+ "ParticipationOnly": true },
{ "Name": "Offline",
"ParticipationOnly": true }
]
}
]
-} \ No newline at end of file
+}
diff --git a/tools/network/cloudflare/createRecord.go b/tools/network/cloudflare/createRecord.go
index b4ff0b69e..23e3515d6 100644
--- a/tools/network/cloudflare/createRecord.go
+++ b/tools/network/cloudflare/createRecord.go
@@ -141,7 +141,7 @@ type CreateDNSRecordResult struct {
Data interface{} `json:"data"`
}
-// parseCreateDNSRecordResponse parses the reponse that was received as a result of a ListDNSRecordRequest
+// parseCreateDNSRecordResponse parses the response that was received as a result of a ListDNSRecordRequest
func parseCreateDNSRecordResponse(response *http.Response) (*CreateDNSRecordResponse, error) {
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
diff --git a/tools/network/cloudflare/deleteRecord.go b/tools/network/cloudflare/deleteRecord.go
index dbe4cb1a5..31fc0be86 100644
--- a/tools/network/cloudflare/deleteRecord.go
+++ b/tools/network/cloudflare/deleteRecord.go
@@ -52,7 +52,7 @@ type DeleteDNSRecordResult struct {
ID string `json:"id"`
}
-// ParseDeleteDNSRecordResponse parses the reponse that was received as a result of a ListDNSRecordRequest
+// ParseDeleteDNSRecordResponse parses the response that was received as a result of a ListDNSRecordRequest
func parseDeleteDNSRecordResponse(response *http.Response) (*DeleteDNSRecordResponse, error) {
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
diff --git a/tools/network/cloudflare/listRecords.go b/tools/network/cloudflare/listRecords.go
index 53d91ff34..9554dc2d3 100644
--- a/tools/network/cloudflare/listRecords.go
+++ b/tools/network/cloudflare/listRecords.go
@@ -117,7 +117,7 @@ type DNSRecordResponseEntry struct {
CreatedOn string `json:"created_on"`
}
-// parseListDNSRecordResponse parses the reponse that was received as a result of a ListDNSRecordRequest
+// parseListDNSRecordResponse parses the response that was received as a result of a ListDNSRecordRequest
func parseListDNSRecordResponse(response *http.Response) (*ListDNSRecordResponse, error) {
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
diff --git a/tools/network/cloudflare/updateRecord.go b/tools/network/cloudflare/updateRecord.go
index 396de20ee..e31117a01 100644
--- a/tools/network/cloudflare/updateRecord.go
+++ b/tools/network/cloudflare/updateRecord.go
@@ -90,7 +90,7 @@ func updateSRVRecordRequest(zoneID string, authEmail string, authKey string, rec
return request, nil
}
-// parseUpdateDNSRecordResponse parses the reponse that was received as a result of a ListDNSRecordRequest
+// parseUpdateDNSRecordResponse parses the response that was received as a result of a ListDNSRecordRequest
func parseUpdateDNSRecordResponse(response *http.Response) (*CreateDNSRecordResponse, error) {
return parseCreateDNSRecordResponse(response)
}
diff --git a/util/db/dbutil.go b/util/db/dbutil.go
index 76545cced..ed2ac8897 100644
--- a/util/db/dbutil.go
+++ b/util/db/dbutil.go
@@ -246,7 +246,7 @@ func (db *Accessor) atomic(fn idemFn, commitLocker sync.Locker, extras ...interf
// see https://www.sqlite.org/sharedcache.html for more details.
// These shared cache constrains are more strict than the WAL based concurrency limitations, which allows
// one writer and multiple readers at the same time.
- // In particular, the shared cache limitation means that since a connection could become a writer, any syncronization
+ // In particular, the shared cache limitation means that since a connection could become a writer, any synchronization
// operating that would prevent this operation from completing could result with a deadlock.
// This is the reason why for shared cache connections, we'll take the lock before starting the write transaction,
// and would keep it along. It will cause a degraded performance when using a shared cache connection
@@ -438,7 +438,7 @@ func dbretry(obj error) bool {
return ok && (err.Code == sqlite3.ErrLocked || err.Code == sqlite3.ErrBusy)
}
-// IsErrBusy examine the input inerr varaible of type error and determine if it's a sqlite3 error for the ErrBusy error code.
+// IsErrBusy examine the input inerr variable of type error and determine if it's a sqlite3 error for the ErrBusy error code.
func IsErrBusy(inerr error) bool {
err, ok := inerr.(sqlite3.Error)
return ok && (err.Code == sqlite3.ErrBusy)
@@ -473,7 +473,7 @@ const (
SynchronousModeExtra SynchronousMode = 3
)
-// SetSynchronousMode updates the syncronous mode of the connection
+// SetSynchronousMode updates the synchronous mode of the connection
func (db *Accessor) SetSynchronousMode(ctx context.Context, mode SynchronousMode, fullfsync bool) (err error) {
if mode < SynchronousModeOff || mode > SynchronousModeExtra {
return fmt.Errorf("invalid value(%d) was provided to mode", mode)
diff --git a/util/db/dbutil_test.go b/util/db/dbutil_test.go
index a8a2044fe..df523f63d 100644
--- a/util/db/dbutil_test.go
+++ b/util/db/dbutil_test.go
@@ -420,7 +420,7 @@ func TestSetSynchronousMode(t *testing.T) {
}
// TestReadingWhileWriting tests the SQLite behaviour when we're using two transactions, writing with one and reading from the other.
-// it demonstates that at any time before we're calling Commit, the database content can be read, and it's containing it's pre-transaction
+// it demonstrates that at any time before we're calling Commit, the database content can be read, and it's containing it's pre-transaction
// value.
func TestReadingWhileWriting(t *testing.T) {
writeAcc, err := MakeAccessor("fn.db", false, false)
diff --git a/util/metrics/counter_test.go b/util/metrics/counter_test.go
index a6c5b3ead..7ac853822 100644
--- a/util/metrics/counter_test.go
+++ b/util/metrics/counter_test.go
@@ -63,8 +63,8 @@ func TestMetricCounter(t *testing.T) {
test.Lock()
defer test.Unlock()
- // the the loop above we've created a single metric name with five diffrent labels set ( host0, host1 .. host 4)
- // let's see if we received all the 5 diffrent labels.
+ // the the loop above we've created a single metric name with five different labels set ( host0, host1 .. host 4)
+ // let's see if we received all the 5 different labels.
require.Equal(t, 5, len(test.metrics), "Missing metric counts were reported.")
for k, v := range test.metrics {
@@ -108,8 +108,8 @@ func TestMetricCounterFastInts(t *testing.T) {
test.Lock()
defer test.Unlock()
- // the the loop above we've created a single metric name with five diffrent labels set ( host0, host1 .. host 4)
- // let's see if we received all the 5 diffrent labels.
+ // the the loop above we've created a single metric name with five different labels set ( host0, host1 .. host 4)
+ // let's see if we received all the 5 different labels.
require.Equal(t, 1, len(test.metrics), "Missing metric counts were reported.")
for k, v := range test.metrics {
@@ -155,8 +155,8 @@ func TestMetricCounterMixed(t *testing.T) {
test.Lock()
defer test.Unlock()
- // the the loop above we've created a single metric name with five diffrent labels set ( host0, host1 .. host 4)
- // let's see if we received all the 5 diffrent labels.
+ // the the loop above we've created a single metric name with five different labels set ( host0, host1 .. host 4)
+ // let's see if we received all the 5 different labels.
require.Equal(t, 1, len(test.metrics), "Missing metric counts were reported.")
for k, v := range test.metrics {
diff --git a/util/metrics/gauge_test.go b/util/metrics/gauge_test.go
index e2262ce7b..90111cf15 100644
--- a/util/metrics/gauge_test.go
+++ b/util/metrics/gauge_test.go
@@ -64,8 +64,8 @@ func TestMetricGauge(t *testing.T) {
test.Lock()
defer test.Unlock()
- // the the loop above we've created a single metric name with five diffrent labels set ( host0, host1 .. host 4)
- // let's see if we received all the 5 diffrent labels.
+ // the the loop above we've created a single metric name with five different labels set ( host0, host1 .. host 4)
+ // let's see if we received all the 5 different labels.
require.Equal(t, 5, len(test.metrics), "Missing metric counts were reported.")
// iterate through the metrics and check the each of the metrics reached it's correct count.
diff --git a/util/metrics/reporter.go b/util/metrics/reporter.go
index 85daa864f..90cc371c3 100644
--- a/util/metrics/reporter.go
+++ b/util/metrics/reporter.go
@@ -84,7 +84,7 @@ func (reporter *MetricReporter) ReporterLoop(ctx context.Context) {
if reporter.gatherInterval != time.Duration(0) {
reporter.gatherMetrics()
}
- // post the collected metrics and retreive sampling rate.
+ // post the collected metrics and retrieve sampling rate.
if !reporter.postGatheredMetrics(ctx) {
// context expired, abort.
return
@@ -218,7 +218,7 @@ func (reporter *MetricReporter) tryInvokeNodeExporter(ctx context.Context) {
return
}
}
- // give the node exporter the same enviroment variable we've received.
+ // give the node exporter the same environment variable we've received.
neAttributes := os.ProcAttr{
Dir: filepath.Dir(os.Args[0]),
Env: os.Environ(),
@@ -241,7 +241,7 @@ func (reporter *MetricReporter) tryInvokeNodeExporter(ctx context.Context) {
reporter.neProcess = proc
- // wait for the process to complete on a separate goroutine, and set the reporter.neProcess varaible to nil once it's done.
+ // wait for the process to complete on a separate goroutine, and set the reporter.neProcess variable to nil once it's done.
go func(proc **os.Process) {
(*proc).Wait()
// status, _ :=
diff --git a/util/metrics/segment_test.go b/util/metrics/segment_test.go
index 3bd07eaa9..725bbb353 100644
--- a/util/metrics/segment_test.go
+++ b/util/metrics/segment_test.go
@@ -32,6 +32,21 @@ type SegmentTest struct {
}
func TestMetricSegment(t *testing.T) {
+ const initialSleepDuration = 10 * time.Millisecond
+ const maxSleepDuration = 4 * time.Second
+ done := false
+ for sleepDuration := initialSleepDuration; sleepDuration <= maxSleepDuration; sleepDuration *= 2 {
+ done = testMetricSegmentHelper(t, sleepDuration)
+ if done {
+ break
+ }
+ }
+ if !done {
+ require.Fail(t, "test failed")
+ }
+}
+
+func testMetricSegmentHelper(t *testing.T, functionTime time.Duration) bool {
test := &SegmentTest{
MetricTest: NewMetricTest(),
@@ -47,8 +62,7 @@ func TestMetricSegment(t *testing.T) {
})
metricService.Start(context.Background())
- functionTime := time.Duration(400 * time.Millisecond)
- acceptedFunctionThreshold := 0.1 // 10 percent.
+ acceptedFunctionThreshold := 1.1 // 10 percent.
segment := MakeSegment(&MetricName{Name: "test_segment_name1", Description: "this is the metric test for segment object"})
segmentTest := func() {
inst, _ := segment.EnterSegment(map[string]string{"pid": "123"})
@@ -78,7 +92,9 @@ func TestMetricSegment(t *testing.T) {
if elapsedTime, err := strconv.ParseFloat(v, 64); err != nil {
t.Fatalf("The metric '%s' has unexpected value of '%s'", k, v)
} else {
- require.InDelta(t, functionTime.Seconds(), elapsedTime, functionTime.Seconds()*acceptedFunctionThreshold, "The metric '%s' reported unexpected elapsed time of '%s'", k, v)
+ if elapsedTime < functionTime.Seconds() || elapsedTime > functionTime.Seconds()*acceptedFunctionThreshold {
+ return false
+ }
}
}
if strings.Contains(k, "test_segment_name1_sec_total{") {
@@ -86,7 +102,9 @@ func TestMetricSegment(t *testing.T) {
if elapsedTime, err := strconv.ParseFloat(v, 64); err != nil {
t.Fatalf("The metric '%s' has unexpected value of '%s'", k, v)
} else {
- require.InDelta(t, 2*functionTime.Seconds(), elapsedTime, 2*functionTime.Seconds()*acceptedFunctionThreshold, "The metric '%s' reported unexpected elapsed time of '%s'", k, v)
+ if elapsedTime < 2*functionTime.Seconds() || elapsedTime > 2*functionTime.Seconds()*acceptedFunctionThreshold {
+ return false
+ }
}
}
if strings.Contains(k, "test_segment_name1_total{") {
@@ -94,4 +112,5 @@ func TestMetricSegment(t *testing.T) {
require.Equal(t, "2", v, "The metric '%s' has unexpected value of '%s'", k, v)
}
}
+ return true
}
diff --git a/util/s3/s3Helper.go b/util/s3/s3Helper.go
index 78f111f5d..a997f20a1 100644
--- a/util/s3/s3Helper.go
+++ b/util/s3/s3Helper.go
@@ -160,7 +160,7 @@ func getAWSCredentials() (awsID string, awsKey string) {
func validateS3Credentials(awsID string, awsKey string) (err error) {
if awsID == "" || awsKey == "" {
- err = fmt.Errorf("AWS credentials must be specified in enviroment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY")
+ err = fmt.Errorf("AWS credentials must be specified in environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY")
return
}
return
diff --git a/util/timers/frozen.go b/util/timers/frozen.go
new file mode 100644
index 000000000..7b668959c
--- /dev/null
+++ b/util/timers/frozen.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 timers
+
+import (
+ "time"
+)
+
+// Frozen is a dummy frozen clock that never fires.
+type Frozen struct {
+ timeoutCh chan time.Time
+}
+
+// MakeFrozenClock creates a new frozen clock.
+func MakeFrozenClock() Clock {
+ return &Frozen{
+ timeoutCh: make(chan time.Time, 1),
+ }
+}
+
+// Zero returns a new Clock reset to the current time.
+func (m *Frozen) Zero() Clock {
+ return MakeFrozenClock()
+}
+
+// TimeoutAt returns a channel that will signal when the duration has elapsed.
+func (m *Frozen) TimeoutAt(delta time.Duration) <-chan time.Time {
+ return m.timeoutCh
+}
+
+// Encode implements Clock.Encode.
+func (m *Frozen) Encode() []byte {
+ return []byte{}
+}
+
+// Decode implements Clock.Decode.
+func (m *Frozen) Decode([]byte) (Clock, error) {
+ return MakeFrozenClock(), nil
+}
+
+func (m *Frozen) String() string {
+ return ""
+}
diff --git a/util/watchdogStreamReader.go b/util/watchdogStreamReader.go
index 5be73a2e3..29d7fa099 100644
--- a/util/watchdogStreamReader.go
+++ b/util/watchdogStreamReader.go
@@ -35,7 +35,7 @@ var ErrWatchdogStreamReaderReaderReachedDataLimit = fmt.Errorf("watchdog stream
// 1. It allows to limit the amount of data being read from the stream between two subsequent Reset calls.
// 2. It allows to limit the amount of time being spent reading and/or waiting for data from the reader between two subsequent Reset calls.
// The intended usage is to attach it directly to a http.Response.Body and to perform the reading from the watchdogStreamReader directly.
-// If data is being pulled as expected, the caller could extend the timeout and or data limits. This is particulary usefull when providing
+// If data is being pulled as expected, the caller could extend the timeout and or data limits. This is particularly useful when providing
// the input stream to components which wouldn't time-limit or data-limit the data, and could end up exhusting the host computer resources.
type watchdogStreamReader struct {
// watchdog configuration
@@ -52,7 +52,7 @@ type watchdogStreamReader struct {
readerClose chan struct{} // channel used to signal the shutting down of the reader goroutine
tickerClose chan struct{} // channel used to signal the shutting down of the ticker goroutine
readerRequest chan struct{} // channel used to signal the reader goroutine that it needs to go and attempt to read from the underlying reader
- readerMu deadlock.Mutex // syncronization mutex for the reader goroutine
+ readerMu deadlock.Mutex // synchronization mutex for the reader goroutine
readerCond *sync.Cond // conditional check variable for the reader goroutine
}