From 3430303732e363a715f69a40eaed68b83ce6fd18 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Wed, 14 Dec 2022 10:05:44 -0500 Subject: [PATCH 1/8] tests: Check for non-empty expected err string (#447) * Check for non-empty expected err string * Follow existing errstring conventions * Revert 1 commit * Finish merging * Test with different sandbox * Revert sdk testing branch * Add check to see if expected error string was present, but no errors were returned --- test/applications_integration_test.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/applications_integration_test.go b/test/applications_integration_test.go index 4392b1c7..09f3adff 100644 --- a/test/applications_integration_test.go +++ b/test/applications_integration_test.go @@ -7,6 +7,7 @@ import ( "encoding/base64" "encoding/binary" "encoding/json" + "errors" "fmt" "reflect" "regexp" @@ -786,11 +787,16 @@ func theContentsOfTheBoxWithNameShouldBeIfThereIsAnErrorItIs(fromClient, encoded err = fmt.Errorf("expecting algod or indexer, got " + fromClient) } if err != nil { - if strings.Contains(err.Error(), errStr) { + // If the expected error string is not empty, check if it is a substring of the actual error string. + // Note that if the expected error string is empty, then the second condition will always return true. + if len(errStr) != 0 && strings.Contains(err.Error(), errStr) { return nil } return err } + if len(errStr) != 0 { + return errors.New("expected an error but none was reported") + } b64Value := base64.StdEncoding.EncodeToString(box.Value) if b64Value != boxContents { From d97ebd1124673665085d97be31c1d13bed9a83f2 Mon Sep 17 00:00:00 2001 From: Will Winder Date: Wed, 14 Dec 2022 17:22:58 -0500 Subject: [PATCH 2/8] Algod Client API: Support StateDelta and Sync endpoints. (#448) --- client/v2/algod/algod.go | 21 +++++++ client/v2/algod/getLedgerStateDelta.go | 22 +++++++ client/v2/algod/getSyncRound.go | 19 ++++++ client/v2/algod/setSyncRound.go | 21 +++++++ client/v2/algod/unsetSyncRound.go | 18 ++++++ client/v2/common/common.go | 5 ++ client/v2/common/common_test.go | 61 +++++++++++++++++++ .../common/models/account_balance_record.go | 10 +++ client/v2/common/models/account_deltas.go | 13 ++++ client/v2/common/models/account_totals.go | 16 +++++ .../v2/common/models/app_resource_record.go | 22 +++++++ .../v2/common/models/asset_resource_record.go | 22 +++++++ .../common/models/get_sync_round_response.go | 7 +++ client/v2/common/models/kv_delta.go | 11 ++++ client/v2/common/models/ledger_state_delta.go | 28 +++++++++ client/v2/common/models/modified_app.go | 13 ++++ client/v2/common/models/modified_asset.go | 13 ++++ client/v2/common/models/tx_lease.go | 13 ++++ test/algodclientv2_test.go | 41 +++++++++++++ test/helpers.go | 10 +++ test/responses_unit_test.go | 12 ++++ test/unit.tags | 4 +- 22 files changed, 401 insertions(+), 1 deletion(-) create mode 100644 client/v2/algod/getLedgerStateDelta.go create mode 100644 client/v2/algod/getSyncRound.go create mode 100644 client/v2/algod/setSyncRound.go create mode 100644 client/v2/algod/unsetSyncRound.go create mode 100644 client/v2/common/common_test.go create mode 100644 client/v2/common/models/account_balance_record.go create mode 100644 client/v2/common/models/account_deltas.go create mode 100644 client/v2/common/models/account_totals.go create mode 100644 client/v2/common/models/app_resource_record.go create mode 100644 client/v2/common/models/asset_resource_record.go create mode 100644 client/v2/common/models/get_sync_round_response.go create mode 100644 client/v2/common/models/kv_delta.go create mode 100644 client/v2/common/models/ledger_state_delta.go create mode 100644 client/v2/common/models/modified_app.go create mode 100644 client/v2/common/models/modified_asset.go create mode 100644 client/v2/common/models/tx_lease.go diff --git a/client/v2/algod/algod.go b/client/v2/algod/algod.go index a5b8ce87..d38b6315 100644 --- a/client/v2/algod/algod.go +++ b/client/v2/algod/algod.go @@ -11,6 +11,11 @@ const authHeader = "X-Algo-API-Token" type Client common.Client +// delete performs a DELETE request to the specific path against the server, assumes JSON response +func (c *Client) delete(ctx context.Context, response interface{}, path string, body interface{}, headers []*common.Header) error { + return (*common.Client)(c).Delete(ctx, response, path, body, headers) +} + // get performs a GET request to the specific path against the server, assumes JSON response func (c *Client) get(ctx context.Context, response interface{}, path string, body interface{}, headers []*common.Header) error { return (*common.Client)(c).Get(ctx, response, path, body, headers) @@ -116,6 +121,10 @@ func (c *Client) PendingTransactionInformation(txid string) *PendingTransactionI return &PendingTransactionInformation{c: c, txid: txid} } +func (c *Client) GetLedgerStateDelta(round uint64) *GetLedgerStateDelta { + return &GetLedgerStateDelta{c: c, round: round} +} + func (c *Client) GetStateProof(round uint64) *GetStateProof { return &GetStateProof{c: c, round: round} } @@ -140,6 +149,18 @@ func (c *Client) GetAssetByID(assetId uint64) *GetAssetByID { return &GetAssetByID{c: c, assetId: assetId} } +func (c *Client) UnsetSyncRound() *UnsetSyncRound { + return &UnsetSyncRound{c: c} +} + +func (c *Client) GetSyncRound() *GetSyncRound { + return &GetSyncRound{c: c} +} + +func (c *Client) SetSyncRound(round uint64) *SetSyncRound { + return &SetSyncRound{c: c, round: round} +} + func (c *Client) TealCompile(source []byte) *TealCompile { return &TealCompile{c: c, source: source} } diff --git a/client/v2/algod/getLedgerStateDelta.go b/client/v2/algod/getLedgerStateDelta.go new file mode 100644 index 00000000..eda780e0 --- /dev/null +++ b/client/v2/algod/getLedgerStateDelta.go @@ -0,0 +1,22 @@ +package algod + +import ( + "context" + "fmt" + + "github.com/algorand/go-algorand-sdk/client/v2/common" + "github.com/algorand/go-algorand-sdk/client/v2/common/models" +) + +// GetLedgerStateDelta get ledger deltas for a round. +type GetLedgerStateDelta struct { + c *Client + + round uint64 +} + +// Do performs the HTTP request +func (s *GetLedgerStateDelta) Do(ctx context.Context, headers ...*common.Header) (response models.LedgerStateDelta, err error) { + err = s.c.get(ctx, &response, fmt.Sprintf("/v2/deltas/%s", common.EscapeParams(s.round)...), nil, headers) + return +} diff --git a/client/v2/algod/getSyncRound.go b/client/v2/algod/getSyncRound.go new file mode 100644 index 00000000..37a15f20 --- /dev/null +++ b/client/v2/algod/getSyncRound.go @@ -0,0 +1,19 @@ +package algod + +import ( + "context" + + "github.com/algorand/go-algorand-sdk/client/v2/common" + "github.com/algorand/go-algorand-sdk/client/v2/common/models" +) + +// GetSyncRound gets the minimum sync round for the ledger. +type GetSyncRound struct { + c *Client +} + +// Do performs the HTTP request +func (s *GetSyncRound) Do(ctx context.Context, headers ...*common.Header) (response models.GetSyncRoundResponse, err error) { + err = s.c.get(ctx, &response, "/v2/ledger/sync", nil, headers) + return +} diff --git a/client/v2/algod/setSyncRound.go b/client/v2/algod/setSyncRound.go new file mode 100644 index 00000000..9292b7b2 --- /dev/null +++ b/client/v2/algod/setSyncRound.go @@ -0,0 +1,21 @@ +package algod + +import ( + "context" + "fmt" + + "github.com/algorand/go-algorand-sdk/client/v2/common" +) + +// SetSyncRound sets the minimum sync round on the ledger. +type SetSyncRound struct { + c *Client + + round uint64 +} + +// Do performs the HTTP request +func (s *SetSyncRound) Do(ctx context.Context, headers ...*common.Header) (response string, err error) { + err = s.c.post(ctx, &response, fmt.Sprintf("/v2/ledger/sync/%s", common.EscapeParams(s.round)...), nil, headers, nil) + return +} diff --git a/client/v2/algod/unsetSyncRound.go b/client/v2/algod/unsetSyncRound.go new file mode 100644 index 00000000..601350c8 --- /dev/null +++ b/client/v2/algod/unsetSyncRound.go @@ -0,0 +1,18 @@ +package algod + +import ( + "context" + + "github.com/algorand/go-algorand-sdk/client/v2/common" +) + +// UnsetSyncRound unset the ledger sync round. +type UnsetSyncRound struct { + c *Client +} + +// Do performs the HTTP request +func (s *UnsetSyncRound) Do(ctx context.Context, headers ...*common.Header) (response string, err error) { + err = s.c.delete(ctx, &response, "/v2/ledger/sync", nil, headers) + return +} diff --git a/client/v2/common/common.go b/client/v2/common/common.go index e9552ae0..5108e567 100644 --- a/client/v2/common/common.go +++ b/client/v2/common/common.go @@ -193,6 +193,11 @@ func (client *Client) submitForm(ctx context.Context, response interface{}, path return err } +// Delete performs a DELETE request to the specific path against the server +func (client *Client) Delete(ctx context.Context, response interface{}, path string, params interface{}, headers []*Header) error { + return client.submitForm(ctx, response, path, params, "DELETE", false /* encodeJSON */, headers, nil) +} + // Get performs a GET request to the specific path against the server func (client *Client) Get(ctx context.Context, response interface{}, path string, params interface{}, headers []*Header) error { return client.submitForm(ctx, response, path, params, "GET", false /* encodeJSON */, headers, nil) diff --git a/client/v2/common/common_test.go b/client/v2/common/common_test.go new file mode 100644 index 00000000..8fdbe6e8 --- /dev/null +++ b/client/v2/common/common_test.go @@ -0,0 +1,61 @@ +package common + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestClient_Verbs(t *testing.T) { + path := "/some/path" + + // Call each of the helper functions, they should make a request with the correct verb. + testcases := []struct { + expectedVerb string + call func(c *Client) error + }{ + { + expectedVerb: "GET", + call: func(c *Client) error { + return c.Get(context.Background(), nil, path, nil, nil) + }, + }, + { + expectedVerb: "POST", + call: func(c *Client) error { + return c.Post(context.Background(), nil, path, nil, nil, nil) + }, + }, + { + expectedVerb: "DELETE", + call: func(c *Client) error { + return c.Delete(context.Background(), nil, path, nil, nil) + }, + }, + } + + for _, tc := range testcases { + tc := tc + t.Run(tc.expectedVerb, func(t *testing.T) { + var receivedMethod string + var receivedPath string + + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + receivedMethod = r.Method + receivedPath = r.URL.String() + })) + + c, err := MakeClient(mockServer.URL, "API-Header", "ASDF") + require.NoError(t, err) + + // Call the test function. + err = tc.call(c) + assert.Equal(t, tc.expectedVerb, receivedMethod) + assert.Equal(t, path, receivedPath) + }) + } +} diff --git a/client/v2/common/models/account_balance_record.go b/client/v2/common/models/account_balance_record.go new file mode 100644 index 00000000..dffe48bf --- /dev/null +++ b/client/v2/common/models/account_balance_record.go @@ -0,0 +1,10 @@ +package models + +// AccountBalanceRecord account and its address +type AccountBalanceRecord struct { + // AccountData updated account data. + AccountData Account `json:"account-data"` + + // Address address of the updated account. + Address string `json:"address"` +} diff --git a/client/v2/common/models/account_deltas.go b/client/v2/common/models/account_deltas.go new file mode 100644 index 00000000..d23a4dcc --- /dev/null +++ b/client/v2/common/models/account_deltas.go @@ -0,0 +1,13 @@ +package models + +// AccountDeltas exposes deltas for account based resources in a single round +type AccountDeltas struct { + // Accounts array of Account updates for the round + Accounts []AccountBalanceRecord `json:"accounts,omitempty"` + + // Apps array of App updates for the round. + Apps []AppResourceRecord `json:"apps,omitempty"` + + // Assets array of Asset updates for the round. + Assets []AssetResourceRecord `json:"assets,omitempty"` +} diff --git a/client/v2/common/models/account_totals.go b/client/v2/common/models/account_totals.go new file mode 100644 index 00000000..ab0afd74 --- /dev/null +++ b/client/v2/common/models/account_totals.go @@ -0,0 +1,16 @@ +package models + +// AccountTotals total Algos in the system grouped by account status +type AccountTotals struct { + // NotParticipating amount of stake in non-participating accounts + NotParticipating uint64 `json:"not-participating"` + + // Offline amount of stake in offline accounts + Offline uint64 `json:"offline"` + + // Online amount of stake in online accounts + Online uint64 `json:"online"` + + // RewardsLevel total number of algos received per reward unit since genesis + RewardsLevel uint64 `json:"rewards-level"` +} diff --git a/client/v2/common/models/app_resource_record.go b/client/v2/common/models/app_resource_record.go new file mode 100644 index 00000000..f1212b33 --- /dev/null +++ b/client/v2/common/models/app_resource_record.go @@ -0,0 +1,22 @@ +package models + +// AppResourceRecord represents AppParams and AppLocalStateDelta in deltas +type AppResourceRecord struct { + // Address app account address + Address string `json:"address"` + + // AppDeleted whether the app was deleted + AppDeleted bool `json:"app-deleted"` + + // AppIndex app index + AppIndex uint64 `json:"app-index"` + + // AppLocalState app local state + AppLocalState ApplicationLocalState `json:"app-local-state,omitempty"` + + // AppLocalStateDeleted whether the app local state was deleted + AppLocalStateDeleted bool `json:"app-local-state-deleted"` + + // AppParams app params + AppParams ApplicationParams `json:"app-params,omitempty"` +} diff --git a/client/v2/common/models/asset_resource_record.go b/client/v2/common/models/asset_resource_record.go new file mode 100644 index 00000000..fcf008e2 --- /dev/null +++ b/client/v2/common/models/asset_resource_record.go @@ -0,0 +1,22 @@ +package models + +// AssetResourceRecord represents AssetParams and AssetHolding in deltas +type AssetResourceRecord struct { + // Address account address of the asset + Address string `json:"address"` + + // AssetDeleted whether the asset was deleted + AssetDeleted bool `json:"asset-deleted"` + + // AssetHolding the asset holding + AssetHolding AssetHolding `json:"asset-holding,omitempty"` + + // AssetHoldingDeleted whether the asset holding was deleted + AssetHoldingDeleted bool `json:"asset-holding-deleted"` + + // AssetIndex index of the asset + AssetIndex uint64 `json:"asset-index"` + + // AssetParams asset params + AssetParams AssetParams `json:"asset-params,omitempty"` +} diff --git a/client/v2/common/models/get_sync_round_response.go b/client/v2/common/models/get_sync_round_response.go new file mode 100644 index 00000000..1b1da397 --- /dev/null +++ b/client/v2/common/models/get_sync_round_response.go @@ -0,0 +1,7 @@ +package models + +// GetSyncRoundResponse response containing the ledger's minimum sync round +type GetSyncRoundResponse struct { + // Round the minimum sync round for the ledger. + Round uint64 `json:"round"` +} diff --git a/client/v2/common/models/kv_delta.go b/client/v2/common/models/kv_delta.go new file mode 100644 index 00000000..c76f1085 --- /dev/null +++ b/client/v2/common/models/kv_delta.go @@ -0,0 +1,11 @@ +package models + +// KvDelta a single Delta containing the key, the previous value and the current +// value for a single round. +type KvDelta struct { + // Key the key, base64 encoded. + Key []byte `json:"key,omitempty"` + + // Value the new value of the KV store entry, base64 encoded. + Value []byte `json:"value,omitempty"` +} diff --git a/client/v2/common/models/ledger_state_delta.go b/client/v2/common/models/ledger_state_delta.go new file mode 100644 index 00000000..d63dc849 --- /dev/null +++ b/client/v2/common/models/ledger_state_delta.go @@ -0,0 +1,28 @@ +package models + +// LedgerStateDelta contains ledger updates. +type LedgerStateDelta struct { + // Accts accountDeltas object + Accts AccountDeltas `json:"accts,omitempty"` + + // KvMods array of KV Deltas + KvMods []KvDelta `json:"kv-mods,omitempty"` + + // ModifiedApps list of modified Apps + ModifiedApps []ModifiedApp `json:"modified-apps,omitempty"` + + // ModifiedAssets list of modified Assets + ModifiedAssets []ModifiedAsset `json:"modified-assets,omitempty"` + + // PrevTimestamp previous block timestamp + PrevTimestamp uint64 `json:"prev-timestamp,omitempty"` + + // StateProofNext next round for which we expect a state proof + StateProofNext uint64 `json:"state-proof-next,omitempty"` + + // Totals account Totals + Totals AccountTotals `json:"totals,omitempty"` + + // TxLeases list of transaction leases + TxLeases []TxLease `json:"tx-leases,omitempty"` +} diff --git a/client/v2/common/models/modified_app.go b/client/v2/common/models/modified_app.go new file mode 100644 index 00000000..bc58ff62 --- /dev/null +++ b/client/v2/common/models/modified_app.go @@ -0,0 +1,13 @@ +package models + +// ModifiedApp app which was created or deleted. +type ModifiedApp struct { + // Created created if true, deleted if false + Created bool `json:"created"` + + // Creator address of the creator. + Creator string `json:"creator"` + + // Id app Id + Id uint64 `json:"id"` +} diff --git a/client/v2/common/models/modified_asset.go b/client/v2/common/models/modified_asset.go new file mode 100644 index 00000000..684c848e --- /dev/null +++ b/client/v2/common/models/modified_asset.go @@ -0,0 +1,13 @@ +package models + +// ModifiedAsset asset which was created or deleted. +type ModifiedAsset struct { + // Created created if true, deleted if false + Created bool `json:"created"` + + // Creator address of the creator. + Creator string `json:"creator"` + + // Id asset Id + Id uint64 `json:"id"` +} diff --git a/client/v2/common/models/tx_lease.go b/client/v2/common/models/tx_lease.go new file mode 100644 index 00000000..cdc25755 --- /dev/null +++ b/client/v2/common/models/tx_lease.go @@ -0,0 +1,13 @@ +package models + +// TxLease +type TxLease struct { + // Expiration round that the lease expires + Expiration uint64 `json:"expiration"` + + // Lease lease data + Lease []byte `json:"lease"` + + // Sender address of the lease sender + Sender string `json:"sender"` +} diff --git a/test/algodclientv2_test.go b/test/algodclientv2_test.go index 25b21a82..f429c489 100644 --- a/test/algodclientv2_test.go +++ b/test/algodclientv2_test.go @@ -36,6 +36,7 @@ func AlgodClientV2Context(s *godog.Suite) { s.Step(`^we make any Suggested Transaction Parameters call$`, weMakeAnySuggestedTransactionParametersCall) s.Step(`^the parsed Suggested Transaction Parameters response should have first round valid of (\d+)$`, theParsedResponseShouldEqualTheMockResponse) s.Step(`^expect the path used to be "([^"]*)"$`, expectThePathUsedToBe) + s.Step(`^expect the request to be "([^"]*)" "([^"]*)"$`, expectTheRequestToBe) s.Step(`^we make a Status after Block call with round (\d+)$`, weMakeAStatusAfterBlockCallWithRound) s.Step(`^we make an Account Information call against account "([^"]*)"$`, weMakeAnAccountInformationCallAgainstAccount) s.Step(`^the parsed Pending Transactions Information response should contain an array of len (\d+) and element number (\d+) should have sender "([^"]*)"$`, theParsedResponseShouldEqualTheMockResponse) @@ -54,6 +55,10 @@ func AlgodClientV2Context(s *godog.Suite) { s.Step(`^we make a GetStateProof call for round (\d+)$`, weMakeAGetStateProofCallForRound) s.Step(`^we make a GetTransactionProof call for round (\d+) txid "([^"]*)" and hashtype "([^"]*)"$`, weMakeAGetTransactionProofCallForRoundTxidAndHashtype) s.Step(`^we make a Lookup Block Hash call against round (\d+)$`, weMakeALookupBlockHashCallAgainstRound) + s.Step(`^we make a GetLedgerStateDelta call against round (\d+)$`, weMakeAGetLedgerStateDeltaCallAgainstRound) + s.Step(`^we make a SetSyncRound call against round (\d+)$`, weMakeASetSyncRoundCallAgainstRound) + s.Step(`^we make a GetSyncRound call$`, weMakeAGetSyncRoundCall) + s.Step(`^we make a UnsetSyncRound call$`, weMakeAUnsetSyncRoundCall) s.BeforeScenario(func(interface{}) { globalErrForExamination = nil @@ -304,3 +309,39 @@ func weMakeALookupBlockHashCallAgainstRound(round int) error { algodClient.GetBlockHash(uint64(round)).Do(context.Background()) return nil } + +func weMakeAGetLedgerStateDeltaCallAgainstRound(round int) error { + algodClient, err := algod.MakeClient(mockServer.URL, "") + if err != nil { + return err + } + algodClient.GetLedgerStateDelta(uint64(round)).Do(context.Background()) + return nil +} + +func weMakeASetSyncRoundCallAgainstRound(round int) error { + algodClient, err := algod.MakeClient(mockServer.URL, "") + if err != nil { + return err + } + algodClient.SetSyncRound(uint64(round)).Do(context.Background()) + return nil +} + +func weMakeAGetSyncRoundCall() error { + algodClient, err := algod.MakeClient(mockServer.URL, "") + if err != nil { + return err + } + algodClient.GetSyncRound().Do(context.Background()) + return nil +} + +func weMakeAUnsetSyncRoundCall() error { + algodClient, err := algod.MakeClient(mockServer.URL, "") + if err != nil { + return err + } + algodClient.UnsetSyncRound().Do(context.Background()) + return nil +} diff --git a/test/helpers.go b/test/helpers.go index f0a932a0..3618b503 100644 --- a/test/helpers.go +++ b/test/helpers.go @@ -63,14 +63,24 @@ func mockHttpResponsesInLoadedFromHelper(jsonfiles, directory string, status int return err } +var receivedMethod string var receivedPath string func mockServerRecordingRequestPaths() error { mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + receivedMethod = r.Method receivedPath = r.URL.String() })) return nil } + +func expectTheRequestToBe(expectedMethod, expectedPath string) error { + if strings.ToLower(expectedMethod) != strings.ToLower(receivedMethod) { + return fmt.Errorf("method used to access mock server was %s but expected %s", receivedMethod, expectedMethod) + } + return expectThePathUsedToBe(expectedPath) +} + func expectThePathUsedToBe(expectedPath string) error { if receivedPath != expectedPath { return fmt.Errorf("path used to access mock server was %s but expected path %s", receivedPath, expectedPath) diff --git a/test/responses_unit_test.go b/test/responses_unit_test.go index 8b33cafa..34cb0e13 100644 --- a/test/responses_unit_test.go +++ b/test/responses_unit_test.go @@ -172,6 +172,18 @@ func weMakeAnyCallTo(client /* algod/indexer */, endpoint string) (err error) { case "GetBlockHash": response, err = algodC.GetBlockHash(123).Do(context.Background()) + case "GetLedgerStateDelta": + response, err = + algodC.GetLedgerStateDelta(123).Do(context.Background()) + case "UnsetSyncRound": + response, err = + algodC.UnsetSyncRound().Do(context.Background()) + case "SetSyncRound": + response, err = + algodC.SetSyncRound(123).Do(context.Background()) + case "GetSyncRound": + response, err = + algodC.GetSyncRound().Do(context.Background()) case "any": // This is an error case // pickup the error as the response diff --git a/test/unit.tags b/test/unit.tags index 905b7e6c..cb55c5bf 100644 --- a/test/unit.tags +++ b/test/unit.tags @@ -18,16 +18,18 @@ @unit.rekey @unit.responses @unit.responses.231 +@unit.responses.blocksummary @unit.responses.genesis @unit.responses.messagepack @unit.responses.messagepack.231 @unit.responses.participationupdates @unit.responses.unlimited_assets -@unit.responses.blocksummary +@unit.responses.statedelta @unit.sourcemap @unit.stateproof.paths @unit.stateproof.responses @unit.stateproof.responses.msgp +@unit.statedelta @unit.tealsign @unit.transactions @unit.transactions.keyreg From 9cca28021fbcaf20a85f64ef818bdc7be4f3a7ec Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Thu, 15 Dec 2022 16:40:14 -0500 Subject: [PATCH 3/8] Delete some stale generated files (#455) --- client/v2/common/models/catchpoint_abort_response.go | 7 ------- client/v2/common/models/catchpoint_start_response.go | 7 ------- 2 files changed, 14 deletions(-) delete mode 100644 client/v2/common/models/catchpoint_abort_response.go delete mode 100644 client/v2/common/models/catchpoint_start_response.go diff --git a/client/v2/common/models/catchpoint_abort_response.go b/client/v2/common/models/catchpoint_abort_response.go deleted file mode 100644 index 89f6d5cb..00000000 --- a/client/v2/common/models/catchpoint_abort_response.go +++ /dev/null @@ -1,7 +0,0 @@ -package models - -// CatchpointAbortResponse -type CatchpointAbortResponse struct { - // CatchupMessage catchup abort response string - CatchupMessage string `json:"catchup-message"` -} diff --git a/client/v2/common/models/catchpoint_start_response.go b/client/v2/common/models/catchpoint_start_response.go deleted file mode 100644 index 0882e751..00000000 --- a/client/v2/common/models/catchpoint_start_response.go +++ /dev/null @@ -1,7 +0,0 @@ -package models - -// CatchpointStartResponse -type CatchpointStartResponse struct { - // CatchupMessage catchup start response string - CatchupMessage string `json:"catchup-message"` -} From 62155f31e5ae6a2799db5f2deddd323068a900bb Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Thu, 15 Dec 2022 17:38:25 -0500 Subject: [PATCH 4/8] v2: Breaking changes from v1 to v2.0.0 (#449) --- CHANGELOG.md | 12 + client/algod/algod.go | 235 - client/algod/models/models.go | 810 ---- client/algod/wrappers.go | 274 -- client/v2/common/models/dryrun_txn_result.go | 4 - crypto/account.go | 23 +- crypto/account_test.go | 18 +- crypto/crypto.go | 13 +- crypto/crypto_test.go | 29 +- examples/gen-addresses/main.go | 4 +- future/transaction.go | 1375 ------ future/transaction_test.go | 1065 ----- logic/bundle_langspec_json.sh | 17 - logic/bundledSpecInject.go | 4036 ----------------- logic/langspec.json | 1 - logic/logic.go | 239 - logic/logic_test.go | 219 - templates/dynamicFee.go | 190 - templates/hashTimeLockedContract.go | 122 - templates/limitOrder.go | 129 - templates/periodicPayment.go | 122 - templates/split.go | 167 - templates/template.go | 85 - templates/templates_test.go | 186 - test/applications_integration_test.go | 30 +- test/steps_test.go | 70 +- test/transactions_test.go | 18 +- .../atomicTransactionComposer.go | 2 +- .../atomicTransactionComposer_test.go | 2 +- {future => transaction}/dryrun.go | 2 +- transaction/transaction.go | 1289 ++++-- {future => transaction}/transactionSigner.go | 2 +- .../transactionSigner_test.go | 2 +- transaction/transaction_test.go | 521 ++- .../waitForConfirmation.go | 2 +- 35 files changed, 1511 insertions(+), 9804 deletions(-) delete mode 100644 client/algod/algod.go delete mode 100644 client/algod/models/models.go delete mode 100644 client/algod/wrappers.go delete mode 100644 future/transaction.go delete mode 100644 future/transaction_test.go delete mode 100755 logic/bundle_langspec_json.sh delete mode 100644 logic/bundledSpecInject.go delete mode 100644 logic/langspec.json delete mode 100644 logic/logic.go delete mode 100644 logic/logic_test.go delete mode 100644 templates/dynamicFee.go delete mode 100644 templates/hashTimeLockedContract.go delete mode 100644 templates/limitOrder.go delete mode 100644 templates/periodicPayment.go delete mode 100644 templates/split.go delete mode 100644 templates/template.go delete mode 100644 templates/templates_test.go rename {future => transaction}/atomicTransactionComposer.go (99%) rename {future => transaction}/atomicTransactionComposer_test.go (99%) rename {future => transaction}/dryrun.go (99%) rename {future => transaction}/transactionSigner.go (99%) rename {future => transaction}/transactionSigner_test.go (99%) rename {future => transaction}/waitForConfirmation.go (98%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 479e0d8f..dc4d30c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# 2.0.0 + +## What's Changed +### Breaking Changes +* Remove `future` package. Move package contents to `transaction`. +* Remove `MakeLogicSigAccount` and replace with `MakeLogicSigAccountEscrow`. Mark `MakeLogicSig` as a private function as well, only intended for internal use. +* Rename `SignLogicsigTransaction` to `SignLogicSigTransaction`. +* Remove logicsig templates, `logic/langspec.json`, and all methods depending on it. +* Remove `DryrunTxnResult.Cost` in favor of 2 fields: `BudgetAdded` and `BudgetConsumed`. `cost` can be derived by `BudgetConsumed - BudgetAdded`. +* Remove v1 algod API (client/algod) due to API end-of-life (2022-12-01). Instead, use v2 algod API (client/v2/algod). +* Remove unused generated types: `CatchpointAbortResponse`, `CatchpointStartResponse`. + # 1.24.0 ## What's Changed ### Bugfixes diff --git a/client/algod/algod.go b/client/algod/algod.go deleted file mode 100644 index 247296ff..00000000 --- a/client/algod/algod.go +++ /dev/null @@ -1,235 +0,0 @@ -package algod - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "strings" - - "github.com/google/go-querystring/query" -) - -const ( - authHeader = "X-Algo-API-Token" - healthCheckEndpoint = "/health" - apiVersionPathPrefix = "/v1" -) - -// unversionedPaths ais a set of paths that should not be prefixed by the API version -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -var unversionedPaths = map[string]bool{ - "/versions": true, - "/health": true, -} - -// rawRequestPaths is a set of paths where the body should not be urlencoded -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -var rawRequestPaths = map[string]bool{ - "/transactions": true, -} - -// Header is a struct for custom headers. -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -type Header struct { - Key string - Value string -} - -// Client manages the REST interface for a calling user. -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -type Client struct { - serverURL url.URL - apiToken string - headers []*Header -} - -// MakeClient is the factory for constructing a Client for a given endpoint. -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func MakeClient(address string, apiToken string) (c Client, err error) { - url, err := url.Parse(address) - if err != nil { - return - } - - c = Client{ - serverURL: *url, - apiToken: apiToken, - } - return -} - -// MakeClientWithHeaders is the factory for constructing a Client for a given endpoint with additional user defined headers. -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func MakeClientWithHeaders(address string, apiToken string, headers []*Header) (c Client, err error) { - c, err = MakeClient(address, apiToken) - if err != nil { - return - } - - c.headers = append(c.headers, headers...) - - return -} - -// extractError checks if the response signifies an error (for now, StatusCode != 200). -// If so, it returns the error. -// Otherwise, it returns nil. -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func extractError(resp *http.Response) error { - if resp.StatusCode == 200 { - return nil - } - - errorBuf, _ := ioutil.ReadAll(resp.Body) // ignore returned error - return fmt.Errorf("HTTP %v: %s", resp.Status, errorBuf) -} - -// stripTransaction gets a transaction of the form "tx-XXXXXXXX" and truncates the "tx-" part, if it starts with "tx-" -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func stripTransaction(tx string) string { - if strings.HasPrefix(tx, "tx-") { - return strings.SplitAfter(tx, "-")[1] - } - return tx -} - -// mergeRawQueries merges two raw queries, appending an "&" if both are non-empty -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func mergeRawQueries(q1, q2 string) string { - if q1 == "" { - return q2 - } else if q2 == "" { - return q1 - } else { - return q1 + "&" + q2 - } -} - -// RawRequest submits the requests, and returns a map of the response fields -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) RawRequest(path string, request interface{}, requestMethod string, encodeJSON bool, headers []*Header) ( - v map[string]interface{}, err error) { - response, err := client.submitFormRaw(path, request, requestMethod, encodeJSON, headers) - if err != nil { - return nil, err - } - - body, err := ioutil.ReadAll(response.Body) - if err != nil { - return nil, err - } - - if err = json.Unmarshal(body, &v); err != nil { - return nil, err - } - return v, err -} - -// submitForm is a helper used for submitting (ex.) GETs and POSTs to the server -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) submitFormRaw(path string, request interface{}, requestMethod string, encodeJSON bool, headers []*Header) (resp *http.Response, err error) { - queryURL := client.serverURL - - // Handle version prefix - if !unversionedPaths[path] { - queryURL.Path += strings.Join([]string{apiVersionPathPrefix, path}, "") - } else { - queryURL.Path += path - } - - var req *http.Request - var body io.Reader - - if request != nil { - if rawRequestPaths[path] { - reqBytes, ok := request.([]byte) - if !ok { - return nil, fmt.Errorf("couldn't decode raw request as bytes") - } - body = bytes.NewBuffer(reqBytes) - } else { - v, err := query.Values(request) - if err != nil { - return nil, err - } - - queryURL.RawQuery = mergeRawQueries(queryURL.RawQuery, v.Encode()) - if encodeJSON { - jsonValue, _ := json.Marshal(request) - body = bytes.NewBuffer(jsonValue) - } - } - } - - req, err = http.NewRequest(requestMethod, queryURL.String(), body) - if err != nil { - return nil, err - } - - // Normally this would not always be set, but due to https://github.com/algorand/go-algorand/issues/1009 it is always needed - req.Header.Set(authHeader, client.apiToken) - - for _, header := range client.headers { - req.Header.Add(header.Key, header.Value) - } - // Add the request headers. - for _, header := range headers { - req.Header.Add(header.Key, header.Value) - } - - httpClient := &http.Client{} - resp, err = httpClient.Do(req) - - if err != nil { - return nil, err - } - - err = extractError(resp) - if err != nil { - resp.Body.Close() - return nil, err - } - return resp, nil -} - -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) submitForm(response interface{}, path string, request interface{}, requestMethod string, encodeJSON bool, headers []*Header) error { - resp, err := client.submitFormRaw(path, request, requestMethod, encodeJSON, headers) - if err != nil { - return err - } - - defer resp.Body.Close() - - dec := json.NewDecoder(resp.Body) - return dec.Decode(&response) -} - -// get performs a GET request to the specific path against the server -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) get(response interface{}, path string, request interface{}, headers []*Header) error { - return client.submitForm(response, path, request, "GET", false /* encodeJSON */, headers) -} - -// post sends a POST request to the given path with the given request object. -// No query parameters will be sent if request is nil. -// response must be a pointer to an object as post writes the response there. -func (client Client) post(response interface{}, path string, request interface{}, headers []*Header) error { - return client.submitForm(response, path, request, "POST", true /* encodeJSON */, headers) -} - -// as post, but with MethodPut -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) put(response interface{}, path string, request interface{}, headers []*Header) error { - return client.submitForm(response, path, request, "PUT", true /* encodeJSON */, headers) -} - -// as post, but with MethodPatch -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) patch(response interface{}, path string, request interface{}, headers []*Header) error { - return client.submitForm(response, path, request, "PATCH", true /* encodeJSON */, headers) -} diff --git a/client/algod/models/models.go b/client/algod/models/models.go deleted file mode 100644 index 4b40394b..00000000 --- a/client/algod/models/models.go +++ /dev/null @@ -1,810 +0,0 @@ -// Package models defines models used by an algod rest client// -// IF YOU MODIFY THIS FILE: IMPORTANT -// In practice, this is straight up copied from /v1/models/model.go. It is duplicated -// from internal model code, to maintain the internal/external client encapsulation. -// It does flatten some embedded structs, however. -// No client should depend on any package in v1. -package models - -import ( - "github.com/algorand/go-algorand-sdk/types" -) - -// NodeStatus contains the information about a node status -// swagger:model NodeStatus -type NodeStatus struct { - // LastRound indicates the last round seen - // - // required: true - LastRound uint64 `json:"lastRound"` - - // LastVersion indicates the last consensus version supported - // - // required: true - LastVersion string `json:"lastConsensusVersion"` - - // NextVersion of consensus protocol to use - // - // required: true - NextVersion string `json:"nextConsensusVersion"` - - // NextVersionRound is the round at which the next consensus version will apply - // - // required: true - NextVersionRound uint64 `json:"nextConsensusVersionRound"` - - // NextVersionSupported indicates whether the next consensus version is supported by this node - // - // required: true - NextVersionSupported bool `json:"nextConsensusVersionSupported"` - - // TimeSinceLastRound in nanoseconds - // - // required: true - TimeSinceLastRound int64 `json:"timeSinceLastRound"` - - // CatchupTime in nanoseconds - // - // required: true - CatchupTime int64 `json:"catchupTime"` - - // HasSyncedSinceStartup indicates whether a round has completed since startup - // Required: true - HasSyncedSinceStartup bool `json:"hasSyncedSinceStartup"` - - // StoppedAtUnsupportedRound indicates that the node does not support the new rounds and has stopped making progress - // - // Required: true - StoppedAtUnsupportedRound bool `json:"stoppedAtUnsupportedRound"` -} - -// TransactionID Description -// swagger:model transactionID -type TransactionID struct { - // TxId is the string encoding of the transaction hash - // - // required: true - TxID string `json:"txId"` -} - -// Participation Description -// swagger:model Participation -type Participation struct { // Round and Address fields are redundant if Participation embedded in Account. Exclude for now. - // ParticipationPK is the root participation public key (if any) currently registered for this round - // - // required: true - // swagger:strfmt byte - ParticipationPK []byte `json:"partpkb64"` - - // VRFPK is the selection public key (if any) currently registered for this round - // - // required: true - // swagger:strfmt byte - VRFPK []byte `json:"vrfpkb64"` - - // VoteFirst is the first round for which this participation is valid. - // - // required: true - VoteFirst uint64 `json:"votefst"` - - // VoteLast is the last round for which this participation is valid. - // - // required: true - VoteLast uint64 `json:"votelst"` - - // VoteKeyDilution is the number of subkeys in for each batch of participation keys. - // - // required: true - VoteKeyDilution uint64 `json:"votekd"` -} - -// Account Description -// swagger:model Account -type Account struct { - // Round indicates the round for which this information is relevant - // - // required: true - Round uint64 `json:"round"` - - // Address indicates the account public key - // - // required: true - Address string `json:"address"` - - // Amount indicates the total number of MicroAlgos in the account - // - // required: true - Amount uint64 `json:"amount"` - - // PendingRewards specifies the amount of MicroAlgos of pending - // rewards in this account. - // - // required: true - PendingRewards uint64 `json:"pendingrewards"` - - // AmountWithoutPendingRewards specifies the amount of MicroAlgos in - // the account, without the pending rewards. - // - // required: true - AmountWithoutPendingRewards uint64 `json:"amountwithoutpendingrewards"` - - // Rewards indicates the total rewards of MicroAlgos the account has received, including pending rewards. - // - // required: true - Rewards uint64 `json:"rewards"` - - // Status indicates the delegation status of the account's MicroAlgos - // Offline - indicates that the associated account is delegated. - // Online - indicates that the associated account used as part of the delegation pool. - // NotParticipating - indicates that the associated account is neither a delegator nor a delegate. - // - // required: true - Status string `json:"status"` - - // Participation is the participation information currently associated with the account, if any. - // This field is optional and may not be set even if participation information is registered. - // In future REST API versions, this field may become required. - // - // required: false - Participation *Participation `json:"participation,omitempty"` - - // AssetParams specifies the parameters of assets created by this account. - // - // required: false - AssetParams map[uint64]AssetParams `json:"thisassettotal,omitempty"` - - // Assets specifies the holdings of assets by this account, - // indexed by the asset ID. - // - // required: false - Assets map[uint64]AssetHolding `json:"assets,omitempty"` -} - -// Asset specifies both the unique identifier and the parameters for an asset -// swagger:model Asset -type Asset struct { - // AssetIndex is the unique asset identifier - // - // required: true - AssetIndex uint64 - - // AssetParams specifies the parameters of asset referred to by AssetIndex - // - // required: true - AssetParams AssetParams -} - -// AssetParams specifies the parameters for an asset. -// swagger:model AssetParams -type AssetParams struct { - // Creator specifies the address that created this asset. - // This is the address where the parameters for this asset - // can be found, and also the address where unwanted asset - // units can be sent in the worst case. - // - // required: true - Creator string `json:"creator"` - - // Total specifies the total number of units of this asset. - // - // required: true - Total uint64 `json:"total"` - - // Decimals specifies the number of digits to use after the decimal - // point when displaying this asset. If 0, the asset is not divisible. - // If 1, the base unit of the asset is in tenths. If 2, the base unit - // of the asset is in hundredths, and so on. - // - // required: true - Decimals uint32 `json:"decimals"` - - // DefaultFrozen specifies whether holdings in this asset - // are frozen by default. - // - // required: false - DefaultFrozen bool `json:"defaultfrozen"` - - // UnitName specifies the name of a unit of this asset, - // as supplied by the creator. - // - // required: false - UnitName string `json:"unitname,omitempty"` - - // AssetName specifies the name of this asset, - // as supplied by the creator. - // - // required: false - AssetName string `json:"assetname,omitempty"` - - // URL specifies a URL where more information about the asset can be - // retrieved - // - // required: false - URL string `json:"url,omitempty"` - - // MetadataHash specifies a commitment to some unspecified asset - // metadata. The format of this metadata is up to the application. - // - // required: false - // swagger:strfmt byte - MetadataHash []byte `json:"metadatahash,omitempty"` - - // ManagerAddr specifies the address used to manage the keys of this - // asset and to destroy it. - // - // required: false - ManagerAddr string `json:"managerkey"` - - // ReserveAddr specifies the address holding reserve (non-minted) - // units of this asset. - // - // required: false - ReserveAddr string `json:"reserveaddr"` - - // FreezeAddr specifies the address used to freeze holdings of - // this asset. If empty, freezing is not permitted. - // - // required: false - FreezeAddr string `json:"freezeaddr"` - - // ClawbackAddr specifies the address used to clawback holdings of - // this asset. If empty, clawback is not permitted. - // - // required: false - ClawbackAddr string `json:"clawbackaddr"` -} - -// AssetHolding specifies the holdings of a particular asset. -// swagger:model AssetHolding -type AssetHolding struct { - // Creator specifies the address that created this asset. - // This is the address where the parameters for this asset - // can be found, and also the address where unwanted asset - // units can be sent in the worst case. - // - // required: true - Creator string `json:"creator"` - - // Amount specifies the number of units held. - // - // required: true - Amount uint64 `json:"amount"` - - // Frozen specifies whether this holding is frozen. - // - // required: false - Frozen bool `json:"frozen"` -} - -// Transaction contains all fields common to all transactions and serves as an envelope to all transactions -// type -// swagger:model Transaction -type Transaction struct { - // Type is the transaction type - // - // required: true - Type types.TxType `json:"type"` - - // TxID is the transaction ID - // - // required: true - TxID string `json:"tx"` - - // From is the sender's address - // - // required: true - From string `json:"from"` - - // Fee is the transaction fee - // - // required: true - Fee uint64 `json:"fee"` - - // FirstRound indicates the first valid round for this transaction - // - // required: true - FirstRound uint64 `json:"first-round"` - - // LastRound indicates the last valid round for this transaction - // - // required: true - LastRound uint64 `json:"last-round"` - - // Note is a free form data - // - // required: false - // swagger:strfmt byte - Note []byte `json:"noteb64,omitempty"` - - // Lease enforces mutual exclusion of transactions. If this field is - // nonzero, then once the transaction is confirmed, it acquires the - // lease identified by the (Sender, Lease) pair of the transaction until - // the LastValid round passes. While this transaction possesses the - // lease, no other transaction specifying this lease can be confirmed. - // - // required: false - // swagger:strfmt byte - Lease []byte `json:"lease,omitempty"` - - // ConfirmedRound indicates the block number this transaction appeared in - // - // required: false - ConfirmedRound uint64 `json:"round"` - - // TransactionResults contains information about the side effects of a transaction - // - // required: false - TransactionResults *TransactionResults `json:"txresults,omitempty"` - - // PoolError indicates the transaction was evicted from this node's transaction - // pool (if non-empty). A non-empty PoolError does not guarantee that the - // transaction will never be committed; other nodes may not have evicted the - // transaction and may attempt to commit it in the future. - // - // required: false - PoolError string `json:"poolerror,omitempty"` - - // This is a list of all supported transactions. - // To add another one, create a struct with XXXTransactionType and embed it here. - // To prevent extraneous fields, all must have the "omitempty" tag. - - // Payment contains the additional fields for a payment transaction. - // - // required: false - Payment *PaymentTransactionType `json:"payment,omitempty"` - - // Keyreg contains the additional fields for a keyreg transaction. - // - // required: false - Keyreg *KeyregTransactionType `json:"keyreg,omitempty"` - - // AssetConfig contains the additional fields for an asset config transaction. - // - // required: false - AssetConfig *AssetConfigTransactionType `json:"curcfg,omitempty"` - - // AssetTransfer contains the additional fields for an asset transfer transaction. - // - // required: false - AssetTransfer *AssetTransferTransactionType `json:"curxfer,omitempty"` - - // AssetFreeze contains the additional fields for an asset freeze transaction. - // - // required: false - AssetFreeze *AssetFreezeTransactionType `json:"curfrz,omitempty"` - - // FromRewards is the amount of pending rewards applied to the From - // account as part of this transaction. - // - // required: false - FromRewards uint64 `json:"fromrewards"` - - // Genesis ID - // - // required: true - GenesisID string `json:"genesisID"` - - // Genesis hash - // - // required: true - // swagger:strfmt byte - GenesisHash []byte `json:"genesishashb64"` - - // Group - // - // required: false - // swagger:strfmt byte - Group []byte `json:"group,omitempty"` -} - -// PaymentTransactionType contains the additional fields for a payment Transaction -// swagger:model PaymentTransactionType -type PaymentTransactionType struct { - // To is the receiver's address - // - // required: true - To string `json:"to"` - - // CloseRemainderTo is the address the sender closed to - // - // required: false - CloseRemainderTo string `json:"close,omitempty"` - - // CloseAmount is the amount sent to CloseRemainderTo, for committed transaction - // - // required: false - CloseAmount uint64 `json:"closeamount,omitempty"` - - // Amount is the amount of MicroAlgos intended to be transferred - // - // required: true - Amount uint64 `json:"amount"` - - // ToRewards is the amount of pending rewards applied to the To account - // as part of this transaction. - // - // required: false - ToRewards uint64 `json:"torewards"` - - // CloseRewards is the amount of pending rewards applied to the CloseRemainderTo - // account as part of this transaction. - // - // required: false - CloseRewards uint64 `json:"closerewards"` -} - -// KeyregTransactionType contains the additional fields for a keyreg Transaction -// swagger:model KeyregTransactionType -type KeyregTransactionType struct { - // VotePK is the participation public key used in key registration transactions - // - // required: false - // swagger:strfmt byte - VotePK []byte `json:"votekey"` - - // SelectionPK is the VRF public key used in key registration transactions - // - // required: false - // swagger:strfmt byte - SelectionPK []byte `json:"selkey"` - - // VoteFirst is the first round this participation key is valid - // - // required: false - VoteFirst uint64 `json:"votefst"` - - // VoteLast is the last round this participation key is valid - // - // required: false - VoteLast uint64 `json:"votelst"` - - // VoteKeyDilution is the dilution for the 2-level participation key - // - // required: false - VoteKeyDilution uint64 `json:"votekd"` -} - -// TransactionResults contains information about the side effects of a transaction -// swagger:model TransactionResults -type TransactionResults struct { - // CreatedAssetIndex indicates the asset index of an asset created by this txn - // - // required: false - CreatedAssetIndex uint64 `json:"createdasset,omitempty"` -} - -// AssetConfigTransactionType contains the additional fields for an asset config transaction -// swagger:model AssetConfigTransactionType -type AssetConfigTransactionType struct { - // AssetID is the asset being configured (or empty if creating) - // - // required: false - AssetID uint64 `json:"id"` - - // Params specifies the new asset parameters (or empty if deleting) - // - // required: false - Params AssetParams `json:"params"` -} - -// AssetTransferTransactionType contains the additional fields for an asset transfer transaction -// swagger:model AssetTransferTransactionType -type AssetTransferTransactionType struct { - // AssetID is the asset being configured (or empty if creating) - // - // required: true - AssetID uint64 `json:"id"` - - // Amount is the amount being transferred. - // - // required: true - Amount uint64 `json:"amt"` - - // Sender is the source account (if using clawback). - // - // required: false - Sender string `json:"snd"` - - // Receiver is the recipient account. - // - // required: true - Receiver string `json:"rcv"` - - // CloseTo is the destination for remaining funds (if closing). - // - // required: false - CloseTo string `json:"closeto"` -} - -// AssetFreezeTransactionType contains the additional fields for an asset freeze transaction -// swagger:model AssetFreezeTransactionType -type AssetFreezeTransactionType struct { - // AssetID is the asset being configured (or empty if creating) - // - // required: true - AssetID uint64 `json:"id"` - - // Account specifies the account where the asset is being frozen or thawed. - // - // required: true - Account string `json:"acct"` - - // NewFreezeStatus specifies the new freeze status. - // - // required: true - NewFreezeStatus bool `json:"freeze"` -} - -// TransactionList contains a list of transactions -// swagger:model TransactionList -type TransactionList struct { - // TransactionList is a list of transactions - // - // required: true - Transactions []Transaction `json:"transactions,omitempty"` -} - -// AssetList contains a list of assets -// swagger:model AssetList -type AssetList struct { - // AssetList is a list of assets - // - // required: true - Assets []Asset `json:"assets,omitempty"` -} - -// TransactionFee contains the suggested fee -// swagger:model TransactionFee -type TransactionFee struct { - // Fee is transaction fee - // Fee is in units of micro-Algos per byte. - // Fee may fall to zero but a group of N atomic transactions must - // still have a fee of at least N*MinTxnFee for the current network protocol. - // - // required: true - Fee uint64 `json:"fee"` -} - -// TransactionParams contains the parameters that help a client construct -// a new transaction. -// swagger:model TransactionParams -type TransactionParams struct { - // Fee is the suggested transaction fee - // Fee is in units of micro-Algos per byte. - // Fee may fall to zero but a group of N atomic transactions must - // still have a fee of at least N*MinTxnFee for the current network protocol. - // - // required: true - Fee uint64 `json:"fee"` - - // Genesis ID - // - // required: true - GenesisID string `json:"genesisID"` - - // Genesis hash - // - // required: true - // swagger:strfmt byte - GenesisHash []byte `json:"genesishashb64"` - - // LastRound indicates the last round seen - // - // required: true - LastRound uint64 `json:"lastRound"` - - // ConsensusVersion indicates the consensus protocol version - // as of LastRound. - // - // required: true - ConsensusVersion string `json:"consensusVersion"` - - // The minimum transaction fee (not per byte) required for the - // txn to validate for the current network protocol. - // - // required: false - MinTxnFee uint64 `json:"minFee"` -} - -// RawResponse is fulfilled by responses that should not be decoded as msgpack -type RawResponse interface { - SetBytes([]byte) -} - -// RawBlock represents an encoded msgpack block -// swagger:model RawBlock -// swagger:strfmt byte -type RawBlock []byte - -// SetBytes fulfills the RawResponse interface on RawBlock -func (rb *RawBlock) SetBytes(b []byte) { - *rb = b -} - -// Block contains a block information -// swagger:model Block -type Block struct { - // Hash is the current block hash - // - // required: true - Hash string `json:"hash"` - - // PreviousBlockHash is the previous block hash - // - // required: true - PreviousBlockHash string `json:"previousBlockHash"` - - // Seed is the sortition seed - // - // required: true - Seed string `json:"seed"` - - // Proposer is the address of this block proposer - // - // required: true - Proposer string `json:"proposer"` - - // Round is the current round on which this block was appended to the chain - // - // required: true - Round uint64 `json:"round"` - - // Period is the period on which the block was confirmed - // - // required: true - Period uint64 `json:"period"` - - // TransactionsRoot authenticates the set of transactions appearing in the block. - // More specifically, it's the root of a merkle tree whose leaves are the block's Txids, in lexicographic order. - // For the empty block, it's 0. - // Note that the TxnRoot does not authenticate the signatures on the transactions, only the transactions themselves. - // Two blocks with the same transactions but in a different order and with different signatures will have the same TxnRoot. - // - // required: true - TransactionsRoot string `json:"txnRoot"` - - // RewardsLevel specifies how many rewards, in MicroAlgos, - // have been distributed to each config.Protocol.RewardUnit - // of MicroAlgos since genesis. - RewardsLevel uint64 `json:"reward"` - - // The number of new MicroAlgos added to the participation stake from rewards at the next round. - RewardsRate uint64 `json:"rate"` - - // The number of leftover MicroAlgos after the distribution of RewardsRate/rewardUnits - // MicroAlgos for every reward unit in the next round. - RewardsResidue uint64 `json:"frac"` - - // Transactions is the list of transactions in this block - Transactions TransactionList `json:"txns"` - - // TimeStamp in seconds since epoch - // - // required: true - Timestamp int64 `json:"timestamp"` - - UpgradeState - UpgradeVote -} - -// UpgradeState contains the information about a current state of an upgrade -// swagger:model UpgradeState -type UpgradeState struct { - // CurrentProtocol is a string that represents the current protocol - // - // required: true - CurrentProtocol string `json:"currentProtocol"` - - // NextProtocol is a string that represents the next proposed protocol - // - // required: true - NextProtocol string `json:"nextProtocol"` - - // NextProtocolApprovals is the number of blocks which approved the protocol upgrade - // - // required: true - NextProtocolApprovals uint64 `json:"nextProtocolApprovals"` - - // NextProtocolVoteBefore is the deadline round for this protocol upgrade (No votes will be consider after this round) - // - // required: true - NextProtocolVoteBefore uint64 `json:"nextProtocolVoteBefore"` - - // NextProtocolSwitchOn is the round on which the protocol upgrade will take effect - // - // required: true - NextProtocolSwitchOn uint64 `json:"nextProtocolSwitchOn"` -} - -// UpgradeVote represents the vote of the block proposer with respect to protocol upgrades. -// swagger:model UpgradeVote -type UpgradeVote struct { - // UpgradePropose indicates a proposed upgrade - // - // required: true - UpgradePropose string `json:"upgradePropose"` - - // UpgradeApprove indicates a yes vote for the current proposal - // - // required: true - UpgradeApprove bool `json:"upgradeApprove"` -} - -// Supply represents the current supply of MicroAlgos in the system -// swagger:model Supply -type Supply struct { - // Round - // - // required: true - Round uint64 `json:"round"` - - // TotalMoney - // - // required: true - TotalMoney uint64 `json:"totalMoney"` - - // OnlineMoney - // - // required: true - OnlineMoney uint64 `json:"onlineMoney"` -} - -// PendingTransactions represents a potentially truncated list of transactions currently in the -// node's transaction pool. -// swagger:model PendingTransactions -type PendingTransactions struct { - // TruncatedTxns - // required: true - TruncatedTxns TransactionList `json:"truncatedTxns"` - // TotalTxns - // required: true - TotalTxns uint64 `json:"totalTxns"` -} - -// Version contains the current algod version. -// -// Note that we annotate this as a model so that legacy clients -// can directly import a swagger generated Version model. -// swagger:model Version -type Version struct { - // required: true - // returns a list of supported protocol versions ( i.e. v1, v2, etc. ) - Versions []string `json:"versions"` - // required: true - GenesisID string `json:"genesis_id"` - // required: true - // swagger:strfmt byte - GenesisHash []byte `json:"genesis_hash_b64"` - // required: true - Build BuildVersion `json:"build"` -} - -// BuildVersion contains the current algod build version information. -type BuildVersion struct { - // required: true - // Algorand's major version number - Major int `json:"major"` - // required: true - // Algorand's minor version number - Minor int `json:"minor"` - // required: true - // Algorand's Build Number - BuildNumber int `json:"build_number"` - // required: true - // Hash of commit the build is based on - CommitHash string `json:"commit_hash"` - // required: true - // Branch the build is based on - Branch string `json:"branch"` - // required: true - // Branch-derived release channel the build is based on - Channel string `json:"channel"` -} - -// VersionsResponse is the response to 'GET /versions' -// -// swagger:response VersionsResponse -type VersionsResponse struct { - // in: body - Body Version -} diff --git a/client/algod/wrappers.go b/client/algod/wrappers.go deleted file mode 100644 index e0a9baaa..00000000 --- a/client/algod/wrappers.go +++ /dev/null @@ -1,274 +0,0 @@ -package algod - -import ( - "context" - "errors" - "fmt" - "io" - "io/ioutil" - "net/http" - "strings" - - "github.com/algorand/go-algorand-sdk/client/algod/models" - "github.com/algorand/go-algorand-sdk/types" -) - -// Status retrieves the StatusResponse from the running node -// the StatusResponse includes data like the consensus version and current round -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) Status(headers ...*Header) (response models.NodeStatus, err error) { - err = client.get(&response, "/status", nil, headers) - return -} - -// HealthCheck does a health check on the the potentially running node, -// returning an error if the API is down -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) HealthCheck(headers ...*Header) error { - return client.get(nil, "/health", nil, headers) -} - -// StatusAfterBlock waits for a block to occur then returns the StatusResponse after that block -// blocks on the node end -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) StatusAfterBlock(blockNum uint64, headers ...*Header) (response models.NodeStatus, err error) { - err = client.get(&response, fmt.Sprintf("/status/wait-for-block-after/%d", blockNum), nil, headers) - return -} - -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -type pendingTransactionsParams struct { - Max uint64 `url:"max"` -} - -// GetPendingTransactions asks algod for a snapshot of current pending txns on the node, bounded by maxTxns. -// If maxTxns = 0, fetches as many transactions as possible. -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) GetPendingTransactions(maxTxns uint64, headers ...*Header) (response models.PendingTransactions, err error) { - err = client.get(&response, fmt.Sprintf("/transactions/pending"), pendingTransactionsParams{maxTxns}, headers) - return -} - -// Versions retrieves the VersionResponse from the running node -// the VersionResponse includes data like version number and genesis ID -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) Versions(headers ...*Header) (response models.Version, err error) { - err = client.get(&response, "/versions", nil, headers) - return -} - -// LedgerSupply gets the supply details for the specified node's Ledger -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) LedgerSupply(headers ...*Header) (response models.Supply, err error) { - err = client.get(&response, "/ledger/supply", nil, headers) - return -} - -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -type transactionsByAddrParams struct { - FirstRound uint64 `url:"firstRound,omitempty"` - LastRound uint64 `url:"lastRound,omitempty"` - FromDate string `url:"fromDate,omitempty"` - ToDate string `url:"toDate,omitempty"` - Max uint64 `url:"max,omitempty"` -} - -// TransactionsByAddr returns all transactions for a PK [addr] in the [first, -// last] rounds range. -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) TransactionsByAddr(addr string, first, last uint64, headers ...*Header) (response models.TransactionList, err error) { - params := transactionsByAddrParams{FirstRound: first, LastRound: last} - err = client.get(&response, fmt.Sprintf("/account/%s/transactions", addr), params, headers) - return -} - -// TransactionsByAddrLimit returns the last [limit] number of transaction for a PK [addr]. -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) TransactionsByAddrLimit(addr string, limit uint64, headers ...*Header) (response models.TransactionList, err error) { - params := transactionsByAddrParams{Max: limit} - err = client.get(&response, fmt.Sprintf("/account/%s/transactions", addr), params, headers) - return -} - -// TransactionsByAddrForDate returns all transactions for a PK [addr] in the [first, -// last] date range. Dates are of the form "2006-01-02". -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) TransactionsByAddrForDate(addr string, first, last string, headers ...*Header) (response models.TransactionList, err error) { - params := transactionsByAddrParams{FromDate: first, ToDate: last} - err = client.get(&response, fmt.Sprintf("/account/%s/transactions", addr), params, headers) - return -} - -// AccountInformation also gets the AccountInformationResponse associated with the passed address -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) AccountInformation(address string, headers ...*Header) (response models.Account, err error) { - err = client.get(&response, fmt.Sprintf("/account/%s", address), nil, headers) - return -} - -// AssetInformation also gets the AssetInformationResponse associated with the passed asset creator and index -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) AssetInformation(index uint64, headers ...*Header) (response models.AssetParams, err error) { - err = client.get(&response, fmt.Sprintf("/asset/%d", index), nil, headers) - return -} - -// TransactionInformation gets information about a specific transaction involving a specific account -// it will only return information about transactions submitted to the node queried -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) TransactionInformation(accountAddress, transactionID string, headers ...*Header) (response models.Transaction, err error) { - transactionID = stripTransaction(transactionID) - err = client.get(&response, fmt.Sprintf("/account/%s/transaction/%s", accountAddress, transactionID), nil, headers) - return -} - -// PendingTransactionInformation gets information about a recently issued -// transaction. There are several cases when this might succeed: -// -// - transaction committed (CommittedRound > 0) -// - transaction still in the pool (CommittedRound = 0, PoolError = "") -// - transaction removed from pool due to error (CommittedRound = 0, PoolError != "") -// -// Or the transaction may have happened sufficiently long ago that the -// node no longer remembers it, and this will return an error. -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) PendingTransactionInformation(transactionID string, headers ...*Header) (response models.Transaction, err error) { - transactionID = stripTransaction(transactionID) - err = client.get(&response, fmt.Sprintf("/transactions/pending/%s", transactionID), nil, headers) - return -} - -// TransactionByID gets a transaction by its ID. Works only if the indexer is enabled on the node -// being queried. -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) TransactionByID(transactionID string, headers ...*Header) (response models.Transaction, err error) { - transactionID = stripTransaction(transactionID) - err = client.get(&response, fmt.Sprintf("/transaction/%s", transactionID), nil, headers) - return -} - -// SuggestedFee gets the recommended transaction fee from the node -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) SuggestedFee(headers ...*Header) (response models.TransactionFee, err error) { - err = client.get(&response, "/transactions/fee", nil, headers) - return -} - -// SuggestedParams gets the suggested transaction parameters -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) SuggestedParams(headers ...*Header) (response models.TransactionParams, err error) { - err = client.get(&response, "/transactions/params", nil, headers) - return -} - -// BuildSuggestedParams gets the suggested transaction parameters and -// builds a types.SuggestedParams to pass to transaction builders (see package future) -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) BuildSuggestedParams(headers ...*Header) (response types.SuggestedParams, err error) { - var httpResponse models.TransactionParams - err = client.get(&httpResponse, "/transactions/params", nil, headers) - response.FlatFee = false - response.Fee = types.MicroAlgos(httpResponse.Fee) - response.GenesisID = httpResponse.GenesisID - response.GenesisHash = httpResponse.GenesisHash - response.FirstRoundValid = types.Round(httpResponse.LastRound) - response.LastRoundValid = types.Round(httpResponse.LastRound + 1000) - response.ConsensusVersion = httpResponse.ConsensusVersion - return -} - -// SendRawTransaction gets the bytes of a SignedTxn and broadcasts it to the network -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) SendRawTransaction(stx []byte, headers ...*Header) (response models.TransactionID, err error) { - // Set default Content-Type, if not the user didn't specify it. - addContentType := true - for _, header := range headers { - if strings.ToLower(header.Key) == "content-type" { - addContentType = false - break - } - } - if addContentType { - headers = append(headers, &Header{"Content-Type", "application/x-binary"}) - } - err = client.post(&response, "/transactions", stx, headers) - return -} - -// Block gets the block info for the given round -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) Block(round uint64, headers ...*Header) (response models.Block, err error) { - err = client.get(&response, fmt.Sprintf("/block/%d", round), nil, headers) - return -} - -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func responseReadAll(resp *http.Response, maxContentLength int64) (body []byte, err error) { - if resp.ContentLength > 0 { - // more efficient path if we know the ContentLength - if maxContentLength > 0 && resp.ContentLength > maxContentLength { - return nil, errors.New("Content too long") - } - body = make([]byte, resp.ContentLength) - _, err = io.ReadFull(resp.Body, body) - return - } - - return ioutil.ReadAll(resp.Body) -} - -// BlockRaw gets the raw block msgpack bytes for the given round -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) BlockRaw(round uint64, headers ...*Header) (blockbytes []byte, err error) { - var resp *http.Response - request := struct { - Raw string `url:"raw"` - }{Raw: "1"} - resp, err = client.submitFormRaw(fmt.Sprintf("/block/%d", round), request, "GET", false, headers) - if err != nil { - return - } - defer resp.Body.Close() - // Current blocks are about 1MB. 10MB should be a safe backstop. - return responseReadAll(resp, 10000000) -} - -// Deprecated: v1 algod client is deprecated, please use the v2 algod client. -func (client Client) doGetWithQuery(ctx context.Context, path string, queryArgs map[string]string) (result string, err error) { - queryURL := client.serverURL - queryURL.Path = path - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return - } - q := req.URL.Query() - for k, v := range queryArgs { - q.Add(k, v) - } - req.URL.RawQuery = q.Encode() - - req.Header.Set(authHeader, client.apiToken) - for _, header := range client.headers { - req.Header.Add(header.Key, header.Value) - } - - httpClient := http.Client{} - resp, err := httpClient.Do(req.WithContext(ctx)) - if err != nil { - return - } - defer resp.Body.Close() - - err = extractError(resp) - if err != nil { - return - } - - bytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - return - } - result = string(bytes) - return -} diff --git a/client/v2/common/models/dryrun_txn_result.go b/client/v2/common/models/dryrun_txn_result.go index 7537bbbd..ca359a68 100644 --- a/client/v2/common/models/dryrun_txn_result.go +++ b/client/v2/common/models/dryrun_txn_result.go @@ -15,10 +15,6 @@ type DryrunTxnResult struct { // BudgetConsumed budget consumed during execution of app call transaction. BudgetConsumed uint64 `json:"budget-consumed,omitempty"` - // Cost net cost of app execution. Field is DEPRECATED and is subject for removal. - // Instead, use `budget-added` and `budget-consumed. - Cost uint64 `json:"cost,omitempty"` - // Disassembly disassembled program line by line. Disassembly []string `json:"disassembly"` diff --git a/crypto/account.go b/crypto/account.go index 4aead19e..bc849eb3 100644 --- a/crypto/account.go +++ b/crypto/account.go @@ -187,23 +187,10 @@ type LogicSigAccount struct { SigningKey ed25519.PublicKey `codec:"sigkey"` } -// MakeLogicSigAccountEscrow creates a new escrow LogicSigAccount. The address -// of this account will be a hash of its program. -// Deprecated: This method is deprecated for not applying basic sanity check over program bytes, -// use `MakeLogicSigAccountEscrowChecked` instead. -func MakeLogicSigAccountEscrow(program []byte, args [][]byte) LogicSigAccount { - return LogicSigAccount{ - Lsig: types.LogicSig{ - Logic: program, - Args: args, - }, - } -} - -// MakeLogicSigAccountEscrowChecked creates a new escrow LogicSigAccount. +// MakeLogicSigAccountEscrow creates a new escrow LogicSigAccount. // The address of this account will be a hash of its program. -func MakeLogicSigAccountEscrowChecked(program []byte, args [][]byte) (LogicSigAccount, error) { - lsig, err := MakeLogicSig(program, args, nil, MultisigAccount{}) +func MakeLogicSigAccountEscrow(program []byte, args [][]byte) (LogicSigAccount, error) { + lsig, err := makeLogicSig(program, args, nil, MultisigAccount{}) if err != nil { return LogicSigAccount{}, err } @@ -218,7 +205,7 @@ func MakeLogicSigAccountEscrowChecked(program []byte, args [][]byte) (LogicSigAc // The parameter signer is the private key of the delegating account. func MakeLogicSigAccountDelegated(program []byte, args [][]byte, signer ed25519.PrivateKey) (lsa LogicSigAccount, err error) { var ma MultisigAccount - lsig, err := MakeLogicSig(program, args, signer, ma) + lsig, err := makeLogicSig(program, args, signer, ma) if err != nil { return } @@ -248,7 +235,7 @@ func MakeLogicSigAccountDelegated(program []byte, args [][]byte, signer ed25519. // delegating multisig account. Use the method AppendMultisigSignature on the // returned LogicSigAccount to add additional signatures from other members. func MakeLogicSigAccountDelegatedMsig(program []byte, args [][]byte, msigAccount MultisigAccount, signer ed25519.PrivateKey) (lsa LogicSigAccount, err error) { - lsig, err := MakeLogicSig(program, args, signer, msigAccount) + lsig, err := makeLogicSig(program, args, signer, msigAccount) if err != nil { return } diff --git a/crypto/account_test.go b/crypto/account_test.go index cb407df1..907a59bf 100644 --- a/crypto/account_test.go +++ b/crypto/account_test.go @@ -126,7 +126,7 @@ func TestLogicSigAddress(t *testing.T) { var sk ed25519.PrivateKey var ma MultisigAccount - lsig, err := MakeLogicSig(program, args, sk, ma) + lsig, err := makeLogicSig(program, args, sk, ma) require.NoError(t, err) actualAddr := LogicSigAddress(lsig) @@ -139,7 +139,7 @@ func TestLogicSigAddress(t *testing.T) { var ma MultisigAccount - lsig, err := MakeLogicSig(program, args, account.PrivateKey, ma) + lsig, err := makeLogicSig(program, args, account.PrivateKey, ma) require.NoError(t, err) // for backwards compatibility, we still expect the hashed program bytes address @@ -150,7 +150,7 @@ func TestLogicSigAddress(t *testing.T) { t.Run("multi sig", func(t *testing.T) { ma, sk1, _, _ := makeTestMultisigAccount(t) - lsig, err := MakeLogicSig(program, args, sk1, ma) + lsig, err := makeLogicSig(program, args, sk1, ma) require.NoError(t, err) // for backwards compatibility, we still expect the hashed program bytes address @@ -167,7 +167,8 @@ func TestMakeLogicSigAccount(t *testing.T) { } t.Run("Escrow", func(t *testing.T) { - lsigAccount := MakeLogicSigAccountEscrow(program, args) + lsigAccount, err := MakeLogicSigAccountEscrow(program, args) + require.NoError(t, err) require.Equal(t, program, lsigAccount.Lsig.Logic) require.Equal(t, args, lsigAccount.Lsig.Args) @@ -261,7 +262,7 @@ func TestLogicSigAccountFromLogicSig(t *testing.T) { var sk ed25519.PrivateKey var ma MultisigAccount - lsig, err := MakeLogicSig(program, args, sk, ma) + lsig, err := makeLogicSig(program, args, sk, ma) require.NoError(t, err) t.Run("with public key", func(t *testing.T) { @@ -286,7 +287,7 @@ func TestLogicSigAccountFromLogicSig(t *testing.T) { var ma MultisigAccount - lsig, err := MakeLogicSig(program, args, account.PrivateKey, ma) + lsig, err := makeLogicSig(program, args, account.PrivateKey, ma) require.NoError(t, err) t.Run("with correct public key", func(t *testing.T) { @@ -316,7 +317,7 @@ func TestLogicSigAccountFromLogicSig(t *testing.T) { t.Run("multi sig", func(t *testing.T) { ma, sk1, _, _ := makeTestMultisigAccount(t) - lsig, err := MakeLogicSig(program, args, sk1, ma) + lsig, err := makeLogicSig(program, args, sk1, ma) require.NoError(t, err) t.Run("with public key", func(t *testing.T) { @@ -350,7 +351,8 @@ func TestLogicSigAccount_Address(t *testing.T) { } t.Run("no sig", func(t *testing.T) { - lsigAccount := MakeLogicSigAccountEscrow(program, args) + lsigAccount, err := MakeLogicSigAccountEscrow(program, args) + require.NoError(t, err) expectedAddr, err := types.DecodeAddress("6Z3C3LDVWGMX23BMSYMANACQOSINPFIRF77H7N3AWJZYV6OH6GWTJKVMXY") require.NoError(t, err) diff --git a/crypto/crypto.go b/crypto/crypto.go index a652dbd2..ee0ba4d0 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -577,7 +577,7 @@ func SignLogicSigAccountTransaction(logicSigAccount LogicSigAccount, tx types.Tr return } -// SignLogicsigTransaction takes LogicSig object and a transaction and returns the +// SignLogicSigTransaction takes LogicSig object and a transaction and returns the // bytes of a signed transaction ready to be broadcasted to the network // Note, LogicSig actually can be attached to any transaction and it is a // program's responsibility to approve/decline the transaction @@ -586,7 +586,7 @@ func SignLogicSigAccountTransaction(logicSigAccount LogicSigAccount, tx types.Tr // the LogicSig's address, EXCEPT IF the LogicSig is delegated to a non-multisig // account. In order to properly handle that case, create a LogicSigAccount and // use SignLogicSigAccountTransaction instead. -func SignLogicsigTransaction(lsig types.LogicSig, tx types.Transaction) (txid string, stxBytes []byte, err error) { +func SignLogicSigTransaction(lsig types.LogicSig, tx types.Transaction) (txid string, stxBytes []byte, err error) { hasSig := lsig.Sig != (types.Signature{}) hasMsig := !lsig.Msig.Blank() @@ -640,18 +640,13 @@ func AddressFromProgram(program []byte) types.Address { return types.Address(hash) } -// MakeLogicSig produces a new LogicSig signature. -// -// Deprecated: THIS FUNCTION IS DEPRECATED. -// It will be removed in v2 of this library. -// Use one of MakeLogicSigAccountEscrow, MakeLogicSigAccountDelegated, or -// MakeLogicSigAccountDelegatedMsig instead. +// makeLogicSig produces a new LogicSig signature. // // The function can work in three modes: // 1. If no sk and ma provided then it returns contract-only LogicSig // 2. If no ma provides, it returns Sig delegated LogicSig // 3. If both sk and ma specified the function returns Multisig delegated LogicSig -func MakeLogicSig(program []byte, args [][]byte, sk ed25519.PrivateKey, ma MultisigAccount) (lsig types.LogicSig, err error) { +func makeLogicSig(program []byte, args [][]byte, sk ed25519.PrivateKey, ma MultisigAccount) (lsig types.LogicSig, err error) { if err = sanityCheckProgram(program); err != nil { return } diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index 3da8677a..f9c2a20b 100644 --- a/crypto/crypto_test.go +++ b/crypto/crypto_test.go @@ -288,7 +288,7 @@ func TestMakeLogicSigBasic(t *testing.T) { var pk MultisigAccount // check empty LogicSig - lsig, err := MakeLogicSig(program, args, sk, pk) + lsig, err := makeLogicSig(program, args, sk, pk) require.Error(t, err) require.Equal(t, types.LogicSig{}, lsig) require.True(t, lsig.Blank()) @@ -298,7 +298,7 @@ func TestMakeLogicSigBasic(t *testing.T) { contractSender, err := types.DecodeAddress(programHash) require.NoError(t, err) - lsig, err = MakeLogicSig(program, args, sk, pk) + lsig, err = makeLogicSig(program, args, sk, pk) require.NoError(t, err) require.Equal(t, program, lsig.Logic) require.Equal(t, args, lsig.Args) @@ -312,7 +312,7 @@ func TestMakeLogicSigBasic(t *testing.T) { args = make([][]byte, 2) args[0] = []byte{1, 2, 3} args[1] = []byte{4, 5, 6} - lsig, err = MakeLogicSig(program, args, sk, pk) + lsig, err = makeLogicSig(program, args, sk, pk) require.NoError(t, err) require.Equal(t, program, lsig.Logic) require.Equal(t, args, lsig.Args) @@ -339,7 +339,7 @@ func TestMakeLogicSigSingle(t *testing.T) { require.NoError(t, err) program = []byte{1, 32, 1, 1, 34} sk = acc.PrivateKey - lsig, err := MakeLogicSig(program, args, sk, pk) + lsig, err := makeLogicSig(program, args, sk, pk) require.NoError(t, err) expectedSig := types.Signature{0x3e, 0x5, 0x3d, 0x39, 0x4d, 0xfb, 0x12, 0xbc, 0x65, 0x79, 0x9f, 0xea, 0x31, 0x8a, 0x7b, 0x8e, 0xa2, 0x51, 0x8b, 0x55, 0x2c, 0x8a, 0xbe, 0x6c, 0xd7, 0xa7, 0x65, 0x2d, 0xd8, 0xb0, 0x18, 0x7e, 0x21, 0x5, 0x2d, 0xb9, 0x24, 0x62, 0x89, 0x16, 0xe5, 0x61, 0x74, 0xcd, 0xf, 0x19, 0xac, 0xb9, 0x6c, 0x45, 0xa4, 0x29, 0x91, 0x99, 0x11, 0x1d, 0xe4, 0x7c, 0xe4, 0xfc, 0x12, 0xec, 0xce, 0x2} require.Equal(t, expectedSig, lsig.Sig) @@ -351,7 +351,7 @@ func TestMakeLogicSigSingle(t *testing.T) { // check that a modified program fails verification modProgram := make([]byte, len(program)) copy(modProgram, program) - lsigModified, err := MakeLogicSig(modProgram, args, sk, pk) + lsigModified, err := makeLogicSig(modProgram, args, sk, pk) require.NoError(t, err) modProgram[3] = 2 verified = VerifyLogicSig(lsigModified, acc.Address) @@ -378,7 +378,7 @@ func TestMakeLogicSigMulti(t *testing.T) { acc := GenerateAccount() sk = acc.PrivateKey - lsig, err := MakeLogicSig(program, args, sk1, ma) + lsig, err := makeLogicSig(program, args, sk1, ma) require.NoError(t, err) require.Equal(t, program, lsig.Logic) require.Equal(t, args, lsig.Args) @@ -400,14 +400,14 @@ func TestMakeLogicSigMulti(t *testing.T) { // check that a modified program fails verification modProgram := make([]byte, len(program)) copy(modProgram, program) - lsigModified, err := MakeLogicSig(modProgram, args, sk1, ma) + lsigModified, err := makeLogicSig(modProgram, args, sk1, ma) require.NoError(t, err) modProgram[3] = 2 verified = VerifyLogicSig(lsigModified, sender) require.False(t, verified) // combine sig and multisig, ensure it fails - lsigf, err := MakeLogicSig(program, args, sk, pk) + lsigf, err := makeLogicSig(program, args, sk, pk) require.NoError(t, err) lsig.Sig = lsigf.Sig @@ -455,7 +455,7 @@ func TestSignLogicsigTransaction(t *testing.T) { }, } - txid, stxnBytes, err := SignLogicsigTransaction(lsig, txn) + txid, stxnBytes, err := SignLogicSigTransaction(lsig, txn) require.NoError(t, err) require.EqualValues(t, expectedBytes, stxnBytes) require.Equal(t, expectedTxid, txid) @@ -477,7 +477,7 @@ func TestSignLogicsigTransaction(t *testing.T) { t.Run("no sig", func(t *testing.T) { var sk ed25519.PrivateKey var ma MultisigAccount - lsig, err := MakeLogicSig(program, args, sk, ma) + lsig, err := makeLogicSig(program, args, sk, ma) require.NoError(t, err) programHash := "6Z3C3LDVWGMX23BMSYMANACQOSINPFIRF77H7N3AWJZYV6OH6GWTJKVMXY" @@ -505,7 +505,7 @@ func TestSignLogicsigTransaction(t *testing.T) { var ma MultisigAccount acc, err := AccountFromPrivateKey(ed25519.PrivateKey{0xd2, 0xdc, 0x4c, 0xcc, 0xe9, 0x98, 0x62, 0xff, 0xcf, 0x8c, 0xeb, 0x93, 0x6, 0xc4, 0x8d, 0xa6, 0x80, 0x50, 0x82, 0xa, 0xbb, 0x29, 0x95, 0x7a, 0xac, 0x82, 0x68, 0x9a, 0x8c, 0x49, 0x5a, 0x38, 0x5e, 0x67, 0x4f, 0x1c, 0xa, 0xee, 0xec, 0x37, 0x71, 0x89, 0x8f, 0x61, 0xc7, 0x6f, 0xf5, 0xd2, 0x4a, 0x19, 0x79, 0x3e, 0x2c, 0x91, 0xfa, 0x8, 0x51, 0x62, 0x63, 0xe3, 0x85, 0x73, 0xea, 0x42}) require.NoError(t, err) - lsig, err := MakeLogicSig(program, args, acc.PrivateKey, ma) + lsig, err := makeLogicSig(program, args, acc.PrivateKey, ma) require.NoError(t, err) t.Run("sender is contract addr", func(t *testing.T) { @@ -533,7 +533,7 @@ func TestSignLogicsigTransaction(t *testing.T) { }, } - _, _, err := SignLogicsigTransaction(lsig, txn) + _, _, err := SignLogicSigTransaction(lsig, txn) require.Error(t, err, errLsigInvalidSignature) }) }) @@ -543,7 +543,7 @@ func TestSignLogicsigTransaction(t *testing.T) { maAddr, err := ma.Address() require.NoError(t, err) - lsig, err := MakeLogicSig(program, args, sk1, ma) + lsig, err := makeLogicSig(program, args, sk1, ma) require.NoError(t, err) err = AppendMultisigToLogicSig(&lsig, sk2) @@ -618,7 +618,8 @@ func TestSignLogicSigAccountTransaction(t *testing.T) { } t.Run("no sig", func(t *testing.T) { - lsigAccount := MakeLogicSigAccountEscrow(program, args) + lsigAccount, err := MakeLogicSigAccountEscrow(program, args) + require.NoError(t, err) programAddr, err := types.DecodeAddress("6Z3C3LDVWGMX23BMSYMANACQOSINPFIRF77H7N3AWJZYV6OH6GWTJKVMXY") require.NoError(t, err) diff --git a/examples/gen-addresses/main.go b/examples/gen-addresses/main.go index 0c6f276e..99e4c1ee 100644 --- a/examples/gen-addresses/main.go +++ b/examples/gen-addresses/main.go @@ -4,12 +4,12 @@ import ( "bytes" "context" "fmt" + "github.com/algorand/go-algorand-sdk/transaction" "strings" "github.com/algorand/go-algorand-sdk/client/kmd" "github.com/algorand/go-algorand-sdk/client/v2/algod" "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/future" "github.com/algorand/go-algorand-sdk/types" ) @@ -119,7 +119,7 @@ func main() { return } - tx, err := future.MakePaymentTxn(addresses[0], addresses[1], 100, nil, "", txParams) + tx, err := transaction.MakePaymentTxn(addresses[0], addresses[1], 100, nil, "", txParams) if err != nil { fmt.Printf("Error creating transaction: %s\n", err) return diff --git a/future/transaction.go b/future/transaction.go deleted file mode 100644 index 642a4f66..00000000 --- a/future/transaction.go +++ /dev/null @@ -1,1375 +0,0 @@ -package future - -import ( - "bytes" - "encoding/base64" - "fmt" - - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/encoding/msgpack" - "github.com/algorand/go-algorand-sdk/transaction" - "github.com/algorand/go-algorand-sdk/types" -) - -// MinTxnFee is v5 consensus params, in microAlgos -const MinTxnFee = transaction.MinTxnFee - -// NumOfAdditionalBytesAfterSigning is the number of bytes added to a txn after signing it -const NumOfAdditionalBytesAfterSigning = 75 - -func setFee(tx types.Transaction, params types.SuggestedParams) (types.Transaction, error) { - if !params.FlatFee { - eSize, err := EstimateSize(tx) - if err != nil { - return types.Transaction{}, err - } - tx.Fee = types.MicroAlgos(eSize * uint64(params.Fee)) - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - } else { - tx.Fee = params.Fee - } - - return tx, nil -} - -// MakePaymentTxn constructs a payment transaction using the passed parameters. -// `from` and `to` addresses should be checksummed, human-readable addresses -// fee is fee per byte as received from algod SuggestedFee API call -func MakePaymentTxn(from, to string, amount uint64, note []byte, closeRemainderTo string, params types.SuggestedParams) (types.Transaction, error) { - // Decode from address - fromAddr, err := types.DecodeAddress(from) - if err != nil { - return types.Transaction{}, err - } - - // Decode to address - toAddr, err := types.DecodeAddress(to) - if err != nil { - return types.Transaction{}, err - } - - // Decode the CloseRemainderTo address, if present - var closeRemainderToAddr types.Address - if closeRemainderTo != "" { - closeRemainderToAddr, err = types.DecodeAddress(closeRemainderTo) - if err != nil { - return types.Transaction{}, err - } - } - - if len(params.GenesisHash) == 0 { - return types.Transaction{}, fmt.Errorf("payment transaction must contain a genesisHash") - } - - var gh types.Digest - copy(gh[:], params.GenesisHash) - - // Build the transaction - tx := types.Transaction{ - Type: types.PaymentTx, - Header: types.Header{ - Sender: fromAddr, - Fee: params.Fee, - FirstValid: params.FirstRoundValid, - LastValid: params.LastRoundValid, - Note: note, - GenesisID: params.GenesisID, - GenesisHash: gh, - }, - PaymentTxnFields: types.PaymentTxnFields{ - Receiver: toAddr, - Amount: types.MicroAlgos(amount), - CloseRemainderTo: closeRemainderToAddr, - }, - } - - return setFee(tx, params) -} - -// MakeKeyRegTxn constructs a keyreg transaction using the passed parameters. -// - account is a checksummed, human-readable address for which we register the given participation key. -// - note is a byte array -// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period -// KeyReg parameters: -// - votePK is a base64-encoded string corresponding to the root participation public key -// - selectionKey is a base64-encoded string corresponding to the vrf public key -// - voteFirst is the first round this participation key is valid -// - voteLast is the last round this participation key is valid -// - voteKeyDilution is the dilution for the 2-level participation key -func MakeKeyRegTxn(account string, note []byte, params types.SuggestedParams, voteKey, selectionKey string, voteFirst, voteLast, voteKeyDilution uint64) (types.Transaction, error) { - // Decode account address - accountAddr, err := types.DecodeAddress(account) - if err != nil { - return types.Transaction{}, err - } - - if len(params.GenesisHash) == 0 { - return types.Transaction{}, fmt.Errorf("key registration transaction must contain a genesisHash") - } - - var gh types.Digest - copy(gh[:], params.GenesisHash) - - votePKBytes, err := byte32FromBase64(voteKey) - if err != nil { - return types.Transaction{}, err - } - - selectionPKBytes, err := byte32FromBase64(selectionKey) - if err != nil { - return types.Transaction{}, err - } - - tx := types.Transaction{ - Type: types.KeyRegistrationTx, - Header: types.Header{ - Sender: accountAddr, - Fee: params.Fee, - FirstValid: params.FirstRoundValid, - LastValid: params.LastRoundValid, - Note: note, - GenesisHash: gh, - GenesisID: params.GenesisID, - }, - KeyregTxnFields: types.KeyregTxnFields{ - VotePK: types.VotePK(votePKBytes), - SelectionPK: types.VRFPK(selectionPKBytes), - VoteFirst: types.Round(voteFirst), - VoteLast: types.Round(voteLast), - VoteKeyDilution: voteKeyDilution, - }, - } - - return setFee(tx, params) -} - -// MakeKeyRegTxnWithStateProofKey constructs a keyreg transaction using the passed parameters. -// - account is a checksummed, human-readable address for which we register the given participation key. -// - note is a byte array -// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period -// KeyReg parameters: -// - votePK is a base64-encoded string corresponding to the root participation public key -// - selectionKey is a base64-encoded string corresponding to the vrf public key -// - stateProofPK is a base64-encoded string corresponding to the block proof public key -// - voteFirst is the first round this participation key is valid -// - voteLast is the last round this participation key is valid -// - voteKeyDilution is the dilution for the 2-level participation key -// - nonpart is an indicator marking a key registration participating or nonparticipating -func MakeKeyRegTxnWithStateProofKey(account string, note []byte, params types.SuggestedParams, voteKey, selectionKey, stateProofPK string, voteFirst, voteLast, voteKeyDilution uint64, nonpart bool) (types.Transaction, error) { - // Decode account address - accountAddr, err := types.DecodeAddress(account) - if err != nil { - return types.Transaction{}, err - } - - if len(params.GenesisHash) == 0 { - return types.Transaction{}, fmt.Errorf("key registration transaction must contain a genesisHash") - } - - var gh types.Digest - copy(gh[:], params.GenesisHash) - var votePKBytes [32]byte - var selectionPKBytes [32]byte - var statePKBytes [64]byte - - if len(voteKey) > 0 { - votePKBytes, err = byte32FromBase64(voteKey) - if err != nil { - return types.Transaction{}, err - } - } - - if len(selectionKey) > 0 { - selectionPKBytes, err = byte32FromBase64(selectionKey) - if err != nil { - return types.Transaction{}, err - } - } - - if len(stateProofPK) > 0 { - statePKBytes, err = byte64FromBase64(stateProofPK) - if err != nil { - return types.Transaction{}, err - } - } - - tx := types.Transaction{ - Type: types.KeyRegistrationTx, - Header: types.Header{ - Sender: accountAddr, - Fee: params.Fee, - FirstValid: params.FirstRoundValid, - LastValid: params.LastRoundValid, - Note: note, - GenesisHash: gh, - GenesisID: params.GenesisID, - }, - KeyregTxnFields: types.KeyregTxnFields{ - VotePK: types.VotePK(votePKBytes), - SelectionPK: types.VRFPK(selectionPKBytes), - VoteFirst: types.Round(voteFirst), - VoteLast: types.Round(voteLast), - VoteKeyDilution: voteKeyDilution, - Nonparticipation: nonpart, - StateProofPK: types.MerkleVerifier(statePKBytes), - }, - } - - return setFee(tx, params) -} - -// MakeAssetCreateTxn constructs an asset creation transaction using the passed parameters. -// - account is a checksummed, human-readable address which will send the transaction. -// - note is a byte array -// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period -// Asset creation parameters: -// - see asset.go -func MakeAssetCreateTxn(account string, note []byte, params types.SuggestedParams, total uint64, decimals uint32, defaultFrozen bool, manager, reserve, freeze, clawback string, unitName, assetName, url, metadataHash string) (types.Transaction, error) { - var tx types.Transaction - var err error - - if decimals > types.AssetMaxNumberOfDecimals { - return tx, fmt.Errorf("cannot create an asset with number of decimals %d (more than maximum %d)", decimals, types.AssetMaxNumberOfDecimals) - } - - tx.Type = types.AssetConfigTx - tx.AssetParams = types.AssetParams{ - Total: total, - Decimals: decimals, - DefaultFrozen: defaultFrozen, - UnitName: unitName, - AssetName: assetName, - URL: url, - } - - if manager != "" { - tx.AssetParams.Manager, err = types.DecodeAddress(manager) - if err != nil { - return tx, err - } - } - if reserve != "" { - tx.AssetParams.Reserve, err = types.DecodeAddress(reserve) - if err != nil { - return tx, err - } - } - if freeze != "" { - tx.AssetParams.Freeze, err = types.DecodeAddress(freeze) - if err != nil { - return tx, err - } - } - if clawback != "" { - tx.AssetParams.Clawback, err = types.DecodeAddress(clawback) - if err != nil { - return tx, err - } - } - - if len(assetName) > types.AssetNameMaxLen { - return tx, fmt.Errorf("asset name too long: %d > %d", len(assetName), types.AssetNameMaxLen) - } - tx.AssetParams.AssetName = assetName - - if len(url) > types.AssetURLMaxLen { - return tx, fmt.Errorf("asset url too long: %d > %d", len(url), types.AssetURLMaxLen) - } - tx.AssetParams.URL = url - - if len(unitName) > types.AssetUnitNameMaxLen { - return tx, fmt.Errorf("asset unit name too long: %d > %d", len(unitName), types.AssetUnitNameMaxLen) - } - tx.AssetParams.UnitName = unitName - - if len(metadataHash) > types.AssetMetadataHashLen { - return tx, fmt.Errorf("asset metadata hash '%s' too long: %d > %d)", metadataHash, len(metadataHash), types.AssetMetadataHashLen) - } - copy(tx.AssetParams.MetadataHash[:], []byte(metadataHash)) - - if len(params.GenesisHash) == 0 { - return types.Transaction{}, fmt.Errorf("asset transaction must contain a genesisHash") - } - var gh types.Digest - copy(gh[:], params.GenesisHash) - - // Fill in header - accountAddr, err := types.DecodeAddress(account) - if err != nil { - return types.Transaction{}, err - } - - tx.Header = types.Header{ - Sender: accountAddr, - Fee: params.Fee, - FirstValid: params.FirstRoundValid, - LastValid: params.LastRoundValid, - GenesisHash: gh, - GenesisID: params.GenesisID, - Note: note, - } - - // Update fee - return setFee(tx, params) -} - -// MakeAssetConfigTxn creates a tx template for changing the -// key configuration of an existing asset. -// Important notes - -// * Every asset config transaction is a fresh one. No parameters will be inherited from the current config. -// * Once an address is set to to the empty string, IT CAN NEVER BE CHANGED AGAIN. For example, if you want to keep -// The current manager, you must specify its address again. -// Parameters - -// - account is a checksummed, human-readable address that will send the transaction -// - note is an arbitrary byte array -// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period -// - index is the asset index id -// - for newManager, newReserve, newFreeze, newClawback see asset.go -// - strictEmptyAddressChecking: if true, disallow empty admin accounts from being set (preventing accidental disable of admin features) -func MakeAssetConfigTxn(account string, note []byte, params types.SuggestedParams, index uint64, newManager, newReserve, newFreeze, newClawback string, strictEmptyAddressChecking bool) (types.Transaction, error) { - var tx types.Transaction - - if strictEmptyAddressChecking && (newManager == "" || newReserve == "" || newFreeze == "" || newClawback == "") { - return tx, fmt.Errorf("strict empty address checking requested but empty address supplied to one or more manager addresses") - } - - tx.Type = types.AssetConfigTx - - accountAddr, err := types.DecodeAddress(account) - if err != nil { - return tx, err - } - - if len(params.GenesisHash) == 0 { - return types.Transaction{}, fmt.Errorf("asset transaction must contain a genesisHash") - } - var gh types.Digest - copy(gh[:], params.GenesisHash) - - tx.Header = types.Header{ - Sender: accountAddr, - Fee: params.Fee, - FirstValid: params.FirstRoundValid, - LastValid: params.LastRoundValid, - GenesisHash: gh, - GenesisID: params.GenesisID, - Note: note, - } - - tx.ConfigAsset = types.AssetIndex(index) - - if newManager != "" { - tx.Type = types.AssetConfigTx - tx.AssetParams.Manager, err = types.DecodeAddress(newManager) - if err != nil { - return tx, err - } - } - - if newReserve != "" { - tx.AssetParams.Reserve, err = types.DecodeAddress(newReserve) - if err != nil { - return tx, err - } - } - - if newFreeze != "" { - tx.AssetParams.Freeze, err = types.DecodeAddress(newFreeze) - if err != nil { - return tx, err - } - } - - if newClawback != "" { - tx.AssetParams.Clawback, err = types.DecodeAddress(newClawback) - if err != nil { - return tx, err - } - } - - // Update fee - return setFee(tx, params) -} - -// transferAssetBuilder is a helper that builds asset transfer transactions: -// either a normal asset transfer, or an asset revocation -func transferAssetBuilder(account, recipient string, amount uint64, note []byte, params types.SuggestedParams, index uint64, closeAssetsTo, revocationTarget string) (types.Transaction, error) { - var tx types.Transaction - tx.Type = types.AssetTransferTx - - accountAddr, err := types.DecodeAddress(account) - if err != nil { - return tx, err - } - - if len(params.GenesisHash) == 0 { - return types.Transaction{}, fmt.Errorf("asset transaction must contain a genesisHash") - } - var gh types.Digest - copy(gh[:], params.GenesisHash) - - tx.Header = types.Header{ - Sender: accountAddr, - Fee: params.Fee, - FirstValid: params.FirstRoundValid, - LastValid: params.LastRoundValid, - GenesisHash: gh, - GenesisID: params.GenesisID, - Note: note, - } - - tx.XferAsset = types.AssetIndex(index) - - recipientAddr, err := types.DecodeAddress(recipient) - if err != nil { - return tx, err - } - tx.AssetReceiver = recipientAddr - - if closeAssetsTo != "" { - closeToAddr, err := types.DecodeAddress(closeAssetsTo) - if err != nil { - return tx, err - } - tx.AssetCloseTo = closeToAddr - } - - if revocationTarget != "" { - revokedAddr, err := types.DecodeAddress(revocationTarget) - if err != nil { - return tx, err - } - tx.AssetSender = revokedAddr - } - - tx.AssetAmount = amount - - // Update fee - return setFee(tx, params) -} - -// MakeAssetTransferTxn creates a tx for sending some asset from an asset holder to another user -// the recipient address must have previously issued an asset acceptance transaction for this asset -// - account is a checksummed, human-readable address that will send the transaction and assets -// - recipient is a checksummed, human-readable address what will receive the assets -// - amount is the number of assets to send -// - note is an arbitrary byte array -// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period -// - closeAssetsTo is a checksummed, human-readable address that behaves as a close-to address for the asset transaction; the remaining assets not sent to recipient will be sent to closeAssetsTo. Leave blank for no close-to behavior. -// - index is the asset index -func MakeAssetTransferTxn(account, recipient string, amount uint64, note []byte, params types.SuggestedParams, closeAssetsTo string, index uint64) (types.Transaction, error) { - revocationTarget := "" // no asset revocation, this is normal asset transfer - return transferAssetBuilder(account, recipient, amount, note, params, index, closeAssetsTo, revocationTarget) -} - -// MakeAssetAcceptanceTxn creates a tx for marking an account as willing to accept the given asset -// - account is a checksummed, human-readable address that will send the transaction and begin accepting the asset -// - note is an arbitrary byte array -// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period -// - index is the asset index -func MakeAssetAcceptanceTxn(account string, note []byte, params types.SuggestedParams, index uint64) (types.Transaction, error) { - return MakeAssetTransferTxn(account, account, 0, note, params, "", index) -} - -// MakeAssetRevocationTxn creates a tx for revoking an asset from an account and sending it to another -// - account is a checksummed, human-readable address; it must be the revocation manager / clawback address from the asset's parameters -// - target is a checksummed, human-readable address; it is the account whose assets will be revoked -// - recipient is a checksummed, human-readable address; it will receive the revoked assets -// - amount defines the number of assets to clawback -// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period -// - index is the asset index -func MakeAssetRevocationTxn(account, target string, amount uint64, recipient string, note []byte, params types.SuggestedParams, index uint64) (types.Transaction, error) { - closeAssetsTo := "" // no close-out, this is an asset revocation - return transferAssetBuilder(account, recipient, amount, note, params, index, closeAssetsTo, target) -} - -// MakeAssetDestroyTxn creates a tx template for destroying an asset, removing it from the record. -// All outstanding asset amount must be held by the creator, and this transaction must be issued by the asset manager. -// - account is a checksummed, human-readable address that will send the transaction; it also must be the asset manager -// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period -// - index is the asset index -func MakeAssetDestroyTxn(account string, note []byte, params types.SuggestedParams, index uint64) (types.Transaction, error) { - // an asset destroy transaction is just a configuration transaction with AssetParams zeroed - return MakeAssetConfigTxn(account, note, params, index, "", "", "", "", false) -} - -// MakeAssetFreezeTxn constructs a transaction that freezes or unfreezes an account's asset holdings -// It must be issued by the freeze address for the asset -// - account is a checksummed, human-readable address which will send the transaction. -// - note is an optional arbitrary byte array -// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period -// - assetIndex is the index for tracking the asset -// - target is the account to be frozen or unfrozen -// - newFreezeSetting is the new state of the target account -func MakeAssetFreezeTxn(account string, note []byte, params types.SuggestedParams, assetIndex uint64, target string, newFreezeSetting bool) (types.Transaction, error) { - var tx types.Transaction - - tx.Type = types.AssetFreezeTx - - accountAddr, err := types.DecodeAddress(account) - if err != nil { - return tx, err - } - - if len(params.GenesisHash) == 0 { - return types.Transaction{}, fmt.Errorf("asset transaction must contain a genesisHash") - } - var gh types.Digest - copy(gh[:], params.GenesisHash) - - tx.Header = types.Header{ - Sender: accountAddr, - Fee: params.Fee, - FirstValid: params.FirstRoundValid, - LastValid: params.LastRoundValid, - GenesisHash: gh, - GenesisID: params.GenesisID, - Note: note, - } - - tx.FreezeAsset = types.AssetIndex(assetIndex) - - tx.FreezeAccount, err = types.DecodeAddress(target) - if err != nil { - return tx, err - } - - tx.AssetFrozen = newFreezeSetting - - // Update fee - return setFee(tx, params) -} - -// byte32FromBase64 decodes the input base64 string and outputs a -// 32 byte array, erroring if the input is the wrong length. -func byte32FromBase64(in string) (out [32]byte, err error) { - slice, err := base64.StdEncoding.DecodeString(in) - if err != nil { - return - } - if len(slice) != 32 { - return out, fmt.Errorf("Input is not 32 bytes") - } - copy(out[:], slice) - return -} - -// byte32FromBase64 decodes the input base64 string and outputs a -// 64 byte array, erroring if the input is the wrong length. -func byte64FromBase64(in string) (out [64]byte, err error) { - slice, err := base64.StdEncoding.DecodeString(in) - if err != nil { - return - } - if len(slice) != 64 { - return out, fmt.Errorf("input is not 64 bytes") - } - copy(out[:], slice) - return -} - -// - accounts lists the accounts (in addition to the sender) that may be accessed -// from the application logic. -// -// - appArgs ApplicationArgs lists some transaction-specific arguments accessible -// from application logic. -// -// - appIdx ApplicationID is the application being interacted with, or 0 if -// creating a new application. -// -// - approvalProg ApprovalProgram determines whether or not this ApplicationCall -// transaction will be approved or not. -// -// - clearProg ClearStateProgram executes when a clear state ApplicationCall -// transaction is executed. This program may not reject the -// transaction, only update state. -// -// - foreignApps lists the applications (in addition to txn.ApplicationID) whose global -// states may be accessed by this application. The access is read-only. -// -// - foreignAssets lists the assets whose global state may be accessed by this application. The access is read-only. -// -// - globalSchema GlobalStateSchema sets limits on the number of strings and -// integers that may be stored in the GlobalState. The larger these -// limits are, the larger minimum balance must be maintained inside -// the creator's account (in order to 'pay' for the state that can -// be used). The GlobalStateSchema is immutable. -// -// - localSchema LocalStateSchema sets limits on the number of strings and integers -// that may be stored in an account's LocalState for this application. -// The larger these limits are, the larger minimum balance must be -// maintained inside the account of any users who opt into this -// application. The LocalStateSchema is immutable. -// -// - extraPages ExtraProgramPages specifies the additional app program size requested in pages. -// A page is 1024 bytes. This field enables execution of app programs -// larger than the default maximum program size. -// -// - onComplete This is the faux application type used to distinguish different -// application actions. Specifically, OnCompletion specifies what -// side effects this transaction will have if it successfully makes -// it into a block. -// -// - boxes lists the boxes to be accessed during evaluation of the application -// call. This also must include the boxes accessed by inner app calls. - -// MakeApplicationCreateTx makes a transaction for creating an application (see above for args desc.) -// - optIn: true for opting in on complete, false for no-op. -// -// NOTE: if you need to use extra pages or boxes, use MakeApplicationCreateTxWithBoxes instead. -func MakeApplicationCreateTx( - optIn bool, - approvalProg []byte, - clearProg []byte, - globalSchema types.StateSchema, - localSchema types.StateSchema, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - return MakeApplicationCreateTxWithBoxes( - optIn, - approvalProg, - clearProg, - globalSchema, - localSchema, - 0, - appArgs, - accounts, - foreignApps, - foreignAssets, - nil, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationCreateTxWithExtraPages makes a transaction for creating an application (see above for args desc.) -// - optIn: true for opting in on complete, false for no-op. -// -// NOTE: if you need to use boxes, use MakeApplicationCreateTxWithBoxes instead. -func MakeApplicationCreateTxWithExtraPages( - optIn bool, - approvalProg []byte, - clearProg []byte, - globalSchema types.StateSchema, - localSchema types.StateSchema, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address, - extraPages uint32) (tx types.Transaction, err error) { - return MakeApplicationCreateTxWithBoxes( - optIn, - approvalProg, - clearProg, - globalSchema, - localSchema, - extraPages, - appArgs, - accounts, - foreignApps, - foreignAssets, - nil, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationCreateTxWithBoxes makes a transaction for creating an application (see above for args desc.) -// - optIn: true for opting in on complete, false for no-op. -func MakeApplicationCreateTxWithBoxes( - optIn bool, - approvalProg []byte, - clearProg []byte, - globalSchema types.StateSchema, - localSchema types.StateSchema, - extraPages uint32, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - appBoxReferences []types.AppBoxReference, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - - oncomp := types.NoOpOC - if optIn { - oncomp = types.OptInOC - } - - return MakeApplicationCallTxWithBoxes( - 0, - appArgs, - accounts, - foreignApps, - foreignAssets, - appBoxReferences, - oncomp, - approvalProg, - clearProg, - globalSchema, - localSchema, - extraPages, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationUpdateTx makes a transaction for updating an application's programs (see above for args desc.) -// -// NOTE: if you need to use boxes, use MakeApplicationUpdateTxWithBoxes instead. -func MakeApplicationUpdateTx( - appIdx uint64, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - approvalProg []byte, - clearProg []byte, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - return MakeApplicationUpdateTxWithBoxes(appIdx, - appArgs, - accounts, - foreignApps, - foreignAssets, - nil, - approvalProg, - clearProg, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationUpdateTxWithBoxes makes a transaction for updating an application's programs (see above for args desc.) -func MakeApplicationUpdateTxWithBoxes( - appIdx uint64, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - appBoxReferences []types.AppBoxReference, - approvalProg []byte, - clearProg []byte, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - return MakeApplicationCallTxWithBoxes(appIdx, - appArgs, - accounts, - foreignApps, - foreignAssets, - appBoxReferences, - types.UpdateApplicationOC, - approvalProg, - clearProg, - emptySchema, - emptySchema, - 0, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationDeleteTx makes a transaction for deleting an application (see above for args desc.) -// -// NOTE: if you need to use boxes, use MakeApplicationDeleteTxWithBoxes instead. -func MakeApplicationDeleteTx( - appIdx uint64, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - return MakeApplicationDeleteTxWithBoxes(appIdx, - appArgs, - accounts, - foreignApps, - foreignAssets, - nil, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationDeleteTxWithBoxes makes a transaction for deleting an application (see above for args desc.) -func MakeApplicationDeleteTxWithBoxes( - appIdx uint64, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - appBoxReferences []types.AppBoxReference, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - return MakeApplicationCallTxWithBoxes(appIdx, - appArgs, - accounts, - foreignApps, - foreignAssets, - appBoxReferences, - types.DeleteApplicationOC, - nil, - nil, - emptySchema, - emptySchema, - 0, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationOptInTx makes a transaction for opting in to (allocating -// some account-specific state for) an application (see above for args desc.) -// -// NOTE: if you need to use boxes, use MakeApplicationOptInTxWithBoxes instead. -func MakeApplicationOptInTx( - appIdx uint64, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - return MakeApplicationOptInTxWithBoxes(appIdx, - appArgs, - accounts, - foreignApps, - foreignAssets, - nil, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationOptInTxWithBoxes makes a transaction for opting in to (allocating -// some account-specific state for) an application (see above for args desc.) -func MakeApplicationOptInTxWithBoxes( - appIdx uint64, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - appBoxReferences []types.AppBoxReference, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - return MakeApplicationCallTxWithBoxes(appIdx, - appArgs, - accounts, - foreignApps, - foreignAssets, - appBoxReferences, - types.OptInOC, - nil, - nil, - emptySchema, - emptySchema, - 0, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationCloseOutTx makes a transaction for closing out of -// (deallocating all account-specific state for) an application (see above for args desc.) -// -// NOTE: if you need to use boxes, use MakeApplicationCloseOutTxWithBoxes -// instead. -func MakeApplicationCloseOutTx( - appIdx uint64, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - return MakeApplicationCloseOutTxWithBoxes(appIdx, - appArgs, - accounts, - foreignApps, - foreignAssets, - nil, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationCloseOutTxWithBoxes makes a transaction for closing out of -// (deallocating all account-specific state for) an application (see above for args desc.) -func MakeApplicationCloseOutTxWithBoxes( - appIdx uint64, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - appBoxReferences []types.AppBoxReference, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - return MakeApplicationCallTxWithBoxes(appIdx, - appArgs, - accounts, - foreignApps, - foreignAssets, - appBoxReferences, - types.CloseOutOC, - nil, - nil, - emptySchema, - emptySchema, - 0, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationClearStateTx makes a transaction for clearing out all -// account-specific state for an application. It may not be rejected by the -// application's logic. (see above for args desc.) -// -// NOTE: if you need to use boxes, use MakeApplicationClearStateTxWithBoxes -// instead. -func MakeApplicationClearStateTx( - appIdx uint64, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - return MakeApplicationClearStateTxWithBoxes(appIdx, - appArgs, - accounts, - foreignApps, - foreignAssets, - nil, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationClearStateTxWithBoxes makes a transaction for clearing out all -// account-specific state for an application. It may not be rejected by the -// application's logic. (see above for args desc.) -func MakeApplicationClearStateTxWithBoxes( - appIdx uint64, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - appBoxReferences []types.AppBoxReference, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - return MakeApplicationCallTxWithBoxes(appIdx, - appArgs, - accounts, - foreignApps, - foreignAssets, - appBoxReferences, - types.ClearStateOC, - nil, - nil, - emptySchema, - emptySchema, - 0, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationNoOpTx makes a transaction for interacting with an existing -// application, potentially updating any account-specific local state and -// global state associated with it. (see above for args desc.) -// -// NOTE: if you need to use boxes, use MakeApplicationNoOpTxWithBoxes instead. -func MakeApplicationNoOpTx( - appIdx uint64, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - return MakeApplicationNoOpTxWithBoxes( - appIdx, - appArgs, - accounts, - foreignApps, - foreignAssets, - nil, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationNoOpTxWithBoxes makes a transaction for interacting with an -// existing application, potentially updating any account-specific local state -// and global state associated with it. (see above for args desc.) -func MakeApplicationNoOpTxWithBoxes( - appIdx uint64, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - appBoxReferences []types.AppBoxReference, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - return MakeApplicationCallTxWithBoxes( - appIdx, - appArgs, - accounts, - foreignApps, - foreignAssets, - appBoxReferences, - types.NoOpOC, - nil, - nil, - emptySchema, - emptySchema, - 0, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationCallTx is a helper for the above ApplicationCall -// transaction constructors. A fully custom ApplicationCall transaction may -// be constructed using this method. (see above for args desc.) -// -// NOTE: if you need to use boxes or extra program pages, use -// MakeApplicationCallTxWithBoxes instead. -func MakeApplicationCallTx( - appIdx uint64, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - onCompletion types.OnCompletion, - approvalProg []byte, - clearProg []byte, - globalSchema types.StateSchema, - localSchema types.StateSchema, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - return MakeApplicationCallTxWithBoxes( - appIdx, - appArgs, - accounts, - foreignApps, - foreignAssets, - nil, - onCompletion, - approvalProg, - clearProg, - globalSchema, - localSchema, - 0, - sp, - sender, - note, - group, - lease, - rekeyTo, - ) -} - -// MakeApplicationCallTxWithExtraPages sets the ExtraProgramPages on an existing -// application call transaction. -// -// Consider using MakeApplicationCallTxWithBoxes instead if you wish to assign -// the extra pages value at creation. -func MakeApplicationCallTxWithExtraPages( - txn types.Transaction, extraPages uint32) (types.Transaction, error) { - txn.ExtraProgramPages = extraPages - return txn, nil -} - -// MakeApplicationCallTxWithBoxes is a helper for the above ApplicationCall -// transaction constructors. A fully custom ApplicationCall transaction may -// be constructed using this method. (see above for args desc.) -func MakeApplicationCallTxWithBoxes( - appIdx uint64, - appArgs [][]byte, - accounts []string, - foreignApps []uint64, - foreignAssets []uint64, - appBoxReferences []types.AppBoxReference, - onCompletion types.OnCompletion, - approvalProg []byte, - clearProg []byte, - globalSchema types.StateSchema, - localSchema types.StateSchema, - extraPages uint32, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) (tx types.Transaction, err error) { - tx.Type = types.ApplicationCallTx - tx.ApplicationID = types.AppIndex(appIdx) - tx.OnCompletion = onCompletion - - tx.ApplicationArgs = appArgs - tx.Accounts, err = parseTxnAccounts(accounts) - if err != nil { - return tx, err - } - - tx.ForeignApps = parseTxnForeignApps(foreignApps) - tx.ForeignAssets = parseTxnForeignAssets(foreignAssets) - tx.BoxReferences, err = parseBoxReferences(appBoxReferences, foreignApps, appIdx) - if err != nil { - return tx, err - } - - tx.ApprovalProgram = approvalProg - tx.ClearStateProgram = clearProg - tx.LocalStateSchema = localSchema - tx.GlobalStateSchema = globalSchema - tx.ExtraProgramPages = extraPages - - var gh types.Digest - copy(gh[:], sp.GenesisHash) - - tx.Header = types.Header{ - Sender: sender, - Fee: sp.Fee, - FirstValid: sp.FirstRoundValid, - LastValid: sp.LastRoundValid, - Note: note, - GenesisID: sp.GenesisID, - GenesisHash: gh, - Group: group, - Lease: lease, - RekeyTo: rekeyTo, - } - - // Update fee - return setFee(tx, sp) -} - -// AssignGroupID computes and return list of transactions with Group field set. -// - txns is a list of transactions to process -// - account specifies a sender field of transaction to return. Set to empty string to return all of them -func AssignGroupID(txns []types.Transaction, account string) (result []types.Transaction, err error) { - gid, err := crypto.ComputeGroupID(txns) - if err != nil { - return - } - var decoded types.Address - if account != "" { - decoded, err = types.DecodeAddress(account) - if err != nil { - return - } - } - for _, tx := range txns { - if account == "" || bytes.Compare(tx.Sender[:], decoded[:]) == 0 { - tx.Group = gid - result = append(result, tx) - } - } - return result, nil -} - -// EstimateSize returns the estimated length of the encoded transaction -func EstimateSize(txn types.Transaction) (uint64, error) { - return uint64(len(msgpack.Encode(txn))) + NumOfAdditionalBytesAfterSigning, nil -} - -func parseTxnAccounts(accounts []string) (parsed []types.Address, err error) { - for _, acct := range accounts { - addr, err := types.DecodeAddress(acct) - if err != nil { - return nil, err - } - parsed = append(parsed, addr) - } - return -} - -func parseTxnForeignApps(foreignApps []uint64) (parsed []types.AppIndex) { - for _, aidx := range foreignApps { - parsed = append(parsed, types.AppIndex(aidx)) - } - return -} - -func parseTxnForeignAssets(foreignAssets []uint64) (parsed []types.AssetIndex) { - for _, aidx := range foreignAssets { - parsed = append(parsed, types.AssetIndex(aidx)) - } - return -} - -func parseBoxReferences(abrs []types.AppBoxReference, foreignApps []uint64, curAppID uint64) (parsed []types.BoxReference, err error) { - for _, abr := range abrs { - // there are a few unintuitive details to the parsing: - // 1. the AppID of the box must either be in the foreign apps array or - // equal to 0, which references the current app. - // 2. if the box references the current app by its appID rather than 0 AND - // the current appID is explicitly provided in the foreign apps array - // then ForeignAppIdx should be set to its index in the array. - br := types.BoxReference{Name: abr.Name} - found := false - - if abr.AppID == 0 { - found = true - br.ForeignAppIdx = 0 - } else { - for idx, appID := range foreignApps { - if appID == abr.AppID { - found = true - br.ForeignAppIdx = uint64(idx + 1) - break - } - } - } - - if !found && abr.AppID == curAppID { - found = true - br.ForeignAppIdx = 0 - } - - if !found { - return nil, fmt.Errorf("the app id %d provided for this box is not in the foreignApps array", abr.AppID) - } - - parsed = append(parsed, br) - } - - return -} - -var emptySchema = types.StateSchema{} diff --git a/future/transaction_test.go b/future/transaction_test.go deleted file mode 100644 index 0bd207a7..00000000 --- a/future/transaction_test.go +++ /dev/null @@ -1,1065 +0,0 @@ -package future - -import ( - "encoding/base64" - "testing" - - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/encoding/msgpack" - "github.com/algorand/go-algorand-sdk/mnemonic" - "github.com/algorand/go-algorand-sdk/types" - "github.com/stretchr/testify/require" -) - -func byteFromBase64(s string) []byte { - b, _ := base64.StdEncoding.DecodeString(s) - return b -} - -func byte32ArrayFromBase64(s string) (out [32]byte) { - slice := byteFromBase64(s) - if len(slice) != 32 { - panic("wrong length: input slice not 32 bytes") - } - copy(out[:], slice) - return -} - -func byte64ArrayFromBase64(s string) (out [64]byte) { - slice := byteFromBase64(s) - if len(slice) != 64 { - panic("wrong length: input slice not 64 bytes") - } - copy(out[:], slice) - return -} - -func TestMakePaymentTxn(t *testing.T) { - const fromAddress = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU" - const toAddress = "PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI" - const referenceTxID = "5FJDJD5LMZC3EHUYYJNH5I23U4X6H2KXABNDGPIL557ZMJ33GZHQ" - const mn = "advice pudding treat near rule blouse same whisper inner electric quit surface sunny dismiss leader blood seat clown cost exist hospital century reform able sponsor" - const golden = "gqNzaWfEQPhUAZ3xkDDcc8FvOVo6UinzmKBCqs0woYSfodlmBMfQvGbeUx3Srxy3dyJDzv7rLm26BRv9FnL2/AuT7NYfiAWjdHhui6NhbXTNA+ilY2xvc2XEIEDpNJKIJWTLzpxZpptnVCaJ6aHDoqnqW2Wm6KRCH/xXo2ZlZc0EmKJmds0wsqNnZW6sZGV2bmV0LXYzMy4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds00mqRub3RlxAjqABVHQ2y/lqNyY3bEIHts4k/rW6zAsWTinCIsV/X2PcOH1DkEglhBHF/hD3wCo3NuZMQg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGkdHlwZaNwYXk=" - gh := byteFromBase64("JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=") - - params := types.SuggestedParams{ - Fee: 4, - FirstRoundValid: 12466, - LastRoundValid: 13466, - GenesisID: "devnet-v33.0", - GenesisHash: gh, - } - txn, err := MakePaymentTxn(fromAddress, toAddress, 1000, byteFromBase64("6gAVR0Nsv5Y="), "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA", params) - require.NoError(t, err) - - key, err := mnemonic.ToPrivateKey(mn) - require.NoError(t, err) - - id, bytes, err := crypto.SignTransaction(key, txn) - require.NoError(t, err) - - stxBytes := byteFromBase64(golden) - require.Equal(t, stxBytes, bytes) - - require.Equal(t, referenceTxID, id) -} - -// should fail on a lack of GenesisHash -func TestMakePaymentTxn2(t *testing.T) { - const fromAddress = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU" - const toAddress = "PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI" - params := types.SuggestedParams{ - Fee: 4, - FirstRoundValid: 12466, - LastRoundValid: 13466, - GenesisID: "devnet-v33.0", - } - _, err := MakePaymentTxn(fromAddress, toAddress, 1000, byteFromBase64("6gAVR0Nsv5Y="), "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA", params) - require.Error(t, err) -} - -func TestMakePaymentTxnWithLease(t *testing.T) { - const fromAddress = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU" - const toAddress = "PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI" - const referenceTxID = "7BG6COBZKF6I6W5XY72ZE4HXV6LLZ6ENSR6DASEGSTXYXR4XJOOQ" - const mn = "advice pudding treat near rule blouse same whisper inner electric quit surface sunny dismiss leader blood seat clown cost exist hospital century reform able sponsor" - const golden = "gqNzaWfEQOMmFSIKsZvpW0txwzhmbgQjxv6IyN7BbV5sZ2aNgFbVcrWUnqPpQQxfPhV/wdu9jzEPUU1jAujYtcNCxJ7ONgejdHhujKNhbXTNA+ilY2xvc2XEIEDpNJKIJWTLzpxZpptnVCaJ6aHDoqnqW2Wm6KRCH/xXo2ZlZc0FLKJmds0wsqNnZW6sZGV2bmV0LXYzMy4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds00mqJseMQgAQIDBAECAwQBAgMEAQIDBAECAwQBAgMEAQIDBAECAwSkbm90ZcQI6gAVR0Nsv5ajcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEIOfw+E0GgR358xyNh4sRVfRnHVGhhcIAkIZn9ElYcGihpHR5cGWjcGF5" - gh := byteFromBase64("JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=") - params := types.SuggestedParams{ - Fee: 4, - FirstRoundValid: 12466, - LastRoundValid: 13466, - GenesisID: "devnet-v33.0", - GenesisHash: gh, - } - lease := [32]byte{1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4} - txn, err := MakePaymentTxn(fromAddress, toAddress, 1000, byteFromBase64("6gAVR0Nsv5Y="), "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA", params) - require.NoError(t, err) - txn.AddLease(lease, 4) - require.NoError(t, err) - - key, err := mnemonic.ToPrivateKey(mn) - require.NoError(t, err) - - id, stxBytes, err := crypto.SignTransaction(key, txn) - require.NoError(t, err) - - goldenBytes := byteFromBase64(golden) - require.Equal(t, goldenBytes, stxBytes) - require.Equal(t, referenceTxID, id) -} - -func TestKeyRegTxn(t *testing.T) { - // preKeyRegTxn is an unsigned signed keyreg txn with zero Sender - const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" - a, err := types.DecodeAddress(addr) - require.NoError(t, err) - const addrSK = "awful drop leaf tennis indoor begin mandate discover uncle seven only coil atom any hospital uncover make any climb actor armed measure need above hundred" - expKeyRegTxn := types.Transaction{ - Type: types.KeyRegistrationTx, - Header: types.Header{ - Sender: a, - Fee: 1000, - FirstValid: 322575, - LastValid: 323575, - GenesisHash: byte32ArrayFromBase64("SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="), - GenesisID: "", - }, - KeyregTxnFields: types.KeyregTxnFields{ - VotePK: byte32ArrayFromBase64("Kv7QI7chi1y6axoy+t7wzAVpePqRq/rkjzWh/RMYyLo="), - SelectionPK: byte32ArrayFromBase64("bPgrv4YogPcdaUAxrt1QysYZTVyRAuUMD4zQmCu9llc="), - VoteFirst: 10000, - VoteLast: 10111, - VoteKeyDilution: 11, - }, - } - const signedGolden = "gqNzaWfEQEA8ANbrvTRxU9c8v6WERcEPw7D/HacRgg4vICa61vEof60Wwtx6KJKDyvBuvViFeacLlngPY6vYCVP0DktTwQ2jdHhui6NmZWXNA+iiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv96ZzZWxrZXnEIGz4K7+GKID3HWlAMa7dUMrGGU1ckQLlDA+M0JgrvZZXo3NuZMQgCfvSdiwI+Gxa5r9t16epAd5mdddQ4H6MXHaYZH224f2kdHlwZaZrZXlyZWendm90ZWZzdM0nEKZ2b3Rla2QLp3ZvdGVrZXnEICr+0CO3IYtcumsaMvre8MwFaXj6kav65I81of0TGMi6p3ZvdGVsc3TNJ38=" - // now, sign - private, err := mnemonic.ToPrivateKey(addrSK) - require.NoError(t, err) - txid, newStxBytes, err := crypto.SignTransaction(private, expKeyRegTxn) - require.NoError(t, err) - require.Equal(t, "MDRIUVH5AW4Z3GMOB67WP44LYLEVM2MP3ZEPKFHUB5J47A2J6TUQ", txid) - require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) -} - -func TestMakeKeyRegTxn(t *testing.T) { - const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" - ghAsArray := byte32ArrayFromBase64("SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=") - params := types.SuggestedParams{ - Fee: 10, - FirstRoundValid: 322575, - LastRoundValid: 323575, - GenesisHash: ghAsArray[:], - } - tx, err := MakeKeyRegTxn(addr, []byte{45, 67}, params, "Kv7QI7chi1y6axoy+t7wzAVpePqRq/rkjzWh/RMYyLo=", "bPgrv4YogPcdaUAxrt1QysYZTVyRAuUMD4zQmCu9llc=", 10000, 10111, 11) - require.NoError(t, err) - - a, err := types.DecodeAddress(addr) - require.NoError(t, err) - expKeyRegTxn := types.Transaction{ - Type: types.KeyRegistrationTx, - Header: types.Header{ - Sender: a, - Fee: 3060, - FirstValid: 322575, - LastValid: 323575, - Note: []byte{45, 67}, - GenesisHash: byte32ArrayFromBase64("SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="), - GenesisID: "", - }, - KeyregTxnFields: types.KeyregTxnFields{ - VotePK: byte32ArrayFromBase64("Kv7QI7chi1y6axoy+t7wzAVpePqRq/rkjzWh/RMYyLo="), - SelectionPK: byte32ArrayFromBase64("bPgrv4YogPcdaUAxrt1QysYZTVyRAuUMD4zQmCu9llc="), - VoteFirst: 10000, - VoteLast: 10111, - VoteKeyDilution: 11, - }, - } - require.Equal(t, expKeyRegTxn, tx) -} - -func TestMakeKeyRegTxnWithStateProofKey(t *testing.T) { - const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" - ghAsArray := byte32ArrayFromBase64("SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=") - params := types.SuggestedParams{ - Fee: 10, - FirstRoundValid: 322575, - LastRoundValid: 323575, - GenesisHash: ghAsArray[:], - } - // nonparticipation - tx, err := MakeKeyRegTxnWithStateProofKey(addr, []byte{45, 67}, params, "", "", "", 0, 0, 0, true) - require.NoError(t, err) - a, err := types.DecodeAddress(addr) - require.NoError(t, err) - expKeyRegTxn := types.Transaction{ - Type: types.KeyRegistrationTx, - Header: types.Header{ - Sender: a, - Fee: 2020, - FirstValid: 322575, - LastValid: 323575, - Note: []byte{45, 67}, - GenesisHash: byte32ArrayFromBase64("SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="), - GenesisID: "", - }, - KeyregTxnFields: types.KeyregTxnFields{ - Nonparticipation: true, - }, - } - require.Equal(t, expKeyRegTxn, tx) - - // online - stateProof := "mYR0GVEObMTSNdsKM6RwYywHYPqVDqg3E4JFzxZOreH9NU8B+tKzUanyY8AQ144hETgSMX7fXWwjBdHz6AWk9w==" - tx, err = MakeKeyRegTxnWithStateProofKey(addr, []byte{45, 67}, params, "Kv7QI7chi1y6axoy+t7wzAVpePqRq/rkjzWh/RMYyLo=", "bPgrv4YogPcdaUAxrt1QysYZTVyRAuUMD4zQmCu9llc=", stateProof, 10000, 10111, 11, false) - require.NoError(t, err) - - a, err = types.DecodeAddress(addr) - require.NoError(t, err) - expKeyRegTxn = types.Transaction{ - Type: types.KeyRegistrationTx, - Header: types.Header{ - Sender: a, - Fee: 3800, - FirstValid: 322575, - LastValid: 323575, - Note: []byte{45, 67}, - GenesisHash: byte32ArrayFromBase64("SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="), - GenesisID: "", - }, - KeyregTxnFields: types.KeyregTxnFields{ - VotePK: byte32ArrayFromBase64("Kv7QI7chi1y6axoy+t7wzAVpePqRq/rkjzWh/RMYyLo="), - SelectionPK: byte32ArrayFromBase64("bPgrv4YogPcdaUAxrt1QysYZTVyRAuUMD4zQmCu9llc="), - VoteFirst: 10000, - VoteLast: 10111, - VoteKeyDilution: 11, - Nonparticipation: false, - StateProofPK: byte64ArrayFromBase64(stateProof), - }, - } - require.Equal(t, expKeyRegTxn, tx) -} - -func TestMakeAssetCreateTxn(t *testing.T) { - const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" - const defaultFrozen = false - const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" - ghAsArray := byte32ArrayFromBase64(genesisHash) - const total = 100 - const reserve = addr - const freeze = addr - const clawback = addr - const unitName = "tst" - const assetName = "testcoin" - const testURL = "website" - const metadataHash = "fACPO4nRgO55j1ndAK3W6Sgc4APkcyFh" - params := types.SuggestedParams{ - Fee: 10, - FirstRoundValid: 322575, - LastRoundValid: 323575, - GenesisHash: ghAsArray[:], - } - tx, err := MakeAssetCreateTxn(addr, nil, params, total, 0, defaultFrozen, addr, reserve, freeze, clawback, unitName, assetName, testURL, metadataHash) - require.NoError(t, err) - - a, err := types.DecodeAddress(addr) - require.NoError(t, err) - expectedAssetCreationTxn := types.Transaction{ - Type: types.AssetConfigTx, - Header: types.Header{ - Sender: a, - Fee: 4020, - FirstValid: 322575, - LastValid: 323575, - GenesisHash: byte32ArrayFromBase64(genesisHash), - GenesisID: "", - }, - } - expectedAssetCreationTxn.AssetParams = types.AssetParams{ - Total: total, - DefaultFrozen: defaultFrozen, - Manager: a, - Reserve: a, - Freeze: a, - Clawback: a, - UnitName: unitName, - AssetName: assetName, - URL: testURL, - } - copy(expectedAssetCreationTxn.AssetParams.MetadataHash[:], []byte(metadataHash)) - require.Equal(t, expectedAssetCreationTxn, tx) - - const addrSK = "awful drop leaf tennis indoor begin mandate discover uncle seven only coil atom any hospital uncover make any climb actor armed measure need above hundred" - private, err := mnemonic.ToPrivateKey(addrSK) - require.NoError(t, err) - _, newStxBytes, err := crypto.SignTransaction(private, tx) - require.NoError(t, err) - signedGolden := "gqNzaWfEQEDd1OMRoQI/rzNlU4iiF50XQXmup3k5czI9hEsNqHT7K4KsfmA/0DUVkbzOwtJdRsHS8trm3Arjpy9r7AXlbAujdHhuh6RhcGFyiaJhbcQgZkFDUE80blJnTzU1ajFuZEFLM1c2U2djNEFQa2N5RmiiYW6odGVzdGNvaW6iYXWnd2Vic2l0ZaFjxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFmxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFtxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFyxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aF0ZKJ1bqN0c3SjZmVlzQ+0omZ2zgAE7A+iZ2jEIEhjtRiks8hOyBDyLU8QgcsPcfBZp6wg3sYvf3DlCToiomx2zgAE7/ejc25kxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aR0eXBlpGFjZmc=" - require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) -} - -func TestMakeAssetCreateTxnWithDecimals(t *testing.T) { - const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" - const defaultFrozen = false - const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" - ghAsArray := byte32ArrayFromBase64(genesisHash) - const total = 100 - const decimals = 1 - const reserve = addr - const freeze = addr - const clawback = addr - const unitName = "tst" - const assetName = "testcoin" - const testURL = "website" - const metadataHash = "fACPO4nRgO55j1ndAK3W6Sgc4APkcyFh" - params := types.SuggestedParams{ - Fee: 10, - FirstRoundValid: 322575, - LastRoundValid: 323575, - GenesisHash: ghAsArray[:], - } - tx, err := MakeAssetCreateTxn(addr, nil, params, total, decimals, defaultFrozen, addr, reserve, freeze, clawback, unitName, assetName, testURL, metadataHash) - require.NoError(t, err) - - a, err := types.DecodeAddress(addr) - require.NoError(t, err) - expectedAssetCreationTxn := types.Transaction{ - Type: types.AssetConfigTx, - Header: types.Header{ - Sender: a, - Fee: 4060, - FirstValid: 322575, - LastValid: 323575, - GenesisHash: byte32ArrayFromBase64(genesisHash), - GenesisID: "", - }, - } - expectedAssetCreationTxn.AssetParams = types.AssetParams{ - Total: total, - Decimals: decimals, - DefaultFrozen: defaultFrozen, - Manager: a, - Reserve: a, - Freeze: a, - Clawback: a, - UnitName: unitName, - AssetName: assetName, - URL: testURL, - } - copy(expectedAssetCreationTxn.AssetParams.MetadataHash[:], []byte(metadataHash)) - require.Equal(t, expectedAssetCreationTxn, tx) - - const addrSK = "awful drop leaf tennis indoor begin mandate discover uncle seven only coil atom any hospital uncover make any climb actor armed measure need above hundred" - private, err := mnemonic.ToPrivateKey(addrSK) - require.NoError(t, err) - _, newStxBytes, err := crypto.SignTransaction(private, tx) - require.NoError(t, err) - signedGolden := "gqNzaWfEQCj5xLqNozR5ahB+LNBlTG+d0gl0vWBrGdAXj1ibsCkvAwOsXs5KHZK1YdLgkdJecQiWm4oiZ+pm5Yg0m3KFqgqjdHhuh6RhcGFyiqJhbcQgZkFDUE80blJnTzU1ajFuZEFLM1c2U2djNEFQa2N5RmiiYW6odGVzdGNvaW6iYXWnd2Vic2l0ZaFjxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aJkYwGhZsQgCfvSdiwI+Gxa5r9t16epAd5mdddQ4H6MXHaYZH224f2hbcQgCfvSdiwI+Gxa5r9t16epAd5mdddQ4H6MXHaYZH224f2hcsQgCfvSdiwI+Gxa5r9t16epAd5mdddQ4H6MXHaYZH224f2hdGSidW6jdHN0o2ZlZc0P3KJmds4ABOwPomdoxCBIY7UYpLPITsgQ8i1PEIHLD3HwWaesIN7GL39w5Qk6IqJsds4ABO/3o3NuZMQgCfvSdiwI+Gxa5r9t16epAd5mdddQ4H6MXHaYZH224f2kdHlwZaRhY2Zn" - require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) -} - -func TestMakeAssetConfigTxn(t *testing.T) { - const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" - const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" - ghAsArray := byte32ArrayFromBase64(genesisHash) - const manager = addr - const reserve = addr - const freeze = addr - const clawback = addr - const assetIndex = 1234 - params := types.SuggestedParams{ - Fee: 10, - FirstRoundValid: 322575, - LastRoundValid: 323575, - GenesisHash: ghAsArray[:], - } - tx, err := MakeAssetConfigTxn(addr, nil, params, assetIndex, manager, reserve, freeze, clawback, false) - require.NoError(t, err) - - a, err := types.DecodeAddress(addr) - require.NoError(t, err) - expectedAssetConfigTxn := types.Transaction{ - Type: types.AssetConfigTx, - Header: types.Header{ - Sender: a, - Fee: 3400, - FirstValid: 322575, - LastValid: 323575, - GenesisHash: byte32ArrayFromBase64(genesisHash), - GenesisID: "", - }, - } - - expectedAssetConfigTxn.AssetParams = types.AssetParams{ - Manager: a, - Reserve: a, - Freeze: a, - Clawback: a, - } - expectedAssetConfigTxn.ConfigAsset = types.AssetIndex(assetIndex) - require.Equal(t, expectedAssetConfigTxn, tx) - - const addrSK = "awful drop leaf tennis indoor begin mandate discover uncle seven only coil atom any hospital uncover make any climb actor armed measure need above hundred" - private, err := mnemonic.ToPrivateKey(addrSK) - require.NoError(t, err) - _, newStxBytes, err := crypto.SignTransaction(private, tx) - require.NoError(t, err) - signedGolden := "gqNzaWfEQBBkfw5n6UevuIMDo2lHyU4dS80JCCQ/vTRUcTx5m0ivX68zTKyuVRrHaTbxbRRc3YpJ4zeVEnC9Fiw3Wf4REwejdHhuiKRhcGFyhKFjxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFmxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFtxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFyxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aRjYWlkzQTSo2ZlZc0NSKJmds4ABOwPomdoxCBIY7UYpLPITsgQ8i1PEIHLD3HwWaesIN7GL39w5Qk6IqJsds4ABO/3o3NuZMQgCfvSdiwI+Gxa5r9t16epAd5mdddQ4H6MXHaYZH224f2kdHlwZaRhY2Zn" - require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) -} - -func TestMakeAssetConfigTxnStrictChecking(t *testing.T) { - const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" - const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" - ghAsArray := byte32ArrayFromBase64(genesisHash) - const manager = addr - const reserve = addr - const freeze = "" - const clawback = addr - const assetIndex = 1234 - params := types.SuggestedParams{ - Fee: 10, - FirstRoundValid: 322575, - LastRoundValid: 323575, - GenesisHash: ghAsArray[:], - } - _, err := MakeAssetConfigTxn(addr, nil, params, assetIndex, manager, reserve, freeze, clawback, true) - require.Error(t, err) -} - -func TestMakeAssetDestroyTxn(t *testing.T) { - const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" - const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" - ghAsArray := byte32ArrayFromBase64(genesisHash) - const creator = addr - const assetIndex = 1 - const firstValidRound = 322575 - const lastValidRound = 323575 - params := types.SuggestedParams{ - Fee: 10, - FirstRoundValid: firstValidRound, - LastRoundValid: lastValidRound, - GenesisHash: ghAsArray[:], - } - tx, err := MakeAssetDestroyTxn(creator, nil, params, assetIndex) - require.NoError(t, err) - - a, err := types.DecodeAddress(creator) - require.NoError(t, err) - - expectedAssetDestroyTxn := types.Transaction{ - Type: types.AssetConfigTx, - Header: types.Header{ - Sender: a, - Fee: 1880, - FirstValid: firstValidRound, - LastValid: lastValidRound, - GenesisHash: byte32ArrayFromBase64(genesisHash), - GenesisID: "", - }, - } - expectedAssetDestroyTxn.AssetParams = types.AssetParams{} - expectedAssetDestroyTxn.ConfigAsset = types.AssetIndex(assetIndex) - require.Equal(t, expectedAssetDestroyTxn, tx) - - const addrSK = "awful drop leaf tennis indoor begin mandate discover uncle seven only coil atom any hospital uncover make any climb actor armed measure need above hundred" - private, err := mnemonic.ToPrivateKey(addrSK) - require.NoError(t, err) - _, newStxBytes, err := crypto.SignTransaction(private, tx) - require.NoError(t, err) - signedGolden := "gqNzaWfEQBSP7HtzD/Lvn4aVvaNpeR4T93dQgo4LvywEwcZgDEoc/WVl3aKsZGcZkcRFoiWk8AidhfOZzZYutckkccB8RgGjdHhuh6RjYWlkAaNmZWXNB1iiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv96NzbmTEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pHR5cGWkYWNmZw==" - require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) -} - -func TestMakeAssetFreezeTxn(t *testing.T) { - const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" - const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" - ghAsArray := byte32ArrayFromBase64(genesisHash) - const assetIndex = 1 - const firstValidRound = 322575 - const lastValidRound = 323576 - const freezeSetting = true - const target = addr - params := types.SuggestedParams{ - Fee: 10, - FirstRoundValid: firstValidRound, - LastRoundValid: lastValidRound, - GenesisHash: ghAsArray[:], - } - tx, err := MakeAssetFreezeTxn(addr, nil, params, assetIndex, target, freezeSetting) - require.NoError(t, err) - - a, err := types.DecodeAddress(addr) - require.NoError(t, err) - - expectedAssetFreezeTxn := types.Transaction{ - Type: types.AssetFreezeTx, - Header: types.Header{ - Sender: a, - Fee: 2330, - FirstValid: firstValidRound, - LastValid: lastValidRound, - GenesisHash: byte32ArrayFromBase64(genesisHash), - GenesisID: "", - }, - } - expectedAssetFreezeTxn.FreezeAsset = types.AssetIndex(assetIndex) - expectedAssetFreezeTxn.AssetFrozen = freezeSetting - expectedAssetFreezeTxn.FreezeAccount = a - require.Equal(t, expectedAssetFreezeTxn, tx) - - const addrSK = "awful drop leaf tennis indoor begin mandate discover uncle seven only coil atom any hospital uncover make any climb actor armed measure need above hundred" - private, err := mnemonic.ToPrivateKey(addrSK) - require.NoError(t, err) - _, newStxBytes, err := crypto.SignTransaction(private, tx) - require.NoError(t, err) - signedGolden := "gqNzaWfEQAhru5V2Xvr19s4pGnI0aslqwY4lA2skzpYtDTAN9DKSH5+qsfQQhm4oq+9VHVj7e1rQC49S28vQZmzDTVnYDQGjdHhuiaRhZnJ6w6RmYWRkxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aRmYWlkAaNmZWXNCRqiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv+KNzbmTEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pHR5cGWkYWZyeg==" - require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) -} - -func TestMakeAssetTransferTxn(t *testing.T) { - const addrSK = "awful drop leaf tennis indoor begin mandate discover uncle seven only coil atom any hospital uncover make any climb actor armed measure need above hundred" - private, err := mnemonic.ToPrivateKey(addrSK) - require.NoError(t, err) - - const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" - const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" - ghAsArray := byte32ArrayFromBase64(genesisHash) - const sender, recipient, closeAssetsTo = addr, addr, addr - const assetIndex = 1 - const firstValidRound = 322575 - const lastValidRound = 323576 - const amountToSend = 1 - params := types.SuggestedParams{ - Fee: 10, - FirstRoundValid: firstValidRound, - LastRoundValid: lastValidRound, - GenesisHash: ghAsArray[:], - } - tx, err := MakeAssetTransferTxn(sender, recipient, amountToSend, nil, params, closeAssetsTo, assetIndex) - require.NoError(t, err) - - sendAddr, err := types.DecodeAddress(sender) - require.NoError(t, err) - - expectedAssetTransferTxn := types.Transaction{ - Type: types.AssetTransferTx, - Header: types.Header{ - Sender: sendAddr, - Fee: 2750, - FirstValid: firstValidRound, - LastValid: lastValidRound, - GenesisHash: byte32ArrayFromBase64(genesisHash), - GenesisID: "", - }, - } - - expectedAssetID := types.AssetIndex(assetIndex) - expectedAssetTransferTxn.XferAsset = expectedAssetID - - receiveAddr, err := types.DecodeAddress(recipient) - require.NoError(t, err) - expectedAssetTransferTxn.AssetReceiver = receiveAddr - - closeAddr, err := types.DecodeAddress(closeAssetsTo) - require.NoError(t, err) - expectedAssetTransferTxn.AssetCloseTo = closeAddr - - expectedAssetTransferTxn.AssetAmount = amountToSend - - require.Equal(t, expectedAssetTransferTxn, tx) - - // now compare tx against a golden - const signedGolden = "gqNzaWfEQNkEs3WdfFq6IQKJdF1n0/hbV9waLsvojy9pM1T4fvwfMNdjGQDy+LeesuQUfQVTneJD4VfMP7zKx4OUlItbrwSjdHhuiqRhYW10AaZhY2xvc2XEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pGFyY3bEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9o2ZlZc0KvqJmds4ABOwPomdoxCBIY7UYpLPITsgQ8i1PEIHLD3HwWaesIN7GL39w5Qk6IqJsds4ABO/4o3NuZMQgCfvSdiwI+Gxa5r9t16epAd5mdddQ4H6MXHaYZH224f2kdHlwZaVheGZlcqR4YWlkAQ==" - _, newStxBytes, err := crypto.SignTransaction(private, tx) - require.NoError(t, err) - require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) -} - -func TestMakeAssetAcceptanceTxn(t *testing.T) { - const sender = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" - const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" - ghAsArray := byte32ArrayFromBase64(genesisHash) - const assetIndex = 1 - const firstValidRound = 322575 - const lastValidRound = 323575 - params := types.SuggestedParams{ - Fee: 10, - FirstRoundValid: firstValidRound, - LastRoundValid: lastValidRound, - GenesisHash: ghAsArray[:], - } - tx, err := MakeAssetAcceptanceTxn(sender, nil, params, assetIndex) - require.NoError(t, err) - - sendAddr, err := types.DecodeAddress(sender) - require.NoError(t, err) - - expectedAssetAcceptanceTxn := types.Transaction{ - Type: types.AssetTransferTx, - Header: types.Header{ - Sender: sendAddr, - Fee: 2280, - FirstValid: firstValidRound, - LastValid: lastValidRound, - GenesisHash: byte32ArrayFromBase64(genesisHash), - GenesisID: "", - }, - } - - expectedAssetID := types.AssetIndex(assetIndex) - expectedAssetAcceptanceTxn.XferAsset = expectedAssetID - expectedAssetAcceptanceTxn.AssetReceiver = sendAddr - expectedAssetAcceptanceTxn.AssetAmount = 0 - - require.Equal(t, expectedAssetAcceptanceTxn, tx) - - const addrSK = "awful drop leaf tennis indoor begin mandate discover uncle seven only coil atom any hospital uncover make any climb actor armed measure need above hundred" - private, err := mnemonic.ToPrivateKey(addrSK) - require.NoError(t, err) - _, newStxBytes, err := crypto.SignTransaction(private, tx) - require.NoError(t, err) - signedGolden := "gqNzaWfEQJ7q2rOT8Sb/wB0F87ld+1zMprxVlYqbUbe+oz0WM63FctIi+K9eYFSqT26XBZ4Rr3+VTJpBE+JLKs8nctl9hgijdHhuiKRhcmN2xCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aNmZWXNCOiiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv96NzbmTEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pHR5cGWlYXhmZXKkeGFpZAE=" - require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) -} - -func TestMakeAssetRevocationTransaction(t *testing.T) { - const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" - const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" - ghAsArray := byte32ArrayFromBase64(genesisHash) - const revoker, recipient, revoked = addr, addr, addr - const assetIndex = 1 - const firstValidRound = 322575 - const lastValidRound = 323575 - const amountToSend = 1 - - params := types.SuggestedParams{ - Fee: 10, - FirstRoundValid: firstValidRound, - LastRoundValid: lastValidRound, - GenesisHash: ghAsArray[:], - } - tx, err := MakeAssetRevocationTxn(revoker, revoked, amountToSend, recipient, nil, params, assetIndex) - require.NoError(t, err) - - sendAddr, err := types.DecodeAddress(revoker) - require.NoError(t, err) - - expectedAssetRevocationTxn := types.Transaction{ - Type: types.AssetTransferTx, - Header: types.Header{ - Sender: sendAddr, - Fee: 2730, - FirstValid: firstValidRound, - LastValid: lastValidRound, - GenesisHash: byte32ArrayFromBase64(genesisHash), - GenesisID: "", - }, - } - - expectedAssetID := types.AssetIndex(assetIndex) - expectedAssetRevocationTxn.XferAsset = expectedAssetID - - receiveAddr, err := types.DecodeAddress(recipient) - require.NoError(t, err) - expectedAssetRevocationTxn.AssetReceiver = receiveAddr - - expectedAssetRevocationTxn.AssetAmount = amountToSend - - targetAddr, err := types.DecodeAddress(revoked) - require.NoError(t, err) - expectedAssetRevocationTxn.AssetSender = targetAddr - - require.Equal(t, expectedAssetRevocationTxn, tx) - - const addrSK = "awful drop leaf tennis indoor begin mandate discover uncle seven only coil atom any hospital uncover make any climb actor armed measure need above hundred" - private, err := mnemonic.ToPrivateKey(addrSK) - require.NoError(t, err) - _, newStxBytes, err := crypto.SignTransaction(private, tx) - require.NoError(t, err) - signedGolden := "gqNzaWfEQHsgfEAmEHUxLLLR9s+Y/yq5WeoGo/jAArCbany+7ZYwExMySzAhmV7M7S8+LBtJalB4EhzEUMKmt3kNKk6+vAWjdHhuiqRhYW10AaRhcmN2xCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aRhc25kxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aNmZWXNCqqiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv96NzbmTEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pHR5cGWlYXhmZXKkeGFpZAE=" - require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) -} - -func TestMakeApplicationCallTx(t *testing.T) { - const fee = 1000 - const firstRound = 2063137 - const genesisID = "devnet-v1.0" - genesisHash := byteFromBase64("sC3P7e2SdbqKJK0tbiCdK9tdSpbe6XeCGKdoNzmlj0E=") - - params := types.SuggestedParams{ - Fee: fee, - FirstRoundValid: firstRound, - LastRoundValid: firstRound + 1000, - GenesisHash: genesisHash, - GenesisID: genesisID, - FlatFee: true, - } - note := byteFromBase64("8xMCTuLQ810=") - program := []byte{1, 32, 1, 1, 34} - args := make([][]byte, 2) - args[0] = []byte("123") - args[1] = []byte("456") - foreignApps := make([]uint64, 1) - foreignApps[0] = 10 - foreignAssets := foreignApps - gSchema := types.StateSchema{NumUint: uint64(1), NumByteSlice: uint64(1)} - lSchema := types.StateSchema{NumUint: uint64(1), NumByteSlice: uint64(1)} - extraPages := uint32(2) - addr := make([]string, 1) - addr[0] = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU" - boxReferences := make([]types.AppBoxReference, 3) - boxReferences[0] = types.AppBoxReference{AppID: 2, Name: []byte("box_name")} - boxReferences[1] = types.AppBoxReference{AppID: 10, Name: []byte("box_name")} - boxReferences[2] = types.AppBoxReference{AppID: 10, Name: []byte("box_name2")} - - tx, err := MakeApplicationCallTxWithBoxes(2, args, addr, foreignApps, foreignAssets, boxReferences, types.NoOpOC, program, program, gSchema, lSchema, extraPages, params, types.Address{}, note, types.Digest{}, [32]byte{}, types.Address{}) - require.NoError(t, err) - require.EqualValues(t, 2, tx.ExtraProgramPages) - - // verify that the correct app index was calculated - require.EqualValues(t, 0, tx.BoxReferences[0].ForeignAppIdx) - require.EqualValues(t, 1, tx.BoxReferences[1].ForeignAppIdx) - require.EqualValues(t, 1, tx.BoxReferences[2].ForeignAppIdx) - - // the current app can also be referenced with AppID = 0 - boxReferences[0].AppID = 0 - tx, err = MakeApplicationCallTxWithBoxes(2, args, addr, foreignApps, foreignAssets, boxReferences, types.NoOpOC, program, program, gSchema, lSchema, extraPages, params, types.Address{}, note, types.Digest{}, [32]byte{}, types.Address{}) - require.NoError(t, err) - require.EqualValues(t, 0, tx.BoxReferences[0].ForeignAppIdx) - require.EqualValues(t, 1, tx.BoxReferences[1].ForeignAppIdx) - require.EqualValues(t, 1, tx.BoxReferences[2].ForeignAppIdx) - - // if the current app's ID is provided explicitly AND is present in the foreignApps array - // then the index in the array should be returned rather than the usual value of 0 - boxReferences[0].AppID = 2 - foreignApps = append(foreignApps, 2) - tx, err = MakeApplicationCallTxWithBoxes(2, args, addr, foreignApps, foreignAssets, boxReferences, types.NoOpOC, program, program, gSchema, lSchema, extraPages, params, types.Address{}, note, types.Digest{}, [32]byte{}, types.Address{}) - require.NoError(t, err) - require.EqualValues(t, 2, tx.BoxReferences[0].ForeignAppIdx) - require.EqualValues(t, 1, tx.BoxReferences[1].ForeignAppIdx) - require.EqualValues(t, 1, tx.BoxReferences[2].ForeignAppIdx) -} - -func TestMakeApplicationCallTxInvalidBoxes(t *testing.T) { - const fee = 1000 - const firstRound = 2063137 - const genesisID = "devnet-v1.0" - genesisHash := byteFromBase64("sC3P7e2SdbqKJK0tbiCdK9tdSpbe6XeCGKdoNzmlj0E=") - - params := types.SuggestedParams{ - Fee: fee, - FirstRoundValid: firstRound, - LastRoundValid: firstRound + 1000, - GenesisHash: genesisHash, - GenesisID: genesisID, - FlatFee: true, - } - note := byteFromBase64("8xMCTuLQ810=") - program := []byte{1, 32, 1, 1, 34} - args := make([][]byte, 2) - args[0] = []byte("123") - args[1] = []byte("456") - foreignApps := make([]uint64, 1) - foreignApps[0] = 10 - foreignAssets := foreignApps - gSchema := types.StateSchema{NumUint: uint64(1), NumByteSlice: uint64(1)} - lSchema := types.StateSchema{NumUint: uint64(1), NumByteSlice: uint64(1)} - extraPages := uint32(2) - addr := make([]string, 1) - addr[0] = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU" - boxReferences := make([]types.AppBoxReference, 3) - boxReferences[0] = types.AppBoxReference{AppID: 2, Name: []byte("box_name")} - boxReferences[1] = types.AppBoxReference{AppID: 10, Name: []byte("box_name")} - boxReferences[2] = types.AppBoxReference{AppID: 11, Name: []byte("box_name")} - - _, err := MakeApplicationCallTxWithBoxes(2, args, addr, foreignApps, foreignAssets, boxReferences, types.NoOpOC, program, program, gSchema, lSchema, extraPages, params, types.Address{}, note, types.Digest{}, [32]byte{}, types.Address{}) - require.Error(t, err, "the app id 10 provided for this box is not in the foreignApps array") -} - -func TestComputeGroupID(t *testing.T) { - // compare regular transactions created in SDK with 'goal clerk send' result - // compare transaction group created in SDK with 'goal clerk group' result - const address = "UPYAFLHSIPMJOHVXU2MPLQ46GXJKSDCEMZ6RLCQ7GWB5PRDKJUWKKXECXI" - const fromAddress, toAddress = address, address - const fee = 1000 - const amount = 2000 - const genesisID = "devnet-v1.0" - genesisHash := byteFromBase64("sC3P7e2SdbqKJK0tbiCdK9tdSpbe6XeCGKdoNzmlj0E=") - - const firstRound1 = 710399 - params1 := types.SuggestedParams{ - Fee: fee, - FirstRoundValid: firstRound1, - LastRoundValid: firstRound1 + 1000, - GenesisHash: genesisHash, - GenesisID: genesisID, - FlatFee: true, - } - note1 := byteFromBase64("wRKw5cJ0CMo=") - tx1, err := MakePaymentTxn(fromAddress, toAddress, amount, note1, "", params1) - require.NoError(t, err) - - const firstRound2 = 710515 - params2 := types.SuggestedParams{ - Fee: fee, - FirstRoundValid: firstRound2, - LastRoundValid: firstRound2 + 1000, - GenesisHash: genesisHash, - GenesisID: genesisID, - FlatFee: true, - } - note2 := byteFromBase64("dBlHI6BdrIg=") - tx2, err := MakePaymentTxn(fromAddress, toAddress, amount, note2, "", params2) - require.NoError(t, err) - - const goldenTx1 = "gaN0eG6Ko2FtdM0H0KNmZWXNA+iiZnbOAArW/6NnZW6rZGV2bmV0LXYxLjCiZ2jEILAtz+3tknW6iiStLW4gnSvbXUqW3ul3ghinaDc5pY9Bomx2zgAK2uekbm90ZcQIwRKw5cJ0CMqjcmN2xCCj8AKs8kPYlx63ppj1w5410qkMRGZ9FYofNYPXxGpNLKNzbmTEIKPwAqzyQ9iXHremmPXDnjXSqQxEZn0Vih81g9fEak0spHR5cGWjcGF5" - const goldenTx2 = "gaN0eG6Ko2FtdM0H0KNmZWXNA+iiZnbOAArXc6NnZW6rZGV2bmV0LXYxLjCiZ2jEILAtz+3tknW6iiStLW4gnSvbXUqW3ul3ghinaDc5pY9Bomx2zgAK21ukbm90ZcQIdBlHI6BdrIijcmN2xCCj8AKs8kPYlx63ppj1w5410qkMRGZ9FYofNYPXxGpNLKNzbmTEIKPwAqzyQ9iXHremmPXDnjXSqQxEZn0Vih81g9fEak0spHR5cGWjcGF5" - - // goal clerk send dumps unsigned transaction as signed with empty signature in order to save tx type - stx1 := types.SignedTxn{Sig: types.Signature{}, Msig: types.MultisigSig{}, Txn: tx1} - stx2 := types.SignedTxn{Sig: types.Signature{}, Msig: types.MultisigSig{}, Txn: tx2} - require.Equal(t, byteFromBase64(goldenTx1), msgpack.Encode(stx1)) - require.Equal(t, byteFromBase64(goldenTx2), msgpack.Encode(stx2)) - - gid, err := crypto.ComputeGroupID([]types.Transaction{tx1, tx2}) - require.NoError(t, err) - - // goal clerk group sets Group to every transaction and concatenate them in output file - // simulating that behavior here - stx1.Txn.Group = gid - stx2.Txn.Group = gid - - var txg []byte - txg = append(txg, msgpack.Encode(stx1)...) - txg = append(txg, msgpack.Encode(stx2)...) - - const goldenTxg = "gaN0eG6Lo2FtdM0H0KNmZWXNA+iiZnbOAArW/6NnZW6rZGV2bmV0LXYxLjCiZ2jEILAtz+3tknW6iiStLW4gnSvbXUqW3ul3ghinaDc5pY9Bo2dycMQgLiQ9OBup9H/bZLSfQUH2S6iHUM6FQ3PLuv9FNKyt09SibHbOAAra56Rub3RlxAjBErDlwnQIyqNyY3bEIKPwAqzyQ9iXHremmPXDnjXSqQxEZn0Vih81g9fEak0so3NuZMQgo/ACrPJD2Jcet6aY9cOeNdKpDERmfRWKHzWD18RqTSykdHlwZaNwYXmBo3R4boujYW10zQfQo2ZlZc0D6KJmds4ACtdzo2dlbqtkZXZuZXQtdjEuMKJnaMQgsC3P7e2SdbqKJK0tbiCdK9tdSpbe6XeCGKdoNzmlj0GjZ3JwxCAuJD04G6n0f9tktJ9BQfZLqIdQzoVDc8u6/0U0rK3T1KJsds4ACttbpG5vdGXECHQZRyOgXayIo3JjdsQgo/ACrPJD2Jcet6aY9cOeNdKpDERmfRWKHzWD18RqTSyjc25kxCCj8AKs8kPYlx63ppj1w5410qkMRGZ9FYofNYPXxGpNLKR0eXBlo3BheQ==" - - require.Equal(t, byteFromBase64(goldenTxg), txg) - - // check transaction.AssignGroupID, do not validate correctness of Group field calculation - result, err := AssignGroupID([]types.Transaction{tx1, tx2}, "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4") - require.NoError(t, err) - require.Equal(t, 0, len(result)) - - result, err = AssignGroupID([]types.Transaction{tx1, tx2}, address) - require.NoError(t, err) - require.Equal(t, 2, len(result)) - - result, err = AssignGroupID([]types.Transaction{tx1, tx2}, "") - require.NoError(t, err) - require.Equal(t, 2, len(result)) -} - -func TestLogicSig(t *testing.T) { - // validate LogicSig signed transaction against goal - const fromAddress = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU" - const toAddress = "PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI" - const referenceTxID = "5FJDJD5LMZC3EHUYYJNH5I23U4X6H2KXABNDGPIL557ZMJ33GZHQ" - const mn = "advice pudding treat near rule blouse same whisper inner electric quit surface sunny dismiss leader blood seat clown cost exist hospital century reform able sponsor" - const fee = 1000 - const amount = 2000 - const firstRound = 2063137 - const genesisID = "devnet-v1.0" - genesisHash := byteFromBase64("sC3P7e2SdbqKJK0tbiCdK9tdSpbe6XeCGKdoNzmlj0E=") - note := byteFromBase64("8xMCTuLQ810=") - - params := types.SuggestedParams{ - Fee: fee, - FirstRoundValid: firstRound, - LastRoundValid: firstRound + 1000, - GenesisHash: genesisHash, - GenesisID: genesisID, - FlatFee: true, - } - tx, err := MakePaymentTxn(fromAddress, toAddress, amount, note, "", params) - require.NoError(t, err) - - // goal clerk send -o tx3 -a 2000 --fee 1000 -d ~/.algorand -w test -L sig.lsig --argb64 MTIz --argb64 NDU2 \ - // -f 47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU \ - // -t PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI - const golden = "gqRsc2lng6NhcmeSxAMxMjPEAzQ1NqFsxAUBIAEBIqNzaWfEQE6HXaI5K0lcq50o/y3bWOYsyw9TLi/oorZB4xaNdn1Z14351u2f6JTON478fl+JhIP4HNRRAIh/I8EWXBPpJQ2jdHhuiqNhbXTNB9CjZmVlzQPoomZ2zgAfeyGjZ2Vuq2Rldm5ldC12MS4womdoxCCwLc/t7ZJ1uookrS1uIJ0r211Klt7pd4IYp2g3OaWPQaJsds4AH38JpG5vdGXECPMTAk7i0PNdo3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaR0eXBlo3BheQ==" - - program := []byte{1, 32, 1, 1, 34} - args := make([][]byte, 2) - args[0] = []byte("123") - args[1] = []byte("456") - key, err := mnemonic.ToPrivateKey(mn) - var pk crypto.MultisigAccount - require.NoError(t, err) - lsig, err := crypto.MakeLogicSig(program, args, key, pk) - require.NoError(t, err) - - _, stxBytes, err := crypto.SignLogicsigTransaction(lsig, tx) - require.NoError(t, err) - - require.Equal(t, byteFromBase64(golden), stxBytes) - - sender, err := types.DecodeAddress(fromAddress) - require.NoError(t, err) - - verified := crypto.VerifyLogicSig(lsig, sender) - require.True(t, verified) -} - -func TestFee(t *testing.T) { - testcases := []struct { - name string - flatFee bool - fee types.MicroAlgos - expected types.MicroAlgos - }{ - { - name: "Use flat fee", - flatFee: true, - fee: 1001, - expected: 1001, - }, - { - name: "Flat fee does not get overridden with min fee", - flatFee: true, - fee: 999, - expected: 999, - }, - { - name: "Estimated fee overridden with min fee", - flatFee: false, - fee: 1, - expected: 1000, - }, - { - name: "Flat fee set to 0", - flatFee: true, - fee: 0, - expected: 0, - }, - } - addr := types.Address{}.String() - for _, testcase := range testcases { - t.Run(testcase.name, func(t *testing.T) { - var tx types.Transaction - var err error - - params := types.SuggestedParams{ - FlatFee: testcase.flatFee, - Fee: testcase.fee, - FirstRoundValid: 1, - LastRoundValid: 1001, - GenesisHash: byteFromBase64("JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI="), - } - - tx, err = MakeAssetTransferTxn(addr, addr, 1, nil, params, "", 1) - require.NoError(t, err) - require.Equal(t, testcase.expected, tx.Fee) - - tx, err = MakeAssetAcceptanceTxn(addr, nil, params, 1) - require.NoError(t, err) - require.Equal(t, testcase.expected, tx.Fee) - - tx, err = MakeAssetRevocationTxn(addr, addr, 1, addr, nil, params, 1) - require.NoError(t, err) - require.Equal(t, testcase.expected, tx.Fee) - - tx, err = MakeAssetDestroyTxn(addr, nil, params, 1) - require.NoError(t, err) - require.Equal(t, testcase.expected, tx.Fee) - - tx, err = MakeAssetCreateTxn(addr, nil, params, 1, 1, false, addr, addr, addr, addr, "", "", "", "") - require.NoError(t, err) - require.Equal(t, testcase.expected, tx.Fee) - - tx, err = MakeAssetConfigTxn(addr, nil, params, 1, addr, addr, addr, addr, false) - require.NoError(t, err) - require.Equal(t, testcase.expected, tx.Fee) - - tx, err = MakeAssetFreezeTxn(addr, nil, params, 1, addr, true) - require.NoError(t, err) - require.Equal(t, testcase.expected, tx.Fee) - }) - } -} - -func TestParseBoxReferences(t *testing.T) { - - genWithAppId := func(appId uint64) types.AppBoxReference { - return types.AppBoxReference{appId, []byte("example")} - } - - genWithNewAppId := func() types.AppBoxReference { - return types.AppBoxReference{0, []byte("example")} - } - - t.Run("appIndexExists", func(t *testing.T) { - appId := uint64(7) - abr := genWithAppId(appId) - - brs, err := parseBoxReferences( - []types.AppBoxReference{abr}, - []uint64{1, 3, 4, appId}, - appId-1) - require.NoError(t, err) - require.Equal(t, - []types.BoxReference{{ - ForeignAppIdx: uint64(4), - Name: abr.Name}}, - brs) - }) - - t.Run("appIndexDoesNotExist", func(t *testing.T) { - appId := uint64(7) - abr := genWithAppId(appId) - - _, err := parseBoxReferences( - []types.AppBoxReference{abr}, - []uint64{1, 3, 4}, - appId-1) - require.Error(t, err) - }) - - t.Run("newAppId", func(t *testing.T) { - abr := genWithNewAppId() - - brs, err := parseBoxReferences( - []types.AppBoxReference{abr}, - []uint64{}, - uint64(1)) - require.NoError(t, err) - require.Equal(t, - []types.BoxReference{{ - ForeignAppIdx: uint64(0), - Name: abr.Name}}, - brs) - }) - - t.Run("fallbackToCurrentApp", func(t *testing.T) { - // Mirrors priority search in goal from `cmd/goal/application.go::translateBoxRefs`. - appId := uint64(7) - abr := genWithAppId(appId) - - // Prefer foreign apps index when present. - brs, err := parseBoxReferences( - []types.AppBoxReference{abr}, - []uint64{1, 3, 4, appId}, - appId) - require.NoError(t, err) - require.Equal(t, - []types.BoxReference{{ - ForeignAppIdx: uint64(4), - Name: abr.Name}}, - brs) - - // Fallback to current app when absent from foreign apps. - brs, err = parseBoxReferences( - []types.AppBoxReference{abr}, - []uint64{1, 3, 4}, - appId) - require.NoError(t, err) - require.Equal(t, - []types.BoxReference{{ - ForeignAppIdx: uint64(0), - Name: abr.Name}}, - brs) - }) -} diff --git a/logic/bundle_langspec_json.sh b/logic/bundle_langspec_json.sh deleted file mode 100755 index 82e794c8..00000000 --- a/logic/bundle_langspec_json.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -THISDIR=$(dirname $0) - -cat < $THISDIR/bundledSpecInject.go -// Code generated during build process, along with langspec.json. DO NOT EDIT. -package logic - -var langSpecJson []byte - -func init() { - langSpecJson = []byte{ - $(cat $THISDIR/langspec.json | hexdump -v -e '1/1 "0x%02X, "' | fmt) - } -} - -EOM \ No newline at end of file diff --git a/logic/bundledSpecInject.go b/logic/bundledSpecInject.go deleted file mode 100644 index 87f1bdec..00000000 --- a/logic/bundledSpecInject.go +++ /dev/null @@ -1,4036 +0,0 @@ -// Code generated during build process, along with langspec.json. DO NOT EDIT. -package logic - -var langSpecJson []byte - -func init() { - langSpecJson = []byte{ - 0x7B, 0x22, 0x45, 0x76, 0x61, 0x6C, 0x4D, 0x61, 0x78, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x36, 0x2C, 0x22, 0x4C, - 0x6F, 0x67, 0x69, 0x63, 0x53, 0x69, 0x67, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6F, 0x6E, 0x22, 0x3A, 0x36, 0x2C, 0x22, 0x4F, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, - 0x22, 0x3A, 0x30, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x65, 0x72, 0x72, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x46, 0x61, - 0x69, 0x6C, 0x20, 0x69, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, - 0x65, 0x6C, 0x79, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x46, 0x6C, 0x6F, 0x77, 0x20, - 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x73, 0x68, - 0x61, 0x32, 0x35, 0x36, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, - 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, - 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x33, 0x35, 0x2C, 0x22, 0x53, 0x69, - 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, - 0x3A, 0x22, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x20, 0x68, 0x61, - 0x73, 0x68, 0x20, 0x6F, 0x66, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, - 0x20, 0x41, 0x2C, 0x20, 0x79, 0x69, 0x65, 0x6C, 0x64, 0x73, 0x20, - 0x5B, 0x33, 0x32, 0x5D, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x22, - 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, - 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x32, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, - 0x6B, 0x65, 0x63, 0x63, 0x61, 0x6B, 0x32, 0x35, 0x36, 0x22, 0x2C, - 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x33, 0x30, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x4B, 0x65, 0x63, - 0x63, 0x61, 0x6B, 0x32, 0x35, 0x36, 0x20, 0x68, 0x61, 0x73, 0x68, - 0x20, 0x6F, 0x66, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x41, - 0x2C, 0x20, 0x79, 0x69, 0x65, 0x6C, 0x64, 0x73, 0x20, 0x5B, 0x33, - 0x32, 0x5D, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, - 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x33, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x73, 0x68, - 0x61, 0x35, 0x31, 0x32, 0x5F, 0x32, 0x35, 0x36, 0x22, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, - 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, - 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x34, 0x35, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x53, 0x48, 0x41, 0x35, 0x31, - 0x32, 0x5F, 0x32, 0x35, 0x36, 0x20, 0x68, 0x61, 0x73, 0x68, 0x20, - 0x6F, 0x66, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x41, 0x2C, - 0x20, 0x79, 0x69, 0x65, 0x6C, 0x64, 0x73, 0x20, 0x5B, 0x33, 0x32, - 0x5D, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, - 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, - 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, - 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x34, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x65, 0x64, 0x32, - 0x35, 0x35, 0x31, 0x39, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x22, - 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, - 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, - 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x39, 0x30, 0x30, 0x2C, 0x22, 0x53, 0x69, 0x7A, - 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, - 0x22, 0x66, 0x6F, 0x72, 0x20, 0x28, 0x64, 0x61, 0x74, 0x61, 0x20, - 0x41, 0x2C, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x20, 0x42, 0x2C, 0x20, 0x70, 0x75, 0x62, 0x6B, 0x65, 0x79, - 0x20, 0x43, 0x29, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x28, 0x5C, 0x22, 0x50, 0x72, - 0x6F, 0x67, 0x44, 0x61, 0x74, 0x61, 0x5C, 0x22, 0x20, 0x7C, 0x7C, - 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x5F, 0x68, 0x61, - 0x73, 0x68, 0x20, 0x7C, 0x7C, 0x20, 0x64, 0x61, 0x74, 0x61, 0x29, - 0x20, 0x61, 0x67, 0x61, 0x69, 0x6E, 0x73, 0x74, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x70, 0x75, 0x62, 0x6B, 0x65, 0x79, 0x20, 0x3D, 0x5C, - 0x75, 0x30, 0x30, 0x33, 0x65, 0x20, 0x7B, 0x30, 0x20, 0x6F, 0x72, - 0x20, 0x31, 0x7D, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, - 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x54, 0x68, 0x65, 0x20, 0x33, - 0x32, 0x20, 0x62, 0x79, 0x74, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6C, - 0x69, 0x63, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x69, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x6C, 0x61, 0x73, 0x74, 0x20, 0x65, 0x6C, 0x65, - 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x6F, 0x6E, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x2C, 0x20, 0x70, 0x72, 0x65, - 0x63, 0x65, 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x36, 0x34, 0x20, 0x62, 0x79, 0x74, 0x65, 0x20, 0x73, - 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x74, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6F, 0x6E, 0x64, - 0x2D, 0x74, 0x6F, 0x2D, 0x6C, 0x61, 0x73, 0x74, 0x20, 0x65, 0x6C, - 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x6F, 0x6E, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x2C, 0x20, 0x70, 0x72, - 0x65, 0x63, 0x65, 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x77, 0x68, 0x69, - 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x69, 0x67, 0x6E, - 0x65, 0x64, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, - 0x68, 0x69, 0x72, 0x64, 0x2D, 0x74, 0x6F, 0x2D, 0x6C, 0x61, 0x73, - 0x74, 0x20, 0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x6F, - 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6B, - 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, - 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, - 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x35, 0x2C, 0x22, 0x4E, 0x61, 0x6D, - 0x65, 0x22, 0x3A, 0x22, 0x65, 0x63, 0x64, 0x73, 0x61, 0x5F, 0x76, - 0x65, 0x72, 0x69, 0x66, 0x79, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, - 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, 0x42, 0x42, 0x42, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x37, 0x30, 0x30, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x32, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x66, 0x6F, - 0x72, 0x20, 0x28, 0x64, 0x61, 0x74, 0x61, 0x20, 0x41, 0x2C, 0x20, - 0x73, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x42, - 0x2C, 0x20, 0x43, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x70, 0x75, 0x62, - 0x6B, 0x65, 0x79, 0x20, 0x44, 0x2C, 0x20, 0x45, 0x29, 0x20, 0x76, - 0x65, 0x72, 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, - 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x6F, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x61, - 0x67, 0x61, 0x69, 0x6E, 0x73, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x70, 0x75, 0x62, 0x6B, 0x65, 0x79, 0x20, 0x3D, 0x5C, 0x75, 0x30, - 0x30, 0x33, 0x65, 0x20, 0x7B, 0x30, 0x20, 0x6F, 0x72, 0x20, 0x31, - 0x7D, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, - 0x61, 0x22, 0x3A, 0x22, 0x54, 0x68, 0x65, 0x20, 0x33, 0x32, 0x20, - 0x62, 0x79, 0x74, 0x65, 0x20, 0x59, 0x2D, 0x63, 0x6F, 0x6D, 0x70, - 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x20, 0x6F, 0x66, 0x20, 0x61, 0x20, - 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x6B, 0x65, 0x79, 0x20, - 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6C, 0x61, 0x73, 0x74, - 0x20, 0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x6F, 0x6E, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x2C, - 0x20, 0x70, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x64, 0x20, 0x62, - 0x79, 0x20, 0x58, 0x2D, 0x63, 0x6F, 0x6D, 0x70, 0x6F, 0x6E, 0x65, - 0x6E, 0x74, 0x20, 0x6F, 0x66, 0x20, 0x61, 0x20, 0x70, 0x75, 0x62, - 0x6B, 0x65, 0x79, 0x2C, 0x20, 0x70, 0x72, 0x65, 0x63, 0x65, 0x64, - 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x53, 0x20, 0x61, 0x6E, 0x64, - 0x20, 0x52, 0x20, 0x63, 0x6F, 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, - 0x74, 0x73, 0x20, 0x6F, 0x66, 0x20, 0x61, 0x20, 0x73, 0x69, 0x67, - 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2C, 0x20, 0x70, 0x72, 0x65, - 0x63, 0x65, 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x68, 0x61, 0x74, - 0x20, 0x69, 0x73, 0x20, 0x66, 0x69, 0x66, 0x74, 0x68, 0x20, 0x65, - 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x6F, 0x6E, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x2E, 0x20, 0x41, - 0x6C, 0x6C, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x20, 0x61, - 0x72, 0x65, 0x20, 0x62, 0x69, 0x67, 0x2D, 0x65, 0x6E, 0x64, 0x69, - 0x61, 0x6E, 0x20, 0x65, 0x6E, 0x63, 0x6F, 0x64, 0x65, 0x64, 0x2E, - 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, - 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x6D, 0x75, 0x73, 0x74, 0x20, - 0x62, 0x65, 0x20, 0x33, 0x32, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, - 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2C, 0x20, 0x61, 0x6E, 0x64, 0x20, - 0x73, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x20, - 0x69, 0x6E, 0x20, 0x6C, 0x6F, 0x77, 0x65, 0x72, 0x2D, 0x53, 0x20, - 0x66, 0x6F, 0x72, 0x6D, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6F, 0x6E, - 0x6C, 0x79, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, - 0x2E, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, - 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, - 0x69, 0x6E, 0x74, 0x38, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, - 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, - 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x36, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x65, 0x63, - 0x64, 0x73, 0x61, 0x5F, 0x70, 0x6B, 0x5F, 0x64, 0x65, 0x63, 0x6F, - 0x6D, 0x70, 0x72, 0x65, 0x73, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, - 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x36, 0x35, 0x30, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x64, 0x65, 0x63, 0x6F, 0x6D, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x70, 0x75, 0x62, 0x6B, 0x65, - 0x79, 0x20, 0x41, 0x20, 0x69, 0x6E, 0x74, 0x6F, 0x20, 0x63, 0x6F, - 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x73, 0x20, 0x58, 0x2C, - 0x20, 0x59, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, - 0x72, 0x61, 0x22, 0x3A, 0x22, 0x54, 0x68, 0x65, 0x20, 0x33, 0x33, - 0x20, 0x62, 0x79, 0x74, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6C, 0x69, - 0x63, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x69, 0x6E, 0x20, 0x61, 0x20, - 0x63, 0x6F, 0x6D, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, - 0x66, 0x6F, 0x72, 0x6D, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x65, 0x20, - 0x64, 0x65, 0x63, 0x6F, 0x6D, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, - 0x64, 0x20, 0x69, 0x6E, 0x74, 0x6F, 0x20, 0x58, 0x20, 0x61, 0x6E, - 0x64, 0x20, 0x59, 0x20, 0x28, 0x74, 0x6F, 0x70, 0x29, 0x20, 0x63, - 0x6F, 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x73, 0x2E, 0x20, - 0x41, 0x6C, 0x6C, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x20, - 0x61, 0x72, 0x65, 0x20, 0x62, 0x69, 0x67, 0x2D, 0x65, 0x6E, 0x64, - 0x69, 0x61, 0x6E, 0x20, 0x65, 0x6E, 0x63, 0x6F, 0x64, 0x65, 0x64, - 0x2E, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, - 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, - 0x69, 0x6E, 0x74, 0x38, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, - 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, - 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x37, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x65, 0x63, - 0x64, 0x73, 0x61, 0x5F, 0x70, 0x6B, 0x5F, 0x72, 0x65, 0x63, 0x6F, - 0x76, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x55, 0x42, 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, - 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x32, 0x30, 0x30, - 0x30, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x32, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x66, 0x6F, 0x72, 0x20, - 0x28, 0x64, 0x61, 0x74, 0x61, 0x20, 0x41, 0x2C, 0x20, 0x72, 0x65, - 0x63, 0x6F, 0x76, 0x65, 0x72, 0x79, 0x20, 0x69, 0x64, 0x20, 0x42, - 0x2C, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x20, 0x43, 0x2C, 0x20, 0x44, 0x29, 0x20, 0x72, 0x65, 0x63, 0x6F, - 0x76, 0x65, 0x72, 0x20, 0x61, 0x20, 0x70, 0x75, 0x62, 0x6C, 0x69, - 0x63, 0x20, 0x6B, 0x65, 0x79, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, - 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x53, 0x20, 0x28, - 0x74, 0x6F, 0x70, 0x29, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x20, - 0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x73, 0x20, 0x6F, 0x66, - 0x20, 0x61, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x2C, 0x20, 0x72, 0x65, 0x63, 0x6F, 0x76, 0x65, 0x72, 0x79, - 0x20, 0x69, 0x64, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x64, 0x61, 0x74, - 0x61, 0x20, 0x28, 0x62, 0x6F, 0x74, 0x74, 0x6F, 0x6D, 0x29, 0x20, - 0x61, 0x72, 0x65, 0x20, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x20, 0x6F, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, - 0x61, 0x63, 0x6B, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x75, 0x73, 0x65, - 0x64, 0x20, 0x74, 0x6F, 0x20, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, - 0x72, 0x20, 0x61, 0x20, 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, - 0x6B, 0x65, 0x79, 0x2E, 0x20, 0x41, 0x6C, 0x6C, 0x20, 0x76, 0x61, - 0x6C, 0x75, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x62, 0x69, - 0x67, 0x2D, 0x65, 0x6E, 0x64, 0x69, 0x61, 0x6E, 0x20, 0x65, 0x6E, - 0x63, 0x6F, 0x64, 0x65, 0x64, 0x2E, 0x20, 0x54, 0x68, 0x65, 0x20, - 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61, - 0x20, 0x6D, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x33, 0x32, - 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, - 0x2E, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, - 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, - 0x69, 0x6E, 0x74, 0x38, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, - 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, - 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x38, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x2B, 0x22, - 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, - 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, - 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, - 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x70, - 0x6C, 0x75, 0x73, 0x20, 0x42, 0x2E, 0x20, 0x46, 0x61, 0x69, 0x6C, - 0x20, 0x6F, 0x6E, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, - 0x77, 0x2E, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, - 0x72, 0x61, 0x22, 0x3A, 0x22, 0x4F, 0x76, 0x65, 0x72, 0x66, 0x6C, - 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6E, 0x20, 0x65, 0x72, - 0x72, 0x6F, 0x72, 0x20, 0x63, 0x6F, 0x6E, 0x64, 0x69, 0x74, 0x69, - 0x6F, 0x6E, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x61, - 0x6C, 0x74, 0x73, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6F, 0x6E, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x66, 0x61, 0x69, 0x6C, - 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x20, 0x46, 0x75, 0x6C, - 0x6C, 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E, - 0x20, 0x69, 0x73, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, - 0x6C, 0x65, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x60, 0x61, 0x64, - 0x64, 0x77, 0x60, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, - 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x39, 0x2C, 0x22, - 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x2D, 0x22, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x6D, 0x69, 0x6E, - 0x75, 0x73, 0x20, 0x42, 0x2E, 0x20, 0x46, 0x61, 0x69, 0x6C, 0x20, - 0x69, 0x66, 0x20, 0x42, 0x20, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x65, - 0x20, 0x41, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, - 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, - 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, - 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x30, 0x2C, 0x22, - 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x2F, 0x22, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x64, 0x69, 0x76, - 0x69, 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x42, 0x20, 0x28, - 0x74, 0x72, 0x75, 0x6E, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x64, - 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x29, 0x2E, 0x20, 0x46, - 0x61, 0x69, 0x6C, 0x20, 0x69, 0x66, 0x20, 0x42, 0x20, 0x3D, 0x3D, - 0x20, 0x30, 0x2E, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, - 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x60, 0x64, 0x69, 0x76, 0x6D, - 0x6F, 0x64, 0x77, 0x60, 0x20, 0x69, 0x73, 0x20, 0x61, 0x76, 0x61, - 0x69, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x64, - 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, - 0x77, 0x6F, 0x2D, 0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, - 0x76, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x64, - 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x60, 0x6D, 0x75, - 0x6C, 0x77, 0x60, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x60, 0x61, 0x64, - 0x64, 0x77, 0x60, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, - 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x31, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x2A, 0x22, 0x2C, - 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, - 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, - 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x74, 0x69, - 0x6D, 0x65, 0x73, 0x20, 0x42, 0x2E, 0x20, 0x46, 0x61, 0x69, 0x6C, - 0x20, 0x6F, 0x6E, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, - 0x77, 0x2E, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, - 0x72, 0x61, 0x22, 0x3A, 0x22, 0x4F, 0x76, 0x65, 0x72, 0x66, 0x6C, - 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6E, 0x20, 0x65, 0x72, - 0x72, 0x6F, 0x72, 0x20, 0x63, 0x6F, 0x6E, 0x64, 0x69, 0x74, 0x69, - 0x6F, 0x6E, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x61, - 0x6C, 0x74, 0x73, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6F, 0x6E, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x66, 0x61, 0x69, 0x6C, - 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x20, 0x46, 0x75, 0x6C, - 0x6C, 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E, - 0x20, 0x69, 0x73, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, - 0x6C, 0x65, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x60, 0x6D, 0x75, - 0x6C, 0x77, 0x60, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, - 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x32, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x5C, 0x75, 0x30, - 0x30, 0x33, 0x63, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, - 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, - 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, - 0x22, 0x41, 0x20, 0x6C, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x61, - 0x6E, 0x20, 0x42, 0x20, 0x3D, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x65, - 0x20, 0x7B, 0x30, 0x20, 0x6F, 0x72, 0x20, 0x31, 0x7D, 0x22, 0x2C, - 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, - 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, - 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, - 0x22, 0x3A, 0x31, 0x33, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x65, 0x22, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x67, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x42, - 0x20, 0x3D, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x65, 0x20, 0x7B, 0x30, - 0x20, 0x6F, 0x72, 0x20, 0x31, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, - 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, - 0x34, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x5C, - 0x75, 0x30, 0x30, 0x33, 0x63, 0x3D, 0x22, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x6C, 0x65, 0x73, 0x73, 0x20, - 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x72, 0x20, 0x65, 0x71, 0x75, - 0x61, 0x6C, 0x20, 0x74, 0x6F, 0x20, 0x42, 0x20, 0x3D, 0x5C, 0x75, - 0x30, 0x30, 0x33, 0x65, 0x20, 0x7B, 0x30, 0x20, 0x6F, 0x72, 0x20, - 0x31, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, - 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, - 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x35, 0x2C, 0x22, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x5C, 0x75, 0x30, 0x30, 0x33, - 0x65, 0x3D, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, - 0x22, 0x55, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x41, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x74, - 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x72, 0x20, 0x65, 0x71, 0x75, 0x61, - 0x6C, 0x20, 0x74, 0x6F, 0x20, 0x42, 0x20, 0x3D, 0x5C, 0x75, 0x30, - 0x30, 0x33, 0x65, 0x20, 0x7B, 0x30, 0x20, 0x6F, 0x72, 0x20, 0x31, - 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, - 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, - 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x36, 0x2C, 0x22, 0x4E, 0x61, - 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x5C, 0x75, 0x30, 0x30, 0x32, 0x36, - 0x5C, 0x75, 0x30, 0x30, 0x32, 0x36, 0x22, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, - 0x74, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x20, 0x61, 0x6E, 0x64, 0x20, - 0x42, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x7A, 0x65, - 0x72, 0x6F, 0x20, 0x3D, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x65, 0x20, - 0x7B, 0x30, 0x20, 0x6F, 0x72, 0x20, 0x31, 0x7D, 0x22, 0x2C, 0x22, - 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, - 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x31, 0x37, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x7C, 0x7C, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, - 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, - 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, - 0x22, 0x41, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x7A, - 0x65, 0x72, 0x6F, 0x20, 0x6F, 0x72, 0x20, 0x42, 0x20, 0x69, 0x73, - 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x20, 0x3D, - 0x5C, 0x75, 0x30, 0x30, 0x33, 0x65, 0x20, 0x7B, 0x30, 0x20, 0x6F, - 0x72, 0x20, 0x31, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, - 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x38, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x3D, 0x3D, 0x22, - 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x2E, - 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, - 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, - 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x69, - 0x73, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6C, 0x20, 0x74, 0x6F, 0x20, - 0x42, 0x20, 0x3D, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x65, 0x20, 0x7B, - 0x30, 0x20, 0x6F, 0x72, 0x20, 0x31, 0x7D, 0x22, 0x2C, 0x22, 0x47, - 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, - 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x31, 0x39, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, - 0x21, 0x3D, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, - 0x22, 0x2E, 0x2E, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x41, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x65, 0x71, - 0x75, 0x61, 0x6C, 0x20, 0x74, 0x6F, 0x20, 0x42, 0x20, 0x3D, 0x5C, - 0x75, 0x30, 0x30, 0x33, 0x65, 0x20, 0x7B, 0x30, 0x20, 0x6F, 0x72, - 0x20, 0x31, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, - 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, - 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, - 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x32, 0x30, 0x2C, 0x22, - 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x21, 0x22, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, - 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, - 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, - 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x3D, 0x3D, 0x20, 0x30, - 0x20, 0x79, 0x69, 0x65, 0x6C, 0x64, 0x73, 0x20, 0x31, 0x3B, 0x20, - 0x65, 0x6C, 0x73, 0x65, 0x20, 0x30, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, - 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x32, - 0x31, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x6C, - 0x65, 0x6E, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, - 0x22, 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, - 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, - 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, - 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x79, - 0x69, 0x65, 0x6C, 0x64, 0x73, 0x20, 0x6C, 0x65, 0x6E, 0x67, 0x74, - 0x68, 0x20, 0x6F, 0x66, 0x20, 0x62, 0x79, 0x74, 0x65, 0x20, 0x76, - 0x61, 0x6C, 0x75, 0x65, 0x20, 0x41, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, - 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x32, - 0x32, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x69, - 0x74, 0x6F, 0x62, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x63, 0x6F, 0x6E, 0x76, 0x65, 0x72, 0x74, 0x73, 0x20, 0x75, 0x69, - 0x6E, 0x74, 0x36, 0x34, 0x20, 0x41, 0x20, 0x74, 0x6F, 0x20, 0x62, - 0x69, 0x67, 0x20, 0x65, 0x6E, 0x64, 0x69, 0x61, 0x6E, 0x20, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, - 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x32, 0x33, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x62, 0x74, 0x6F, - 0x69, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, - 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, - 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x63, 0x6F, - 0x6E, 0x76, 0x65, 0x72, 0x74, 0x73, 0x20, 0x62, 0x79, 0x74, 0x65, - 0x73, 0x20, 0x41, 0x20, 0x61, 0x73, 0x20, 0x62, 0x69, 0x67, 0x20, - 0x65, 0x6E, 0x64, 0x69, 0x61, 0x6E, 0x20, 0x74, 0x6F, 0x20, 0x75, - 0x69, 0x6E, 0x74, 0x36, 0x34, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, - 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x60, 0x62, 0x74, - 0x6F, 0x69, 0x60, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x73, 0x20, 0x69, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6E, 0x70, 0x75, 0x74, - 0x20, 0x69, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x65, 0x72, 0x20, - 0x74, 0x68, 0x61, 0x6E, 0x20, 0x38, 0x20, 0x62, 0x79, 0x74, 0x65, - 0x73, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, - 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, - 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x32, 0x34, 0x2C, 0x22, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x25, 0x22, 0x2C, 0x22, 0x41, - 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, 0x22, - 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, - 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, - 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x6D, 0x6F, 0x64, 0x75, - 0x6C, 0x6F, 0x20, 0x42, 0x2E, 0x20, 0x46, 0x61, 0x69, 0x6C, 0x20, - 0x69, 0x66, 0x20, 0x42, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x2E, 0x22, - 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, - 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, - 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, - 0x65, 0x22, 0x3A, 0x32, 0x35, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, - 0x22, 0x3A, 0x22, 0x7C, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, - 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, - 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, - 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, - 0x3A, 0x22, 0x41, 0x20, 0x62, 0x69, 0x74, 0x77, 0x69, 0x73, 0x65, - 0x2D, 0x6F, 0x72, 0x20, 0x42, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, - 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, - 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, - 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x32, 0x36, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x5C, 0x75, - 0x30, 0x30, 0x32, 0x36, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, - 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, - 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, - 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, - 0x3A, 0x22, 0x41, 0x20, 0x62, 0x69, 0x74, 0x77, 0x69, 0x73, 0x65, - 0x2D, 0x61, 0x6E, 0x64, 0x20, 0x42, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, - 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x32, - 0x37, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x5E, - 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, - 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, - 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, - 0x62, 0x69, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2D, 0x78, 0x6F, 0x72, - 0x20, 0x42, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, - 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, - 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x32, 0x38, 0x2C, 0x22, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x7E, 0x22, 0x2C, 0x22, 0x41, - 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x62, 0x69, 0x74, 0x77, 0x69, 0x73, 0x65, - 0x20, 0x69, 0x6E, 0x76, 0x65, 0x72, 0x74, 0x20, 0x76, 0x61, 0x6C, - 0x75, 0x65, 0x20, 0x41, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, - 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x32, 0x39, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x75, 0x6C, - 0x77, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, - 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x41, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x73, 0x20, 0x42, 0x20, 0x61, - 0x73, 0x20, 0x61, 0x20, 0x31, 0x32, 0x38, 0x2D, 0x62, 0x69, 0x74, - 0x20, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x20, 0x69, 0x6E, 0x20, - 0x74, 0x77, 0x6F, 0x20, 0x75, 0x69, 0x6E, 0x74, 0x36, 0x34, 0x73, - 0x2E, 0x20, 0x58, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x68, 0x69, 0x67, 0x68, 0x20, 0x36, 0x34, 0x20, 0x62, 0x69, 0x74, - 0x73, 0x2C, 0x20, 0x59, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x6C, 0x6F, 0x77, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, - 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x33, 0x30, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x61, 0x64, 0x64, - 0x77, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, - 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x41, 0x20, 0x70, 0x6C, 0x75, 0x73, 0x20, 0x42, 0x20, 0x61, 0x73, - 0x20, 0x61, 0x20, 0x31, 0x32, 0x38, 0x2D, 0x62, 0x69, 0x74, 0x20, - 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x2E, 0x20, 0x58, 0x20, 0x69, - 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x72, 0x72, 0x79, - 0x2D, 0x62, 0x69, 0x74, 0x2C, 0x20, 0x59, 0x20, 0x69, 0x73, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x6C, 0x6F, 0x77, 0x2D, 0x6F, 0x72, 0x64, - 0x65, 0x72, 0x20, 0x36, 0x34, 0x20, 0x62, 0x69, 0x74, 0x73, 0x2E, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, - 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, - 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, - 0x64, 0x65, 0x22, 0x3A, 0x33, 0x31, 0x2C, 0x22, 0x4E, 0x61, 0x6D, - 0x65, 0x22, 0x3A, 0x22, 0x64, 0x69, 0x76, 0x6D, 0x6F, 0x64, 0x77, - 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, - 0x55, 0x55, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x55, 0x55, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x32, 0x30, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x57, 0x2C, 0x58, 0x20, 0x3D, 0x20, 0x28, - 0x41, 0x2C, 0x42, 0x20, 0x2F, 0x20, 0x43, 0x2C, 0x44, 0x29, 0x3B, - 0x20, 0x59, 0x2C, 0x5A, 0x20, 0x3D, 0x20, 0x28, 0x41, 0x2C, 0x42, - 0x20, 0x6D, 0x6F, 0x64, 0x75, 0x6C, 0x6F, 0x20, 0x43, 0x2C, 0x44, - 0x29, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, - 0x61, 0x22, 0x3A, 0x22, 0x54, 0x68, 0x65, 0x20, 0x6E, 0x6F, 0x74, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x4A, 0x2C, 0x4B, 0x20, 0x69, - 0x6E, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, 0x68, - 0x61, 0x74, 0x20, 0x74, 0x77, 0x6F, 0x20, 0x75, 0x69, 0x6E, 0x74, - 0x36, 0x34, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x20, 0x4A, - 0x20, 0x61, 0x6E, 0x64, 0x20, 0x4B, 0x20, 0x61, 0x72, 0x65, 0x20, - 0x69, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, - 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x75, 0x69, 0x6E, 0x74, 0x31, - 0x32, 0x38, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x2C, 0x20, 0x77, - 0x69, 0x74, 0x68, 0x20, 0x4A, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, 0x75, 0x69, 0x6E, 0x74, - 0x36, 0x34, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x4B, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x6C, 0x6F, 0x77, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, - 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x33, - 0x32, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x69, - 0x6E, 0x74, 0x63, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, - 0x7A, 0x65, 0x22, 0x3A, 0x30, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, - 0x3A, 0x22, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x20, 0x62, - 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6F, 0x66, 0x20, 0x75, 0x69, 0x6E, - 0x74, 0x36, 0x34, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, - 0x74, 0x73, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x75, 0x73, 0x65, 0x20, - 0x62, 0x79, 0x20, 0x69, 0x6E, 0x74, 0x63, 0x22, 0x2C, 0x22, 0x44, - 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x60, - 0x69, 0x6E, 0x74, 0x63, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x60, 0x20, - 0x6C, 0x6F, 0x61, 0x64, 0x73, 0x20, 0x66, 0x6F, 0x6C, 0x6C, 0x6F, - 0x77, 0x69, 0x6E, 0x67, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, - 0x6D, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x69, 0x6E, 0x74, - 0x6F, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, - 0x6F, 0x66, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x20, - 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x73, 0x20, 0x69, - 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x61, 0x6C, 0x75, - 0x61, 0x74, 0x6F, 0x72, 0x2E, 0x20, 0x54, 0x68, 0x65, 0x73, 0x65, - 0x20, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x20, 0x63, 0x6F, - 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x73, 0x20, 0x63, 0x61, 0x6E, - 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, - 0x64, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x79, 0x20, 0x60, 0x69, 0x6E, - 0x74, 0x63, 0x60, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x60, 0x69, 0x6E, - 0x74, 0x63, 0x5F, 0x2A, 0x60, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, - 0x20, 0x77, 0x69, 0x6C, 0x6C, 0x20, 0x70, 0x75, 0x73, 0x68, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x6F, - 0x6E, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, - 0x63, 0x6B, 0x2E, 0x20, 0x53, 0x75, 0x62, 0x73, 0x65, 0x71, 0x75, - 0x65, 0x6E, 0x74, 0x20, 0x63, 0x61, 0x6C, 0x6C, 0x73, 0x20, 0x74, - 0x6F, 0x20, 0x60, 0x69, 0x6E, 0x74, 0x63, 0x62, 0x6C, 0x6F, 0x63, - 0x6B, 0x60, 0x20, 0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x61, 0x6E, - 0x64, 0x20, 0x72, 0x65, 0x70, 0x6C, 0x61, 0x63, 0x65, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x20, - 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x73, 0x20, 0x61, - 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x74, 0x6F, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x2E, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, - 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x76, - 0x61, 0x72, 0x75, 0x69, 0x6E, 0x74, 0x20, 0x6C, 0x65, 0x6E, 0x67, - 0x74, 0x68, 0x7D, 0x20, 0x5B, 0x7B, 0x76, 0x61, 0x72, 0x75, 0x69, - 0x6E, 0x74, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x7D, 0x2C, 0x20, - 0x2E, 0x2E, 0x2E, 0x5D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, - 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x33, 0x33, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x69, 0x6E, 0x74, 0x63, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, - 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, - 0x7A, 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, - 0x3A, 0x22, 0x49, 0x74, 0x68, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, - 0x61, 0x6E, 0x74, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x69, 0x6E, - 0x74, 0x63, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x22, 0x2C, 0x22, 0x49, - 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, - 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, - 0x69, 0x6E, 0x74, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, - 0x74, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, - 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, - 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, - 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, - 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x33, 0x34, 0x2C, 0x22, 0x4E, 0x61, - 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x69, 0x6E, 0x74, 0x63, 0x5F, 0x30, - 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, - 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, - 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x63, 0x6F, 0x6E, - 0x73, 0x74, 0x61, 0x6E, 0x74, 0x20, 0x30, 0x20, 0x66, 0x72, 0x6F, - 0x6D, 0x20, 0x69, 0x6E, 0x74, 0x63, 0x62, 0x6C, 0x6F, 0x63, 0x6B, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, - 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, - 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x33, 0x35, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x69, 0x6E, 0x74, - 0x63, 0x5F, 0x31, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x20, 0x31, 0x20, - 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x69, 0x6E, 0x74, 0x63, 0x62, 0x6C, - 0x6F, 0x63, 0x6B, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, - 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, - 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x33, 0x36, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, - 0x69, 0x6E, 0x74, 0x63, 0x5F, 0x32, 0x22, 0x2C, 0x22, 0x52, 0x65, - 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, - 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, - 0x22, 0x3A, 0x22, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, - 0x20, 0x32, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x69, 0x6E, 0x74, - 0x63, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, - 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, - 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, - 0x65, 0x22, 0x3A, 0x33, 0x37, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, - 0x22, 0x3A, 0x22, 0x69, 0x6E, 0x74, 0x63, 0x5F, 0x33, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x63, 0x6F, 0x6E, 0x73, 0x74, - 0x61, 0x6E, 0x74, 0x20, 0x33, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, - 0x69, 0x6E, 0x74, 0x63, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x22, 0x2C, - 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, - 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, - 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, - 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x33, 0x38, 0x2C, 0x22, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x62, 0x79, 0x74, 0x65, 0x63, - 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, - 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, - 0x3A, 0x30, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x70, - 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x20, 0x62, 0x6C, 0x6F, 0x63, - 0x6B, 0x20, 0x6F, 0x66, 0x20, 0x62, 0x79, 0x74, 0x65, 0x2D, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, - 0x6E, 0x74, 0x73, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x75, 0x73, 0x65, - 0x20, 0x62, 0x79, 0x20, 0x62, 0x79, 0x74, 0x65, 0x63, 0x22, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, - 0x22, 0x60, 0x62, 0x79, 0x74, 0x65, 0x63, 0x62, 0x6C, 0x6F, 0x63, - 0x6B, 0x60, 0x20, 0x6C, 0x6F, 0x61, 0x64, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x66, 0x6F, 0x6C, 0x6C, 0x6F, 0x77, 0x69, 0x6E, 0x67, - 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x62, 0x79, - 0x74, 0x65, 0x73, 0x20, 0x69, 0x6E, 0x74, 0x6F, 0x20, 0x61, 0x6E, - 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6F, 0x66, 0x20, 0x62, - 0x79, 0x74, 0x65, 0x2D, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x63, - 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x73, 0x20, 0x69, 0x6E, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x61, 0x6C, 0x75, 0x61, - 0x74, 0x6F, 0x72, 0x2E, 0x20, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, - 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x73, 0x20, 0x63, - 0x61, 0x6E, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x72, 0x65, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x79, 0x20, 0x60, - 0x62, 0x79, 0x74, 0x65, 0x63, 0x60, 0x20, 0x61, 0x6E, 0x64, 0x20, - 0x60, 0x62, 0x79, 0x74, 0x65, 0x63, 0x5F, 0x2A, 0x60, 0x20, 0x77, - 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x69, 0x6C, 0x6C, 0x20, 0x70, - 0x75, 0x73, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6C, - 0x75, 0x65, 0x20, 0x6F, 0x6E, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x2E, 0x20, 0x53, 0x75, 0x62, - 0x73, 0x65, 0x71, 0x75, 0x65, 0x6E, 0x74, 0x20, 0x63, 0x61, 0x6C, - 0x6C, 0x73, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x62, 0x79, 0x74, 0x65, - 0x63, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x60, 0x20, 0x72, 0x65, 0x73, - 0x65, 0x74, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, 0x65, 0x70, 0x6C, - 0x61, 0x63, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x79, 0x74, - 0x65, 0x73, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, - 0x73, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, 0x6C, 0x65, - 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x2E, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, - 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, - 0x22, 0x7B, 0x76, 0x61, 0x72, 0x75, 0x69, 0x6E, 0x74, 0x20, 0x6C, - 0x65, 0x6E, 0x67, 0x74, 0x68, 0x7D, 0x20, 0x5B, 0x28, 0x7B, 0x76, - 0x61, 0x72, 0x75, 0x69, 0x6E, 0x74, 0x20, 0x76, 0x61, 0x6C, 0x75, - 0x65, 0x20, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x7D, 0x20, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x29, 0x2C, 0x20, 0x2E, 0x2E, 0x2E, 0x5D, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, - 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, - 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x33, 0x39, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x63, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, - 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, - 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, - 0x3A, 0x32, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x49, - 0x74, 0x68, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, - 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x62, 0x79, 0x74, 0x65, 0x63, - 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, - 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, - 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x62, 0x79, - 0x74, 0x65, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, - 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, - 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, - 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, - 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, - 0x64, 0x65, 0x22, 0x3A, 0x34, 0x30, 0x2C, 0x22, 0x4E, 0x61, 0x6D, - 0x65, 0x22, 0x3A, 0x22, 0x62, 0x79, 0x74, 0x65, 0x63, 0x5F, 0x30, - 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, - 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x63, 0x6F, 0x6E, - 0x73, 0x74, 0x61, 0x6E, 0x74, 0x20, 0x30, 0x20, 0x66, 0x72, 0x6F, - 0x6D, 0x20, 0x62, 0x79, 0x74, 0x65, 0x63, 0x62, 0x6C, 0x6F, 0x63, - 0x6B, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, - 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, - 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x34, 0x31, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x63, 0x5F, 0x31, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, - 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, - 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, - 0x3A, 0x22, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x20, - 0x31, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x62, 0x79, 0x74, 0x65, - 0x63, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, - 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, - 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, - 0x65, 0x22, 0x3A, 0x34, 0x32, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, - 0x22, 0x3A, 0x22, 0x62, 0x79, 0x74, 0x65, 0x63, 0x5F, 0x32, 0x22, - 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, - 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x63, 0x6F, 0x6E, 0x73, - 0x74, 0x61, 0x6E, 0x74, 0x20, 0x32, 0x20, 0x66, 0x72, 0x6F, 0x6D, - 0x20, 0x62, 0x79, 0x74, 0x65, 0x63, 0x62, 0x6C, 0x6F, 0x63, 0x6B, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, - 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, - 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x34, 0x33, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x63, 0x5F, 0x33, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, - 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, - 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, - 0x22, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x20, 0x33, - 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x62, 0x79, 0x74, 0x65, 0x63, - 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, - 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, - 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, - 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, - 0x22, 0x3A, 0x34, 0x34, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x61, 0x72, 0x67, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, - 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, - 0x7A, 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, - 0x3A, 0x22, 0x4E, 0x74, 0x68, 0x20, 0x4C, 0x6F, 0x67, 0x69, 0x63, - 0x53, 0x69, 0x67, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, - 0x74, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, - 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, - 0x69, 0x6E, 0x74, 0x38, 0x20, 0x61, 0x72, 0x67, 0x20, 0x69, 0x6E, - 0x64, 0x65, 0x78, 0x20, 0x4E, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, - 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, - 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, - 0x65, 0x22, 0x3A, 0x34, 0x35, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, - 0x22, 0x3A, 0x22, 0x61, 0x72, 0x67, 0x5F, 0x30, 0x22, 0x2C, 0x22, - 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, - 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, - 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x4C, 0x6F, 0x67, 0x69, 0x63, 0x53, - 0x69, 0x67, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, - 0x20, 0x30, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, - 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x34, - 0x36, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x61, - 0x72, 0x67, 0x5F, 0x31, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, - 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, - 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, - 0x22, 0x4C, 0x6F, 0x67, 0x69, 0x63, 0x53, 0x69, 0x67, 0x20, 0x61, - 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x31, 0x22, 0x2C, - 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, - 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, - 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, - 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x34, 0x37, 0x2C, 0x22, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x61, 0x72, 0x67, 0x5F, 0x32, - 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, - 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x4C, 0x6F, 0x67, - 0x69, 0x63, 0x53, 0x69, 0x67, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6D, - 0x65, 0x6E, 0x74, 0x20, 0x32, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, - 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, - 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, - 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, - 0x22, 0x3A, 0x34, 0x38, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x61, 0x72, 0x67, 0x5F, 0x33, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x4C, 0x6F, 0x67, 0x69, 0x63, 0x53, 0x69, - 0x67, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x20, - 0x33, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, - 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, - 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x34, 0x39, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x74, 0x78, - 0x6E, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, - 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x32, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x22, - 0x3A, 0x5B, 0x22, 0x53, 0x65, 0x6E, 0x64, 0x65, 0x72, 0x22, 0x2C, - 0x22, 0x46, 0x65, 0x65, 0x22, 0x2C, 0x22, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x22, 0x2C, 0x22, 0x46, 0x69, - 0x72, 0x73, 0x74, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x54, 0x69, 0x6D, - 0x65, 0x22, 0x2C, 0x22, 0x4C, 0x61, 0x73, 0x74, 0x56, 0x61, 0x6C, - 0x69, 0x64, 0x22, 0x2C, 0x22, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x2C, - 0x22, 0x4C, 0x65, 0x61, 0x73, 0x65, 0x22, 0x2C, 0x22, 0x52, 0x65, - 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, 0x6D, - 0x6F, 0x75, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x43, 0x6C, 0x6F, 0x73, - 0x65, 0x52, 0x65, 0x6D, 0x61, 0x69, 0x6E, 0x64, 0x65, 0x72, 0x54, - 0x6F, 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x50, 0x4B, 0x22, - 0x2C, 0x22, 0x53, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, - 0x50, 0x4B, 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x46, 0x69, - 0x72, 0x73, 0x74, 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x4C, - 0x61, 0x73, 0x74, 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x4B, - 0x65, 0x79, 0x44, 0x69, 0x6C, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x22, - 0x2C, 0x22, 0x54, 0x79, 0x70, 0x65, 0x22, 0x2C, 0x22, 0x54, 0x79, - 0x70, 0x65, 0x45, 0x6E, 0x75, 0x6D, 0x22, 0x2C, 0x22, 0x58, 0x66, - 0x65, 0x72, 0x41, 0x73, 0x73, 0x65, 0x74, 0x22, 0x2C, 0x22, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x41, 0x6D, 0x6F, 0x75, 0x6E, 0x74, 0x22, - 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x53, 0x65, 0x6E, 0x64, - 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, - 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x43, 0x6C, 0x6F, 0x73, 0x65, 0x54, 0x6F, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x49, 0x6E, 0x64, - 0x65, 0x78, 0x22, 0x2C, 0x22, 0x54, 0x78, 0x49, 0x44, 0x22, 0x2C, - 0x22, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, - 0x6E, 0x49, 0x44, 0x22, 0x2C, 0x22, 0x4F, 0x6E, 0x43, 0x6F, 0x6D, - 0x70, 0x6C, 0x65, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x41, - 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x41, - 0x72, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x41, 0x70, - 0x70, 0x41, 0x72, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x63, 0x63, - 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, - 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x22, 0x2C, 0x22, - 0x41, 0x70, 0x70, 0x72, 0x6F, 0x76, 0x61, 0x6C, 0x50, 0x72, 0x6F, - 0x67, 0x72, 0x61, 0x6D, 0x22, 0x2C, 0x22, 0x43, 0x6C, 0x65, 0x61, - 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6F, 0x67, 0x72, - 0x61, 0x6D, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x6B, 0x65, 0x79, 0x54, - 0x6F, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, - 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x6F, 0x74, 0x61, - 0x6C, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x44, 0x65, 0x63, 0x69, 0x6D, 0x61, 0x6C, - 0x73, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, - 0x46, 0x72, 0x6F, 0x7A, 0x65, 0x6E, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x55, 0x6E, - 0x69, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4E, 0x61, - 0x6D, 0x65, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x55, 0x52, 0x4C, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x4D, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x61, 0x73, - 0x68, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, - 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x43, 0x6C, 0x61, 0x77, 0x62, 0x61, 0x63, 0x6B, 0x22, 0x2C, 0x22, - 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x22, 0x2C, 0x22, 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x22, - 0x2C, 0x22, 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x46, 0x72, 0x6F, 0x7A, 0x65, 0x6E, 0x22, 0x2C, 0x22, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, - 0x6D, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, - 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, - 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x41, 0x70, 0x70, 0x6C, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x2C, 0x22, 0x47, - 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x55, 0x69, 0x6E, - 0x74, 0x22, 0x2C, 0x22, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x4E, - 0x75, 0x6D, 0x42, 0x79, 0x74, 0x65, 0x53, 0x6C, 0x69, 0x63, 0x65, - 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x63, 0x61, 0x6C, 0x4E, 0x75, 0x6D, - 0x55, 0x69, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x63, 0x61, - 0x6C, 0x4E, 0x75, 0x6D, 0x42, 0x79, 0x74, 0x65, 0x53, 0x6C, 0x69, - 0x63, 0x65, 0x22, 0x2C, 0x22, 0x45, 0x78, 0x74, 0x72, 0x61, 0x50, - 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x50, 0x61, 0x67, 0x65, 0x73, - 0x22, 0x2C, 0x22, 0x4E, 0x6F, 0x6E, 0x70, 0x61, 0x72, 0x74, 0x69, - 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, - 0x4C, 0x6F, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x4C, - 0x6F, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, 0x44, 0x22, 0x2C, - 0x22, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x70, 0x70, - 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x22, - 0x2C, 0x22, 0x4C, 0x61, 0x73, 0x74, 0x4C, 0x6F, 0x67, 0x22, 0x2C, - 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6F, 0x6F, 0x66, - 0x50, 0x4B, 0x22, 0x5D, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, - 0x75, 0x6D, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x3A, 0x22, 0x42, - 0x55, 0x55, 0x55, 0x55, 0x42, 0x42, 0x42, 0x55, 0x42, 0x42, 0x42, - 0x55, 0x55, 0x55, 0x42, 0x55, 0x55, 0x55, 0x42, 0x42, 0x42, 0x55, - 0x42, 0x55, 0x55, 0x42, 0x55, 0x42, 0x55, 0x42, 0x42, 0x42, 0x55, - 0x55, 0x55, 0x55, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x55, 0x42, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x42, 0x55, 0x55, 0x55, 0x42, 0x42, 0x22, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x66, 0x69, 0x65, 0x6C, 0x64, - 0x20, 0x46, 0x20, 0x6F, 0x66, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6E, 0x74, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, - 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x56, 0x61, 0x6C, 0x69, 0x64, 0x54, 0x69, 0x6D, 0x65, 0x20, 0x63, - 0x61, 0x75, 0x73, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, - 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x74, 0x6F, 0x20, 0x66, - 0x61, 0x69, 0x6C, 0x2E, 0x20, 0x54, 0x68, 0x65, 0x20, 0x66, 0x69, - 0x65, 0x6C, 0x64, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x66, 0x75, - 0x74, 0x75, 0x72, 0x65, 0x20, 0x75, 0x73, 0x65, 0x2E, 0x22, 0x2C, - 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, - 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, - 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x69, 0x6E, - 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, - 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x35, 0x30, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, - 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x46, 0x22, 0x2C, 0x22, 0x49, - 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, - 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, - 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x66, 0x69, 0x65, 0x6C, - 0x64, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, - 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, - 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, - 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, - 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x35, 0x31, 0x2C, 0x22, 0x4E, 0x61, - 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x67, 0x74, 0x78, 0x6E, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x33, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x22, 0x3A, 0x5B, 0x22, - 0x53, 0x65, 0x6E, 0x64, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x46, 0x65, - 0x65, 0x22, 0x2C, 0x22, 0x46, 0x69, 0x72, 0x73, 0x74, 0x56, 0x61, - 0x6C, 0x69, 0x64, 0x22, 0x2C, 0x22, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x56, 0x61, 0x6C, 0x69, 0x64, 0x54, 0x69, 0x6D, 0x65, 0x22, 0x2C, - 0x22, 0x4C, 0x61, 0x73, 0x74, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x22, - 0x2C, 0x22, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x2C, 0x22, 0x4C, 0x65, - 0x61, 0x73, 0x65, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x63, 0x65, 0x69, - 0x76, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, 0x6D, 0x6F, 0x75, 0x6E, - 0x74, 0x22, 0x2C, 0x22, 0x43, 0x6C, 0x6F, 0x73, 0x65, 0x52, 0x65, - 0x6D, 0x61, 0x69, 0x6E, 0x64, 0x65, 0x72, 0x54, 0x6F, 0x22, 0x2C, - 0x22, 0x56, 0x6F, 0x74, 0x65, 0x50, 0x4B, 0x22, 0x2C, 0x22, 0x53, - 0x65, 0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x50, 0x4B, 0x22, - 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x4C, 0x61, 0x73, 0x74, - 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x44, - 0x69, 0x6C, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x54, - 0x79, 0x70, 0x65, 0x22, 0x2C, 0x22, 0x54, 0x79, 0x70, 0x65, 0x45, - 0x6E, 0x75, 0x6D, 0x22, 0x2C, 0x22, 0x58, 0x66, 0x65, 0x72, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x41, 0x6D, 0x6F, 0x75, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x53, 0x65, 0x6E, 0x64, 0x65, 0x72, 0x22, - 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, - 0x69, 0x76, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x43, 0x6C, 0x6F, 0x73, 0x65, 0x54, 0x6F, 0x22, 0x2C, 0x22, - 0x47, 0x72, 0x6F, 0x75, 0x70, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x22, - 0x2C, 0x22, 0x54, 0x78, 0x49, 0x44, 0x22, 0x2C, 0x22, 0x41, 0x70, - 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, - 0x22, 0x2C, 0x22, 0x4F, 0x6E, 0x43, 0x6F, 0x6D, 0x70, 0x6C, 0x65, - 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x6C, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x41, 0x72, 0x67, 0x73, - 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x41, 0x70, 0x70, 0x41, 0x72, - 0x67, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, - 0x74, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x41, 0x63, 0x63, - 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, - 0x72, 0x6F, 0x76, 0x61, 0x6C, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, - 0x6D, 0x22, 0x2C, 0x22, 0x43, 0x6C, 0x65, 0x61, 0x72, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x22, - 0x2C, 0x22, 0x52, 0x65, 0x6B, 0x65, 0x79, 0x54, 0x6F, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x54, 0x6F, 0x74, 0x61, 0x6C, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x44, 0x65, 0x63, 0x69, 0x6D, 0x61, 0x6C, 0x73, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x46, 0x72, 0x6F, - 0x7A, 0x65, 0x6E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, - 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x55, 0x6E, 0x69, 0x74, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, - 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x55, 0x52, 0x4C, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, - 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4D, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x61, 0x73, 0x68, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x46, - 0x72, 0x65, 0x65, 0x7A, 0x65, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, - 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x43, 0x6C, 0x61, - 0x77, 0x62, 0x61, 0x63, 0x6B, 0x22, 0x2C, 0x22, 0x46, 0x72, 0x65, - 0x65, 0x7A, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x22, 0x2C, 0x22, - 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x46, - 0x72, 0x65, 0x65, 0x7A, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x46, - 0x72, 0x6F, 0x7A, 0x65, 0x6E, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x6C, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x2C, 0x22, - 0x4E, 0x75, 0x6D, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x2C, 0x22, 0x47, 0x6C, 0x6F, 0x62, - 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x55, 0x69, 0x6E, 0x74, 0x22, 0x2C, - 0x22, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x42, - 0x79, 0x74, 0x65, 0x53, 0x6C, 0x69, 0x63, 0x65, 0x22, 0x2C, 0x22, - 0x4C, 0x6F, 0x63, 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x55, 0x69, 0x6E, - 0x74, 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x63, 0x61, 0x6C, 0x4E, 0x75, - 0x6D, 0x42, 0x79, 0x74, 0x65, 0x53, 0x6C, 0x69, 0x63, 0x65, 0x22, - 0x2C, 0x22, 0x45, 0x78, 0x74, 0x72, 0x61, 0x50, 0x72, 0x6F, 0x67, - 0x72, 0x61, 0x6D, 0x50, 0x61, 0x67, 0x65, 0x73, 0x22, 0x2C, 0x22, - 0x4E, 0x6F, 0x6E, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x67, - 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x4C, 0x6F, 0x67, 0x73, - 0x22, 0x2C, 0x22, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x49, 0x44, 0x22, 0x2C, 0x22, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x22, 0x2C, 0x22, 0x4C, - 0x61, 0x73, 0x74, 0x4C, 0x6F, 0x67, 0x22, 0x2C, 0x22, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x50, 0x72, 0x6F, 0x6F, 0x66, 0x50, 0x4B, 0x22, - 0x5D, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x54, - 0x79, 0x70, 0x65, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x55, 0x55, 0x55, - 0x55, 0x42, 0x42, 0x42, 0x55, 0x42, 0x42, 0x42, 0x55, 0x55, 0x55, - 0x42, 0x55, 0x55, 0x55, 0x42, 0x42, 0x42, 0x55, 0x42, 0x55, 0x55, - 0x42, 0x55, 0x42, 0x55, 0x42, 0x42, 0x42, 0x55, 0x55, 0x55, 0x55, - 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x55, 0x42, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x42, - 0x55, 0x55, 0x55, 0x42, 0x42, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, - 0x22, 0x3A, 0x22, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x46, 0x20, - 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x74, 0x68, 0x20, - 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, - 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6E, 0x74, 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, 0x22, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, - 0x3A, 0x22, 0x66, 0x6F, 0x72, 0x20, 0x6E, 0x6F, 0x74, 0x65, 0x73, - 0x20, 0x6F, 0x6E, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x73, - 0x20, 0x61, 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x2C, - 0x20, 0x73, 0x65, 0x65, 0x20, 0x60, 0x74, 0x78, 0x6E, 0x60, 0x2E, - 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, 0x72, - 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, - 0x73, 0x20, 0x5F, 0x69, 0x5F, 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, 0x2C, 0x20, 0x60, 0x67, - 0x74, 0x78, 0x6E, 0x20, 0x69, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, - 0x60, 0x20, 0x69, 0x73, 0x20, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, - 0x6C, 0x65, 0x6E, 0x74, 0x20, 0x74, 0x6F, 0x20, 0x60, 0x74, 0x78, - 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x60, 0x2E, 0x22, 0x2C, - 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, - 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, - 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6F, 0x6E, 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, 0x20, 0x69, 0x6E, - 0x64, 0x65, 0x78, 0x7D, 0x20, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, - 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, - 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x69, 0x6E, 0x64, - 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, - 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, - 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x35, 0x32, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, - 0x6C, 0x6F, 0x61, 0x64, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, - 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, - 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, - 0x22, 0x49, 0x74, 0x68, 0x20, 0x73, 0x63, 0x72, 0x61, 0x74, 0x63, - 0x68, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x76, 0x61, 0x6C, - 0x75, 0x65, 0x2E, 0x20, 0x41, 0x6C, 0x6C, 0x20, 0x73, 0x63, 0x72, - 0x61, 0x74, 0x63, 0x68, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, - 0x20, 0x61, 0x72, 0x65, 0x20, 0x30, 0x20, 0x61, 0x74, 0x20, 0x70, - 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x2E, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, - 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, - 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x70, 0x6F, 0x73, 0x69, 0x74, - 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x73, 0x63, 0x72, 0x61, - 0x74, 0x63, 0x68, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x74, - 0x6F, 0x20, 0x6C, 0x6F, 0x61, 0x64, 0x20, 0x66, 0x72, 0x6F, 0x6D, - 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, - 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, - 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x35, 0x33, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x73, 0x74, - 0x6F, 0x72, 0x65, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, - 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x32, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x73, 0x74, 0x6F, - 0x72, 0x65, 0x20, 0x41, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x49, 0x74, 0x68, 0x20, 0x73, 0x63, 0x72, 0x61, 0x74, 0x63, - 0x68, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x2C, 0x22, 0x49, - 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, - 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, - 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x6E, - 0x20, 0x73, 0x63, 0x72, 0x61, 0x74, 0x63, 0x68, 0x20, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x73, 0x74, 0x6F, 0x72, - 0x65, 0x20, 0x74, 0x6F, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, - 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, - 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, - 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, - 0x22, 0x3A, 0x35, 0x34, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x74, 0x78, 0x6E, 0x61, 0x22, 0x2C, 0x22, 0x52, 0x65, - 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, - 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x33, 0x2C, 0x22, 0x41, 0x72, 0x67, - 0x45, 0x6E, 0x75, 0x6D, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x70, 0x70, - 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x41, 0x72, 0x67, - 0x73, 0x22, 0x2C, 0x22, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, - 0x73, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, - 0x2C, 0x22, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x73, 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x67, 0x73, 0x22, - 0x5D, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x54, - 0x79, 0x70, 0x65, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, 0x55, 0x55, - 0x42, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x49, - 0x74, 0x68, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x6F, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, - 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x46, 0x20, 0x6F, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, - 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, - 0x6E, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, - 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, - 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, - 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x20, 0x7B, 0x75, 0x69, - 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, - 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, - 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, - 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, - 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x35, 0x35, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x67, 0x74, - 0x78, 0x6E, 0x61, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x34, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, - 0x6D, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x41, 0x72, 0x67, 0x73, 0x22, 0x2C, - 0x22, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x22, 0x2C, - 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, - 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, - 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x67, 0x73, 0x22, 0x5D, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x54, 0x79, 0x70, 0x65, - 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, 0x55, 0x55, 0x42, 0x22, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x49, 0x74, 0x68, 0x20, - 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x66, 0x69, 0x65, - 0x6C, 0x64, 0x20, 0x46, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x54, 0x74, 0x68, 0x20, 0x74, 0x72, 0x61, 0x6E, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x6E, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, - 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, 0x22, 0x2C, 0x22, 0x49, 0x6D, - 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, - 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, - 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, - 0x67, 0x72, 0x6F, 0x75, 0x70, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, - 0x7D, 0x20, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, - 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, - 0x69, 0x65, 0x6C, 0x64, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, - 0x20, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, - 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, - 0x65, 0x6C, 0x64, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x69, - 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, - 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, - 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, - 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, - 0x22, 0x3A, 0x35, 0x36, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x67, 0x74, 0x78, 0x6E, 0x73, 0x22, 0x2C, 0x22, 0x41, - 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x22, 0x3A, 0x5B, 0x22, 0x53, 0x65, - 0x6E, 0x64, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x46, 0x65, 0x65, 0x22, - 0x2C, 0x22, 0x46, 0x69, 0x72, 0x73, 0x74, 0x56, 0x61, 0x6C, 0x69, - 0x64, 0x22, 0x2C, 0x22, 0x46, 0x69, 0x72, 0x73, 0x74, 0x56, 0x61, - 0x6C, 0x69, 0x64, 0x54, 0x69, 0x6D, 0x65, 0x22, 0x2C, 0x22, 0x4C, - 0x61, 0x73, 0x74, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x22, 0x2C, 0x22, - 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x2C, 0x22, 0x4C, 0x65, 0x61, 0x73, - 0x65, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, - 0x72, 0x22, 0x2C, 0x22, 0x41, 0x6D, 0x6F, 0x75, 0x6E, 0x74, 0x22, - 0x2C, 0x22, 0x43, 0x6C, 0x6F, 0x73, 0x65, 0x52, 0x65, 0x6D, 0x61, - 0x69, 0x6E, 0x64, 0x65, 0x72, 0x54, 0x6F, 0x22, 0x2C, 0x22, 0x56, - 0x6F, 0x74, 0x65, 0x50, 0x4B, 0x22, 0x2C, 0x22, 0x53, 0x65, 0x6C, - 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x50, 0x4B, 0x22, 0x2C, 0x22, - 0x56, 0x6F, 0x74, 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, 0x22, 0x2C, - 0x22, 0x56, 0x6F, 0x74, 0x65, 0x4C, 0x61, 0x73, 0x74, 0x22, 0x2C, - 0x22, 0x56, 0x6F, 0x74, 0x65, 0x4B, 0x65, 0x79, 0x44, 0x69, 0x6C, - 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x54, 0x79, 0x70, - 0x65, 0x22, 0x2C, 0x22, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6E, 0x75, - 0x6D, 0x22, 0x2C, 0x22, 0x58, 0x66, 0x65, 0x72, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x41, - 0x6D, 0x6F, 0x75, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x53, 0x65, 0x6E, 0x64, 0x65, 0x72, 0x22, 0x2C, 0x22, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, - 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x43, - 0x6C, 0x6F, 0x73, 0x65, 0x54, 0x6F, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x22, 0x2C, 0x22, - 0x54, 0x78, 0x49, 0x44, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x6C, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x22, 0x2C, - 0x22, 0x4F, 0x6E, 0x43, 0x6F, 0x6D, 0x70, 0x6C, 0x65, 0x74, 0x69, - 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x41, 0x72, 0x67, 0x73, 0x22, 0x2C, - 0x22, 0x4E, 0x75, 0x6D, 0x41, 0x70, 0x70, 0x41, 0x72, 0x67, 0x73, - 0x22, 0x2C, 0x22, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, - 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x41, 0x63, 0x63, 0x6F, 0x75, - 0x6E, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x72, 0x6F, - 0x76, 0x61, 0x6C, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x22, - 0x2C, 0x22, 0x43, 0x6C, 0x65, 0x61, 0x72, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x22, 0x2C, 0x22, - 0x52, 0x65, 0x6B, 0x65, 0x79, 0x54, 0x6F, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x54, 0x6F, 0x74, 0x61, 0x6C, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x44, - 0x65, 0x63, 0x69, 0x6D, 0x61, 0x6C, 0x73, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x44, - 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x46, 0x72, 0x6F, 0x7A, 0x65, - 0x6E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x55, 0x6E, 0x69, 0x74, 0x4E, 0x61, 0x6D, - 0x65, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x55, 0x52, 0x4C, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, - 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4D, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x48, 0x61, 0x73, 0x68, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4D, - 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, - 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x46, 0x72, 0x65, - 0x65, 0x7A, 0x65, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, - 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x43, 0x6C, 0x61, 0x77, 0x62, - 0x61, 0x63, 0x6B, 0x22, 0x2C, 0x22, 0x46, 0x72, 0x65, 0x65, 0x7A, - 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x22, 0x2C, 0x22, 0x46, 0x72, - 0x65, 0x65, 0x7A, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x41, 0x63, - 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x46, 0x72, 0x65, - 0x65, 0x7A, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x46, 0x72, 0x6F, - 0x7A, 0x65, 0x6E, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, - 0x6D, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, - 0x6E, 0x73, 0x22, 0x2C, 0x22, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, - 0x4E, 0x75, 0x6D, 0x55, 0x69, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x47, - 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x42, 0x79, 0x74, - 0x65, 0x53, 0x6C, 0x69, 0x63, 0x65, 0x22, 0x2C, 0x22, 0x4C, 0x6F, - 0x63, 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x55, 0x69, 0x6E, 0x74, 0x22, - 0x2C, 0x22, 0x4C, 0x6F, 0x63, 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x42, - 0x79, 0x74, 0x65, 0x53, 0x6C, 0x69, 0x63, 0x65, 0x22, 0x2C, 0x22, - 0x45, 0x78, 0x74, 0x72, 0x61, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, - 0x6D, 0x50, 0x61, 0x67, 0x65, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x6F, - 0x6E, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x67, 0x73, 0x22, - 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x4C, 0x6F, 0x67, 0x73, 0x22, 0x2C, - 0x22, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x49, 0x44, 0x22, 0x2C, 0x22, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x22, 0x2C, 0x22, 0x4C, 0x61, 0x73, - 0x74, 0x4C, 0x6F, 0x67, 0x22, 0x2C, 0x22, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x50, 0x72, 0x6F, 0x6F, 0x66, 0x50, 0x4B, 0x22, 0x5D, 0x2C, - 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x54, 0x79, 0x70, - 0x65, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x55, 0x55, 0x55, 0x55, 0x42, - 0x42, 0x42, 0x55, 0x42, 0x42, 0x42, 0x55, 0x55, 0x55, 0x42, 0x55, - 0x55, 0x55, 0x42, 0x42, 0x42, 0x55, 0x42, 0x55, 0x55, 0x42, 0x55, - 0x42, 0x55, 0x42, 0x42, 0x42, 0x55, 0x55, 0x55, 0x55, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x55, 0x42, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x42, 0x55, 0x55, - 0x55, 0x42, 0x42, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, - 0x22, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x46, 0x20, 0x6F, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x74, 0x68, 0x20, 0x74, 0x72, - 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, - 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6E, 0x74, 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, 0x22, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, - 0x66, 0x6F, 0x72, 0x20, 0x6E, 0x6F, 0x74, 0x65, 0x73, 0x20, 0x6F, - 0x6E, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x73, 0x20, 0x61, - 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x2C, 0x20, 0x73, - 0x65, 0x65, 0x20, 0x60, 0x74, 0x78, 0x6E, 0x60, 0x2E, 0x20, 0x49, - 0x66, 0x20, 0x74, 0x6F, 0x70, 0x20, 0x6F, 0x66, 0x20, 0x73, 0x74, - 0x61, 0x63, 0x6B, 0x20, 0x69, 0x73, 0x20, 0x5F, 0x69, 0x5F, 0x2C, - 0x20, 0x60, 0x67, 0x74, 0x78, 0x6E, 0x73, 0x20, 0x66, 0x69, 0x65, - 0x6C, 0x64, 0x60, 0x20, 0x69, 0x73, 0x20, 0x65, 0x71, 0x75, 0x69, - 0x76, 0x61, 0x6C, 0x65, 0x6E, 0x74, 0x20, 0x74, 0x6F, 0x20, 0x60, - 0x67, 0x74, 0x78, 0x6E, 0x20, 0x5F, 0x69, 0x5F, 0x20, 0x66, 0x69, - 0x65, 0x6C, 0x64, 0x60, 0x2E, 0x20, 0x67, 0x74, 0x78, 0x6E, 0x73, - 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x20, 0x73, 0x6F, 0x20, - 0x74, 0x68, 0x61, 0x74, 0x20, 0x5F, 0x69, 0x5F, 0x20, 0x63, 0x61, - 0x6E, 0x20, 0x62, 0x65, 0x20, 0x63, 0x61, 0x6C, 0x63, 0x75, 0x6C, - 0x61, 0x74, 0x65, 0x64, 0x2C, 0x20, 0x6F, 0x66, 0x74, 0x65, 0x6E, - 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6F, 0x6E, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x6F, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, - 0x74, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6F, 0x6E, 0x2E, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, - 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, - 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, - 0x6C, 0x64, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, - 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, - 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, - 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, - 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x35, 0x37, 0x2C, 0x22, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x67, 0x74, 0x78, 0x6E, 0x73, - 0x61, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, - 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x33, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x22, - 0x3A, 0x5B, 0x22, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x41, 0x72, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x41, - 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, - 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x2C, - 0x22, 0x4C, 0x6F, 0x67, 0x73, 0x22, 0x5D, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x42, 0x55, 0x55, 0x42, 0x22, 0x2C, 0x22, 0x44, - 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x49, 0x74, 0x68, 0x20, 0x76, 0x61, - 0x6C, 0x75, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, - 0x20, 0x46, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x41, 0x74, 0x68, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x20, 0x67, - 0x72, 0x6F, 0x75, 0x70, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, - 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, - 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, - 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, - 0x65, 0x6C, 0x64, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x20, - 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, - 0x6C, 0x64, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x69, 0x6E, - 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, - 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x35, 0x38, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x67, 0x6C, 0x6F, 0x61, 0x64, 0x22, 0x2C, 0x22, 0x52, 0x65, - 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, - 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x33, 0x2C, 0x22, 0x44, 0x6F, 0x63, - 0x22, 0x3A, 0x22, 0x49, 0x74, 0x68, 0x20, 0x73, 0x63, 0x72, 0x61, - 0x74, 0x63, 0x68, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x76, - 0x61, 0x6C, 0x75, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x54, 0x74, 0x68, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x20, 0x67, - 0x72, 0x6F, 0x75, 0x70, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, - 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x60, 0x67, 0x6C, 0x6F, - 0x61, 0x64, 0x60, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x73, 0x20, 0x75, - 0x6E, 0x6C, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x20, 0x74, 0x72, - 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, - 0x73, 0x20, 0x61, 0x6E, 0x20, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x43, 0x61, 0x6C, 0x6C, 0x20, 0x61, - 0x6E, 0x64, 0x20, 0x54, 0x20, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x63, - 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x49, 0x6E, 0x64, 0x65, 0x78, - 0x2E, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, - 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, - 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, - 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x20, 0x7B, 0x75, 0x69, - 0x6E, 0x74, 0x38, 0x20, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, - 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x73, 0x63, 0x72, 0x61, 0x74, 0x63, - 0x68, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x74, 0x6F, 0x20, - 0x6C, 0x6F, 0x61, 0x64, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x7D, 0x22, - 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, - 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, - 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, - 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x35, 0x39, 0x2C, 0x22, - 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x67, 0x6C, 0x6F, 0x61, - 0x64, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, - 0x22, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, - 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, - 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, - 0x3A, 0x32, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x49, - 0x74, 0x68, 0x20, 0x73, 0x63, 0x72, 0x61, 0x74, 0x63, 0x68, 0x20, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, - 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x74, 0x68, - 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, - 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6E, 0x74, 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, - 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, - 0x22, 0x3A, 0x22, 0x60, 0x67, 0x6C, 0x6F, 0x61, 0x64, 0x73, 0x60, - 0x20, 0x66, 0x61, 0x69, 0x6C, 0x73, 0x20, 0x75, 0x6E, 0x6C, 0x65, - 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x65, 0x64, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x73, 0x20, 0x61, - 0x6E, 0x20, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x43, 0x61, 0x6C, 0x6C, 0x20, 0x61, 0x6E, 0x64, 0x20, - 0x41, 0x20, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x63, 0x20, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x22, 0x2C, - 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, - 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, - 0x38, 0x20, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x20, - 0x69, 0x6E, 0x20, 0x73, 0x63, 0x72, 0x61, 0x74, 0x63, 0x68, 0x20, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x6C, 0x6F, - 0x61, 0x64, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x7D, 0x22, 0x2C, 0x22, - 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, - 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, - 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, - 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x36, 0x30, 0x2C, 0x22, 0x4E, 0x61, - 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x67, 0x61, 0x69, 0x64, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x49, 0x44, 0x20, 0x6F, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x73, 0x73, 0x65, 0x74, 0x20, - 0x6F, 0x72, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x74, 0x68, - 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, - 0x6E, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6E, 0x74, 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, - 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, - 0x22, 0x3A, 0x22, 0x60, 0x67, 0x61, 0x69, 0x64, 0x60, 0x20, 0x66, - 0x61, 0x69, 0x6C, 0x73, 0x20, 0x75, 0x6E, 0x6C, 0x65, 0x73, 0x73, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x65, 0x64, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x73, 0x73, 0x65, 0x74, 0x20, - 0x6F, 0x72, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x54, 0x20, 0x5C, - 0x75, 0x30, 0x30, 0x33, 0x63, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, - 0x49, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x22, 0x2C, 0x22, 0x49, 0x6D, - 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, - 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, - 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, - 0x67, 0x72, 0x6F, 0x75, 0x70, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, - 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, - 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, - 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x36, 0x31, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x67, 0x61, - 0x69, 0x64, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x49, 0x44, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, - 0x73, 0x73, 0x65, 0x74, 0x20, 0x6F, 0x72, 0x20, 0x61, 0x70, 0x70, - 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x41, 0x74, 0x68, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x6F, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x20, - 0x67, 0x72, 0x6F, 0x75, 0x70, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, - 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x60, 0x67, 0x61, - 0x69, 0x64, 0x73, 0x60, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x73, 0x20, - 0x75, 0x6E, 0x6C, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x20, 0x74, - 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, 0x6E, 0x20, - 0x61, 0x73, 0x73, 0x65, 0x74, 0x20, 0x6F, 0x72, 0x20, 0x61, 0x70, - 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x61, - 0x6E, 0x64, 0x20, 0x41, 0x20, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x63, - 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x49, 0x6E, 0x64, 0x65, 0x78, - 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, - 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, - 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x36, 0x32, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x6C, 0x6F, - 0x61, 0x64, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x41, 0x74, 0x68, 0x20, 0x73, 0x63, 0x72, 0x61, 0x74, 0x63, 0x68, - 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x76, 0x61, 0x6C, 0x75, - 0x65, 0x2E, 0x20, 0x20, 0x41, 0x6C, 0x6C, 0x20, 0x73, 0x63, 0x72, - 0x61, 0x74, 0x63, 0x68, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, - 0x20, 0x61, 0x72, 0x65, 0x20, 0x30, 0x20, 0x61, 0x74, 0x20, 0x70, - 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, - 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x36, - 0x33, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x73, - 0x74, 0x6F, 0x72, 0x65, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, - 0x73, 0x22, 0x3A, 0x22, 0x55, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x73, 0x74, 0x6F, 0x72, 0x65, 0x20, 0x42, 0x20, 0x74, 0x6F, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x41, 0x74, 0x68, 0x20, 0x73, 0x63, 0x72, - 0x61, 0x74, 0x63, 0x68, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, - 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, - 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, - 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, - 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x36, 0x34, 0x2C, 0x22, - 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x62, 0x6E, 0x7A, 0x22, - 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x33, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x20, - 0x74, 0x6F, 0x20, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x20, 0x69, - 0x66, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x41, 0x20, 0x69, - 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x22, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, - 0x3A, 0x22, 0x54, 0x68, 0x65, 0x20, 0x60, 0x62, 0x6E, 0x7A, 0x60, - 0x20, 0x69, 0x6E, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6F, - 0x6E, 0x20, 0x6F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x20, 0x30, 0x78, - 0x34, 0x30, 0x20, 0x69, 0x73, 0x20, 0x66, 0x6F, 0x6C, 0x6C, 0x6F, - 0x77, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x77, 0x6F, 0x20, - 0x69, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x64, - 0x61, 0x74, 0x61, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x77, - 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x20, - 0x68, 0x69, 0x67, 0x68, 0x20, 0x62, 0x79, 0x74, 0x65, 0x20, 0x66, - 0x69, 0x72, 0x73, 0x74, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x6C, 0x6F, - 0x77, 0x20, 0x62, 0x79, 0x74, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6F, - 0x6E, 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x6F, - 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x66, 0x6F, 0x72, 0x6D, - 0x20, 0x61, 0x20, 0x31, 0x36, 0x20, 0x62, 0x69, 0x74, 0x20, 0x6F, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6E, 0x73, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x6D, 0x61, 0x79, 0x20, 0x62, - 0x72, 0x61, 0x6E, 0x63, 0x68, 0x20, 0x74, 0x6F, 0x2E, 0x20, 0x46, - 0x6F, 0x72, 0x20, 0x61, 0x20, 0x62, 0x6E, 0x7A, 0x20, 0x69, 0x6E, - 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x61, - 0x74, 0x20, 0x60, 0x70, 0x63, 0x60, 0x2C, 0x20, 0x69, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x6C, 0x61, 0x73, 0x74, 0x20, 0x65, 0x6C, - 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x20, 0x69, 0x73, 0x20, - 0x6E, 0x6F, 0x74, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x20, 0x74, 0x68, - 0x65, 0x6E, 0x20, 0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x20, 0x74, - 0x6F, 0x20, 0x69, 0x6E, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, - 0x6F, 0x6E, 0x20, 0x61, 0x74, 0x20, 0x60, 0x70, 0x63, 0x20, 0x2B, - 0x20, 0x33, 0x20, 0x2B, 0x20, 0x4E, 0x60, 0x2C, 0x20, 0x65, 0x6C, - 0x73, 0x65, 0x20, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x65, 0x64, 0x20, - 0x74, 0x6F, 0x20, 0x6E, 0x65, 0x78, 0x74, 0x20, 0x69, 0x6E, 0x73, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x61, 0x74, - 0x20, 0x60, 0x70, 0x63, 0x20, 0x2B, 0x20, 0x33, 0x60, 0x2E, 0x20, - 0x42, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x20, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x73, 0x20, 0x6D, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, - 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x20, 0x69, 0x6E, - 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2E, - 0x20, 0x28, 0x65, 0x2E, 0x67, 0x2E, 0x20, 0x42, 0x72, 0x61, 0x6E, - 0x63, 0x68, 0x69, 0x6E, 0x67, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x20, 0x62, 0x79, - 0x74, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x61, 0x20, 0x32, 0x20, 0x62, - 0x79, 0x74, 0x65, 0x20, 0x6F, 0x70, 0x20, 0x77, 0x69, 0x6C, 0x6C, - 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x6A, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x2E, 0x29, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6E, - 0x67, 0x20, 0x61, 0x74, 0x20, 0x76, 0x34, 0x2C, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x69, 0x73, - 0x20, 0x74, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, - 0x20, 0x61, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x20, 0x31, - 0x36, 0x20, 0x62, 0x69, 0x74, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x67, - 0x65, 0x72, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x69, 0x6E, 0x67, - 0x20, 0x66, 0x6F, 0x72, 0x20, 0x62, 0x61, 0x63, 0x6B, 0x77, 0x61, - 0x72, 0x64, 0x20, 0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, - 0x20, 0x61, 0x6E, 0x64, 0x20, 0x6C, 0x6F, 0x6F, 0x70, 0x69, 0x6E, - 0x67, 0x2E, 0x20, 0x49, 0x6E, 0x20, 0x70, 0x72, 0x69, 0x6F, 0x72, - 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x28, 0x76, - 0x31, 0x20, 0x74, 0x6F, 0x20, 0x76, 0x33, 0x29, 0x2C, 0x20, 0x62, - 0x72, 0x61, 0x6E, 0x63, 0x68, 0x20, 0x6F, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6C, 0x69, 0x6D, 0x69, - 0x74, 0x65, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x66, 0x6F, 0x72, 0x77, - 0x61, 0x72, 0x64, 0x20, 0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x65, - 0x73, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x2C, 0x20, 0x30, 0x2D, 0x30, - 0x78, 0x37, 0x66, 0x66, 0x66, 0x2E, 0x5C, 0x6E, 0x5C, 0x6E, 0x41, - 0x74, 0x20, 0x76, 0x32, 0x20, 0x69, 0x74, 0x20, 0x62, 0x65, 0x63, - 0x61, 0x6D, 0x65, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, - 0x20, 0x74, 0x6F, 0x20, 0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x20, - 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6E, 0x64, 0x20, - 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6F, 0x67, - 0x72, 0x61, 0x6D, 0x20, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6C, 0x79, - 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x6C, 0x61, 0x73, 0x74, 0x20, 0x69, 0x6E, 0x73, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x62, 0x6E, 0x7A, 0x20, - 0x74, 0x6F, 0x20, 0x62, 0x79, 0x74, 0x65, 0x20, 0x4E, 0x20, 0x28, - 0x77, 0x69, 0x74, 0x68, 0x20, 0x30, 0x2D, 0x69, 0x6E, 0x64, 0x65, - 0x78, 0x69, 0x6E, 0x67, 0x29, 0x20, 0x77, 0x61, 0x73, 0x20, 0x69, - 0x6C, 0x6C, 0x65, 0x67, 0x61, 0x6C, 0x20, 0x66, 0x6F, 0x72, 0x20, - 0x61, 0x20, 0x54, 0x45, 0x41, 0x4C, 0x20, 0x70, 0x72, 0x6F, 0x67, - 0x72, 0x61, 0x6D, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x4E, 0x20, - 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x62, 0x65, 0x66, 0x6F, 0x72, - 0x65, 0x20, 0x76, 0x32, 0x2C, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x69, - 0x73, 0x20, 0x6C, 0x65, 0x67, 0x61, 0x6C, 0x20, 0x61, 0x66, 0x74, - 0x65, 0x72, 0x20, 0x69, 0x74, 0x2E, 0x20, 0x54, 0x68, 0x69, 0x73, - 0x20, 0x63, 0x68, 0x61, 0x6E, 0x67, 0x65, 0x20, 0x65, 0x6C, 0x69, - 0x6D, 0x69, 0x6E, 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x6E, 0x65, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x61, - 0x20, 0x6C, 0x61, 0x73, 0x74, 0x20, 0x69, 0x6E, 0x73, 0x74, 0x72, - 0x75, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x6F, 0x66, 0x20, 0x6E, - 0x6F, 0x2D, 0x6F, 0x70, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x62, - 0x72, 0x61, 0x6E, 0x63, 0x68, 0x20, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6E, - 0x64, 0x2E, 0x20, 0x28, 0x42, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x69, - 0x6E, 0x67, 0x20, 0x62, 0x65, 0x79, 0x6F, 0x6E, 0x64, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x65, 0x6E, 0x64, 0x2D, 0x2D, 0x69, 0x6E, 0x20, - 0x6F, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x6F, 0x72, 0x64, 0x73, - 0x2C, 0x20, 0x74, 0x6F, 0x20, 0x61, 0x20, 0x62, 0x79, 0x74, 0x65, - 0x20, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, - 0x6E, 0x20, 0x4E, 0x2D, 0x2D, 0x69, 0x73, 0x20, 0x73, 0x74, 0x69, - 0x6C, 0x6C, 0x20, 0x69, 0x6C, 0x6C, 0x65, 0x67, 0x61, 0x6C, 0x20, - 0x61, 0x6E, 0x64, 0x20, 0x77, 0x69, 0x6C, 0x6C, 0x20, 0x63, 0x61, - 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6F, - 0x67, 0x72, 0x61, 0x6D, 0x20, 0x74, 0x6F, 0x20, 0x66, 0x61, 0x69, - 0x6C, 0x2E, 0x29, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, - 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, - 0x7B, 0x69, 0x6E, 0x74, 0x31, 0x36, 0x20, 0x62, 0x72, 0x61, 0x6E, - 0x63, 0x68, 0x20, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2C, 0x20, - 0x62, 0x69, 0x67, 0x20, 0x65, 0x6E, 0x64, 0x69, 0x61, 0x6E, 0x7D, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, - 0x5B, 0x22, 0x46, 0x6C, 0x6F, 0x77, 0x20, 0x43, 0x6F, 0x6E, 0x74, - 0x72, 0x6F, 0x6C, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, - 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x36, 0x35, 0x2C, 0x22, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x62, 0x7A, 0x22, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, - 0x7A, 0x65, 0x22, 0x3A, 0x33, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, - 0x3A, 0x22, 0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x20, 0x74, 0x6F, - 0x20, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x20, 0x69, 0x66, 0x20, - 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x41, 0x20, 0x69, 0x73, 0x20, - 0x7A, 0x65, 0x72, 0x6F, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, - 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x53, 0x65, 0x65, 0x20, - 0x60, 0x62, 0x6E, 0x7A, 0x60, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x64, - 0x65, 0x74, 0x61, 0x69, 0x6C, 0x73, 0x20, 0x6F, 0x6E, 0x20, 0x68, - 0x6F, 0x77, 0x20, 0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, - 0x20, 0x77, 0x6F, 0x72, 0x6B, 0x2E, 0x20, 0x60, 0x62, 0x7A, 0x60, - 0x20, 0x69, 0x6E, 0x76, 0x65, 0x72, 0x74, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6F, 0x72, 0x20, - 0x6F, 0x66, 0x20, 0x60, 0x62, 0x6E, 0x7A, 0x60, 0x2E, 0x22, 0x2C, - 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, - 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x69, 0x6E, 0x74, 0x31, - 0x36, 0x20, 0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x20, 0x6F, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x2C, 0x20, 0x62, 0x69, 0x67, 0x20, 0x65, - 0x6E, 0x64, 0x69, 0x61, 0x6E, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x46, 0x6C, 0x6F, - 0x77, 0x20, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x36, 0x36, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x62, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x33, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x62, 0x72, 0x61, 0x6E, - 0x63, 0x68, 0x20, 0x75, 0x6E, 0x63, 0x6F, 0x6E, 0x64, 0x69, 0x74, - 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x6C, 0x79, 0x20, 0x74, 0x6F, 0x20, - 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x22, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x53, 0x65, - 0x65, 0x20, 0x60, 0x62, 0x6E, 0x7A, 0x60, 0x20, 0x66, 0x6F, 0x72, - 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6C, 0x73, 0x20, 0x6F, 0x6E, - 0x20, 0x68, 0x6F, 0x77, 0x20, 0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, - 0x65, 0x73, 0x20, 0x77, 0x6F, 0x72, 0x6B, 0x2E, 0x20, 0x60, 0x62, - 0x60, 0x20, 0x61, 0x6C, 0x77, 0x61, 0x79, 0x73, 0x20, 0x6A, 0x75, - 0x6D, 0x70, 0x73, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2E, 0x22, 0x2C, 0x22, 0x49, - 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, - 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x69, 0x6E, 0x74, 0x31, 0x36, 0x20, - 0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x20, 0x6F, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x2C, 0x20, 0x62, 0x69, 0x67, 0x20, 0x65, 0x6E, 0x64, - 0x69, 0x61, 0x6E, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x46, 0x6C, 0x6F, 0x77, 0x20, - 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x36, - 0x37, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, - 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, - 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, - 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x75, - 0x73, 0x65, 0x20, 0x41, 0x20, 0x61, 0x73, 0x20, 0x73, 0x75, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x3B, - 0x20, 0x65, 0x6E, 0x64, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x46, 0x6C, 0x6F, 0x77, 0x20, - 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x36, - 0x38, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x61, - 0x73, 0x73, 0x65, 0x72, 0x74, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, - 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, - 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, - 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x69, - 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x6C, 0x79, 0x20, - 0x66, 0x61, 0x69, 0x6C, 0x20, 0x75, 0x6E, 0x6C, 0x65, 0x73, 0x73, - 0x20, 0x41, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x6E, 0x6F, 0x6E, - 0x2D, 0x7A, 0x65, 0x72, 0x6F, 0x20, 0x6E, 0x75, 0x6D, 0x62, 0x65, - 0x72, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x46, 0x6C, 0x6F, 0x77, 0x20, 0x43, 0x6F, 0x6E, - 0x74, 0x72, 0x6F, 0x6C, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, - 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x37, 0x32, 0x2C, 0x22, - 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x70, 0x6F, 0x70, 0x22, - 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, - 0x20, 0x41, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x46, 0x6C, 0x6F, 0x77, 0x20, 0x43, 0x6F, - 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x37, 0x33, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x64, 0x75, 0x70, - 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x2E, - 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, - 0x3A, 0x22, 0x2E, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x64, 0x75, - 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x22, 0x2C, - 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, - 0x46, 0x6C, 0x6F, 0x77, 0x20, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, - 0x6C, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, - 0x64, 0x65, 0x22, 0x3A, 0x37, 0x34, 0x2C, 0x22, 0x4E, 0x61, 0x6D, - 0x65, 0x22, 0x3A, 0x22, 0x64, 0x75, 0x70, 0x32, 0x22, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x2E, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x2E, 0x2E, 0x2E, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x64, 0x75, - 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x20, 0x61, - 0x6E, 0x64, 0x20, 0x42, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x46, 0x6C, 0x6F, 0x77, 0x20, - 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x37, - 0x35, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x64, - 0x69, 0x67, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, - 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, - 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x4E, 0x74, 0x68, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x66, - 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6F, 0x70, - 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, - 0x63, 0x6B, 0x2E, 0x20, 0x64, 0x69, 0x67, 0x20, 0x30, 0x20, 0x69, - 0x73, 0x20, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6C, 0x65, 0x6E, - 0x74, 0x20, 0x74, 0x6F, 0x20, 0x64, 0x75, 0x70, 0x22, 0x2C, 0x22, - 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, - 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, - 0x20, 0x64, 0x65, 0x70, 0x74, 0x68, 0x7D, 0x22, 0x2C, 0x22, 0x47, - 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x46, 0x6C, - 0x6F, 0x77, 0x20, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x22, - 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, - 0x22, 0x3A, 0x37, 0x36, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x73, 0x77, 0x61, 0x70, 0x22, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x2E, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x2E, - 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, - 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x73, 0x77, 0x61, 0x70, 0x73, 0x20, - 0x41, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x42, 0x20, 0x6F, 0x6E, 0x20, - 0x73, 0x74, 0x61, 0x63, 0x6B, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, - 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x46, 0x6C, 0x6F, 0x77, - 0x20, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x37, 0x37, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, - 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x22, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x2E, 0x55, 0x22, 0x2C, 0x22, - 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, - 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, - 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, - 0x73, 0x20, 0x6F, 0x6E, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x77, - 0x6F, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x20, 0x62, 0x61, - 0x73, 0x65, 0x64, 0x20, 0x6F, 0x6E, 0x20, 0x74, 0x6F, 0x70, 0x2D, - 0x6F, 0x66, 0x2D, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x3A, 0x20, 0x42, - 0x20, 0x69, 0x66, 0x20, 0x43, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x2C, - 0x20, 0x65, 0x6C, 0x73, 0x65, 0x20, 0x41, 0x22, 0x2C, 0x22, 0x47, - 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x46, 0x6C, - 0x6F, 0x77, 0x20, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x22, - 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, - 0x22, 0x3A, 0x37, 0x38, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x63, 0x6F, 0x76, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, - 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x72, 0x65, 0x6D, 0x6F, 0x76, 0x65, 0x20, - 0x74, 0x6F, 0x70, 0x20, 0x6F, 0x66, 0x20, 0x73, 0x74, 0x61, 0x63, - 0x6B, 0x2C, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x70, 0x6C, 0x61, 0x63, - 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x65, 0x65, 0x70, 0x65, 0x72, - 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, - 0x63, 0x6B, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x74, 0x68, 0x61, - 0x74, 0x20, 0x4E, 0x20, 0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, - 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x62, 0x6F, 0x76, 0x65, - 0x20, 0x69, 0x74, 0x2E, 0x20, 0x46, 0x61, 0x69, 0x6C, 0x73, 0x20, - 0x69, 0x66, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x20, 0x64, 0x65, - 0x70, 0x74, 0x68, 0x20, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x63, 0x3D, - 0x20, 0x4E, 0x2E, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, - 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, - 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x64, 0x65, 0x70, 0x74, - 0x68, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x46, 0x6C, 0x6F, 0x77, 0x20, 0x43, 0x6F, - 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x37, 0x39, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x75, 0x6E, 0x63, - 0x6F, 0x76, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, - 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, - 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, - 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, - 0x22, 0x72, 0x65, 0x6D, 0x6F, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x61, 0x74, 0x20, 0x64, - 0x65, 0x70, 0x74, 0x68, 0x20, 0x4E, 0x20, 0x69, 0x6E, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x20, 0x61, 0x6E, - 0x64, 0x20, 0x73, 0x68, 0x69, 0x66, 0x74, 0x20, 0x61, 0x62, 0x6F, - 0x76, 0x65, 0x20, 0x69, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x64, 0x6F, - 0x77, 0x6E, 0x20, 0x73, 0x6F, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4E, - 0x74, 0x68, 0x20, 0x64, 0x65, 0x65, 0x70, 0x20, 0x76, 0x61, 0x6C, - 0x75, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6F, 0x6E, 0x20, 0x74, 0x6F, - 0x70, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, - 0x61, 0x63, 0x6B, 0x2E, 0x20, 0x46, 0x61, 0x69, 0x6C, 0x73, 0x20, - 0x69, 0x66, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x20, 0x64, 0x65, - 0x70, 0x74, 0x68, 0x20, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x63, 0x3D, - 0x20, 0x4E, 0x2E, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, - 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, - 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x64, 0x65, 0x70, 0x74, - 0x68, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x46, 0x6C, 0x6F, 0x77, 0x20, 0x43, 0x6F, - 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x38, 0x30, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x63, 0x6F, 0x6E, - 0x63, 0x61, 0x74, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, - 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, - 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, - 0x22, 0x6A, 0x6F, 0x69, 0x6E, 0x20, 0x41, 0x20, 0x61, 0x6E, 0x64, - 0x20, 0x42, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, - 0x72, 0x61, 0x22, 0x3A, 0x22, 0x60, 0x63, 0x6F, 0x6E, 0x63, 0x61, - 0x74, 0x60, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x73, 0x20, 0x69, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, - 0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64, 0x20, 0x62, 0x65, 0x20, 0x67, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6E, - 0x20, 0x34, 0x30, 0x39, 0x36, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, - 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, - 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, - 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x38, 0x31, 0x2C, 0x22, 0x4E, 0x61, - 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x73, 0x75, 0x62, 0x73, 0x74, 0x72, - 0x69, 0x6E, 0x67, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x33, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x41, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x65, 0x20, 0x6F, 0x66, 0x20, - 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, - 0x41, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6E, 0x67, 0x20, - 0x61, 0x74, 0x20, 0x53, 0x20, 0x75, 0x70, 0x20, 0x74, 0x6F, 0x20, - 0x62, 0x75, 0x74, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x69, 0x6E, 0x63, - 0x6C, 0x75, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x45, 0x2E, 0x20, 0x49, - 0x66, 0x20, 0x45, 0x20, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x63, 0x20, - 0x53, 0x2C, 0x20, 0x6F, 0x72, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, - 0x72, 0x20, 0x69, 0x73, 0x20, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x72, - 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, - 0x2C, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, - 0x61, 0x6D, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x73, 0x22, 0x2C, 0x22, - 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, - 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, - 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x70, 0x6F, 0x73, 0x69, - 0x74, 0x69, 0x6F, 0x6E, 0x7D, 0x20, 0x7B, 0x75, 0x69, 0x6E, 0x74, - 0x38, 0x20, 0x65, 0x6E, 0x64, 0x20, 0x70, 0x6F, 0x73, 0x69, 0x74, - 0x69, 0x6F, 0x6E, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, - 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x4D, 0x61, 0x6E, 0x69, 0x70, - 0x75, 0x6C, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x38, - 0x32, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x73, - 0x75, 0x62, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x33, 0x22, 0x2C, - 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x55, 0x55, - 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, - 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x72, - 0x61, 0x6E, 0x67, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x62, 0x79, 0x74, - 0x65, 0x73, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x41, 0x20, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x61, 0x74, 0x20, - 0x42, 0x20, 0x75, 0x70, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x75, 0x74, - 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, - 0x69, 0x6E, 0x67, 0x20, 0x43, 0x2E, 0x20, 0x49, 0x66, 0x20, 0x43, - 0x20, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x63, 0x20, 0x42, 0x2C, 0x20, - 0x6F, 0x72, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, - 0x73, 0x20, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, - 0x61, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, - 0x79, 0x20, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x2C, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, - 0x66, 0x61, 0x69, 0x6C, 0x73, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, - 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x42, 0x79, 0x74, 0x65, - 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x4D, 0x61, 0x6E, 0x69, - 0x70, 0x75, 0x6C, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x38, 0x33, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, - 0x67, 0x65, 0x74, 0x62, 0x69, 0x74, 0x22, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x55, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x42, 0x74, 0x68, 0x20, 0x62, 0x69, 0x74, - 0x20, 0x6F, 0x66, 0x20, 0x28, 0x62, 0x79, 0x74, 0x65, 0x2D, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x6F, 0x72, 0x20, 0x69, 0x6E, 0x74, - 0x65, 0x67, 0x65, 0x72, 0x29, 0x20, 0x41, 0x2E, 0x22, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, - 0x73, 0x65, 0x65, 0x20, 0x65, 0x78, 0x70, 0x6C, 0x61, 0x6E, 0x61, - 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x6F, 0x66, 0x20, 0x62, 0x69, 0x74, - 0x20, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, - 0x6E, 0x20, 0x73, 0x65, 0x74, 0x62, 0x69, 0x74, 0x22, 0x2C, 0x22, - 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, - 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x38, 0x34, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x73, 0x65, 0x74, 0x62, 0x69, 0x74, 0x22, 0x2C, 0x22, 0x41, - 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x55, 0x55, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x43, 0x6F, 0x70, 0x79, 0x20, - 0x6F, 0x66, 0x20, 0x28, 0x62, 0x79, 0x74, 0x65, 0x2D, 0x61, 0x72, - 0x72, 0x61, 0x79, 0x20, 0x6F, 0x72, 0x20, 0x69, 0x6E, 0x74, 0x65, - 0x67, 0x65, 0x72, 0x29, 0x20, 0x41, 0x2C, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x42, 0x74, 0x68, 0x20, 0x62, - 0x69, 0x74, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x6F, 0x20, 0x28, - 0x30, 0x20, 0x6F, 0x72, 0x20, 0x31, 0x29, 0x20, 0x43, 0x22, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, - 0x22, 0x57, 0x68, 0x65, 0x6E, 0x20, 0x41, 0x20, 0x69, 0x73, 0x20, - 0x61, 0x20, 0x75, 0x69, 0x6E, 0x74, 0x36, 0x34, 0x2C, 0x20, 0x69, - 0x6E, 0x64, 0x65, 0x78, 0x20, 0x30, 0x20, 0x69, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x6C, 0x65, 0x61, 0x73, 0x74, 0x20, 0x73, 0x69, - 0x67, 0x6E, 0x69, 0x66, 0x69, 0x63, 0x61, 0x6E, 0x74, 0x20, 0x62, - 0x69, 0x74, 0x2E, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, - 0x20, 0x62, 0x69, 0x74, 0x20, 0x33, 0x20, 0x74, 0x6F, 0x20, 0x31, - 0x20, 0x6F, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6E, 0x74, - 0x65, 0x67, 0x65, 0x72, 0x20, 0x30, 0x20, 0x79, 0x69, 0x65, 0x6C, - 0x64, 0x73, 0x20, 0x38, 0x2C, 0x20, 0x6F, 0x72, 0x20, 0x32, 0x5E, - 0x33, 0x2E, 0x20, 0x57, 0x68, 0x65, 0x6E, 0x20, 0x41, 0x20, 0x69, - 0x73, 0x20, 0x61, 0x20, 0x62, 0x79, 0x74, 0x65, 0x20, 0x61, 0x72, - 0x72, 0x61, 0x79, 0x2C, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, - 0x30, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6C, 0x65, - 0x66, 0x74, 0x6D, 0x6F, 0x73, 0x74, 0x20, 0x62, 0x69, 0x74, 0x20, - 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6C, 0x65, 0x66, 0x74, - 0x6D, 0x6F, 0x73, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x2E, 0x20, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x62, 0x69, 0x74, - 0x73, 0x20, 0x30, 0x20, 0x74, 0x68, 0x72, 0x6F, 0x75, 0x67, 0x68, - 0x20, 0x31, 0x31, 0x20, 0x74, 0x6F, 0x20, 0x31, 0x20, 0x69, 0x6E, - 0x20, 0x61, 0x20, 0x34, 0x2D, 0x62, 0x79, 0x74, 0x65, 0x2D, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x6F, 0x66, 0x20, 0x30, 0x73, 0x20, - 0x79, 0x69, 0x65, 0x6C, 0x64, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x62, 0x79, 0x74, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, - 0x30, 0x78, 0x66, 0x66, 0x66, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2E, - 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x62, 0x69, - 0x74, 0x20, 0x33, 0x20, 0x74, 0x6F, 0x20, 0x31, 0x20, 0x6F, 0x6E, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x31, 0x2D, 0x62, 0x79, 0x74, 0x65, - 0x2D, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x30, 0x78, 0x30, 0x30, - 0x20, 0x79, 0x69, 0x65, 0x6C, 0x64, 0x73, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x62, 0x79, 0x74, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x20, 0x30, 0x78, 0x31, 0x30, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, - 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x38, - 0x35, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x67, - 0x65, 0x74, 0x62, 0x79, 0x74, 0x65, 0x22, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x55, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x42, 0x74, 0x68, 0x20, 0x62, 0x79, 0x74, - 0x65, 0x20, 0x6F, 0x66, 0x20, 0x41, 0x2C, 0x20, 0x61, 0x73, 0x20, - 0x61, 0x6E, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, - 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, - 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, - 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, - 0x65, 0x22, 0x3A, 0x38, 0x36, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, - 0x22, 0x3A, 0x22, 0x73, 0x65, 0x74, 0x62, 0x79, 0x74, 0x65, 0x22, - 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x55, - 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, - 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x43, 0x6F, - 0x70, 0x79, 0x20, 0x6F, 0x66, 0x20, 0x41, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x42, 0x74, 0x68, 0x20, 0x62, - 0x79, 0x74, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x6F, 0x20, - 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x67, - 0x65, 0x72, 0x20, 0x28, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6E, - 0x20, 0x30, 0x2E, 0x2E, 0x32, 0x35, 0x35, 0x29, 0x20, 0x43, 0x22, - 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, - 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, - 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, - 0x65, 0x22, 0x3A, 0x38, 0x37, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, - 0x22, 0x3A, 0x22, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x22, - 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, - 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, - 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x33, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x72, 0x61, - 0x6E, 0x67, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x62, 0x79, 0x74, 0x65, - 0x73, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x41, 0x20, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x61, 0x74, 0x20, 0x53, - 0x20, 0x75, 0x70, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x75, 0x74, 0x20, - 0x6E, 0x6F, 0x74, 0x20, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x69, - 0x6E, 0x67, 0x20, 0x53, 0x2B, 0x4C, 0x2E, 0x20, 0x49, 0x66, 0x20, - 0x4C, 0x20, 0x69, 0x73, 0x20, 0x30, 0x2C, 0x20, 0x74, 0x68, 0x65, - 0x6E, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x20, 0x74, - 0x6F, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6E, 0x64, 0x20, 0x6F, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, - 0x67, 0x2E, 0x20, 0x49, 0x66, 0x20, 0x53, 0x20, 0x6F, 0x72, 0x20, - 0x53, 0x2B, 0x4C, 0x20, 0x69, 0x73, 0x20, 0x6C, 0x61, 0x72, 0x67, - 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6C, 0x65, 0x6E, 0x67, - 0x74, 0x68, 0x2C, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6F, - 0x67, 0x72, 0x61, 0x6D, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x73, 0x22, - 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, - 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, - 0x74, 0x38, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x70, 0x6F, - 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x7D, 0x20, 0x7B, 0x75, 0x69, - 0x6E, 0x74, 0x38, 0x20, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x7D, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, - 0x5B, 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, 0x41, 0x72, 0x72, 0x61, - 0x79, 0x20, 0x4D, 0x61, 0x6E, 0x69, 0x70, 0x75, 0x6C, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, - 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x38, 0x38, 0x2C, 0x22, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x65, 0x78, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x33, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x55, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, - 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, - 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, - 0x3A, 0x22, 0x41, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x65, 0x20, 0x6F, - 0x66, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6F, - 0x6D, 0x20, 0x41, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6E, - 0x67, 0x20, 0x61, 0x74, 0x20, 0x42, 0x20, 0x75, 0x70, 0x20, 0x74, - 0x6F, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x69, - 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x42, 0x2B, - 0x43, 0x2E, 0x20, 0x49, 0x66, 0x20, 0x42, 0x2B, 0x43, 0x20, 0x69, - 0x73, 0x20, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, - 0x61, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, - 0x79, 0x20, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x2C, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, - 0x66, 0x61, 0x69, 0x6C, 0x73, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, - 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x42, 0x79, 0x74, 0x65, - 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x4D, 0x61, 0x6E, 0x69, - 0x70, 0x75, 0x6C, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x38, 0x39, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, - 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5F, 0x75, 0x69, 0x6E, - 0x74, 0x31, 0x36, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, - 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, - 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, - 0x22, 0x41, 0x20, 0x75, 0x69, 0x6E, 0x74, 0x31, 0x36, 0x20, 0x66, - 0x6F, 0x72, 0x6D, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, - 0x61, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x65, 0x20, 0x6F, 0x66, 0x20, - 0x62, 0x69, 0x67, 0x2D, 0x65, 0x6E, 0x64, 0x69, 0x61, 0x6E, 0x20, - 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, - 0x41, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6E, 0x67, 0x20, - 0x61, 0x74, 0x20, 0x42, 0x20, 0x75, 0x70, 0x20, 0x74, 0x6F, 0x20, - 0x62, 0x75, 0x74, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x69, 0x6E, 0x63, - 0x6C, 0x75, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x42, 0x2B, 0x32, 0x2E, - 0x20, 0x49, 0x66, 0x20, 0x42, 0x2B, 0x32, 0x20, 0x69, 0x73, 0x20, - 0x6C, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6E, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, - 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x2C, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x66, 0x61, - 0x69, 0x6C, 0x73, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, - 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x4D, 0x61, 0x6E, 0x69, 0x70, 0x75, - 0x6C, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, - 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x39, 0x30, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x65, 0x78, - 0x74, 0x72, 0x61, 0x63, 0x74, 0x5F, 0x75, 0x69, 0x6E, 0x74, 0x33, - 0x32, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, - 0x42, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, - 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, - 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, - 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, - 0x20, 0x75, 0x69, 0x6E, 0x74, 0x33, 0x32, 0x20, 0x66, 0x6F, 0x72, - 0x6D, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x61, 0x20, - 0x72, 0x61, 0x6E, 0x67, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x62, 0x69, - 0x67, 0x2D, 0x65, 0x6E, 0x64, 0x69, 0x61, 0x6E, 0x20, 0x62, 0x79, - 0x74, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x41, 0x20, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x61, 0x74, - 0x20, 0x42, 0x20, 0x75, 0x70, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x75, - 0x74, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x69, 0x6E, 0x63, 0x6C, 0x75, - 0x64, 0x69, 0x6E, 0x67, 0x20, 0x42, 0x2B, 0x34, 0x2E, 0x20, 0x49, - 0x66, 0x20, 0x42, 0x2B, 0x34, 0x20, 0x69, 0x73, 0x20, 0x6C, 0x61, - 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6C, 0x65, - 0x6E, 0x67, 0x74, 0x68, 0x2C, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, - 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x66, 0x61, 0x69, 0x6C, - 0x73, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, 0x41, 0x72, 0x72, - 0x61, 0x79, 0x20, 0x4D, 0x61, 0x6E, 0x69, 0x70, 0x75, 0x6C, 0x61, - 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, - 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x39, 0x31, 0x2C, 0x22, - 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x65, 0x78, 0x74, 0x72, - 0x61, 0x63, 0x74, 0x5F, 0x75, 0x69, 0x6E, 0x74, 0x36, 0x34, 0x22, - 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x55, - 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, - 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, - 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x75, - 0x69, 0x6E, 0x74, 0x36, 0x34, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x65, - 0x64, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x61, 0x20, 0x72, 0x61, - 0x6E, 0x67, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x62, 0x69, 0x67, 0x2D, - 0x65, 0x6E, 0x64, 0x69, 0x61, 0x6E, 0x20, 0x62, 0x79, 0x74, 0x65, - 0x73, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x41, 0x20, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x61, 0x74, 0x20, 0x42, - 0x20, 0x75, 0x70, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x75, 0x74, 0x20, - 0x6E, 0x6F, 0x74, 0x20, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x69, - 0x6E, 0x67, 0x20, 0x42, 0x2B, 0x38, 0x2E, 0x20, 0x49, 0x66, 0x20, - 0x42, 0x2B, 0x38, 0x20, 0x69, 0x73, 0x20, 0x6C, 0x61, 0x72, 0x67, - 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6C, 0x65, 0x6E, 0x67, - 0x74, 0x68, 0x2C, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6F, - 0x67, 0x72, 0x61, 0x6D, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x73, 0x22, - 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, - 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, - 0x20, 0x4D, 0x61, 0x6E, 0x69, 0x70, 0x75, 0x6C, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, - 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x39, 0x36, 0x2C, 0x22, 0x4E, 0x61, - 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x62, 0x61, 0x6C, 0x61, 0x6E, 0x63, - 0x65, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, - 0x2E, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, - 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x67, 0x65, - 0x74, 0x20, 0x62, 0x61, 0x6C, 0x61, 0x6E, 0x63, 0x65, 0x20, 0x66, - 0x6F, 0x72, 0x20, 0x61, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, - 0x41, 0x2C, 0x20, 0x69, 0x6E, 0x20, 0x6D, 0x69, 0x63, 0x72, 0x6F, - 0x61, 0x6C, 0x67, 0x6F, 0x73, 0x2E, 0x20, 0x54, 0x68, 0x65, 0x20, - 0x62, 0x61, 0x6C, 0x61, 0x6E, 0x63, 0x65, 0x20, 0x69, 0x73, 0x20, - 0x6F, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, - 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x66, 0x66, - 0x65, 0x63, 0x74, 0x73, 0x20, 0x6F, 0x66, 0x20, 0x70, 0x72, 0x65, - 0x76, 0x69, 0x6F, 0x75, 0x73, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x69, 0x6E, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, 0x2C, 0x20, - 0x61, 0x6E, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x66, 0x65, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, - 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, - 0x6E, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65, 0x64, 0x75, 0x63, 0x74, - 0x65, 0x64, 0x2E, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, - 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6D, - 0x73, 0x3A, 0x20, 0x54, 0x78, 0x6E, 0x2E, 0x41, 0x63, 0x63, 0x6F, - 0x75, 0x6E, 0x74, 0x73, 0x20, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x20, 0x28, 0x6F, 0x72, 0x2C, 0x20, 0x73, 0x69, 0x6E, 0x63, 0x65, - 0x20, 0x76, 0x34, 0x2C, 0x20, 0x61, 0x6E, 0x20, 0x5F, 0x61, 0x76, - 0x61, 0x69, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x20, 0x61, 0x63, - 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x29, 0x2C, 0x20, 0x5F, 0x61, 0x76, 0x61, 0x69, 0x6C, - 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x64, 0x20, 0x28, - 0x6F, 0x72, 0x2C, 0x20, 0x73, 0x69, 0x6E, 0x63, 0x65, 0x20, 0x76, - 0x34, 0x2C, 0x20, 0x61, 0x20, 0x54, 0x78, 0x6E, 0x2E, 0x46, 0x6F, - 0x72, 0x65, 0x69, 0x67, 0x6E, 0x41, 0x70, 0x70, 0x73, 0x20, 0x6F, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x2E, 0x20, 0x52, 0x65, 0x74, - 0x75, 0x72, 0x6E, 0x3A, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x2E, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, - 0x5B, 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, - 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x39, 0x37, 0x2C, 0x22, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x61, 0x70, 0x70, 0x5F, 0x6F, - 0x70, 0x74, 0x65, 0x64, 0x5F, 0x69, 0x6E, 0x22, 0x2C, 0x22, 0x41, - 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x55, 0x22, 0x2C, 0x22, - 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, - 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, - 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x31, 0x20, 0x69, 0x66, 0x20, 0x61, - 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x41, 0x20, 0x69, 0x73, - 0x20, 0x6F, 0x70, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6E, 0x20, 0x74, - 0x6F, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x20, 0x42, 0x2C, 0x20, 0x65, 0x6C, 0x73, 0x65, 0x20, - 0x30, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, - 0x61, 0x22, 0x3A, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73, 0x3A, - 0x20, 0x54, 0x78, 0x6E, 0x2E, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, - 0x74, 0x73, 0x20, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x28, - 0x6F, 0x72, 0x2C, 0x20, 0x73, 0x69, 0x6E, 0x63, 0x65, 0x20, 0x76, - 0x34, 0x2C, 0x20, 0x61, 0x6E, 0x20, 0x5F, 0x61, 0x76, 0x61, 0x69, - 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x20, 0x61, 0x63, 0x63, 0x6F, - 0x75, 0x6E, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x29, 0x2C, 0x20, 0x5F, 0x61, 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, - 0x6C, 0x65, 0x5F, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x64, 0x20, 0x28, 0x6F, 0x72, - 0x2C, 0x20, 0x73, 0x69, 0x6E, 0x63, 0x65, 0x20, 0x76, 0x34, 0x2C, - 0x20, 0x61, 0x20, 0x54, 0x78, 0x6E, 0x2E, 0x46, 0x6F, 0x72, 0x65, - 0x69, 0x67, 0x6E, 0x41, 0x70, 0x70, 0x73, 0x20, 0x6F, 0x66, 0x66, - 0x73, 0x65, 0x74, 0x29, 0x2E, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x3A, 0x20, 0x31, 0x20, 0x69, 0x66, 0x20, 0x6F, 0x70, 0x74, - 0x65, 0x64, 0x20, 0x69, 0x6E, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x30, - 0x20, 0x6F, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x2E, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, - 0x5B, 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, - 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x39, 0x38, 0x2C, 0x22, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x61, 0x70, 0x70, 0x5F, 0x6C, - 0x6F, 0x63, 0x61, 0x6C, 0x5F, 0x67, 0x65, 0x74, 0x22, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x42, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x6C, 0x6F, 0x63, 0x61, 0x6C, - 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x42, 0x20, 0x69, 0x6E, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, - 0x74, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x61, 0x63, 0x63, 0x6F, 0x75, - 0x6E, 0x74, 0x20, 0x41, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, - 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x70, 0x61, 0x72, 0x61, - 0x6D, 0x73, 0x3A, 0x20, 0x54, 0x78, 0x6E, 0x2E, 0x41, 0x63, 0x63, - 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x20, 0x6F, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x20, 0x28, 0x6F, 0x72, 0x2C, 0x20, 0x73, 0x69, 0x6E, 0x63, - 0x65, 0x20, 0x76, 0x34, 0x2C, 0x20, 0x61, 0x6E, 0x20, 0x5F, 0x61, - 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x20, 0x61, - 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x29, 0x2C, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x20, 0x6B, 0x65, 0x79, 0x2E, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x3A, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x2E, 0x20, 0x54, - 0x68, 0x65, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x69, 0x73, - 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x20, 0x28, 0x6F, 0x66, 0x20, 0x74, - 0x79, 0x70, 0x65, 0x20, 0x75, 0x69, 0x6E, 0x74, 0x36, 0x34, 0x29, - 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6B, 0x65, 0x79, - 0x20, 0x64, 0x6F, 0x65, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x65, - 0x78, 0x69, 0x73, 0x74, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, - 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x39, 0x39, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, - 0x61, 0x70, 0x70, 0x5F, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x5F, 0x67, - 0x65, 0x74, 0x5F, 0x65, 0x78, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, - 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x55, 0x42, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x55, - 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, - 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x58, 0x20, 0x69, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x20, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x61, 0x70, 0x70, 0x6C, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x42, 0x2C, 0x20, - 0x6B, 0x65, 0x79, 0x20, 0x43, 0x20, 0x69, 0x6E, 0x20, 0x61, 0x63, - 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x41, 0x2E, 0x20, 0x59, 0x20, - 0x69, 0x73, 0x20, 0x31, 0x20, 0x69, 0x66, 0x20, 0x6B, 0x65, 0x79, - 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x2C, 0x20, 0x65, - 0x6C, 0x73, 0x65, 0x20, 0x30, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, - 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x70, 0x61, 0x72, - 0x61, 0x6D, 0x73, 0x3A, 0x20, 0x54, 0x78, 0x6E, 0x2E, 0x41, 0x63, - 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x20, 0x6F, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x20, 0x28, 0x6F, 0x72, 0x2C, 0x20, 0x73, 0x69, 0x6E, - 0x63, 0x65, 0x20, 0x76, 0x34, 0x2C, 0x20, 0x61, 0x6E, 0x20, 0x5F, - 0x61, 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x20, - 0x61, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x29, 0x2C, 0x20, 0x5F, 0x61, 0x76, 0x61, - 0x69, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x20, 0x61, 0x70, 0x70, - 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x64, - 0x20, 0x28, 0x6F, 0x72, 0x2C, 0x20, 0x73, 0x69, 0x6E, 0x63, 0x65, - 0x20, 0x76, 0x34, 0x2C, 0x20, 0x61, 0x20, 0x54, 0x78, 0x6E, 0x2E, - 0x46, 0x6F, 0x72, 0x65, 0x69, 0x67, 0x6E, 0x41, 0x70, 0x70, 0x73, - 0x20, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x2C, 0x20, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x20, 0x6B, 0x65, 0x79, 0x2E, 0x20, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x3A, 0x20, 0x64, 0x69, 0x64, 0x5F, - 0x65, 0x78, 0x69, 0x73, 0x74, 0x20, 0x66, 0x6C, 0x61, 0x67, 0x20, - 0x28, 0x74, 0x6F, 0x70, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x2C, 0x20, 0x31, 0x20, 0x69, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x61, 0x6E, 0x64, 0x20, - 0x6B, 0x65, 0x79, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, - 0x20, 0x61, 0x6E, 0x64, 0x20, 0x30, 0x20, 0x6F, 0x74, 0x68, 0x65, - 0x72, 0x77, 0x69, 0x73, 0x65, 0x29, 0x2C, 0x20, 0x76, 0x61, 0x6C, - 0x75, 0x65, 0x2E, 0x20, 0x54, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6C, - 0x75, 0x65, 0x20, 0x69, 0x73, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x20, - 0x28, 0x6F, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x75, 0x69, - 0x6E, 0x74, 0x36, 0x34, 0x29, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x64, 0x6F, 0x65, 0x73, 0x20, - 0x6E, 0x6F, 0x74, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x2E, 0x22, - 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, - 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, - 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x30, 0x30, 0x2C, 0x22, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x61, 0x70, 0x70, 0x5F, 0x67, - 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x5F, 0x67, 0x65, 0x74, 0x22, 0x2C, - 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x67, 0x6C, 0x6F, 0x62, 0x61, - 0x6C, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x6F, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x41, 0x20, 0x69, - 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6E, 0x74, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, - 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6D, - 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x6B, 0x65, - 0x79, 0x2E, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x3A, 0x20, - 0x76, 0x61, 0x6C, 0x75, 0x65, 0x2E, 0x20, 0x54, 0x68, 0x65, 0x20, - 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x69, 0x73, 0x20, 0x7A, 0x65, - 0x72, 0x6F, 0x20, 0x28, 0x6F, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, - 0x20, 0x75, 0x69, 0x6E, 0x74, 0x36, 0x34, 0x29, 0x20, 0x69, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x64, 0x6F, - 0x65, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x65, 0x78, 0x69, 0x73, - 0x74, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x30, 0x31, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x61, 0x70, - 0x70, 0x5F, 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x5F, 0x67, 0x65, - 0x74, 0x5F, 0x65, 0x78, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, - 0x22, 0x3A, 0x22, 0x55, 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, - 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x55, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, - 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, - 0x22, 0x3A, 0x22, 0x58, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x2C, 0x20, 0x6B, - 0x65, 0x79, 0x20, 0x42, 0x2E, 0x20, 0x59, 0x20, 0x69, 0x73, 0x20, - 0x31, 0x20, 0x69, 0x66, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x65, 0x78, - 0x69, 0x73, 0x74, 0x65, 0x64, 0x2C, 0x20, 0x65, 0x6C, 0x73, 0x65, - 0x20, 0x30, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, - 0x72, 0x61, 0x22, 0x3A, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73, - 0x3A, 0x20, 0x54, 0x78, 0x6E, 0x2E, 0x46, 0x6F, 0x72, 0x65, 0x69, - 0x67, 0x6E, 0x41, 0x70, 0x70, 0x73, 0x20, 0x6F, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x20, 0x28, 0x6F, 0x72, 0x2C, 0x20, 0x73, 0x69, 0x6E, - 0x63, 0x65, 0x20, 0x76, 0x34, 0x2C, 0x20, 0x61, 0x6E, 0x20, 0x5F, - 0x61, 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x20, - 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, - 0x20, 0x69, 0x64, 0x29, 0x2C, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x20, 0x6B, 0x65, 0x79, 0x2E, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x3A, 0x20, 0x64, 0x69, 0x64, 0x5F, 0x65, 0x78, 0x69, 0x73, - 0x74, 0x20, 0x66, 0x6C, 0x61, 0x67, 0x20, 0x28, 0x74, 0x6F, 0x70, - 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, - 0x63, 0x6B, 0x2C, 0x20, 0x31, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x6B, 0x65, 0x79, 0x20, - 0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x20, 0x61, 0x6E, 0x64, - 0x20, 0x30, 0x20, 0x6F, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, - 0x65, 0x29, 0x2C, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x2E, 0x20, - 0x54, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x69, - 0x73, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x20, 0x28, 0x6F, 0x66, 0x20, - 0x74, 0x79, 0x70, 0x65, 0x20, 0x75, 0x69, 0x6E, 0x74, 0x36, 0x34, - 0x29, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6B, 0x65, - 0x79, 0x20, 0x64, 0x6F, 0x65, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, - 0x65, 0x78, 0x69, 0x73, 0x74, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x31, 0x30, 0x32, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x61, 0x70, 0x70, 0x5F, 0x6C, 0x6F, 0x63, 0x61, 0x6C, - 0x5F, 0x70, 0x75, 0x74, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, - 0x22, 0x3A, 0x22, 0x2E, 0x42, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x43, 0x20, 0x74, 0x6F, 0x20, - 0x6B, 0x65, 0x79, 0x20, 0x42, 0x20, 0x69, 0x6E, 0x20, 0x61, 0x63, - 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x41, 0x27, 0x73, 0x20, 0x6C, - 0x6F, 0x63, 0x61, 0x6C, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, - 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6E, 0x74, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, - 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x70, 0x61, 0x72, 0x61, - 0x6D, 0x73, 0x3A, 0x20, 0x54, 0x78, 0x6E, 0x2E, 0x41, 0x63, 0x63, - 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x20, 0x6F, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x20, 0x28, 0x6F, 0x72, 0x2C, 0x20, 0x73, 0x69, 0x6E, 0x63, - 0x65, 0x20, 0x76, 0x34, 0x2C, 0x20, 0x61, 0x6E, 0x20, 0x5F, 0x61, - 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x20, 0x61, - 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x29, 0x2C, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x20, 0x6B, 0x65, 0x79, 0x2C, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, - 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, - 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x30, 0x33, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x61, 0x70, 0x70, - 0x5F, 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x5F, 0x70, 0x75, 0x74, - 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, - 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x77, 0x72, 0x69, 0x74, 0x65, - 0x20, 0x42, 0x20, 0x74, 0x6F, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x41, - 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6C, 0x6F, - 0x62, 0x61, 0x6C, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x6F, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6E, 0x74, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, - 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, - 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x30, - 0x34, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x61, - 0x70, 0x70, 0x5F, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x5F, 0x64, 0x65, - 0x6C, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, - 0x2E, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x64, 0x65, 0x6C, 0x65, - 0x74, 0x65, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x42, 0x20, 0x66, 0x72, - 0x6F, 0x6D, 0x20, 0x61, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, - 0x41, 0x27, 0x73, 0x20, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x20, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x20, 0x61, 0x70, - 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, - 0x22, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73, 0x3A, 0x20, 0x54, 0x78, - 0x6E, 0x2E, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x20, - 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x28, 0x6F, 0x72, 0x2C, - 0x20, 0x73, 0x69, 0x6E, 0x63, 0x65, 0x20, 0x76, 0x34, 0x2C, 0x20, - 0x61, 0x6E, 0x20, 0x5F, 0x61, 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, - 0x6C, 0x65, 0x5F, 0x20, 0x61, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, - 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x29, 0x2C, 0x20, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x6B, 0x65, 0x79, 0x2E, 0x5C, - 0x6E, 0x5C, 0x6E, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x69, 0x6E, 0x67, - 0x20, 0x61, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x77, 0x68, 0x69, 0x63, - 0x68, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6C, 0x72, 0x65, 0x61, 0x64, - 0x79, 0x20, 0x61, 0x62, 0x73, 0x65, 0x6E, 0x74, 0x20, 0x68, 0x61, - 0x73, 0x20, 0x6E, 0x6F, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, - 0x20, 0x6F, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, - 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x6C, 0x6F, - 0x63, 0x61, 0x6C, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2E, 0x20, - 0x28, 0x49, 0x6E, 0x20, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x75, - 0x6C, 0x61, 0x72, 0x2C, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x65, - 0x73, 0x20, 0x5F, 0x6E, 0x6F, 0x74, 0x5F, 0x20, 0x63, 0x61, 0x75, - 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6F, 0x67, - 0x72, 0x61, 0x6D, 0x20, 0x74, 0x6F, 0x20, 0x66, 0x61, 0x69, 0x6C, - 0x2E, 0x29, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x30, 0x35, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x61, 0x70, - 0x70, 0x5F, 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x5F, 0x64, 0x65, - 0x6C, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, - 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x64, 0x65, 0x6C, 0x65, 0x74, - 0x65, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x41, 0x20, 0x66, 0x72, 0x6F, - 0x6D, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6C, 0x6F, 0x62, 0x61, - 0x6C, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x6F, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, - 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, - 0x6E, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, - 0x61, 0x22, 0x3A, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73, 0x3A, - 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x6B, 0x65, 0x79, 0x2E, - 0x5C, 0x6E, 0x5C, 0x6E, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x69, 0x6E, - 0x67, 0x20, 0x61, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x77, 0x68, 0x69, - 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6C, 0x72, 0x65, 0x61, - 0x64, 0x79, 0x20, 0x61, 0x62, 0x73, 0x65, 0x6E, 0x74, 0x20, 0x68, - 0x61, 0x73, 0x20, 0x6E, 0x6F, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, - 0x74, 0x20, 0x6F, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, - 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x67, - 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2E, 0x20, 0x28, 0x49, 0x6E, 0x20, 0x70, 0x61, 0x72, 0x74, 0x69, - 0x63, 0x75, 0x6C, 0x61, 0x72, 0x2C, 0x20, 0x69, 0x74, 0x20, 0x64, - 0x6F, 0x65, 0x73, 0x20, 0x5F, 0x6E, 0x6F, 0x74, 0x5F, 0x20, 0x63, - 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, - 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x74, 0x6F, 0x20, 0x66, 0x61, - 0x69, 0x6C, 0x2E, 0x29, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, - 0x31, 0x32, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, - 0x61, 0x73, 0x73, 0x65, 0x74, 0x5F, 0x68, 0x6F, 0x6C, 0x64, 0x69, - 0x6E, 0x67, 0x5F, 0x67, 0x65, 0x74, 0x22, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x55, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x55, - 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x41, - 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x22, 0x3A, 0x5B, 0x22, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x42, 0x61, 0x6C, 0x61, 0x6E, 0x63, 0x65, - 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x46, 0x72, 0x6F, - 0x7A, 0x65, 0x6E, 0x22, 0x5D, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, - 0x6E, 0x75, 0x6D, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x55, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x58, 0x20, 0x69, 0x73, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, - 0x46, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x61, 0x63, 0x63, 0x6F, - 0x75, 0x6E, 0x74, 0x20, 0x41, 0x27, 0x73, 0x20, 0x68, 0x6F, 0x6C, - 0x64, 0x69, 0x6E, 0x67, 0x20, 0x6F, 0x66, 0x20, 0x61, 0x73, 0x73, - 0x65, 0x74, 0x20, 0x42, 0x2E, 0x20, 0x59, 0x20, 0x69, 0x73, 0x20, - 0x31, 0x20, 0x69, 0x66, 0x20, 0x41, 0x20, 0x69, 0x73, 0x20, 0x6F, - 0x70, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6E, 0x74, 0x6F, 0x20, 0x42, - 0x2C, 0x20, 0x65, 0x6C, 0x73, 0x65, 0x20, 0x30, 0x22, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, - 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73, 0x3A, 0x20, 0x54, 0x78, 0x6E, - 0x2E, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x20, 0x6F, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x28, 0x6F, 0x72, 0x2C, 0x20, - 0x73, 0x69, 0x6E, 0x63, 0x65, 0x20, 0x76, 0x34, 0x2C, 0x20, 0x61, - 0x6E, 0x20, 0x5F, 0x61, 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, 0x6C, - 0x65, 0x5F, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x29, - 0x2C, 0x20, 0x61, 0x73, 0x73, 0x65, 0x74, 0x20, 0x69, 0x64, 0x20, - 0x28, 0x6F, 0x72, 0x2C, 0x20, 0x73, 0x69, 0x6E, 0x63, 0x65, 0x20, - 0x76, 0x34, 0x2C, 0x20, 0x61, 0x20, 0x54, 0x78, 0x6E, 0x2E, 0x46, - 0x6F, 0x72, 0x65, 0x69, 0x67, 0x6E, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x73, 0x20, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x2E, 0x20, - 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x3A, 0x20, 0x64, 0x69, 0x64, - 0x5F, 0x65, 0x78, 0x69, 0x73, 0x74, 0x20, 0x66, 0x6C, 0x61, 0x67, - 0x20, 0x28, 0x31, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x61, 0x73, 0x73, 0x65, 0x74, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, - 0x65, 0x64, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x30, 0x20, 0x6F, 0x74, - 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x29, 0x2C, 0x20, 0x76, - 0x61, 0x6C, 0x75, 0x65, 0x2E, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, - 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, - 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x61, 0x73, - 0x73, 0x65, 0x74, 0x20, 0x68, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, - 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x69, 0x6E, 0x64, 0x65, - 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x31, 0x33, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x61, 0x73, - 0x73, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73, 0x5F, - 0x67, 0x65, 0x74, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x55, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, - 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, - 0x75, 0x6D, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x54, 0x6F, 0x74, 0x61, 0x6C, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x44, 0x65, 0x63, 0x69, 0x6D, 0x61, 0x6C, 0x73, 0x22, - 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, - 0x75, 0x6C, 0x74, 0x46, 0x72, 0x6F, 0x7A, 0x65, 0x6E, 0x22, 0x2C, - 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x55, 0x6E, 0x69, 0x74, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x55, 0x52, 0x4C, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x4D, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x61, - 0x73, 0x68, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4D, - 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x22, - 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x46, 0x72, 0x65, 0x65, - 0x7A, 0x65, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x43, - 0x6C, 0x61, 0x77, 0x62, 0x61, 0x63, 0x6B, 0x22, 0x2C, 0x22, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6F, 0x72, - 0x22, 0x5D, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, - 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x55, - 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x22, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x58, 0x20, 0x69, 0x73, - 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x46, 0x20, 0x66, 0x72, - 0x6F, 0x6D, 0x20, 0x61, 0x73, 0x73, 0x65, 0x74, 0x20, 0x41, 0x2E, - 0x20, 0x59, 0x20, 0x69, 0x73, 0x20, 0x31, 0x20, 0x69, 0x66, 0x20, - 0x41, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x2C, 0x20, 0x65, - 0x6C, 0x73, 0x65, 0x20, 0x30, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, - 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x70, 0x61, 0x72, - 0x61, 0x6D, 0x73, 0x3A, 0x20, 0x54, 0x78, 0x6E, 0x2E, 0x46, 0x6F, - 0x72, 0x65, 0x69, 0x67, 0x6E, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, - 0x20, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x28, 0x6F, 0x72, - 0x2C, 0x20, 0x73, 0x69, 0x6E, 0x63, 0x65, 0x20, 0x76, 0x34, 0x2C, - 0x20, 0x61, 0x6E, 0x20, 0x5F, 0x61, 0x76, 0x61, 0x69, 0x6C, 0x61, - 0x62, 0x6C, 0x65, 0x5F, 0x20, 0x61, 0x73, 0x73, 0x65, 0x74, 0x20, - 0x69, 0x64, 0x2E, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x3A, - 0x20, 0x64, 0x69, 0x64, 0x5F, 0x65, 0x78, 0x69, 0x73, 0x74, 0x20, - 0x66, 0x6C, 0x61, 0x67, 0x20, 0x28, 0x31, 0x20, 0x69, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x61, 0x73, 0x73, 0x65, 0x74, 0x20, 0x65, - 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x20, 0x61, 0x6E, 0x64, 0x20, - 0x30, 0x20, 0x6F, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, - 0x29, 0x2C, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x2E, 0x22, 0x2C, - 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, - 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, - 0x38, 0x20, 0x61, 0x73, 0x73, 0x65, 0x74, 0x20, 0x70, 0x61, 0x72, - 0x61, 0x6D, 0x73, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x69, - 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, - 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x31, 0x31, 0x34, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x61, 0x70, 0x70, 0x5F, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73, - 0x5F, 0x67, 0x65, 0x74, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, - 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, - 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x55, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, - 0x7A, 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, - 0x6E, 0x75, 0x6D, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x70, 0x70, 0x41, - 0x70, 0x70, 0x72, 0x6F, 0x76, 0x61, 0x6C, 0x50, 0x72, 0x6F, 0x67, - 0x72, 0x61, 0x6D, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x43, 0x6C, - 0x65, 0x61, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6F, - 0x67, 0x72, 0x61, 0x6D, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x47, - 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x55, 0x69, 0x6E, - 0x74, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x47, 0x6C, 0x6F, 0x62, - 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x42, 0x79, 0x74, 0x65, 0x53, 0x6C, - 0x69, 0x63, 0x65, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x4C, 0x6F, - 0x63, 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x55, 0x69, 0x6E, 0x74, 0x22, - 0x2C, 0x22, 0x41, 0x70, 0x70, 0x4C, 0x6F, 0x63, 0x61, 0x6C, 0x4E, - 0x75, 0x6D, 0x42, 0x79, 0x74, 0x65, 0x53, 0x6C, 0x69, 0x63, 0x65, - 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x45, 0x78, 0x74, 0x72, 0x61, - 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x50, 0x61, 0x67, 0x65, - 0x73, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x6F, 0x72, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x5D, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x42, 0x55, 0x55, 0x55, 0x55, 0x55, 0x42, 0x42, - 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x58, 0x20, - 0x69, 0x73, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x46, 0x20, - 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x61, 0x70, 0x70, 0x20, 0x41, 0x2E, - 0x20, 0x59, 0x20, 0x69, 0x73, 0x20, 0x31, 0x20, 0x69, 0x66, 0x20, - 0x41, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x2C, 0x20, 0x65, - 0x6C, 0x73, 0x65, 0x20, 0x30, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, - 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x70, 0x61, 0x72, - 0x61, 0x6D, 0x73, 0x3A, 0x20, 0x54, 0x78, 0x6E, 0x2E, 0x46, 0x6F, - 0x72, 0x65, 0x69, 0x67, 0x6E, 0x41, 0x70, 0x70, 0x73, 0x20, 0x6F, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x6F, 0x72, 0x20, 0x61, 0x6E, - 0x20, 0x5F, 0x61, 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, 0x6C, 0x65, - 0x5F, 0x20, 0x61, 0x70, 0x70, 0x20, 0x69, 0x64, 0x2E, 0x20, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x3A, 0x20, 0x64, 0x69, 0x64, 0x5F, - 0x65, 0x78, 0x69, 0x73, 0x74, 0x20, 0x66, 0x6C, 0x61, 0x67, 0x20, - 0x28, 0x31, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, - 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, - 0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x20, 0x61, 0x6E, 0x64, - 0x20, 0x30, 0x20, 0x6F, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, - 0x65, 0x29, 0x2C, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x2E, 0x22, - 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, - 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, - 0x74, 0x38, 0x20, 0x61, 0x70, 0x70, 0x20, 0x70, 0x61, 0x72, 0x61, - 0x6D, 0x73, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x69, 0x6E, - 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, - 0x31, 0x35, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, - 0x61, 0x63, 0x63, 0x74, 0x5F, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73, - 0x5F, 0x67, 0x65, 0x74, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, - 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, - 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x55, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, - 0x7A, 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, - 0x3A, 0x22, 0x58, 0x20, 0x69, 0x73, 0x20, 0x66, 0x69, 0x65, 0x6C, - 0x64, 0x20, 0x46, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x61, 0x63, - 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x41, 0x2E, 0x20, 0x59, 0x20, - 0x69, 0x73, 0x20, 0x31, 0x20, 0x69, 0x66, 0x20, 0x41, 0x20, 0x6F, - 0x77, 0x6E, 0x73, 0x20, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x20, 0x61, 0x6C, 0x67, 0x6F, 0x73, 0x2C, 0x20, 0x65, 0x6C, - 0x73, 0x65, 0x20, 0x30, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, - 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, - 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x61, 0x63, 0x63, - 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73, - 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x69, 0x6E, 0x64, 0x65, - 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x32, 0x30, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, - 0x6E, 0x5F, 0x62, 0x61, 0x6C, 0x61, 0x6E, 0x63, 0x65, 0x22, 0x2C, - 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x67, 0x65, 0x74, 0x20, 0x6D, - 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x20, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x20, 0x62, 0x61, 0x6C, 0x61, 0x6E, 0x63, - 0x65, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x61, 0x63, 0x63, 0x6F, 0x75, - 0x6E, 0x74, 0x20, 0x41, 0x2C, 0x20, 0x69, 0x6E, 0x20, 0x6D, 0x69, - 0x63, 0x72, 0x6F, 0x61, 0x6C, 0x67, 0x6F, 0x73, 0x2E, 0x20, 0x52, - 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x62, 0x61, 0x6C, - 0x61, 0x6E, 0x63, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x66, 0x66, - 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x5B, 0x41, - 0x53, 0x41, 0x5D, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, - 0x2F, 0x64, 0x65, 0x76, 0x65, 0x6C, 0x6F, 0x70, 0x65, 0x72, 0x2E, - 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2E, 0x6F, 0x72, - 0x67, 0x2F, 0x64, 0x6F, 0x63, 0x73, 0x2F, 0x66, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x73, 0x2F, 0x61, 0x73, 0x61, 0x2F, 0x23, 0x61, - 0x73, 0x73, 0x65, 0x74, 0x73, 0x2D, 0x6F, 0x76, 0x65, 0x72, 0x76, - 0x69, 0x65, 0x77, 0x29, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x5B, 0x41, - 0x70, 0x70, 0x5D, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, - 0x2F, 0x64, 0x65, 0x76, 0x65, 0x6C, 0x6F, 0x70, 0x65, 0x72, 0x2E, - 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x61, 0x6E, 0x64, 0x2E, 0x6F, 0x72, - 0x67, 0x2F, 0x64, 0x6F, 0x63, 0x73, 0x2F, 0x66, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x73, 0x2F, 0x61, 0x73, 0x63, 0x31, 0x2F, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x66, 0x75, 0x6C, 0x2F, 0x23, 0x6D, 0x69, - 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x2D, 0x62, 0x61, 0x6C, 0x61, 0x6E, - 0x63, 0x65, 0x2D, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6D, - 0x65, 0x6E, 0x74, 0x2D, 0x66, 0x6F, 0x72, 0x2D, 0x61, 0x2D, 0x73, - 0x6D, 0x61, 0x72, 0x74, 0x2D, 0x63, 0x6F, 0x6E, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x29, 0x20, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2E, 0x20, - 0x57, 0x68, 0x65, 0x6E, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, - 0x6E, 0x67, 0x20, 0x6F, 0x72, 0x20, 0x6F, 0x70, 0x74, 0x69, 0x6E, - 0x67, 0x20, 0x69, 0x6E, 0x74, 0x6F, 0x20, 0x61, 0x6E, 0x20, 0x61, - 0x70, 0x70, 0x2C, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6D, 0x69, 0x6E, - 0x69, 0x6D, 0x75, 0x6D, 0x20, 0x62, 0x61, 0x6C, 0x61, 0x6E, 0x63, - 0x65, 0x20, 0x67, 0x72, 0x6F, 0x77, 0x73, 0x20, 0x62, 0x65, 0x66, - 0x6F, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, - 0x20, 0x63, 0x6F, 0x64, 0x65, 0x20, 0x72, 0x75, 0x6E, 0x73, 0x2C, - 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6F, 0x72, 0x65, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x69, 0x6E, 0x63, 0x72, 0x65, 0x61, 0x73, - 0x65, 0x20, 0x69, 0x73, 0x20, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6C, - 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2E, 0x20, 0x57, 0x68, - 0x65, 0x6E, 0x20, 0x64, 0x65, 0x6C, 0x65, 0x74, 0x69, 0x6E, 0x67, - 0x20, 0x6F, 0x72, 0x20, 0x63, 0x6C, 0x6F, 0x73, 0x69, 0x6E, 0x67, - 0x20, 0x6F, 0x75, 0x74, 0x2C, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6D, - 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x20, 0x62, 0x61, 0x6C, 0x61, - 0x6E, 0x63, 0x65, 0x20, 0x64, 0x65, 0x63, 0x72, 0x65, 0x61, 0x73, - 0x65, 0x73, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x61, 0x70, 0x70, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x65, 0x73, 0x2E, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, - 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x70, 0x61, 0x72, 0x61, - 0x6D, 0x73, 0x3A, 0x20, 0x54, 0x78, 0x6E, 0x2E, 0x41, 0x63, 0x63, - 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x20, 0x6F, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x20, 0x28, 0x6F, 0x72, 0x2C, 0x20, 0x73, 0x69, 0x6E, 0x63, - 0x65, 0x20, 0x76, 0x34, 0x2C, 0x20, 0x61, 0x6E, 0x20, 0x5F, 0x61, - 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x20, 0x61, - 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x29, 0x2C, 0x20, 0x5F, 0x61, 0x76, 0x61, 0x69, - 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x20, 0x61, 0x70, 0x70, 0x6C, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x64, 0x20, - 0x28, 0x6F, 0x72, 0x2C, 0x20, 0x73, 0x69, 0x6E, 0x63, 0x65, 0x20, - 0x76, 0x34, 0x2C, 0x20, 0x61, 0x20, 0x54, 0x78, 0x6E, 0x2E, 0x46, - 0x6F, 0x72, 0x65, 0x69, 0x67, 0x6E, 0x41, 0x70, 0x70, 0x73, 0x20, - 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x2E, 0x20, 0x52, 0x65, - 0x74, 0x75, 0x72, 0x6E, 0x3A, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, - 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, - 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x32, 0x38, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x70, 0x75, 0x73, - 0x68, 0x62, 0x79, 0x74, 0x65, 0x73, 0x22, 0x2C, 0x22, 0x52, 0x65, - 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, - 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x30, 0x2C, 0x22, 0x44, 0x6F, 0x63, - 0x22, 0x3A, 0x22, 0x69, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, - 0x65, 0x20, 0x42, 0x59, 0x54, 0x45, 0x53, 0x22, 0x2C, 0x22, 0x44, - 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x70, - 0x75, 0x73, 0x68, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x61, 0x72, - 0x67, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6E, 0x6F, 0x74, 0x20, - 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x62, 0x79, 0x74, 0x65, 0x63, 0x62, 0x6C, 0x6F, 0x63, - 0x6B, 0x20, 0x64, 0x75, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x61, 0x73, - 0x73, 0x65, 0x6D, 0x62, 0x6C, 0x79, 0x20, 0x70, 0x72, 0x6F, 0x63, - 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, - 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, - 0x3A, 0x22, 0x7B, 0x76, 0x61, 0x72, 0x75, 0x69, 0x6E, 0x74, 0x20, - 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x7D, 0x20, 0x7B, 0x62, 0x79, - 0x74, 0x65, 0x73, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, - 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x31, 0x32, 0x39, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x70, 0x75, 0x73, 0x68, 0x69, 0x6E, 0x74, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x30, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x69, 0x6D, 0x6D, 0x65, 0x64, - 0x69, 0x61, 0x74, 0x65, 0x20, 0x55, 0x49, 0x4E, 0x54, 0x22, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, - 0x22, 0x70, 0x75, 0x73, 0x68, 0x69, 0x6E, 0x74, 0x20, 0x61, 0x72, - 0x67, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6E, 0x6F, 0x74, 0x20, - 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x69, 0x6E, 0x74, 0x63, 0x62, 0x6C, 0x6F, 0x63, 0x6B, - 0x20, 0x64, 0x75, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x61, 0x73, 0x73, - 0x65, 0x6D, 0x62, 0x6C, 0x79, 0x20, 0x70, 0x72, 0x6F, 0x63, 0x65, - 0x73, 0x73, 0x65, 0x73, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, - 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, - 0x22, 0x7B, 0x76, 0x61, 0x72, 0x75, 0x69, 0x6E, 0x74, 0x20, 0x69, - 0x6E, 0x74, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, - 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, - 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x31, 0x33, 0x36, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x63, 0x61, 0x6C, 0x6C, 0x73, 0x75, 0x62, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, - 0x7A, 0x65, 0x22, 0x3A, 0x33, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, - 0x3A, 0x22, 0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x20, 0x75, 0x6E, - 0x63, 0x6F, 0x6E, 0x64, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x61, 0x6C, - 0x6C, 0x79, 0x20, 0x74, 0x6F, 0x20, 0x54, 0x41, 0x52, 0x47, 0x45, - 0x54, 0x2C, 0x20, 0x73, 0x61, 0x76, 0x69, 0x6E, 0x67, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x6E, 0x65, 0x78, 0x74, 0x20, 0x69, 0x6E, 0x73, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6C, 0x6C, 0x20, 0x73, - 0x74, 0x61, 0x63, 0x6B, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, - 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x54, 0x68, 0x65, 0x20, - 0x63, 0x61, 0x6C, 0x6C, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x20, - 0x69, 0x73, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, - 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, - 0x61, 0x74, 0x61, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x2E, 0x20, - 0x4F, 0x6E, 0x6C, 0x79, 0x20, 0x60, 0x63, 0x61, 0x6C, 0x6C, 0x73, - 0x75, 0x62, 0x60, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x60, 0x72, 0x65, - 0x74, 0x73, 0x75, 0x62, 0x60, 0x20, 0x6D, 0x61, 0x6E, 0x69, 0x70, - 0x75, 0x6C, 0x61, 0x74, 0x65, 0x20, 0x69, 0x74, 0x2E, 0x22, 0x2C, - 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, - 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x69, 0x6E, 0x74, 0x31, - 0x36, 0x20, 0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x20, 0x6F, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x2C, 0x20, 0x62, 0x69, 0x67, 0x20, 0x65, - 0x6E, 0x64, 0x69, 0x61, 0x6E, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x46, 0x6C, 0x6F, - 0x77, 0x20, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x31, 0x33, 0x37, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x72, 0x65, 0x74, 0x73, 0x75, 0x62, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, - 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, - 0x3A, 0x22, 0x70, 0x6F, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, - 0x6F, 0x70, 0x20, 0x69, 0x6E, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x63, 0x61, 0x6C, 0x6C, 0x20, 0x73, 0x74, 0x61, 0x63, - 0x6B, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x62, 0x72, 0x61, 0x6E, 0x63, - 0x68, 0x20, 0x74, 0x6F, 0x20, 0x69, 0x74, 0x22, 0x2C, 0x22, 0x44, - 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x54, - 0x68, 0x65, 0x20, 0x63, 0x61, 0x6C, 0x6C, 0x20, 0x73, 0x74, 0x61, - 0x63, 0x6B, 0x20, 0x69, 0x73, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, - 0x61, 0x74, 0x65, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x73, 0x74, 0x61, 0x63, - 0x6B, 0x2E, 0x20, 0x4F, 0x6E, 0x6C, 0x79, 0x20, 0x60, 0x63, 0x61, - 0x6C, 0x6C, 0x73, 0x75, 0x62, 0x60, 0x20, 0x61, 0x6E, 0x64, 0x20, - 0x60, 0x72, 0x65, 0x74, 0x73, 0x75, 0x62, 0x60, 0x20, 0x6D, 0x61, - 0x6E, 0x69, 0x70, 0x75, 0x6C, 0x61, 0x74, 0x65, 0x20, 0x69, 0x74, - 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x46, 0x6C, 0x6F, 0x77, 0x20, 0x43, 0x6F, 0x6E, - 0x74, 0x72, 0x6F, 0x6C, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, - 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x34, 0x34, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x73, 0x68, 0x6C, - 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, - 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, - 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, - 0x74, 0x69, 0x6D, 0x65, 0x73, 0x20, 0x32, 0x5E, 0x42, 0x2C, 0x20, - 0x6D, 0x6F, 0x64, 0x75, 0x6C, 0x6F, 0x20, 0x32, 0x5E, 0x36, 0x34, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, - 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, - 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, - 0x64, 0x65, 0x22, 0x3A, 0x31, 0x34, 0x35, 0x2C, 0x22, 0x4E, 0x61, - 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x73, 0x68, 0x72, 0x22, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x64, 0x69, 0x76, - 0x69, 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x32, 0x5E, 0x42, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, - 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, - 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, - 0x64, 0x65, 0x22, 0x3A, 0x31, 0x34, 0x36, 0x2C, 0x22, 0x4E, 0x61, - 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x73, 0x71, 0x72, 0x74, 0x22, 0x2C, - 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x34, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x54, 0x68, 0x65, 0x20, 0x6C, - 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6E, 0x74, 0x65, - 0x67, 0x65, 0x72, 0x20, 0x49, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, - 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x5E, 0x32, 0x20, 0x5C, 0x75, - 0x30, 0x30, 0x33, 0x63, 0x3D, 0x20, 0x41, 0x22, 0x2C, 0x22, 0x47, - 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, - 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x31, 0x34, 0x37, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x62, 0x69, 0x74, 0x6C, 0x65, 0x6E, 0x22, 0x2C, 0x22, 0x41, - 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x54, 0x68, 0x65, 0x20, 0x68, 0x69, 0x67, - 0x68, 0x65, 0x73, 0x74, 0x20, 0x73, 0x65, 0x74, 0x20, 0x62, 0x69, - 0x74, 0x20, 0x69, 0x6E, 0x20, 0x41, 0x2E, 0x20, 0x49, 0x66, 0x20, - 0x41, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x62, 0x79, 0x74, 0x65, - 0x2D, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2C, 0x20, 0x69, 0x74, 0x20, - 0x69, 0x73, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, - 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x62, 0x69, - 0x67, 0x2D, 0x65, 0x6E, 0x64, 0x69, 0x61, 0x6E, 0x20, 0x75, 0x6E, - 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x20, 0x69, 0x6E, 0x74, 0x65, - 0x67, 0x65, 0x72, 0x2E, 0x20, 0x62, 0x69, 0x74, 0x6C, 0x65, 0x6E, - 0x20, 0x6F, 0x66, 0x20, 0x30, 0x20, 0x69, 0x73, 0x20, 0x30, 0x2C, - 0x20, 0x62, 0x69, 0x74, 0x6C, 0x65, 0x6E, 0x20, 0x6F, 0x66, 0x20, - 0x38, 0x20, 0x69, 0x73, 0x20, 0x34, 0x22, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x62, 0x69, - 0x74, 0x6C, 0x65, 0x6E, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x65, 0x74, 0x73, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x73, - 0x20, 0x61, 0x73, 0x20, 0x62, 0x69, 0x67, 0x2D, 0x65, 0x6E, 0x64, - 0x69, 0x61, 0x6E, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, - 0x73, 0x2C, 0x20, 0x75, 0x6E, 0x6C, 0x69, 0x6B, 0x65, 0x20, 0x73, - 0x65, 0x74, 0x62, 0x69, 0x74, 0x2F, 0x67, 0x65, 0x74, 0x62, 0x69, - 0x74, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, - 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, - 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x34, 0x38, 0x2C, 0x22, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x65, 0x78, 0x70, 0x22, 0x2C, - 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, - 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, - 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x72, 0x61, - 0x69, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x42, 0x74, 0x68, 0x20, 0x70, 0x6F, 0x77, 0x65, 0x72, 0x2E, - 0x20, 0x46, 0x61, 0x69, 0x6C, 0x20, 0x69, 0x66, 0x20, 0x41, 0x20, - 0x3D, 0x3D, 0x20, 0x42, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x20, 0x61, - 0x6E, 0x64, 0x20, 0x6F, 0x6E, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x66, - 0x6C, 0x6F, 0x77, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, - 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, - 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, - 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x34, 0x39, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x65, 0x78, 0x70, - 0x77, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, - 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x30, 0x2C, 0x22, 0x53, 0x69, 0x7A, - 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, - 0x22, 0x41, 0x20, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0x20, 0x74, - 0x6F, 0x20, 0x74, 0x68, 0x65, 0x20, 0x42, 0x74, 0x68, 0x20, 0x70, - 0x6F, 0x77, 0x65, 0x72, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x31, - 0x32, 0x38, 0x2D, 0x62, 0x69, 0x74, 0x20, 0x72, 0x65, 0x73, 0x75, - 0x6C, 0x74, 0x20, 0x69, 0x6E, 0x20, 0x74, 0x77, 0x6F, 0x20, 0x75, - 0x69, 0x6E, 0x74, 0x36, 0x34, 0x73, 0x2E, 0x20, 0x58, 0x20, 0x69, - 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, - 0x36, 0x34, 0x20, 0x62, 0x69, 0x74, 0x73, 0x2C, 0x20, 0x59, 0x20, - 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6C, 0x6F, 0x77, 0x2E, - 0x20, 0x46, 0x61, 0x69, 0x6C, 0x20, 0x69, 0x66, 0x20, 0x41, 0x20, - 0x3D, 0x3D, 0x20, 0x42, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x20, 0x6F, - 0x72, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, - 0x73, 0x75, 0x6C, 0x74, 0x73, 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, - 0x64, 0x73, 0x20, 0x32, 0x5E, 0x31, 0x32, 0x38, 0x2D, 0x31, 0x22, - 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, - 0x22, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, - 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, - 0x65, 0x22, 0x3A, 0x31, 0x35, 0x30, 0x2C, 0x22, 0x4E, 0x61, 0x6D, - 0x65, 0x22, 0x3A, 0x22, 0x62, 0x73, 0x71, 0x72, 0x74, 0x22, 0x2C, - 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x34, - 0x30, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x54, 0x68, 0x65, 0x20, - 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6E, 0x74, - 0x65, 0x67, 0x65, 0x72, 0x20, 0x49, 0x20, 0x73, 0x75, 0x63, 0x68, - 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x5E, 0x32, 0x20, 0x5C, - 0x75, 0x30, 0x30, 0x33, 0x63, 0x3D, 0x20, 0x41, 0x2E, 0x20, 0x41, - 0x20, 0x61, 0x6E, 0x64, 0x20, 0x49, 0x20, 0x61, 0x72, 0x65, 0x20, - 0x69, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, - 0x20, 0x61, 0x73, 0x20, 0x62, 0x69, 0x67, 0x2D, 0x65, 0x6E, 0x64, - 0x69, 0x61, 0x6E, 0x20, 0x75, 0x6E, 0x73, 0x69, 0x67, 0x6E, 0x65, - 0x64, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x22, - 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, - 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, - 0x20, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, - 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, - 0x65, 0x22, 0x3A, 0x31, 0x35, 0x31, 0x2C, 0x22, 0x4E, 0x61, 0x6D, - 0x65, 0x22, 0x3A, 0x22, 0x64, 0x69, 0x76, 0x77, 0x22, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x55, 0x22, - 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, - 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x2C, 0x42, 0x20, - 0x2F, 0x20, 0x43, 0x2E, 0x20, 0x46, 0x61, 0x69, 0x6C, 0x20, 0x69, - 0x66, 0x20, 0x43, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x20, 0x6F, 0x72, - 0x20, 0x69, 0x66, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x20, - 0x6F, 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 0x73, 0x2E, 0x22, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, - 0x3A, 0x22, 0x54, 0x68, 0x65, 0x20, 0x6E, 0x6F, 0x74, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x2C, 0x42, 0x20, 0x69, 0x6E, 0x64, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, - 0x20, 0x41, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x42, 0x20, 0x61, 0x72, - 0x65, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, - 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x75, 0x69, 0x6E, - 0x74, 0x31, 0x32, 0x38, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x2C, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x41, 0x20, 0x61, 0x73, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, 0x75, 0x69, - 0x6E, 0x74, 0x36, 0x34, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x42, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x6C, 0x6F, 0x77, 0x2E, 0x22, 0x2C, 0x22, - 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x41, - 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x31, 0x36, 0x30, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x62, 0x2B, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, - 0x22, 0x3A, 0x22, 0x42, 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, - 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x30, 0x2C, 0x22, 0x53, - 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, - 0x22, 0x3A, 0x22, 0x41, 0x20, 0x70, 0x6C, 0x75, 0x73, 0x20, 0x42, - 0x2E, 0x20, 0x41, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x42, 0x20, 0x61, - 0x72, 0x65, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, - 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x62, 0x69, 0x67, 0x2D, - 0x65, 0x6E, 0x64, 0x69, 0x61, 0x6E, 0x20, 0x75, 0x6E, 0x73, 0x69, - 0x67, 0x6E, 0x65, 0x64, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, - 0x72, 0x73, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, 0x41, 0x72, - 0x72, 0x61, 0x79, 0x20, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, - 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, - 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x36, 0x31, 0x2C, 0x22, - 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x62, 0x2D, 0x22, 0x2C, - 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, 0x22, - 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, - 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, - 0x31, 0x30, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x6D, - 0x69, 0x6E, 0x75, 0x73, 0x20, 0x42, 0x2E, 0x20, 0x41, 0x20, 0x61, - 0x6E, 0x64, 0x20, 0x42, 0x20, 0x61, 0x72, 0x65, 0x20, 0x69, 0x6E, - 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x20, 0x61, - 0x73, 0x20, 0x62, 0x69, 0x67, 0x2D, 0x65, 0x6E, 0x64, 0x69, 0x61, - 0x6E, 0x20, 0x75, 0x6E, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x20, - 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x2E, 0x20, 0x46, - 0x61, 0x69, 0x6C, 0x20, 0x6F, 0x6E, 0x20, 0x75, 0x6E, 0x64, 0x65, - 0x72, 0x66, 0x6C, 0x6F, 0x77, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x42, 0x79, 0x74, - 0x65, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x41, 0x72, 0x69, - 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, - 0x36, 0x32, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, - 0x62, 0x2F, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, - 0x22, 0x42, 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x32, 0x30, 0x2C, 0x22, 0x53, 0x69, 0x7A, - 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, - 0x22, 0x41, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, - 0x62, 0x79, 0x20, 0x42, 0x20, 0x28, 0x74, 0x72, 0x75, 0x6E, 0x63, - 0x61, 0x74, 0x65, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x73, 0x69, - 0x6F, 0x6E, 0x29, 0x2E, 0x20, 0x41, 0x20, 0x61, 0x6E, 0x64, 0x20, - 0x42, 0x20, 0x61, 0x72, 0x65, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, - 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x62, - 0x69, 0x67, 0x2D, 0x65, 0x6E, 0x64, 0x69, 0x61, 0x6E, 0x20, 0x75, - 0x6E, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x20, 0x69, 0x6E, 0x74, - 0x65, 0x67, 0x65, 0x72, 0x73, 0x2E, 0x20, 0x46, 0x61, 0x69, 0x6C, - 0x20, 0x69, 0x66, 0x20, 0x42, 0x20, 0x69, 0x73, 0x20, 0x7A, 0x65, - 0x72, 0x6F, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, - 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, - 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, - 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x36, 0x33, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x62, 0x2A, 0x22, - 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, - 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, - 0x3A, 0x32, 0x30, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, - 0x74, 0x69, 0x6D, 0x65, 0x73, 0x20, 0x42, 0x2E, 0x20, 0x41, 0x20, - 0x61, 0x6E, 0x64, 0x20, 0x42, 0x20, 0x61, 0x72, 0x65, 0x20, 0x69, - 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x20, - 0x61, 0x73, 0x20, 0x62, 0x69, 0x67, 0x2D, 0x65, 0x6E, 0x64, 0x69, - 0x61, 0x6E, 0x20, 0x75, 0x6E, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, - 0x20, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x2E, 0x22, - 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, - 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, - 0x20, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, - 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, - 0x65, 0x22, 0x3A, 0x31, 0x36, 0x34, 0x2C, 0x22, 0x4E, 0x61, 0x6D, - 0x65, 0x22, 0x3A, 0x22, 0x62, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x63, - 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, - 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, - 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x31, 0x20, - 0x69, 0x66, 0x20, 0x41, 0x20, 0x69, 0x73, 0x20, 0x6C, 0x65, 0x73, - 0x73, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x42, 0x2C, 0x20, 0x65, - 0x6C, 0x73, 0x65, 0x20, 0x30, 0x2E, 0x20, 0x41, 0x20, 0x61, 0x6E, - 0x64, 0x20, 0x42, 0x20, 0x61, 0x72, 0x65, 0x20, 0x69, 0x6E, 0x74, - 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, - 0x20, 0x62, 0x69, 0x67, 0x2D, 0x65, 0x6E, 0x64, 0x69, 0x61, 0x6E, - 0x20, 0x75, 0x6E, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x20, 0x69, - 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x22, 0x2C, 0x22, 0x47, - 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x42, 0x79, - 0x74, 0x65, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x41, 0x72, - 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x31, 0x36, 0x35, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x62, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x65, 0x22, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x31, 0x20, 0x69, 0x66, 0x20, - 0x41, 0x20, 0x69, 0x73, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x72, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x42, 0x2C, 0x20, 0x65, - 0x6C, 0x73, 0x65, 0x20, 0x30, 0x2E, 0x20, 0x41, 0x20, 0x61, 0x6E, - 0x64, 0x20, 0x42, 0x20, 0x61, 0x72, 0x65, 0x20, 0x69, 0x6E, 0x74, - 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, - 0x20, 0x62, 0x69, 0x67, 0x2D, 0x65, 0x6E, 0x64, 0x69, 0x61, 0x6E, - 0x20, 0x75, 0x6E, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x20, 0x69, - 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x22, 0x2C, 0x22, 0x47, - 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x42, 0x79, - 0x74, 0x65, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x41, 0x72, - 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x31, 0x36, 0x36, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x62, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x63, 0x3D, 0x22, 0x2C, - 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, 0x22, - 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, - 0x22, 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x31, 0x20, 0x69, 0x66, - 0x20, 0x41, 0x20, 0x69, 0x73, 0x20, 0x6C, 0x65, 0x73, 0x73, 0x20, - 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x72, 0x20, 0x65, 0x71, 0x75, - 0x61, 0x6C, 0x20, 0x74, 0x6F, 0x20, 0x42, 0x2C, 0x20, 0x65, 0x6C, - 0x73, 0x65, 0x20, 0x30, 0x2E, 0x20, 0x41, 0x20, 0x61, 0x6E, 0x64, - 0x20, 0x42, 0x20, 0x61, 0x72, 0x65, 0x20, 0x69, 0x6E, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, - 0x62, 0x69, 0x67, 0x2D, 0x65, 0x6E, 0x64, 0x69, 0x61, 0x6E, 0x20, - 0x75, 0x6E, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x20, 0x69, 0x6E, - 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x42, 0x79, 0x74, - 0x65, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x41, 0x72, 0x69, - 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, - 0x36, 0x37, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, - 0x62, 0x5C, 0x75, 0x30, 0x30, 0x33, 0x65, 0x3D, 0x22, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x31, 0x20, 0x69, 0x66, 0x20, - 0x41, 0x20, 0x69, 0x73, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x72, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x72, 0x20, 0x65, - 0x71, 0x75, 0x61, 0x6C, 0x20, 0x74, 0x6F, 0x20, 0x42, 0x2C, 0x20, - 0x65, 0x6C, 0x73, 0x65, 0x20, 0x30, 0x2E, 0x20, 0x41, 0x20, 0x61, - 0x6E, 0x64, 0x20, 0x42, 0x20, 0x61, 0x72, 0x65, 0x20, 0x69, 0x6E, - 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x20, 0x61, - 0x73, 0x20, 0x62, 0x69, 0x67, 0x2D, 0x65, 0x6E, 0x64, 0x69, 0x61, - 0x6E, 0x20, 0x75, 0x6E, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x20, - 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x22, 0x2C, 0x22, - 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x42, - 0x79, 0x74, 0x65, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x41, - 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x31, 0x36, 0x38, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x62, 0x3D, 0x3D, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, - 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, - 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, - 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, - 0x22, 0x3A, 0x22, 0x31, 0x20, 0x69, 0x66, 0x20, 0x41, 0x20, 0x69, - 0x73, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6C, 0x20, 0x74, 0x6F, 0x20, - 0x42, 0x2C, 0x20, 0x65, 0x6C, 0x73, 0x65, 0x20, 0x30, 0x2E, 0x20, - 0x41, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x42, 0x20, 0x61, 0x72, 0x65, - 0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, - 0x64, 0x20, 0x61, 0x73, 0x20, 0x62, 0x69, 0x67, 0x2D, 0x65, 0x6E, - 0x64, 0x69, 0x61, 0x6E, 0x20, 0x75, 0x6E, 0x73, 0x69, 0x67, 0x6E, - 0x65, 0x64, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, - 0x5B, 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, 0x41, 0x72, 0x72, 0x61, - 0x79, 0x20, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, - 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, - 0x64, 0x65, 0x22, 0x3A, 0x31, 0x36, 0x39, 0x2C, 0x22, 0x4E, 0x61, - 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x62, 0x21, 0x3D, 0x22, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, 0x22, 0x2C, - 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x30, 0x20, 0x69, 0x66, 0x20, - 0x41, 0x20, 0x69, 0x73, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6C, 0x20, - 0x74, 0x6F, 0x20, 0x42, 0x2C, 0x20, 0x65, 0x6C, 0x73, 0x65, 0x20, - 0x31, 0x2E, 0x20, 0x41, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x42, 0x20, - 0x61, 0x72, 0x65, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x65, 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x62, 0x69, 0x67, - 0x2D, 0x65, 0x6E, 0x64, 0x69, 0x61, 0x6E, 0x20, 0x75, 0x6E, 0x73, - 0x69, 0x67, 0x6E, 0x65, 0x64, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x67, - 0x65, 0x72, 0x73, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, - 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6D, - 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, - 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x37, 0x30, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x62, 0x25, 0x22, - 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, - 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, - 0x3A, 0x32, 0x30, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, - 0x6D, 0x6F, 0x64, 0x75, 0x6C, 0x6F, 0x20, 0x42, 0x2E, 0x20, 0x41, - 0x20, 0x61, 0x6E, 0x64, 0x20, 0x42, 0x20, 0x61, 0x72, 0x65, 0x20, - 0x69, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, - 0x20, 0x61, 0x73, 0x20, 0x62, 0x69, 0x67, 0x2D, 0x65, 0x6E, 0x64, - 0x69, 0x61, 0x6E, 0x20, 0x75, 0x6E, 0x73, 0x69, 0x67, 0x6E, 0x65, - 0x64, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x2E, - 0x20, 0x46, 0x61, 0x69, 0x6C, 0x20, 0x69, 0x66, 0x20, 0x42, 0x20, - 0x69, 0x73, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x2E, 0x22, 0x2C, 0x22, - 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x42, - 0x79, 0x74, 0x65, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x41, - 0x72, 0x69, 0x74, 0x68, 0x6D, 0x65, 0x74, 0x69, 0x63, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x31, 0x37, 0x31, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x62, 0x7C, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, - 0x22, 0x3A, 0x22, 0x42, 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, - 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x36, 0x2C, 0x22, 0x53, 0x69, - 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, - 0x3A, 0x22, 0x41, 0x20, 0x62, 0x69, 0x74, 0x77, 0x69, 0x73, 0x65, - 0x2D, 0x6F, 0x72, 0x20, 0x42, 0x2E, 0x20, 0x41, 0x20, 0x61, 0x6E, - 0x64, 0x20, 0x42, 0x20, 0x61, 0x72, 0x65, 0x20, 0x7A, 0x65, 0x72, - 0x6F, 0x2D, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x65, 0x78, 0x74, 0x65, - 0x6E, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x6F, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6C, 0x65, 0x6E, 0x67, - 0x74, 0x68, 0x73, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, - 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x4C, 0x6F, 0x67, 0x69, 0x63, 0x22, - 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, - 0x22, 0x3A, 0x31, 0x37, 0x32, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, - 0x22, 0x3A, 0x22, 0x62, 0x5C, 0x75, 0x30, 0x30, 0x32, 0x36, 0x22, - 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, - 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, - 0x3A, 0x36, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x20, 0x62, - 0x69, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2D, 0x61, 0x6E, 0x64, 0x20, - 0x42, 0x2E, 0x20, 0x41, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x42, 0x20, - 0x61, 0x72, 0x65, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x2D, 0x6C, 0x65, - 0x66, 0x74, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, - 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x72, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x69, 0x72, 0x20, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x73, 0x22, - 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, - 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, - 0x20, 0x4C, 0x6F, 0x67, 0x69, 0x63, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, - 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x37, - 0x33, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x62, - 0x5E, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, - 0x42, 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, - 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, - 0x74, 0x22, 0x3A, 0x36, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, - 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, - 0x20, 0x62, 0x69, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2D, 0x78, 0x6F, - 0x72, 0x20, 0x42, 0x2E, 0x20, 0x41, 0x20, 0x61, 0x6E, 0x64, 0x20, - 0x42, 0x20, 0x61, 0x72, 0x65, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x2D, - 0x6C, 0x65, 0x66, 0x74, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6E, 0x64, - 0x65, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x6F, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x69, 0x72, 0x20, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, - 0x73, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, 0x41, 0x72, 0x72, - 0x61, 0x79, 0x20, 0x4C, 0x6F, 0x67, 0x69, 0x63, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x31, 0x37, 0x34, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x62, 0x7E, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x34, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x41, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6C, 0x6C, 0x20, - 0x62, 0x69, 0x74, 0x73, 0x20, 0x69, 0x6E, 0x76, 0x65, 0x72, 0x74, - 0x65, 0x64, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x42, 0x79, 0x74, 0x65, 0x20, 0x41, 0x72, - 0x72, 0x61, 0x79, 0x20, 0x4C, 0x6F, 0x67, 0x69, 0x63, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x31, 0x37, 0x35, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x62, 0x7A, 0x65, 0x72, 0x6F, 0x22, 0x2C, 0x22, 0x41, - 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x7A, 0x65, 0x72, 0x6F, 0x20, 0x66, 0x69, - 0x6C, 0x6C, 0x65, 0x64, 0x20, 0x62, 0x79, 0x74, 0x65, 0x2D, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x6F, 0x66, 0x20, 0x6C, 0x65, 0x6E, - 0x67, 0x74, 0x68, 0x20, 0x41, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, - 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, - 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, - 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, - 0x22, 0x3A, 0x31, 0x37, 0x36, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, - 0x22, 0x3A, 0x22, 0x6C, 0x6F, 0x67, 0x22, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x41, 0x20, 0x74, 0x6F, 0x20, - 0x6C, 0x6F, 0x67, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x6F, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6E, 0x74, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, - 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x60, 0x6C, 0x6F, 0x67, 0x60, - 0x20, 0x66, 0x61, 0x69, 0x6C, 0x73, 0x20, 0x69, 0x66, 0x20, 0x63, - 0x61, 0x6C, 0x6C, 0x65, 0x64, 0x20, 0x6D, 0x6F, 0x72, 0x65, 0x20, - 0x74, 0x68, 0x61, 0x6E, 0x20, 0x4D, 0x61, 0x78, 0x4C, 0x6F, 0x67, - 0x43, 0x61, 0x6C, 0x6C, 0x73, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x73, - 0x20, 0x69, 0x6E, 0x20, 0x61, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, - 0x61, 0x6D, 0x2C, 0x20, 0x6F, 0x72, 0x20, 0x69, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x73, 0x75, 0x6D, 0x20, 0x6F, 0x66, 0x20, 0x6C, - 0x6F, 0x67, 0x67, 0x65, 0x64, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, - 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x73, 0x20, 0x31, 0x30, - 0x32, 0x34, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2E, 0x22, 0x2C, - 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, - 0x64, 0x65, 0x22, 0x3A, 0x31, 0x37, 0x37, 0x2C, 0x22, 0x4E, 0x61, - 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x69, 0x74, 0x78, 0x6E, 0x5F, 0x62, - 0x65, 0x67, 0x69, 0x6E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x62, 0x65, - 0x67, 0x69, 0x6E, 0x20, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x61, - 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x6F, 0x66, 0x20, 0x61, 0x20, 0x6E, - 0x65, 0x77, 0x20, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x74, 0x72, - 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, - 0x6E, 0x20, 0x61, 0x20, 0x6E, 0x65, 0x77, 0x20, 0x74, 0x72, 0x61, - 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x67, 0x72, - 0x6F, 0x75, 0x70, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, - 0x74, 0x72, 0x61, 0x22, 0x3A, 0x22, 0x60, 0x69, 0x74, 0x78, 0x6E, - 0x5F, 0x62, 0x65, 0x67, 0x69, 0x6E, 0x60, 0x20, 0x69, 0x6E, 0x69, - 0x74, 0x69, 0x61, 0x6C, 0x69, 0x7A, 0x65, 0x73, 0x20, 0x53, 0x65, - 0x6E, 0x64, 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, - 0x6E, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3B, 0x20, - 0x46, 0x65, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x20, 0x61, 0x6C, 0x6C, - 0x6F, 0x77, 0x61, 0x62, 0x6C, 0x65, 0x2C, 0x20, 0x74, 0x61, 0x6B, - 0x69, 0x6E, 0x67, 0x20, 0x69, 0x6E, 0x74, 0x6F, 0x20, 0x61, 0x63, - 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x4D, 0x69, 0x6E, 0x54, 0x78, - 0x6E, 0x46, 0x65, 0x65, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x63, 0x72, - 0x65, 0x64, 0x69, 0x74, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x6F, - 0x76, 0x65, 0x72, 0x70, 0x61, 0x79, 0x69, 0x6E, 0x67, 0x20, 0x69, - 0x6E, 0x20, 0x65, 0x61, 0x72, 0x6C, 0x69, 0x65, 0x72, 0x20, 0x74, - 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, - 0x3B, 0x20, 0x46, 0x69, 0x72, 0x73, 0x74, 0x56, 0x61, 0x6C, 0x69, - 0x64, 0x2F, 0x4C, 0x61, 0x73, 0x74, 0x56, 0x61, 0x6C, 0x69, 0x64, - 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6C, - 0x75, 0x65, 0x73, 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x69, 0x6E, 0x76, 0x6F, 0x6B, 0x69, 0x6E, 0x67, 0x20, 0x74, 0x72, - 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x2C, 0x20, - 0x61, 0x6E, 0x64, 0x20, 0x61, 0x6C, 0x6C, 0x20, 0x6F, 0x74, 0x68, - 0x65, 0x72, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x73, 0x20, 0x74, - 0x6F, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x20, 0x6F, 0x72, 0x20, 0x65, - 0x6D, 0x70, 0x74, 0x79, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x73, - 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, - 0x3A, 0x5B, 0x22, 0x49, 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x54, 0x72, - 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, - 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, - 0x22, 0x3A, 0x31, 0x37, 0x38, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, - 0x22, 0x3A, 0x22, 0x69, 0x74, 0x78, 0x6E, 0x5F, 0x66, 0x69, 0x65, - 0x6C, 0x64, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, - 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, - 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x32, 0x2C, - 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x22, 0x3A, 0x5B, - 0x22, 0x53, 0x65, 0x6E, 0x64, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x46, - 0x65, 0x65, 0x22, 0x2C, 0x22, 0x46, 0x69, 0x72, 0x73, 0x74, 0x56, - 0x61, 0x6C, 0x69, 0x64, 0x22, 0x2C, 0x22, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x54, 0x69, 0x6D, 0x65, 0x22, - 0x2C, 0x22, 0x4C, 0x61, 0x73, 0x74, 0x56, 0x61, 0x6C, 0x69, 0x64, - 0x22, 0x2C, 0x22, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x2C, 0x22, 0x4C, - 0x65, 0x61, 0x73, 0x65, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x63, 0x65, - 0x69, 0x76, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, 0x6D, 0x6F, 0x75, - 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x43, 0x6C, 0x6F, 0x73, 0x65, 0x52, - 0x65, 0x6D, 0x61, 0x69, 0x6E, 0x64, 0x65, 0x72, 0x54, 0x6F, 0x22, - 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x50, 0x4B, 0x22, 0x2C, 0x22, - 0x53, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x50, 0x4B, - 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x4C, 0x61, 0x73, - 0x74, 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x4B, 0x65, 0x79, - 0x44, 0x69, 0x6C, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, - 0x54, 0x79, 0x70, 0x65, 0x22, 0x2C, 0x22, 0x54, 0x79, 0x70, 0x65, - 0x45, 0x6E, 0x75, 0x6D, 0x22, 0x2C, 0x22, 0x58, 0x66, 0x65, 0x72, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x41, 0x6D, 0x6F, 0x75, 0x6E, 0x74, 0x22, 0x2C, 0x22, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x53, 0x65, 0x6E, 0x64, 0x65, 0x72, - 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x63, - 0x65, 0x69, 0x76, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x43, 0x6C, 0x6F, 0x73, 0x65, 0x54, 0x6F, 0x22, 0x2C, - 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x49, 0x6E, 0x64, 0x65, 0x78, - 0x22, 0x2C, 0x22, 0x54, 0x78, 0x49, 0x44, 0x22, 0x2C, 0x22, 0x41, - 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x49, - 0x44, 0x22, 0x2C, 0x22, 0x4F, 0x6E, 0x43, 0x6F, 0x6D, 0x70, 0x6C, - 0x65, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, - 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x41, 0x72, 0x67, - 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x41, 0x70, 0x70, 0x41, - 0x72, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x63, 0x63, 0x6F, 0x75, - 0x6E, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x41, 0x63, - 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x70, - 0x70, 0x72, 0x6F, 0x76, 0x61, 0x6C, 0x50, 0x72, 0x6F, 0x67, 0x72, - 0x61, 0x6D, 0x22, 0x2C, 0x22, 0x43, 0x6C, 0x65, 0x61, 0x72, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, - 0x22, 0x2C, 0x22, 0x52, 0x65, 0x6B, 0x65, 0x79, 0x54, 0x6F, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x6F, 0x74, 0x61, 0x6C, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x44, 0x65, 0x63, 0x69, 0x6D, 0x61, 0x6C, 0x73, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x46, 0x72, - 0x6F, 0x7A, 0x65, 0x6E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, - 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x55, 0x6E, 0x69, 0x74, - 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, - 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, - 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x55, 0x52, 0x4C, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4D, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x61, 0x73, 0x68, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x43, 0x6C, - 0x61, 0x77, 0x62, 0x61, 0x63, 0x6B, 0x22, 0x2C, 0x22, 0x46, 0x72, - 0x65, 0x65, 0x7A, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x22, 0x2C, - 0x22, 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x22, 0x2C, 0x22, - 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x46, 0x72, 0x6F, 0x7A, 0x65, 0x6E, 0x22, 0x2C, 0x22, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, - 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x2C, - 0x22, 0x4E, 0x75, 0x6D, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x2C, 0x22, 0x47, 0x6C, 0x6F, - 0x62, 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x55, 0x69, 0x6E, 0x74, 0x22, - 0x2C, 0x22, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x4E, 0x75, 0x6D, - 0x42, 0x79, 0x74, 0x65, 0x53, 0x6C, 0x69, 0x63, 0x65, 0x22, 0x2C, - 0x22, 0x4C, 0x6F, 0x63, 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x55, 0x69, - 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x63, 0x61, 0x6C, 0x4E, - 0x75, 0x6D, 0x42, 0x79, 0x74, 0x65, 0x53, 0x6C, 0x69, 0x63, 0x65, - 0x22, 0x2C, 0x22, 0x45, 0x78, 0x74, 0x72, 0x61, 0x50, 0x72, 0x6F, - 0x67, 0x72, 0x61, 0x6D, 0x50, 0x61, 0x67, 0x65, 0x73, 0x22, 0x2C, - 0x22, 0x4E, 0x6F, 0x6E, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, - 0x70, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x4C, 0x6F, - 0x67, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x4C, 0x6F, 0x67, - 0x73, 0x22, 0x2C, 0x22, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, 0x44, 0x22, 0x2C, 0x22, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x70, 0x70, 0x6C, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x22, 0x2C, 0x22, - 0x4C, 0x61, 0x73, 0x74, 0x4C, 0x6F, 0x67, 0x22, 0x2C, 0x22, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6F, 0x6F, 0x66, 0x50, 0x4B, - 0x22, 0x5D, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, - 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x55, 0x55, - 0x55, 0x55, 0x42, 0x42, 0x42, 0x55, 0x42, 0x42, 0x42, 0x55, 0x55, - 0x55, 0x42, 0x55, 0x55, 0x55, 0x42, 0x42, 0x42, 0x55, 0x42, 0x55, - 0x55, 0x42, 0x55, 0x42, 0x55, 0x42, 0x42, 0x42, 0x55, 0x55, 0x55, - 0x55, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x55, 0x42, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x42, 0x55, 0x55, 0x55, 0x42, 0x42, 0x22, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x73, 0x65, 0x74, 0x20, 0x66, 0x69, 0x65, - 0x6C, 0x64, 0x20, 0x46, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x20, 0x69, 0x6E, - 0x6E, 0x65, 0x72, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x74, 0x6F, 0x20, 0x41, 0x22, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, - 0x22, 0x60, 0x69, 0x74, 0x78, 0x6E, 0x5F, 0x66, 0x69, 0x65, 0x6C, - 0x64, 0x60, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x73, 0x20, 0x69, 0x66, - 0x20, 0x41, 0x20, 0x69, 0x73, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x77, 0x72, 0x6F, 0x6E, 0x67, 0x20, 0x74, 0x79, 0x70, - 0x65, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x46, 0x2C, 0x20, 0x69, 0x6E, - 0x63, 0x6C, 0x75, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x61, 0x20, 0x62, - 0x79, 0x74, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6F, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x72, 0x6F, 0x6E, 0x67, - 0x20, 0x73, 0x69, 0x7A, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x75, - 0x73, 0x65, 0x20, 0x61, 0x73, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x77, 0x68, 0x65, 0x6E, 0x20, - 0x46, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x2E, - 0x20, 0x60, 0x69, 0x74, 0x78, 0x6E, 0x5F, 0x66, 0x69, 0x65, 0x6C, - 0x64, 0x60, 0x20, 0x61, 0x6C, 0x73, 0x6F, 0x20, 0x66, 0x61, 0x69, - 0x6C, 0x73, 0x20, 0x69, 0x66, 0x20, 0x41, 0x20, 0x69, 0x73, 0x20, - 0x61, 0x6E, 0x20, 0x61, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x2C, - 0x20, 0x61, 0x73, 0x73, 0x65, 0x74, 0x2C, 0x20, 0x6F, 0x72, 0x20, - 0x61, 0x70, 0x70, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, - 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x5F, 0x61, 0x76, 0x61, 0x69, 0x6C, - 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x2C, 0x20, 0x6F, 0x72, 0x20, 0x61, - 0x6E, 0x20, 0x61, 0x74, 0x74, 0x65, 0x6D, 0x70, 0x74, 0x20, 0x69, - 0x73, 0x20, 0x6D, 0x61, 0x64, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, - 0x6E, 0x64, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x62, 0x65, 0x79, 0x6F, - 0x6E, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6C, 0x69, 0x6D, 0x69, - 0x74, 0x20, 0x69, 0x6D, 0x70, 0x6F, 0x73, 0x65, 0x64, 0x20, 0x62, - 0x79, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x65, 0x6E, 0x73, 0x75, 0x73, - 0x20, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x65, 0x74, 0x65, 0x72, 0x73, - 0x2E, 0x20, 0x28, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, - 0x73, 0x20, 0x73, 0x65, 0x74, 0x20, 0x69, 0x6E, 0x74, 0x6F, 0x20, - 0x61, 0x73, 0x73, 0x65, 0x74, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6D, - 0x73, 0x20, 0x6F, 0x66, 0x20, 0x61, 0x63, 0x66, 0x67, 0x20, 0x74, - 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, - 0x20, 0x6E, 0x65, 0x65, 0x64, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x62, - 0x65, 0x20, 0x5F, 0x61, 0x76, 0x61, 0x69, 0x6C, 0x61, 0x62, 0x6C, - 0x65, 0x5F, 0x2E, 0x29, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, - 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, - 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, - 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, - 0x65, 0x6C, 0x64, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, - 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, - 0x22, 0x49, 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x54, 0x72, 0x61, 0x6E, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x31, 0x37, 0x39, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x69, 0x74, 0x78, 0x6E, 0x5F, 0x73, 0x75, 0x62, 0x6D, 0x69, - 0x74, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, - 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6E, 0x74, 0x20, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x74, - 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, - 0x67, 0x72, 0x6F, 0x75, 0x70, 0x2E, 0x20, 0x46, 0x61, 0x69, 0x6C, - 0x20, 0x69, 0x66, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6E, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x67, 0x72, 0x6F, - 0x75, 0x70, 0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64, 0x20, 0x65, 0x78, - 0x63, 0x65, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6E, - 0x6E, 0x65, 0x72, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x2C, - 0x20, 0x6F, 0x72, 0x20, 0x69, 0x66, 0x20, 0x61, 0x6E, 0x79, 0x20, - 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, - 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6F, - 0x75, 0x70, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x73, 0x2E, 0x22, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3A, - 0x22, 0x60, 0x69, 0x74, 0x78, 0x6E, 0x5F, 0x73, 0x75, 0x62, 0x6D, - 0x69, 0x74, 0x60, 0x20, 0x72, 0x65, 0x73, 0x65, 0x74, 0x73, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, - 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, - 0x6E, 0x20, 0x73, 0x6F, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, - 0x74, 0x20, 0x63, 0x61, 0x6E, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x62, - 0x65, 0x20, 0x72, 0x65, 0x73, 0x75, 0x62, 0x6D, 0x69, 0x74, 0x74, - 0x65, 0x64, 0x2E, 0x20, 0x41, 0x20, 0x6E, 0x65, 0x77, 0x20, 0x60, - 0x69, 0x74, 0x78, 0x6E, 0x5F, 0x62, 0x65, 0x67, 0x69, 0x6E, 0x60, - 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, - 0x64, 0x20, 0x74, 0x6F, 0x20, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, - 0x65, 0x20, 0x61, 0x6E, 0x6F, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, - 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x49, 0x6E, 0x6E, - 0x65, 0x72, 0x20, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, - 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x38, 0x30, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x69, 0x74, 0x78, - 0x6E, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, - 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x32, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x22, - 0x3A, 0x5B, 0x22, 0x53, 0x65, 0x6E, 0x64, 0x65, 0x72, 0x22, 0x2C, - 0x22, 0x46, 0x65, 0x65, 0x22, 0x2C, 0x22, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x22, 0x2C, 0x22, 0x46, 0x69, - 0x72, 0x73, 0x74, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x54, 0x69, 0x6D, - 0x65, 0x22, 0x2C, 0x22, 0x4C, 0x61, 0x73, 0x74, 0x56, 0x61, 0x6C, - 0x69, 0x64, 0x22, 0x2C, 0x22, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x2C, - 0x22, 0x4C, 0x65, 0x61, 0x73, 0x65, 0x22, 0x2C, 0x22, 0x52, 0x65, - 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, 0x6D, - 0x6F, 0x75, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x43, 0x6C, 0x6F, 0x73, - 0x65, 0x52, 0x65, 0x6D, 0x61, 0x69, 0x6E, 0x64, 0x65, 0x72, 0x54, - 0x6F, 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x50, 0x4B, 0x22, - 0x2C, 0x22, 0x53, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, - 0x50, 0x4B, 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x46, 0x69, - 0x72, 0x73, 0x74, 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x4C, - 0x61, 0x73, 0x74, 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x4B, - 0x65, 0x79, 0x44, 0x69, 0x6C, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x22, - 0x2C, 0x22, 0x54, 0x79, 0x70, 0x65, 0x22, 0x2C, 0x22, 0x54, 0x79, - 0x70, 0x65, 0x45, 0x6E, 0x75, 0x6D, 0x22, 0x2C, 0x22, 0x58, 0x66, - 0x65, 0x72, 0x41, 0x73, 0x73, 0x65, 0x74, 0x22, 0x2C, 0x22, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x41, 0x6D, 0x6F, 0x75, 0x6E, 0x74, 0x22, - 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x53, 0x65, 0x6E, 0x64, - 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, - 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x43, 0x6C, 0x6F, 0x73, 0x65, 0x54, 0x6F, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x49, 0x6E, 0x64, - 0x65, 0x78, 0x22, 0x2C, 0x22, 0x54, 0x78, 0x49, 0x44, 0x22, 0x2C, - 0x22, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, - 0x6E, 0x49, 0x44, 0x22, 0x2C, 0x22, 0x4F, 0x6E, 0x43, 0x6F, 0x6D, - 0x70, 0x6C, 0x65, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x41, - 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x41, - 0x72, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x41, 0x70, - 0x70, 0x41, 0x72, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x63, 0x63, - 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, - 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x22, 0x2C, 0x22, - 0x41, 0x70, 0x70, 0x72, 0x6F, 0x76, 0x61, 0x6C, 0x50, 0x72, 0x6F, - 0x67, 0x72, 0x61, 0x6D, 0x22, 0x2C, 0x22, 0x43, 0x6C, 0x65, 0x61, - 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6F, 0x67, 0x72, - 0x61, 0x6D, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x6B, 0x65, 0x79, 0x54, - 0x6F, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, - 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x6F, 0x74, 0x61, - 0x6C, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x44, 0x65, 0x63, 0x69, 0x6D, 0x61, 0x6C, - 0x73, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, - 0x46, 0x72, 0x6F, 0x7A, 0x65, 0x6E, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x55, 0x6E, - 0x69, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4E, 0x61, - 0x6D, 0x65, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x55, 0x52, 0x4C, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x4D, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x61, 0x73, - 0x68, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, - 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x22, 0x2C, 0x22, - 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x43, 0x6C, 0x61, 0x77, 0x62, 0x61, 0x63, 0x6B, 0x22, 0x2C, 0x22, - 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x22, 0x2C, 0x22, 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x22, - 0x2C, 0x22, 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x46, 0x72, 0x6F, 0x7A, 0x65, 0x6E, 0x22, 0x2C, 0x22, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, - 0x6D, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, - 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, - 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x41, 0x70, 0x70, 0x6C, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x2C, 0x22, 0x47, - 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x55, 0x69, 0x6E, - 0x74, 0x22, 0x2C, 0x22, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x4E, - 0x75, 0x6D, 0x42, 0x79, 0x74, 0x65, 0x53, 0x6C, 0x69, 0x63, 0x65, - 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x63, 0x61, 0x6C, 0x4E, 0x75, 0x6D, - 0x55, 0x69, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x63, 0x61, - 0x6C, 0x4E, 0x75, 0x6D, 0x42, 0x79, 0x74, 0x65, 0x53, 0x6C, 0x69, - 0x63, 0x65, 0x22, 0x2C, 0x22, 0x45, 0x78, 0x74, 0x72, 0x61, 0x50, - 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x50, 0x61, 0x67, 0x65, 0x73, - 0x22, 0x2C, 0x22, 0x4E, 0x6F, 0x6E, 0x70, 0x61, 0x72, 0x74, 0x69, - 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, - 0x4C, 0x6F, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x4C, - 0x6F, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, 0x44, 0x22, 0x2C, - 0x22, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x70, 0x70, - 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x22, - 0x2C, 0x22, 0x4C, 0x61, 0x73, 0x74, 0x4C, 0x6F, 0x67, 0x22, 0x2C, - 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6F, 0x6F, 0x66, - 0x50, 0x4B, 0x22, 0x5D, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, - 0x75, 0x6D, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x3A, 0x22, 0x42, - 0x55, 0x55, 0x55, 0x55, 0x42, 0x42, 0x42, 0x55, 0x42, 0x42, 0x42, - 0x55, 0x55, 0x55, 0x42, 0x55, 0x55, 0x55, 0x42, 0x42, 0x42, 0x55, - 0x42, 0x55, 0x55, 0x42, 0x55, 0x42, 0x55, 0x42, 0x42, 0x42, 0x55, - 0x55, 0x55, 0x55, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x55, 0x42, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x42, 0x55, 0x55, 0x55, 0x42, 0x42, 0x22, 0x2C, 0x22, - 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x66, 0x69, 0x65, 0x6C, 0x64, - 0x20, 0x46, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6C, - 0x61, 0x73, 0x74, 0x20, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x74, - 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x22, - 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, - 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, - 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x69, - 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, - 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x49, 0x6E, 0x6E, 0x65, - 0x72, 0x20, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6F, 0x6E, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, - 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x38, 0x31, 0x2C, 0x22, - 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x69, 0x74, 0x78, 0x6E, - 0x61, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, - 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x33, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x22, - 0x3A, 0x5B, 0x22, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x41, 0x72, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x41, - 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, - 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x2C, - 0x22, 0x4C, 0x6F, 0x67, 0x73, 0x22, 0x5D, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x42, 0x55, 0x55, 0x42, 0x22, 0x2C, 0x22, 0x44, - 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x49, 0x74, 0x68, 0x20, 0x76, 0x61, - 0x6C, 0x75, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, - 0x20, 0x46, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6C, - 0x61, 0x73, 0x74, 0x20, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x74, - 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x22, - 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, - 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, - 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x69, - 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x20, 0x7B, 0x75, 0x69, 0x6E, 0x74, - 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x61, 0x72, - 0x72, 0x61, 0x79, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, - 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, - 0x22, 0x49, 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x54, 0x72, 0x61, 0x6E, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x31, 0x38, 0x32, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x69, 0x74, 0x78, 0x6E, 0x5F, 0x6E, 0x65, 0x78, 0x74, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, - 0x63, 0x22, 0x3A, 0x22, 0x62, 0x65, 0x67, 0x69, 0x6E, 0x20, 0x70, - 0x72, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, - 0x6F, 0x66, 0x20, 0x61, 0x20, 0x6E, 0x65, 0x77, 0x20, 0x69, 0x6E, - 0x6E, 0x65, 0x72, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x73, 0x61, 0x6D, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x67, 0x72, 0x6F, 0x75, - 0x70, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x45, 0x78, 0x74, 0x72, - 0x61, 0x22, 0x3A, 0x22, 0x60, 0x69, 0x74, 0x78, 0x6E, 0x5F, 0x6E, - 0x65, 0x78, 0x74, 0x60, 0x20, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x61, - 0x6C, 0x69, 0x7A, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, - 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, - 0x65, 0x78, 0x61, 0x63, 0x74, 0x6C, 0x79, 0x20, 0x61, 0x73, 0x20, - 0x60, 0x69, 0x74, 0x78, 0x6E, 0x5F, 0x62, 0x65, 0x67, 0x69, 0x6E, - 0x60, 0x20, 0x64, 0x6F, 0x65, 0x73, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x49, 0x6E, 0x6E, - 0x65, 0x72, 0x20, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, - 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x38, 0x33, 0x2C, - 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x67, 0x69, 0x74, - 0x78, 0x6E, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, - 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, - 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, - 0x3A, 0x33, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, - 0x22, 0x3A, 0x5B, 0x22, 0x53, 0x65, 0x6E, 0x64, 0x65, 0x72, 0x22, - 0x2C, 0x22, 0x46, 0x65, 0x65, 0x22, 0x2C, 0x22, 0x46, 0x69, 0x72, - 0x73, 0x74, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x22, 0x2C, 0x22, 0x46, - 0x69, 0x72, 0x73, 0x74, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x54, 0x69, - 0x6D, 0x65, 0x22, 0x2C, 0x22, 0x4C, 0x61, 0x73, 0x74, 0x56, 0x61, - 0x6C, 0x69, 0x64, 0x22, 0x2C, 0x22, 0x4E, 0x6F, 0x74, 0x65, 0x22, - 0x2C, 0x22, 0x4C, 0x65, 0x61, 0x73, 0x65, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, - 0x6D, 0x6F, 0x75, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x43, 0x6C, 0x6F, - 0x73, 0x65, 0x52, 0x65, 0x6D, 0x61, 0x69, 0x6E, 0x64, 0x65, 0x72, - 0x54, 0x6F, 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x50, 0x4B, - 0x22, 0x2C, 0x22, 0x53, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, - 0x6E, 0x50, 0x4B, 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, 0x46, - 0x69, 0x72, 0x73, 0x74, 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, - 0x4C, 0x61, 0x73, 0x74, 0x22, 0x2C, 0x22, 0x56, 0x6F, 0x74, 0x65, - 0x4B, 0x65, 0x79, 0x44, 0x69, 0x6C, 0x75, 0x74, 0x69, 0x6F, 0x6E, - 0x22, 0x2C, 0x22, 0x54, 0x79, 0x70, 0x65, 0x22, 0x2C, 0x22, 0x54, - 0x79, 0x70, 0x65, 0x45, 0x6E, 0x75, 0x6D, 0x22, 0x2C, 0x22, 0x58, - 0x66, 0x65, 0x72, 0x41, 0x73, 0x73, 0x65, 0x74, 0x22, 0x2C, 0x22, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x41, 0x6D, 0x6F, 0x75, 0x6E, 0x74, - 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x53, 0x65, 0x6E, - 0x64, 0x65, 0x72, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x22, 0x2C, 0x22, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x43, 0x6C, 0x6F, 0x73, 0x65, 0x54, - 0x6F, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x49, 0x6E, - 0x64, 0x65, 0x78, 0x22, 0x2C, 0x22, 0x54, 0x78, 0x49, 0x44, 0x22, - 0x2C, 0x22, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x49, 0x44, 0x22, 0x2C, 0x22, 0x4F, 0x6E, 0x43, 0x6F, - 0x6D, 0x70, 0x6C, 0x65, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, 0x22, - 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x41, - 0x70, 0x70, 0x41, 0x72, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x63, - 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, - 0x6D, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x22, 0x2C, - 0x22, 0x41, 0x70, 0x70, 0x72, 0x6F, 0x76, 0x61, 0x6C, 0x50, 0x72, - 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x22, 0x2C, 0x22, 0x43, 0x6C, 0x65, - 0x61, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6F, 0x67, - 0x72, 0x61, 0x6D, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x6B, 0x65, 0x79, - 0x54, 0x6F, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, - 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x6F, 0x74, - 0x61, 0x6C, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x44, 0x65, 0x63, 0x69, 0x6D, 0x61, - 0x6C, 0x73, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, - 0x74, 0x46, 0x72, 0x6F, 0x7A, 0x65, 0x6E, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x55, - 0x6E, 0x69, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, - 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x55, 0x52, 0x4C, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x4D, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x61, - 0x73, 0x68, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, - 0x72, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x43, 0x6C, 0x61, 0x77, 0x62, 0x61, 0x63, 0x6B, 0x22, 0x2C, - 0x22, 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x22, 0x2C, 0x22, 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, - 0x22, 0x2C, 0x22, 0x46, 0x72, 0x65, 0x65, 0x7A, 0x65, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x46, 0x72, 0x6F, 0x7A, 0x65, 0x6E, 0x22, 0x2C, - 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x4E, - 0x75, 0x6D, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, - 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, - 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, 0x41, 0x70, 0x70, 0x6C, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x2C, 0x22, - 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x55, 0x69, - 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, - 0x4E, 0x75, 0x6D, 0x42, 0x79, 0x74, 0x65, 0x53, 0x6C, 0x69, 0x63, - 0x65, 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x63, 0x61, 0x6C, 0x4E, 0x75, - 0x6D, 0x55, 0x69, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x63, - 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x42, 0x79, 0x74, 0x65, 0x53, 0x6C, - 0x69, 0x63, 0x65, 0x22, 0x2C, 0x22, 0x45, 0x78, 0x74, 0x72, 0x61, - 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x50, 0x61, 0x67, 0x65, - 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x6F, 0x6E, 0x70, 0x61, 0x72, 0x74, - 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x22, 0x2C, - 0x22, 0x4C, 0x6F, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x4E, 0x75, 0x6D, - 0x4C, 0x6F, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, 0x44, 0x22, - 0x2C, 0x22, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x70, - 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, - 0x22, 0x2C, 0x22, 0x4C, 0x61, 0x73, 0x74, 0x4C, 0x6F, 0x67, 0x22, - 0x2C, 0x22, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6F, 0x6F, - 0x66, 0x50, 0x4B, 0x22, 0x5D, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, - 0x6E, 0x75, 0x6D, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x3A, 0x22, - 0x42, 0x55, 0x55, 0x55, 0x55, 0x42, 0x42, 0x42, 0x55, 0x42, 0x42, - 0x42, 0x55, 0x55, 0x55, 0x42, 0x55, 0x55, 0x55, 0x42, 0x42, 0x42, - 0x55, 0x42, 0x55, 0x55, 0x42, 0x55, 0x42, 0x55, 0x42, 0x42, 0x42, - 0x55, 0x55, 0x55, 0x55, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x55, 0x42, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x42, 0x55, 0x55, 0x55, 0x42, 0x42, 0x22, 0x2C, - 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x66, 0x69, 0x65, 0x6C, - 0x64, 0x20, 0x46, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x54, 0x74, 0x68, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x6C, 0x61, 0x73, 0x74, 0x20, 0x69, 0x6E, 0x6E, 0x65, 0x72, - 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, 0x20, 0x73, 0x75, 0x62, 0x6D, - 0x69, 0x74, 0x74, 0x65, 0x64, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, - 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, - 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, - 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x67, - 0x72, 0x6F, 0x75, 0x70, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, - 0x20, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, - 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, - 0x65, 0x6C, 0x64, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, - 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, - 0x22, 0x49, 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x54, 0x72, 0x61, 0x6E, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x5D, 0x7D, - 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, - 0x31, 0x38, 0x34, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, - 0x22, 0x67, 0x69, 0x74, 0x78, 0x6E, 0x61, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x34, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x70, - 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x41, 0x72, - 0x67, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, - 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, - 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x67, 0x73, - 0x22, 0x5D, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, - 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, 0x55, - 0x55, 0x42, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x49, 0x74, 0x68, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x6F, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x46, 0x20, 0x66, 0x72, - 0x6F, 0x6D, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x74, 0x68, 0x20, - 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, - 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6C, 0x61, 0x73, - 0x74, 0x20, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x67, 0x72, 0x6F, - 0x75, 0x70, 0x20, 0x73, 0x75, 0x62, 0x6D, 0x69, 0x74, 0x74, 0x65, - 0x64, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, - 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, - 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, - 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x20, 0x7B, 0x75, 0x69, - 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, - 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x20, 0x7B, 0x75, 0x69, 0x6E, - 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, - 0x5B, 0x22, 0x49, 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x54, 0x72, 0x61, - 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x31, 0x39, 0x32, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x74, 0x78, 0x6E, 0x61, 0x73, 0x22, 0x2C, 0x22, 0x41, - 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, - 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, - 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x70, - 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x41, 0x72, - 0x67, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, - 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, - 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x67, 0x73, - 0x22, 0x5D, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, - 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, 0x55, - 0x55, 0x42, 0x22, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x41, 0x74, 0x68, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x6F, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x46, 0x20, 0x6F, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, - 0x74, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6F, 0x6E, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, - 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, - 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, - 0x64, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, - 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, - 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, - 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, - 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x39, 0x33, 0x2C, 0x22, 0x4E, - 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x67, 0x74, 0x78, 0x6E, 0x61, - 0x73, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, - 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, - 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, - 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, - 0x33, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x22, - 0x3A, 0x5B, 0x22, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x41, 0x72, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x41, - 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x70, 0x70, - 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x2C, - 0x22, 0x4C, 0x6F, 0x67, 0x73, 0x22, 0x5D, 0x2C, 0x22, 0x41, 0x72, - 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, - 0x3A, 0x22, 0x42, 0x42, 0x55, 0x55, 0x42, 0x22, 0x2C, 0x22, 0x44, - 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x74, 0x68, 0x20, 0x76, 0x61, - 0x6C, 0x75, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, - 0x20, 0x46, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x54, 0x74, 0x68, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x20, 0x67, - 0x72, 0x6F, 0x75, 0x70, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, - 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, - 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, - 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x67, 0x72, - 0x6F, 0x75, 0x70, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x20, - 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, - 0x6C, 0x64, 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, - 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, - 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, - 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, - 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x39, 0x34, 0x2C, 0x22, - 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x67, 0x74, 0x78, 0x6E, - 0x73, 0x61, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, - 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, - 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, - 0x75, 0x6D, 0x22, 0x3A, 0x5B, 0x22, 0x41, 0x70, 0x70, 0x6C, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x2C, 0x22, 0x41, 0x63, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x22, - 0x2C, 0x22, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x2C, 0x22, - 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, - 0x73, 0x22, 0x2C, 0x22, 0x4C, 0x6F, 0x67, 0x73, 0x22, 0x5D, 0x2C, - 0x22, 0x41, 0x72, 0x67, 0x45, 0x6E, 0x75, 0x6D, 0x54, 0x79, 0x70, - 0x65, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x42, 0x55, 0x55, 0x42, 0x22, - 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x42, 0x74, 0x68, - 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x66, 0x69, - 0x65, 0x6C, 0x64, 0x20, 0x46, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x41, 0x74, 0x68, 0x20, 0x74, 0x72, 0x61, - 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x6E, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, - 0x74, 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, 0x22, 0x2C, 0x22, 0x49, - 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x4E, 0x6F, 0x74, - 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x20, - 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, - 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x69, 0x6E, 0x64, 0x65, - 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, - 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, - 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, - 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, - 0x39, 0x35, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, - 0x61, 0x72, 0x67, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, - 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, - 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x42, 0x22, 0x2C, 0x22, 0x43, - 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, - 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, - 0x22, 0x41, 0x74, 0x68, 0x20, 0x4C, 0x6F, 0x67, 0x69, 0x63, 0x53, - 0x69, 0x67, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, - 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, - 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x56, - 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, - 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x39, 0x36, - 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x67, 0x6C, - 0x6F, 0x61, 0x64, 0x73, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, - 0x73, 0x22, 0x3A, 0x22, 0x55, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, - 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, - 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, - 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x44, 0x6F, 0x63, - 0x22, 0x3A, 0x22, 0x42, 0x74, 0x68, 0x20, 0x73, 0x63, 0x72, 0x61, - 0x74, 0x63, 0x68, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x76, - 0x61, 0x6C, 0x75, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x41, 0x74, 0x68, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x20, 0x67, - 0x72, 0x6F, 0x75, 0x70, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, 0x75, - 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x4C, 0x6F, 0x61, 0x64, 0x69, - 0x6E, 0x67, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x22, 0x5D, - 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, 0x63, 0x6F, 0x64, 0x65, 0x22, - 0x3A, 0x31, 0x39, 0x37, 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, - 0x3A, 0x22, 0x69, 0x74, 0x78, 0x6E, 0x61, 0x73, 0x22, 0x2C, 0x22, - 0x41, 0x72, 0x67, 0x73, 0x22, 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, - 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, - 0x22, 0x2C, 0x22, 0x43, 0x6F, 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, - 0x22, 0x53, 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x32, 0x2C, 0x22, 0x44, - 0x6F, 0x63, 0x22, 0x3A, 0x22, 0x41, 0x74, 0x68, 0x20, 0x76, 0x61, - 0x6C, 0x75, 0x65, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, - 0x20, 0x46, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6C, - 0x61, 0x73, 0x74, 0x20, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x74, - 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x22, - 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, - 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, 0x69, 0x6E, - 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x69, - 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, 0x6F, - 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x49, 0x6E, 0x6E, 0x65, - 0x72, 0x20, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6F, 0x6E, 0x73, 0x22, 0x5D, 0x7D, 0x2C, 0x7B, 0x22, 0x4F, 0x70, - 0x63, 0x6F, 0x64, 0x65, 0x22, 0x3A, 0x31, 0x39, 0x38, 0x2C, 0x22, - 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x67, 0x69, 0x74, 0x78, - 0x6E, 0x61, 0x73, 0x22, 0x2C, 0x22, 0x41, 0x72, 0x67, 0x73, 0x22, - 0x3A, 0x22, 0x55, 0x22, 0x2C, 0x22, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6E, 0x73, 0x22, 0x3A, 0x22, 0x2E, 0x22, 0x2C, 0x22, 0x43, 0x6F, - 0x73, 0x74, 0x22, 0x3A, 0x31, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, - 0x22, 0x3A, 0x33, 0x2C, 0x22, 0x44, 0x6F, 0x63, 0x22, 0x3A, 0x22, - 0x41, 0x74, 0x68, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x6F, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x46, 0x20, 0x66, 0x72, - 0x6F, 0x6D, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x74, 0x68, 0x20, - 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, - 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6C, 0x61, 0x73, - 0x74, 0x20, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x67, 0x72, 0x6F, - 0x75, 0x70, 0x20, 0x73, 0x75, 0x62, 0x6D, 0x69, 0x74, 0x74, 0x65, - 0x64, 0x22, 0x2C, 0x22, 0x49, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, - 0x74, 0x65, 0x4E, 0x6F, 0x74, 0x65, 0x22, 0x3A, 0x22, 0x7B, 0x75, - 0x69, 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x67, 0x72, 0x6F, 0x75, 0x70, - 0x20, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x20, 0x7B, 0x75, 0x69, - 0x6E, 0x74, 0x38, 0x20, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, - 0x69, 0x6E, 0x64, 0x65, 0x78, 0x7D, 0x22, 0x2C, 0x22, 0x47, 0x72, - 0x6F, 0x75, 0x70, 0x73, 0x22, 0x3A, 0x5B, 0x22, 0x49, 0x6E, 0x6E, - 0x65, 0x72, 0x20, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6F, 0x6E, 0x73, 0x22, 0x5D, 0x7D, 0x5D, 0x7D, 0x0A, - } -} diff --git a/logic/langspec.json b/logic/langspec.json deleted file mode 100644 index ee94b0d3..00000000 --- a/logic/langspec.json +++ /dev/null @@ -1 +0,0 @@ -{"EvalMaxVersion":6,"LogicSigVersion":6,"Ops":[{"Opcode":0,"Name":"err","Cost":1,"Size":1,"Doc":"Fail immediately.","Groups":["Flow Control"]},{"Opcode":1,"Name":"sha256","Args":"B","Returns":"B","Cost":35,"Size":1,"Doc":"SHA256 hash of value A, yields [32]byte","Groups":["Arithmetic"]},{"Opcode":2,"Name":"keccak256","Args":"B","Returns":"B","Cost":130,"Size":1,"Doc":"Keccak256 hash of value A, yields [32]byte","Groups":["Arithmetic"]},{"Opcode":3,"Name":"sha512_256","Args":"B","Returns":"B","Cost":45,"Size":1,"Doc":"SHA512_256 hash of value A, yields [32]byte","Groups":["Arithmetic"]},{"Opcode":4,"Name":"ed25519verify","Args":"BBB","Returns":"U","Cost":1900,"Size":1,"Doc":"for (data A, signature B, pubkey C) verify the signature of (\"ProgData\" || program_hash || data) against the pubkey =\u003e {0 or 1}","DocExtra":"The 32 byte public key is the last element on the stack, preceded by the 64 byte signature at the second-to-last element on the stack, preceded by the data which was signed at the third-to-last element on the stack.","Groups":["Arithmetic"]},{"Opcode":5,"Name":"ecdsa_verify","Args":"BBBBB","Returns":"U","Cost":1700,"Size":2,"Doc":"for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey =\u003e {0 or 1}","DocExtra":"The 32 byte Y-component of a public key is the last element on the stack, preceded by X-component of a pubkey, preceded by S and R components of a signature, preceded by the data that is fifth element on the stack. All values are big-endian encoded. The signed data must be 32 bytes long, and signatures in lower-S form are only accepted.","ImmediateNote":"{uint8 curve index}","Groups":["Arithmetic"]},{"Opcode":6,"Name":"ecdsa_pk_decompress","Args":"B","Returns":"BB","Cost":650,"Size":2,"Doc":"decompress pubkey A into components X, Y","DocExtra":"The 33 byte public key in a compressed form to be decompressed into X and Y (top) components. All values are big-endian encoded.","ImmediateNote":"{uint8 curve index}","Groups":["Arithmetic"]},{"Opcode":7,"Name":"ecdsa_pk_recover","Args":"BUBB","Returns":"BB","Cost":2000,"Size":2,"Doc":"for (data A, recovery id B, signature C, D) recover a public key","DocExtra":"S (top) and R elements of a signature, recovery id and data (bottom) are expected on the stack and used to deriver a public key. All values are big-endian encoded. The signed data must be 32 bytes long.","ImmediateNote":"{uint8 curve index}","Groups":["Arithmetic"]},{"Opcode":8,"Name":"+","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A plus B. Fail on overflow.","DocExtra":"Overflow is an error condition which halts execution and fails the transaction. Full precision is available from `addw`.","Groups":["Arithmetic"]},{"Opcode":9,"Name":"-","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A minus B. Fail if B \u003e A.","Groups":["Arithmetic"]},{"Opcode":10,"Name":"/","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A divided by B (truncated division). Fail if B == 0.","DocExtra":"`divmodw` is available to divide the two-element values produced by `mulw` and `addw`.","Groups":["Arithmetic"]},{"Opcode":11,"Name":"*","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A times B. Fail on overflow.","DocExtra":"Overflow is an error condition which halts execution and fails the transaction. Full precision is available from `mulw`.","Groups":["Arithmetic"]},{"Opcode":12,"Name":"\u003c","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A less than B =\u003e {0 or 1}","Groups":["Arithmetic"]},{"Opcode":13,"Name":"\u003e","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A greater than B =\u003e {0 or 1}","Groups":["Arithmetic"]},{"Opcode":14,"Name":"\u003c=","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A less than or equal to B =\u003e {0 or 1}","Groups":["Arithmetic"]},{"Opcode":15,"Name":"\u003e=","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A greater than or equal to B =\u003e {0 or 1}","Groups":["Arithmetic"]},{"Opcode":16,"Name":"\u0026\u0026","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A is not zero and B is not zero =\u003e {0 or 1}","Groups":["Arithmetic"]},{"Opcode":17,"Name":"||","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A is not zero or B is not zero =\u003e {0 or 1}","Groups":["Arithmetic"]},{"Opcode":18,"Name":"==","Args":"..","Returns":"U","Cost":1,"Size":1,"Doc":"A is equal to B =\u003e {0 or 1}","Groups":["Arithmetic"]},{"Opcode":19,"Name":"!=","Args":"..","Returns":"U","Cost":1,"Size":1,"Doc":"A is not equal to B =\u003e {0 or 1}","Groups":["Arithmetic"]},{"Opcode":20,"Name":"!","Args":"U","Returns":"U","Cost":1,"Size":1,"Doc":"A == 0 yields 1; else 0","Groups":["Arithmetic"]},{"Opcode":21,"Name":"len","Args":"B","Returns":"U","Cost":1,"Size":1,"Doc":"yields length of byte value A","Groups":["Arithmetic"]},{"Opcode":22,"Name":"itob","Args":"U","Returns":"B","Cost":1,"Size":1,"Doc":"converts uint64 A to big endian bytes","Groups":["Arithmetic"]},{"Opcode":23,"Name":"btoi","Args":"B","Returns":"U","Cost":1,"Size":1,"Doc":"converts bytes A as big endian to uint64","DocExtra":"`btoi` fails if the input is longer than 8 bytes.","Groups":["Arithmetic"]},{"Opcode":24,"Name":"%","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A modulo B. Fail if B == 0.","Groups":["Arithmetic"]},{"Opcode":25,"Name":"|","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A bitwise-or B","Groups":["Arithmetic"]},{"Opcode":26,"Name":"\u0026","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A bitwise-and B","Groups":["Arithmetic"]},{"Opcode":27,"Name":"^","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A bitwise-xor B","Groups":["Arithmetic"]},{"Opcode":28,"Name":"~","Args":"U","Returns":"U","Cost":1,"Size":1,"Doc":"bitwise invert value A","Groups":["Arithmetic"]},{"Opcode":29,"Name":"mulw","Args":"UU","Returns":"UU","Cost":1,"Size":1,"Doc":"A times B as a 128-bit result in two uint64s. X is the high 64 bits, Y is the low","Groups":["Arithmetic"]},{"Opcode":30,"Name":"addw","Args":"UU","Returns":"UU","Cost":1,"Size":1,"Doc":"A plus B as a 128-bit result. X is the carry-bit, Y is the low-order 64 bits.","Groups":["Arithmetic"]},{"Opcode":31,"Name":"divmodw","Args":"UUUU","Returns":"UUUU","Cost":20,"Size":1,"Doc":"W,X = (A,B / C,D); Y,Z = (A,B modulo C,D)","DocExtra":"The notation J,K indicates that two uint64 values J and K are interpreted as a uint128 value, with J as the high uint64 and K the low.","Groups":["Arithmetic"]},{"Opcode":32,"Name":"intcblock","Cost":1,"Size":0,"Doc":"prepare block of uint64 constants for use by intc","DocExtra":"`intcblock` loads following program bytes into an array of integer constants in the evaluator. These integer constants can be referred to by `intc` and `intc_*` which will push the value onto the stack. Subsequent calls to `intcblock` reset and replace the integer constants available to the script.","ImmediateNote":"{varuint length} [{varuint value}, ...]","Groups":["Loading Values"]},{"Opcode":33,"Name":"intc","Returns":"U","Cost":1,"Size":2,"Doc":"Ith constant from intcblock","ImmediateNote":"{uint8 int constant index}","Groups":["Loading Values"]},{"Opcode":34,"Name":"intc_0","Returns":"U","Cost":1,"Size":1,"Doc":"constant 0 from intcblock","Groups":["Loading Values"]},{"Opcode":35,"Name":"intc_1","Returns":"U","Cost":1,"Size":1,"Doc":"constant 1 from intcblock","Groups":["Loading Values"]},{"Opcode":36,"Name":"intc_2","Returns":"U","Cost":1,"Size":1,"Doc":"constant 2 from intcblock","Groups":["Loading Values"]},{"Opcode":37,"Name":"intc_3","Returns":"U","Cost":1,"Size":1,"Doc":"constant 3 from intcblock","Groups":["Loading Values"]},{"Opcode":38,"Name":"bytecblock","Cost":1,"Size":0,"Doc":"prepare block of byte-array constants for use by bytec","DocExtra":"`bytecblock` loads the following program bytes into an array of byte-array constants in the evaluator. These constants can be referred to by `bytec` and `bytec_*` which will push the value onto the stack. Subsequent calls to `bytecblock` reset and replace the bytes constants available to the script.","ImmediateNote":"{varuint length} [({varuint value length} bytes), ...]","Groups":["Loading Values"]},{"Opcode":39,"Name":"bytec","Returns":"B","Cost":1,"Size":2,"Doc":"Ith constant from bytecblock","ImmediateNote":"{uint8 byte constant index}","Groups":["Loading Values"]},{"Opcode":40,"Name":"bytec_0","Returns":"B","Cost":1,"Size":1,"Doc":"constant 0 from bytecblock","Groups":["Loading Values"]},{"Opcode":41,"Name":"bytec_1","Returns":"B","Cost":1,"Size":1,"Doc":"constant 1 from bytecblock","Groups":["Loading Values"]},{"Opcode":42,"Name":"bytec_2","Returns":"B","Cost":1,"Size":1,"Doc":"constant 2 from bytecblock","Groups":["Loading Values"]},{"Opcode":43,"Name":"bytec_3","Returns":"B","Cost":1,"Size":1,"Doc":"constant 3 from bytecblock","Groups":["Loading Values"]},{"Opcode":44,"Name":"arg","Returns":"B","Cost":1,"Size":2,"Doc":"Nth LogicSig argument","ImmediateNote":"{uint8 arg index N}","Groups":["Loading Values"]},{"Opcode":45,"Name":"arg_0","Returns":"B","Cost":1,"Size":1,"Doc":"LogicSig argument 0","Groups":["Loading Values"]},{"Opcode":46,"Name":"arg_1","Returns":"B","Cost":1,"Size":1,"Doc":"LogicSig argument 1","Groups":["Loading Values"]},{"Opcode":47,"Name":"arg_2","Returns":"B","Cost":1,"Size":1,"Doc":"LogicSig argument 2","Groups":["Loading Values"]},{"Opcode":48,"Name":"arg_3","Returns":"B","Cost":1,"Size":1,"Doc":"LogicSig argument 3","Groups":["Loading Values"]},{"Opcode":49,"Name":"txn","Returns":".","Cost":1,"Size":2,"ArgEnum":["Sender","Fee","FirstValid","FirstValidTime","LastValid","Note","Lease","Receiver","Amount","CloseRemainderTo","VotePK","SelectionPK","VoteFirst","VoteLast","VoteKeyDilution","Type","TypeEnum","XferAsset","AssetAmount","AssetSender","AssetReceiver","AssetCloseTo","GroupIndex","TxID","ApplicationID","OnCompletion","ApplicationArgs","NumAppArgs","Accounts","NumAccounts","ApprovalProgram","ClearStateProgram","RekeyTo","ConfigAsset","ConfigAssetTotal","ConfigAssetDecimals","ConfigAssetDefaultFrozen","ConfigAssetUnitName","ConfigAssetName","ConfigAssetURL","ConfigAssetMetadataHash","ConfigAssetManager","ConfigAssetReserve","ConfigAssetFreeze","ConfigAssetClawback","FreezeAsset","FreezeAssetAccount","FreezeAssetFrozen","Assets","NumAssets","Applications","NumApplications","GlobalNumUint","GlobalNumByteSlice","LocalNumUint","LocalNumByteSlice","ExtraProgramPages","Nonparticipation","Logs","NumLogs","CreatedAssetID","CreatedApplicationID","LastLog","StateProofPK"],"ArgEnumTypes":"BUUUUBBBUBBBUUUBUUUBBBUBUUBUBUBBBUUUUBBBBBBBBUBUUUUUUUUUUUBUUUBB","Doc":"field F of current transaction","DocExtra":"FirstValidTime causes the program to fail. The field is reserved for future use.","ImmediateNote":"{uint8 transaction field index}","Groups":["Loading Values"]},{"Opcode":50,"Name":"global","Returns":".","Cost":1,"Size":2,"Doc":"global field F","ImmediateNote":"{uint8 global field index}","Groups":["Loading Values"]},{"Opcode":51,"Name":"gtxn","Returns":".","Cost":1,"Size":3,"ArgEnum":["Sender","Fee","FirstValid","FirstValidTime","LastValid","Note","Lease","Receiver","Amount","CloseRemainderTo","VotePK","SelectionPK","VoteFirst","VoteLast","VoteKeyDilution","Type","TypeEnum","XferAsset","AssetAmount","AssetSender","AssetReceiver","AssetCloseTo","GroupIndex","TxID","ApplicationID","OnCompletion","ApplicationArgs","NumAppArgs","Accounts","NumAccounts","ApprovalProgram","ClearStateProgram","RekeyTo","ConfigAsset","ConfigAssetTotal","ConfigAssetDecimals","ConfigAssetDefaultFrozen","ConfigAssetUnitName","ConfigAssetName","ConfigAssetURL","ConfigAssetMetadataHash","ConfigAssetManager","ConfigAssetReserve","ConfigAssetFreeze","ConfigAssetClawback","FreezeAsset","FreezeAssetAccount","FreezeAssetFrozen","Assets","NumAssets","Applications","NumApplications","GlobalNumUint","GlobalNumByteSlice","LocalNumUint","LocalNumByteSlice","ExtraProgramPages","Nonparticipation","Logs","NumLogs","CreatedAssetID","CreatedApplicationID","LastLog","StateProofPK"],"ArgEnumTypes":"BUUUUBBBUBBBUUUBUUUBBBUBUUBUBUBBBUUUUBBBBBBBBUBUUUUUUUUUUUBUUUBB","Doc":"field F of the Tth transaction in the current group","DocExtra":"for notes on transaction fields available, see `txn`. If this transaction is _i_ in the group, `gtxn i field` is equivalent to `txn field`.","ImmediateNote":"{uint8 transaction group index} {uint8 transaction field index}","Groups":["Loading Values"]},{"Opcode":52,"Name":"load","Returns":".","Cost":1,"Size":2,"Doc":"Ith scratch space value. All scratch spaces are 0 at program start.","ImmediateNote":"{uint8 position in scratch space to load from}","Groups":["Loading Values"]},{"Opcode":53,"Name":"store","Args":".","Cost":1,"Size":2,"Doc":"store A to the Ith scratch space","ImmediateNote":"{uint8 position in scratch space to store to}","Groups":["Loading Values"]},{"Opcode":54,"Name":"txna","Returns":".","Cost":1,"Size":3,"ArgEnum":["ApplicationArgs","Accounts","Assets","Applications","Logs"],"ArgEnumTypes":"BBUUB","Doc":"Ith value of the array field F of the current transaction","ImmediateNote":"{uint8 transaction field index} {uint8 transaction field array index}","Groups":["Loading Values"]},{"Opcode":55,"Name":"gtxna","Returns":".","Cost":1,"Size":4,"ArgEnum":["ApplicationArgs","Accounts","Assets","Applications","Logs"],"ArgEnumTypes":"BBUUB","Doc":"Ith value of the array field F from the Tth transaction in the current group","ImmediateNote":"{uint8 transaction group index} {uint8 transaction field index} {uint8 transaction field array index}","Groups":["Loading Values"]},{"Opcode":56,"Name":"gtxns","Args":"U","Returns":".","Cost":1,"Size":2,"ArgEnum":["Sender","Fee","FirstValid","FirstValidTime","LastValid","Note","Lease","Receiver","Amount","CloseRemainderTo","VotePK","SelectionPK","VoteFirst","VoteLast","VoteKeyDilution","Type","TypeEnum","XferAsset","AssetAmount","AssetSender","AssetReceiver","AssetCloseTo","GroupIndex","TxID","ApplicationID","OnCompletion","ApplicationArgs","NumAppArgs","Accounts","NumAccounts","ApprovalProgram","ClearStateProgram","RekeyTo","ConfigAsset","ConfigAssetTotal","ConfigAssetDecimals","ConfigAssetDefaultFrozen","ConfigAssetUnitName","ConfigAssetName","ConfigAssetURL","ConfigAssetMetadataHash","ConfigAssetManager","ConfigAssetReserve","ConfigAssetFreeze","ConfigAssetClawback","FreezeAsset","FreezeAssetAccount","FreezeAssetFrozen","Assets","NumAssets","Applications","NumApplications","GlobalNumUint","GlobalNumByteSlice","LocalNumUint","LocalNumByteSlice","ExtraProgramPages","Nonparticipation","Logs","NumLogs","CreatedAssetID","CreatedApplicationID","LastLog","StateProofPK"],"ArgEnumTypes":"BUUUUBBBUBBBUUUBUUUBBBUBUUBUBUBBBUUUUBBBBBBBBUBUUUUUUUUUUUBUUUBB","Doc":"field F of the Ath transaction in the current group","DocExtra":"for notes on transaction fields available, see `txn`. If top of stack is _i_, `gtxns field` is equivalent to `gtxn _i_ field`. gtxns exists so that _i_ can be calculated, often based on the index of the current transaction.","ImmediateNote":"{uint8 transaction field index}","Groups":["Loading Values"]},{"Opcode":57,"Name":"gtxnsa","Args":"U","Returns":".","Cost":1,"Size":3,"ArgEnum":["ApplicationArgs","Accounts","Assets","Applications","Logs"],"ArgEnumTypes":"BBUUB","Doc":"Ith value of the array field F from the Ath transaction in the current group","ImmediateNote":"{uint8 transaction field index} {uint8 transaction field array index}","Groups":["Loading Values"]},{"Opcode":58,"Name":"gload","Returns":".","Cost":1,"Size":3,"Doc":"Ith scratch space value of the Tth transaction in the current group","DocExtra":"`gload` fails unless the requested transaction is an ApplicationCall and T \u003c GroupIndex.","ImmediateNote":"{uint8 transaction group index} {uint8 position in scratch space to load from}","Groups":["Loading Values"]},{"Opcode":59,"Name":"gloads","Args":"U","Returns":".","Cost":1,"Size":2,"Doc":"Ith scratch space value of the Ath transaction in the current group","DocExtra":"`gloads` fails unless the requested transaction is an ApplicationCall and A \u003c GroupIndex.","ImmediateNote":"{uint8 position in scratch space to load from}","Groups":["Loading Values"]},{"Opcode":60,"Name":"gaid","Returns":"U","Cost":1,"Size":2,"Doc":"ID of the asset or application created in the Tth transaction of the current group","DocExtra":"`gaid` fails unless the requested transaction created an asset or application and T \u003c GroupIndex.","ImmediateNote":"{uint8 transaction group index}","Groups":["Loading Values"]},{"Opcode":61,"Name":"gaids","Args":"U","Returns":"U","Cost":1,"Size":1,"Doc":"ID of the asset or application created in the Ath transaction of the current group","DocExtra":"`gaids` fails unless the requested transaction created an asset or application and A \u003c GroupIndex.","Groups":["Loading Values"]},{"Opcode":62,"Name":"loads","Args":"U","Returns":".","Cost":1,"Size":1,"Doc":"Ath scratch space value. All scratch spaces are 0 at program start.","Groups":["Loading Values"]},{"Opcode":63,"Name":"stores","Args":"U.","Cost":1,"Size":1,"Doc":"store B to the Ath scratch space","Groups":["Loading Values"]},{"Opcode":64,"Name":"bnz","Args":"U","Cost":1,"Size":3,"Doc":"branch to TARGET if value A is not zero","DocExtra":"The `bnz` instruction opcode 0x40 is followed by two immediate data bytes which are a high byte first and low byte second which together form a 16 bit offset which the instruction may branch to. For a bnz instruction at `pc`, if the last element of the stack is not zero then branch to instruction at `pc + 3 + N`, else proceed to next instruction at `pc + 3`. Branch targets must be aligned instructions. (e.g. Branching to the second byte of a 2 byte op will be rejected.) Starting at v4, the offset is treated as a signed 16 bit integer allowing for backward branches and looping. In prior version (v1 to v3), branch offsets are limited to forward branches only, 0-0x7fff.\n\nAt v2 it became allowed to branch to the end of the program exactly after the last instruction: bnz to byte N (with 0-indexing) was illegal for a TEAL program with N bytes before v2, and is legal after it. This change eliminates the need for a last instruction of no-op as a branch target at the end. (Branching beyond the end--in other words, to a byte larger than N--is still illegal and will cause the program to fail.)","ImmediateNote":"{int16 branch offset, big endian}","Groups":["Flow Control"]},{"Opcode":65,"Name":"bz","Args":"U","Cost":1,"Size":3,"Doc":"branch to TARGET if value A is zero","DocExtra":"See `bnz` for details on how branches work. `bz` inverts the behavior of `bnz`.","ImmediateNote":"{int16 branch offset, big endian}","Groups":["Flow Control"]},{"Opcode":66,"Name":"b","Cost":1,"Size":3,"Doc":"branch unconditionally to TARGET","DocExtra":"See `bnz` for details on how branches work. `b` always jumps to the offset.","ImmediateNote":"{int16 branch offset, big endian}","Groups":["Flow Control"]},{"Opcode":67,"Name":"return","Args":"U","Cost":1,"Size":1,"Doc":"use A as success value; end","Groups":["Flow Control"]},{"Opcode":68,"Name":"assert","Args":"U","Cost":1,"Size":1,"Doc":"immediately fail unless A is a non-zero number","Groups":["Flow Control"]},{"Opcode":72,"Name":"pop","Args":".","Cost":1,"Size":1,"Doc":"discard A","Groups":["Flow Control"]},{"Opcode":73,"Name":"dup","Args":".","Returns":"..","Cost":1,"Size":1,"Doc":"duplicate A","Groups":["Flow Control"]},{"Opcode":74,"Name":"dup2","Args":"..","Returns":"....","Cost":1,"Size":1,"Doc":"duplicate A and B","Groups":["Flow Control"]},{"Opcode":75,"Name":"dig","Args":".","Returns":"..","Cost":1,"Size":2,"Doc":"Nth value from the top of the stack. dig 0 is equivalent to dup","ImmediateNote":"{uint8 depth}","Groups":["Flow Control"]},{"Opcode":76,"Name":"swap","Args":"..","Returns":"..","Cost":1,"Size":1,"Doc":"swaps A and B on stack","Groups":["Flow Control"]},{"Opcode":77,"Name":"select","Args":"..U","Returns":".","Cost":1,"Size":1,"Doc":"selects one of two values based on top-of-stack: B if C != 0, else A","Groups":["Flow Control"]},{"Opcode":78,"Name":"cover","Args":".","Returns":".","Cost":1,"Size":2,"Doc":"remove top of stack, and place it deeper in the stack such that N elements are above it. Fails if stack depth \u003c= N.","ImmediateNote":"{uint8 depth}","Groups":["Flow Control"]},{"Opcode":79,"Name":"uncover","Args":".","Returns":".","Cost":1,"Size":2,"Doc":"remove the value at depth N in the stack and shift above items down so the Nth deep value is on top of the stack. Fails if stack depth \u003c= N.","ImmediateNote":"{uint8 depth}","Groups":["Flow Control"]},{"Opcode":80,"Name":"concat","Args":"BB","Returns":"B","Cost":1,"Size":1,"Doc":"join A and B","DocExtra":"`concat` fails if the result would be greater than 4096 bytes.","Groups":["Arithmetic"]},{"Opcode":81,"Name":"substring","Args":"B","Returns":"B","Cost":1,"Size":3,"Doc":"A range of bytes from A starting at S up to but not including E. If E \u003c S, or either is larger than the array length, the program fails","ImmediateNote":"{uint8 start position} {uint8 end position}","Groups":["Byte Array Manipulation"]},{"Opcode":82,"Name":"substring3","Args":"BUU","Returns":"B","Cost":1,"Size":1,"Doc":"A range of bytes from A starting at B up to but not including C. If C \u003c B, or either is larger than the array length, the program fails","Groups":["Byte Array Manipulation"]},{"Opcode":83,"Name":"getbit","Args":".U","Returns":"U","Cost":1,"Size":1,"Doc":"Bth bit of (byte-array or integer) A.","DocExtra":"see explanation of bit ordering in setbit","Groups":["Arithmetic"]},{"Opcode":84,"Name":"setbit","Args":".UU","Returns":".","Cost":1,"Size":1,"Doc":"Copy of (byte-array or integer) A, with the Bth bit set to (0 or 1) C","DocExtra":"When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on the integer 0 yields 8, or 2^3. When A is a byte array, index 0 is the leftmost bit of the leftmost byte. Setting bits 0 through 11 to 1 in a 4-byte-array of 0s yields the byte array 0xfff00000. Setting bit 3 to 1 on the 1-byte-array 0x00 yields the byte array 0x10.","Groups":["Arithmetic"]},{"Opcode":85,"Name":"getbyte","Args":"BU","Returns":"U","Cost":1,"Size":1,"Doc":"Bth byte of A, as an integer","Groups":["Arithmetic"]},{"Opcode":86,"Name":"setbyte","Args":"BUU","Returns":"B","Cost":1,"Size":1,"Doc":"Copy of A with the Bth byte set to small integer (between 0..255) C","Groups":["Arithmetic"]},{"Opcode":87,"Name":"extract","Args":"B","Returns":"B","Cost":1,"Size":3,"Doc":"A range of bytes from A starting at S up to but not including S+L. 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","ImmediateNote":"{uint8 start position} {uint8 length}","Groups":["Byte Array Manipulation"]},{"Opcode":88,"Name":"extract3","Args":"BUU","Returns":"B","Cost":1,"Size":1,"Doc":"A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails","Groups":["Byte Array Manipulation"]},{"Opcode":89,"Name":"extract_uint16","Args":"BU","Returns":"U","Cost":1,"Size":1,"Doc":"A uint16 formed from a range of big-endian bytes from A starting at B up to but not including B+2. If B+2 is larger than the array length, the program fails","Groups":["Byte Array Manipulation"]},{"Opcode":90,"Name":"extract_uint32","Args":"BU","Returns":"U","Cost":1,"Size":1,"Doc":"A uint32 formed from a range of big-endian bytes from A starting at B up to but not including B+4. If B+4 is larger than the array length, the program fails","Groups":["Byte Array Manipulation"]},{"Opcode":91,"Name":"extract_uint64","Args":"BU","Returns":"U","Cost":1,"Size":1,"Doc":"A uint64 formed from a range of big-endian bytes from A starting at B up to but not including B+8. If B+8 is larger than the array length, the program fails","Groups":["Byte Array Manipulation"]},{"Opcode":96,"Name":"balance","Args":".","Returns":"U","Cost":1,"Size":1,"Doc":"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.","DocExtra":"params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.","Groups":["State Access"]},{"Opcode":97,"Name":"app_opted_in","Args":".U","Returns":"U","Cost":1,"Size":1,"Doc":"1 if account A is opted in to application B, else 0","DocExtra":"params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: 1 if opted in and 0 otherwise.","Groups":["State Access"]},{"Opcode":98,"Name":"app_local_get","Args":".B","Returns":".","Cost":1,"Size":1,"Doc":"local state of the key B in the current application in account A","DocExtra":"params: Txn.Accounts offset (or, since v4, an _available_ account address), state key. Return: value. The value is zero (of type uint64) if the key does not exist.","Groups":["State Access"]},{"Opcode":99,"Name":"app_local_get_ex","Args":".UB","Returns":".U","Cost":1,"Size":1,"Doc":"X is the local state of application B, key C in account A. Y is 1 if key existed, else 0","DocExtra":"params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.","Groups":["State Access"]},{"Opcode":100,"Name":"app_global_get","Args":"B","Returns":".","Cost":1,"Size":1,"Doc":"global state of the key A in the current application","DocExtra":"params: state key. Return: value. The value is zero (of type uint64) if the key does not exist.","Groups":["State Access"]},{"Opcode":101,"Name":"app_global_get_ex","Args":"UB","Returns":".U","Cost":1,"Size":1,"Doc":"X is the global state of application A, key B. Y is 1 if key existed, else 0","DocExtra":"params: Txn.ForeignApps offset (or, since v4, an _available_ application id), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.","Groups":["State Access"]},{"Opcode":102,"Name":"app_local_put","Args":".B.","Cost":1,"Size":1,"Doc":"write C to key B in account A's local state of the current application","DocExtra":"params: Txn.Accounts offset (or, since v4, an _available_ account address), state key, value.","Groups":["State Access"]},{"Opcode":103,"Name":"app_global_put","Args":"B.","Cost":1,"Size":1,"Doc":"write B to key A in the global state of the current application","Groups":["State Access"]},{"Opcode":104,"Name":"app_local_del","Args":".B","Cost":1,"Size":1,"Doc":"delete key B from account A's local state of the current application","DocExtra":"params: Txn.Accounts offset (or, since v4, an _available_ account address), state key.\n\nDeleting a key which is already absent has no effect on the application local state. (In particular, it does _not_ cause the program to fail.)","Groups":["State Access"]},{"Opcode":105,"Name":"app_global_del","Args":"B","Cost":1,"Size":1,"Doc":"delete key A from the global state of the current application","DocExtra":"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.)","Groups":["State Access"]},{"Opcode":112,"Name":"asset_holding_get","Args":".U","Returns":".U","Cost":1,"Size":2,"ArgEnum":["AssetBalance","AssetFrozen"],"ArgEnumTypes":"UU","Doc":"X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0","DocExtra":"params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.","ImmediateNote":"{uint8 asset holding field index}","Groups":["State Access"]},{"Opcode":113,"Name":"asset_params_get","Args":"U","Returns":".U","Cost":1,"Size":2,"ArgEnum":["AssetTotal","AssetDecimals","AssetDefaultFrozen","AssetUnitName","AssetName","AssetURL","AssetMetadataHash","AssetManager","AssetReserve","AssetFreeze","AssetClawback","AssetCreator"],"ArgEnumTypes":"UUUBBBBBBBBB","Doc":"X is field F from asset A. Y is 1 if A exists, else 0","DocExtra":"params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.","ImmediateNote":"{uint8 asset params field index}","Groups":["State Access"]},{"Opcode":114,"Name":"app_params_get","Args":"U","Returns":".U","Cost":1,"Size":2,"ArgEnum":["AppApprovalProgram","AppClearStateProgram","AppGlobalNumUint","AppGlobalNumByteSlice","AppLocalNumUint","AppLocalNumByteSlice","AppExtraProgramPages","AppCreator","AppAddress"],"ArgEnumTypes":"BBUUUUUBB","Doc":"X is field F from app A. Y is 1 if A exists, else 0","DocExtra":"params: Txn.ForeignApps offset or an _available_ app id. Return: did_exist flag (1 if the application existed and 0 otherwise), value.","ImmediateNote":"{uint8 app params field index}","Groups":["State Access"]},{"Opcode":115,"Name":"acct_params_get","Args":".","Returns":".U","Cost":1,"Size":2,"Doc":"X is field F from account A. Y is 1 if A owns positive algos, else 0","ImmediateNote":"{uint8 account params field index}","Groups":["State Access"]},{"Opcode":120,"Name":"min_balance","Args":".","Returns":"U","Cost":1,"Size":1,"Doc":"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.","DocExtra":"params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.","Groups":["State Access"]},{"Opcode":128,"Name":"pushbytes","Returns":"B","Cost":1,"Size":0,"Doc":"immediate BYTES","DocExtra":"pushbytes args are not added to the bytecblock during assembly processes","ImmediateNote":"{varuint length} {bytes}","Groups":["Loading Values"]},{"Opcode":129,"Name":"pushint","Returns":"U","Cost":1,"Size":0,"Doc":"immediate UINT","DocExtra":"pushint args are not added to the intcblock during assembly processes","ImmediateNote":"{varuint int}","Groups":["Loading Values"]},{"Opcode":136,"Name":"callsub","Cost":1,"Size":3,"Doc":"branch unconditionally to TARGET, saving the next instruction on the call stack","DocExtra":"The call stack is separate from the data stack. Only `callsub` and `retsub` manipulate it.","ImmediateNote":"{int16 branch offset, big endian}","Groups":["Flow Control"]},{"Opcode":137,"Name":"retsub","Cost":1,"Size":1,"Doc":"pop the top instruction from the call stack and branch to it","DocExtra":"The call stack is separate from the data stack. Only `callsub` and `retsub` manipulate it.","Groups":["Flow Control"]},{"Opcode":144,"Name":"shl","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A times 2^B, modulo 2^64","Groups":["Arithmetic"]},{"Opcode":145,"Name":"shr","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A divided by 2^B","Groups":["Arithmetic"]},{"Opcode":146,"Name":"sqrt","Args":"U","Returns":"U","Cost":4,"Size":1,"Doc":"The largest integer I such that I^2 \u003c= A","Groups":["Arithmetic"]},{"Opcode":147,"Name":"bitlen","Args":".","Returns":"U","Cost":1,"Size":1,"Doc":"The highest set bit in A. If A is a byte-array, it is interpreted as a big-endian unsigned integer. bitlen of 0 is 0, bitlen of 8 is 4","DocExtra":"bitlen interprets arrays as big-endian integers, unlike setbit/getbit","Groups":["Arithmetic"]},{"Opcode":148,"Name":"exp","Args":"UU","Returns":"U","Cost":1,"Size":1,"Doc":"A raised to the Bth power. Fail if A == B == 0 and on overflow","Groups":["Arithmetic"]},{"Opcode":149,"Name":"expw","Args":"UU","Returns":"UU","Cost":10,"Size":1,"Doc":"A raised to the Bth power as a 128-bit result in two uint64s. X is the high 64 bits, Y is the low. Fail if A == B == 0 or if the results exceeds 2^128-1","Groups":["Arithmetic"]},{"Opcode":150,"Name":"bsqrt","Args":"B","Returns":"B","Cost":40,"Size":1,"Doc":"The largest integer I such that I^2 \u003c= A. A and I are interpreted as big-endian unsigned integers","Groups":["Byte Array Arithmetic"]},{"Opcode":151,"Name":"divw","Args":"UUU","Returns":"U","Cost":1,"Size":1,"Doc":"A,B / C. Fail if C == 0 or if result overflows.","DocExtra":"The notation A,B indicates that A and B are interpreted as a uint128 value, with A as the high uint64 and B the low.","Groups":["Arithmetic"]},{"Opcode":160,"Name":"b+","Args":"BB","Returns":"B","Cost":10,"Size":1,"Doc":"A plus B. A and B are interpreted as big-endian unsigned integers","Groups":["Byte Array Arithmetic"]},{"Opcode":161,"Name":"b-","Args":"BB","Returns":"B","Cost":10,"Size":1,"Doc":"A minus B. A and B are interpreted as big-endian unsigned integers. Fail on underflow.","Groups":["Byte Array Arithmetic"]},{"Opcode":162,"Name":"b/","Args":"BB","Returns":"B","Cost":20,"Size":1,"Doc":"A divided by B (truncated division). A and B are interpreted as big-endian unsigned integers. Fail if B is zero.","Groups":["Byte Array Arithmetic"]},{"Opcode":163,"Name":"b*","Args":"BB","Returns":"B","Cost":20,"Size":1,"Doc":"A times B. A and B are interpreted as big-endian unsigned integers.","Groups":["Byte Array Arithmetic"]},{"Opcode":164,"Name":"b\u003c","Args":"BB","Returns":"U","Cost":1,"Size":1,"Doc":"1 if A is less than B, else 0. A and B are interpreted as big-endian unsigned integers","Groups":["Byte Array Arithmetic"]},{"Opcode":165,"Name":"b\u003e","Args":"BB","Returns":"U","Cost":1,"Size":1,"Doc":"1 if A is greater than B, else 0. A and B are interpreted as big-endian unsigned integers","Groups":["Byte Array Arithmetic"]},{"Opcode":166,"Name":"b\u003c=","Args":"BB","Returns":"U","Cost":1,"Size":1,"Doc":"1 if A is less than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers","Groups":["Byte Array Arithmetic"]},{"Opcode":167,"Name":"b\u003e=","Args":"BB","Returns":"U","Cost":1,"Size":1,"Doc":"1 if A is greater than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers","Groups":["Byte Array Arithmetic"]},{"Opcode":168,"Name":"b==","Args":"BB","Returns":"U","Cost":1,"Size":1,"Doc":"1 if A is equal to B, else 0. A and B are interpreted as big-endian unsigned integers","Groups":["Byte Array Arithmetic"]},{"Opcode":169,"Name":"b!=","Args":"BB","Returns":"U","Cost":1,"Size":1,"Doc":"0 if A is equal to B, else 1. A and B are interpreted as big-endian unsigned integers","Groups":["Byte Array Arithmetic"]},{"Opcode":170,"Name":"b%","Args":"BB","Returns":"B","Cost":20,"Size":1,"Doc":"A modulo B. A and B are interpreted as big-endian unsigned integers. Fail if B is zero.","Groups":["Byte Array Arithmetic"]},{"Opcode":171,"Name":"b|","Args":"BB","Returns":"B","Cost":6,"Size":1,"Doc":"A bitwise-or B. A and B are zero-left extended to the greater of their lengths","Groups":["Byte Array Logic"]},{"Opcode":172,"Name":"b\u0026","Args":"BB","Returns":"B","Cost":6,"Size":1,"Doc":"A bitwise-and B. A and B are zero-left extended to the greater of their lengths","Groups":["Byte Array Logic"]},{"Opcode":173,"Name":"b^","Args":"BB","Returns":"B","Cost":6,"Size":1,"Doc":"A bitwise-xor B. A and B are zero-left extended to the greater of their lengths","Groups":["Byte Array Logic"]},{"Opcode":174,"Name":"b~","Args":"B","Returns":"B","Cost":4,"Size":1,"Doc":"A with all bits inverted","Groups":["Byte Array Logic"]},{"Opcode":175,"Name":"bzero","Args":"U","Returns":"B","Cost":1,"Size":1,"Doc":"zero filled byte-array of length A","Groups":["Loading Values"]},{"Opcode":176,"Name":"log","Args":"B","Cost":1,"Size":1,"Doc":"write A to log state of the current application","DocExtra":"`log` fails if called more than MaxLogCalls times in a program, or if the sum of logged bytes exceeds 1024 bytes.","Groups":["State Access"]},{"Opcode":177,"Name":"itxn_begin","Cost":1,"Size":1,"Doc":"begin preparation of a new inner transaction in a new transaction group","DocExtra":"`itxn_begin` initializes Sender to the application address; Fee to the minimum allowable, taking into account MinTxnFee and credit from overpaying in earlier transactions; FirstValid/LastValid to the values in the invoking transaction, and all other fields to zero or empty values.","Groups":["Inner Transactions"]},{"Opcode":178,"Name":"itxn_field","Args":".","Cost":1,"Size":2,"ArgEnum":["Sender","Fee","FirstValid","FirstValidTime","LastValid","Note","Lease","Receiver","Amount","CloseRemainderTo","VotePK","SelectionPK","VoteFirst","VoteLast","VoteKeyDilution","Type","TypeEnum","XferAsset","AssetAmount","AssetSender","AssetReceiver","AssetCloseTo","GroupIndex","TxID","ApplicationID","OnCompletion","ApplicationArgs","NumAppArgs","Accounts","NumAccounts","ApprovalProgram","ClearStateProgram","RekeyTo","ConfigAsset","ConfigAssetTotal","ConfigAssetDecimals","ConfigAssetDefaultFrozen","ConfigAssetUnitName","ConfigAssetName","ConfigAssetURL","ConfigAssetMetadataHash","ConfigAssetManager","ConfigAssetReserve","ConfigAssetFreeze","ConfigAssetClawback","FreezeAsset","FreezeAssetAccount","FreezeAssetFrozen","Assets","NumAssets","Applications","NumApplications","GlobalNumUint","GlobalNumByteSlice","LocalNumUint","LocalNumByteSlice","ExtraProgramPages","Nonparticipation","Logs","NumLogs","CreatedAssetID","CreatedApplicationID","LastLog","StateProofPK"],"ArgEnumTypes":"BUUUUBBBUBBBUUUBUUUBBBUBUUBUBUBBBUUUUBBBBBBBBUBUUUUUUUUUUUBUUUBB","Doc":"set field F of the current inner transaction to A","DocExtra":"`itxn_field` fails if A is of the wrong type for F, including a byte array of the wrong size for use as an address when F is an address field. `itxn_field` also fails if A is an account, asset, or app that is not _available_, or an attempt is made extend an array field beyond the limit imposed by consensus parameters. (Addresses set into asset params of acfg transactions need not be _available_.)","ImmediateNote":"{uint8 transaction field index}","Groups":["Inner Transactions"]},{"Opcode":179,"Name":"itxn_submit","Cost":1,"Size":1,"Doc":"execute the current inner transaction group. Fail if executing this group would exceed the inner transaction limit, or if any transaction in the group fails.","DocExtra":"`itxn_submit` resets the current transaction so that it can not be resubmitted. A new `itxn_begin` is required to prepare another inner transaction.","Groups":["Inner Transactions"]},{"Opcode":180,"Name":"itxn","Returns":".","Cost":1,"Size":2,"ArgEnum":["Sender","Fee","FirstValid","FirstValidTime","LastValid","Note","Lease","Receiver","Amount","CloseRemainderTo","VotePK","SelectionPK","VoteFirst","VoteLast","VoteKeyDilution","Type","TypeEnum","XferAsset","AssetAmount","AssetSender","AssetReceiver","AssetCloseTo","GroupIndex","TxID","ApplicationID","OnCompletion","ApplicationArgs","NumAppArgs","Accounts","NumAccounts","ApprovalProgram","ClearStateProgram","RekeyTo","ConfigAsset","ConfigAssetTotal","ConfigAssetDecimals","ConfigAssetDefaultFrozen","ConfigAssetUnitName","ConfigAssetName","ConfigAssetURL","ConfigAssetMetadataHash","ConfigAssetManager","ConfigAssetReserve","ConfigAssetFreeze","ConfigAssetClawback","FreezeAsset","FreezeAssetAccount","FreezeAssetFrozen","Assets","NumAssets","Applications","NumApplications","GlobalNumUint","GlobalNumByteSlice","LocalNumUint","LocalNumByteSlice","ExtraProgramPages","Nonparticipation","Logs","NumLogs","CreatedAssetID","CreatedApplicationID","LastLog","StateProofPK"],"ArgEnumTypes":"BUUUUBBBUBBBUUUBUUUBBBUBUUBUBUBBBUUUUBBBBBBBBUBUUUUUUUUUUUBUUUBB","Doc":"field F of the last inner transaction","ImmediateNote":"{uint8 transaction field index}","Groups":["Inner Transactions"]},{"Opcode":181,"Name":"itxna","Returns":".","Cost":1,"Size":3,"ArgEnum":["ApplicationArgs","Accounts","Assets","Applications","Logs"],"ArgEnumTypes":"BBUUB","Doc":"Ith value of the array field F of the last inner transaction","ImmediateNote":"{uint8 transaction field index} {uint8 transaction field array index}","Groups":["Inner Transactions"]},{"Opcode":182,"Name":"itxn_next","Cost":1,"Size":1,"Doc":"begin preparation of a new inner transaction in the same transaction group","DocExtra":"`itxn_next` initializes the transaction exactly as `itxn_begin` does","Groups":["Inner Transactions"]},{"Opcode":183,"Name":"gitxn","Returns":".","Cost":1,"Size":3,"ArgEnum":["Sender","Fee","FirstValid","FirstValidTime","LastValid","Note","Lease","Receiver","Amount","CloseRemainderTo","VotePK","SelectionPK","VoteFirst","VoteLast","VoteKeyDilution","Type","TypeEnum","XferAsset","AssetAmount","AssetSender","AssetReceiver","AssetCloseTo","GroupIndex","TxID","ApplicationID","OnCompletion","ApplicationArgs","NumAppArgs","Accounts","NumAccounts","ApprovalProgram","ClearStateProgram","RekeyTo","ConfigAsset","ConfigAssetTotal","ConfigAssetDecimals","ConfigAssetDefaultFrozen","ConfigAssetUnitName","ConfigAssetName","ConfigAssetURL","ConfigAssetMetadataHash","ConfigAssetManager","ConfigAssetReserve","ConfigAssetFreeze","ConfigAssetClawback","FreezeAsset","FreezeAssetAccount","FreezeAssetFrozen","Assets","NumAssets","Applications","NumApplications","GlobalNumUint","GlobalNumByteSlice","LocalNumUint","LocalNumByteSlice","ExtraProgramPages","Nonparticipation","Logs","NumLogs","CreatedAssetID","CreatedApplicationID","LastLog","StateProofPK"],"ArgEnumTypes":"BUUUUBBBUBBBUUUBUUUBBBUBUUBUBUBBBUUUUBBBBBBBBUBUUUUUUUUUUUBUUUBB","Doc":"field F of the Tth transaction in the last inner group submitted","ImmediateNote":"{uint8 transaction group index} {uint8 transaction field index}","Groups":["Inner Transactions"]},{"Opcode":184,"Name":"gitxna","Returns":".","Cost":1,"Size":4,"ArgEnum":["ApplicationArgs","Accounts","Assets","Applications","Logs"],"ArgEnumTypes":"BBUUB","Doc":"Ith value of the array field F from the Tth transaction in the last inner group submitted","ImmediateNote":"{uint8 transaction group index} {uint8 transaction field index} {uint8 transaction field array index}","Groups":["Inner Transactions"]},{"Opcode":192,"Name":"txnas","Args":"U","Returns":".","Cost":1,"Size":2,"ArgEnum":["ApplicationArgs","Accounts","Assets","Applications","Logs"],"ArgEnumTypes":"BBUUB","Doc":"Ath value of the array field F of the current transaction","ImmediateNote":"{uint8 transaction field index}","Groups":["Loading Values"]},{"Opcode":193,"Name":"gtxnas","Args":"U","Returns":".","Cost":1,"Size":3,"ArgEnum":["ApplicationArgs","Accounts","Assets","Applications","Logs"],"ArgEnumTypes":"BBUUB","Doc":"Ath value of the array field F from the Tth transaction in the current group","ImmediateNote":"{uint8 transaction group index} {uint8 transaction field index}","Groups":["Loading Values"]},{"Opcode":194,"Name":"gtxnsas","Args":"UU","Returns":".","Cost":1,"Size":2,"ArgEnum":["ApplicationArgs","Accounts","Assets","Applications","Logs"],"ArgEnumTypes":"BBUUB","Doc":"Bth value of the array field F from the Ath transaction in the current group","ImmediateNote":"{uint8 transaction field index}","Groups":["Loading Values"]},{"Opcode":195,"Name":"args","Args":"U","Returns":"B","Cost":1,"Size":1,"Doc":"Ath LogicSig argument","Groups":["Loading Values"]},{"Opcode":196,"Name":"gloadss","Args":"UU","Returns":".","Cost":1,"Size":1,"Doc":"Bth scratch space value of the Ath transaction in the current group","Groups":["Loading Values"]},{"Opcode":197,"Name":"itxnas","Args":"U","Returns":".","Cost":1,"Size":2,"Doc":"Ath value of the array field F of the last inner transaction","ImmediateNote":"{uint8 transaction field index}","Groups":["Inner Transactions"]},{"Opcode":198,"Name":"gitxnas","Args":"U","Returns":".","Cost":1,"Size":3,"Doc":"Ath value of the array field F from the Tth transaction in the last inner group submitted","ImmediateNote":"{uint8 transaction group index} {uint8 transaction field index}","Groups":["Inner Transactions"]}]} diff --git a/logic/logic.go b/logic/logic.go deleted file mode 100644 index 1e98768c..00000000 --- a/logic/logic.go +++ /dev/null @@ -1,239 +0,0 @@ -package logic - -//go:generate ./bundle_langspec_json.sh - -import ( - "encoding/binary" - "encoding/json" - "fmt" - - "github.com/algorand/go-algorand-sdk/types" -) - -// Deprecated -type langSpec struct { - EvalMaxVersion int - LogicSigVersion int - Ops []operation -} - -// Deprecated -type operation struct { - Opcode int - Name string - Cost int - Size int - Returns string - ArgEnum []string - ArgEnumTypes string - Doc string - ImmediateNote string - Group []string -} - -// Deprecated -var spec *langSpec - -// Deprecated -var opcodes []operation - -// CheckProgram performs basic program validation: instruction count and program cost -// Deprecated: Validation relies on metadata (`langspec.json`) that does not accurately represent opcode behavior across program versions. -// The behavior of `CheckProgram` relies on `langspec.json`. Thus, this method is being deprecated. -func CheckProgram(program []byte, args [][]byte) error { - _, _, err := ReadProgram(program, args) - return err -} - -// ReadProgram is used to validate a program as well as extract found variables -// Deprecated: Validation relies on metadata (`langspec.json`) that does not accurately represent opcode behavior across program versions. -// The behavior of `ReadProgram` relies on `langspec.json`. Thus, this method is being deprecated. -func ReadProgram(program []byte, args [][]byte) (ints []uint64, byteArrays [][]byte, err error) { - const intcblockOpcode = 32 - const bytecblockOpcode = 38 - const pushbytesOpcode = 128 - const pushintOpcode = 129 - if program == nil || len(program) == 0 { - err = fmt.Errorf("empty program") - return - } - - if spec == nil { - spec = new(langSpec) - if err = json.Unmarshal(langSpecJson, spec); err != nil { - return - } - } - version, vlen := binary.Uvarint(program) - if vlen <= 0 { - err = fmt.Errorf("version parsing error") - return - } - if int(version) > spec.EvalMaxVersion { - err = fmt.Errorf("unsupported version") - return - } - - cost := 0 - length := len(program) - for _, arg := range args { - length += len(arg) - } - - if length > types.LogicSigMaxSize { - err = fmt.Errorf("program too long") - return - } - - if opcodes == nil { - opcodes = make([]operation, 256) - for _, op := range spec.Ops { - opcodes[op.Opcode] = op - } - } - - for pc := vlen; pc < len(program); { - op := opcodes[program[pc]] - if op.Name == "" { - err = fmt.Errorf("invalid instruction") - return - } - - cost = cost + op.Cost - size := op.Size - if size == 0 { - switch op.Opcode { - case intcblockOpcode: - var foundInts []uint64 - size, foundInts, err = readIntConstBlock(program, pc) - ints = append(ints, foundInts...) - if err != nil { - return - } - case bytecblockOpcode: - var foundByteArrays [][]byte - size, foundByteArrays, err = readByteConstBlock(program, pc) - byteArrays = append(byteArrays, foundByteArrays...) - if err != nil { - return - } - case pushintOpcode: - var foundInt uint64 - size, foundInt, err = readPushIntOp(program, pc) - ints = append(ints, foundInt) - if err != nil { - return - } - case pushbytesOpcode: - var foundByteArray []byte - size, foundByteArray, err = readPushByteOp(program, pc) - byteArrays = append(byteArrays, foundByteArray) - if err != nil { - return - } - default: - err = fmt.Errorf("invalid instruction") - return - } - } - pc = pc + size - } - - // costs calculated dynamically starting in v4 - if version < 4 && cost > types.LogicSigMaxCost { - err = fmt.Errorf("program too costly for version < 4. consider using v4.") - } - - return -} - -// Deprecated -func readIntConstBlock(program []byte, pc int) (size int, ints []uint64, err error) { - size = 1 - numInts, bytesUsed := binary.Uvarint(program[pc+size:]) - if bytesUsed <= 0 { - err = fmt.Errorf("could not decode int const block size at pc=%d", pc+size) - return - } - - size += bytesUsed - for i := uint64(0); i < numInts; i++ { - if pc+size >= len(program) { - err = fmt.Errorf("intcblock ran past end of program") - return - } - num, bytesUsed := binary.Uvarint(program[pc+size:]) - if bytesUsed <= 0 { - err = fmt.Errorf("could not decode int const[%d] at pc=%d", i, pc+size) - return - } - ints = append(ints, num) - size += bytesUsed - } - return -} - -// Deprecated -func readByteConstBlock(program []byte, pc int) (size int, byteArrays [][]byte, err error) { - size = 1 - numInts, bytesUsed := binary.Uvarint(program[pc+size:]) - if bytesUsed <= 0 { - err = fmt.Errorf("could not decode []byte const block size at pc=%d", pc+size) - return - } - - size += bytesUsed - for i := uint64(0); i < numInts; i++ { - if pc+size >= len(program) { - err = fmt.Errorf("bytecblock ran past end of program") - return - } - scanTarget := program[pc+size:] - itemLen, bytesUsed := binary.Uvarint(scanTarget) - if bytesUsed <= 0 { - err = fmt.Errorf("could not decode []byte const[%d] at pc=%d", i, pc+size) - return - } - size += bytesUsed - if pc+size+int(itemLen) > len(program) { - err = fmt.Errorf("bytecblock ran past end of program") - return - } - byteArray := program[pc+size : pc+size+int(itemLen)] - byteArrays = append(byteArrays, byteArray) - size += int(itemLen) - } - return -} - -// Deprecated -func readPushIntOp(program []byte, pc int) (size int, foundInt uint64, err error) { - size = 1 - foundInt, bytesUsed := binary.Uvarint(program[pc+size:]) - if bytesUsed <= 0 { - err = fmt.Errorf("could not decode push int const at pc=%d", pc+size) - return - } - - size += bytesUsed - return -} - -// Deprecated -func readPushByteOp(program []byte, pc int) (size int, byteArray []byte, err error) { - size = 1 - itemLen, bytesUsed := binary.Uvarint(program[pc+size:]) - if bytesUsed <= 0 { - err = fmt.Errorf("could not decode push []byte const size at pc=%d", pc+size) - return - } - - size += bytesUsed - if pc+size+int(itemLen) > len(program) { - err = fmt.Errorf("pushbytes ran past end of program") - return - } - byteArray = program[pc+size : pc+size+int(itemLen)] - size += int(itemLen) - return -} diff --git a/logic/logic_test.go b/logic/logic_test.go deleted file mode 100644 index b17668ca..00000000 --- a/logic/logic_test.go +++ /dev/null @@ -1,219 +0,0 @@ -package logic - -import ( - "encoding/hex" - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestCheckProgram(t *testing.T) { - program := []byte{1, 32, 1, 1, 34} // int 1 - var args [][]byte - err := CheckProgram(program, args) - require.NoError(t, err) - - args = make([][]byte, 1) - args[0] = []byte(strings.Repeat("a", 10)) - err = CheckProgram(program, args) - require.NoError(t, err) - - // too long arg - args[0] = []byte(strings.Repeat("a", 1000)) - err = CheckProgram(program, args) - require.Error(t, err) - - program = append(program, []byte(strings.Repeat("\x22", 10))...) - args[0] = []byte(strings.Repeat("a", 10)) - err = CheckProgram(program, args) - require.NoError(t, err) - - // too long program - program = append(program, []byte(strings.Repeat("\x22", 1000))...) - args[0] = []byte(strings.Repeat("a", 10)) - err = CheckProgram(program, args) - require.EqualError(t, err, "program too long") - - // invalid opcode - program = []byte{1, 32, 1, 1, 34} // int 1 - program[4] = 255 - args[0] = []byte(strings.Repeat("a", 10)) - err = CheckProgram(program, args) - require.EqualError(t, err, "invalid instruction") - - // check single keccak256 and 10x keccak256 work - program = []byte{0x01, 0x26, 0x01, 0x01, 0x01, 0x28, 0x02} // byte 0x01 + keccak256 - err = CheckProgram(program, args) - require.NoError(t, err) - - program = append(program, []byte(strings.Repeat("\x02", 10))...) // append 10x keccak256 - err = CheckProgram(program, args) - require.NoError(t, err) - - // check 800x keccak256 fail for v3 and below - versions := []byte{0x1, 0x2, 0x3} - program = append(program, []byte(strings.Repeat("\x02", 800))...) // append 800x keccak256 - for _, v := range versions { - program[0] = v - err = CheckProgram(program, args) - require.EqualError(t, err, "program too costly for version < 4. consider using v4.") - } - - // check 800x keccak256 ok for v4 and above - versions = []byte{0x4} - for _, v := range versions { - program[0] = v - err = CheckProgram(program, args) - require.NoError(t, err) - } -} - -func TestCheckProgramV2(t *testing.T) { - // check program v2 opcodes - require.True(t, spec.EvalMaxVersion >= 2) - require.True(t, spec.LogicSigVersion >= 2) - - args := make([][]byte, 0) - - // balance - program := []byte{0x02, 0x20, 0x01, 0x00, 0x22, 0x60} // int 0; balance - err := CheckProgram(program, args) - require.NoError(t, err) - - // app_opted_in - program = []byte{0x02, 0x20, 0x01, 0x00, 0x22, 0x22, 0x61} // int 0; int 0; app_opted_in - err = CheckProgram(program, args) - require.NoError(t, err) - - // asset_holding_get - program = []byte{0x02, 0x20, 0x01, 0x00, 0x22, 0x70, 0x00} // int 0; int 0; asset_holding_get Balance - err = CheckProgram(program, args) - require.NoError(t, err) -} - -func TestCheckProgramV3(t *testing.T) { - // check program v3 opcodes - require.True(t, spec.EvalMaxVersion >= 3) - require.True(t, spec.LogicSigVersion >= 3) - - args := make([][]byte, 0) - - // min_balance - program := []byte{0x03, 0x20, 0x01, 0x00, 0x22, 0x78} // int 0; min_balance - err := CheckProgram(program, args) - require.NoError(t, err) - - // pushbytes - program = []byte{0x03, 0x20, 0x01, 0x00, 0x22, 0x80, 0x02, 0x68, 0x69, 0x48} // int 0; pushbytes "hi"; pop - err = CheckProgram(program, args) - require.NoError(t, err) - - // pushint - program = []byte{0x03, 0x20, 0x01, 0x00, 0x22, 0x81, 0x01, 0x48} // int 0; pushint 1; pop - err = CheckProgram(program, args) - require.NoError(t, err) - - // swap - program = []byte{0x03, 0x20, 0x02, 0x00, 0x01, 0x22, 0x23, 0x4c, 0x48} // int 0; int 1; swap; pop - err = CheckProgram(program, args) - require.NoError(t, err) -} - -func TestCheckProgramV4(t *testing.T) { - // check program v4 opcodes - require.True(t, spec.EvalMaxVersion >= 4) - - args := make([][]byte, 0) - - // divmodw - program := []byte{0x04, 0x20, 0x03, 0x01, 0x00, 0x02, 0x22, 0x81, 0xd0, 0x0f, 0x23, 0x24, 0x1f} // int 1; pushint 2000; int 0; int 2; divmodw - err := CheckProgram(program, args) - require.NoError(t, err) - - // gloads i - program = []byte{0x04, 0x20, 0x01, 0x00, 0x22, 0x3b, 0x00} // int 0; gloads 0 - err = CheckProgram(program, args) - require.NoError(t, err) - - // callsub - program = []byte{0x04, 0x20, 0x02, 0x01, 0x02, 0x22, 0x88, 0x00, 0x02, 0x23, 0x12, 0x49} // int 1; callsub double; int 2; ==; double: dup; - err = CheckProgram(program, args) - require.NoError(t, err) - - // b>= - program = []byte{0x04, 0x26, 0x02, 0x01, 0x11, 0x01, 0x10, 0x28, 0x29, 0xa7} // byte 0x11; byte 0x10; b>= - err = CheckProgram(program, args) - require.NoError(t, err) - - // b^ - program = []byte{0x04, 0x26, 0x03, 0x01, 0x11, 0x01, 0x10, 0x01, 0x01, 0x28, 0x29, 0xad, 0x2a, 0x12} // byte 0x11; byte 0x10; b^; byte 0x01; == - err = CheckProgram(program, args) - require.NoError(t, err) - - // callsub, retsub. - program = []byte{0x04, 0x20, 0x02, 0x01, 0x02, 0x22, 0x88, 0x00, 0x03, 0x23, 0x12, 0x43, 0x49, 0x08, 0x89} // int 1; callsub double; int 2; ==; return; double: dup; +; retsub; - err = CheckProgram(program, args) - require.NoError(t, err) - - // loop - program = []byte{0x04, 0x20, 0x04, 0x01, 0x02, 0x0a, 0x10, 0x22, 0x23, 0x0b, 0x49, 0x24, 0x0c, 0x40, 0xff, 0xf8, 0x25, 0x12} // int 1; loop: int 2; *; dup; int 10; <; bnz loop; int 16; == - err = CheckProgram(program, args) - require.NoError(t, err) -} - -func TestCheckProgramV5(t *testing.T) { - // check program v5 opcodes - require.True(t, spec.EvalMaxVersion >= 5) - - args := make([][]byte, 0) - - // itxn ops - program, err := hex.DecodeString("052001c0843db18101b21022b2083100b207b3b4082212") - // itxn_begin; int pay; itxn_field TypeEnum; int 1000000; itxn_field Amount; txn Sender; itxn_field Receiver; itxn_submit; itxn Amount; int 1000000; == - require.NoError(t, err) - err = CheckProgram(program, args) - require.NoError(t, err) - - // ECDSA ops - program, err = hex.DecodeString("058008746573746461746103802079bfa8245aeac0e714b7bd2b3252d03979e5e7a43cb039715a5f8109a7dd9ba180200753d317e54350d1d102289afbde3002add4529f10b9f7d3d223843985de62e0802103abfb5e6e331fb871e423f354e2bd78a384ef7cb07ac8bbf27d2dd1eca00e73c106000500") - // byte "testdata"; sha512_256; byte 0x79bfa8245aeac0e714b7bd2b3252d03979e5e7a43cb039715a5f8109a7dd9ba1; byte 0x0753d317e54350d1d102289afbde3002add4529f10b9f7d3d223843985de62e0; byte 0x03abfb5e6e331fb871e423f354e2bd78a384ef7cb07ac8bbf27d2dd1eca00e73c1; ecdsa_pk_decompress Secp256k1; ecdsa_verify Secp256k1 - require.NoError(t, err) - err = CheckProgram(program, args) - require.NoError(t, err) - - // cover, uncover, log - program, err = hex.DecodeString("058001618001628001634e024f025050b08101") - // byte "a"; byte "b"; byte "c"; cover 2; uncover 2; concat; concat; log; int 1 - require.NoError(t, err) - err = CheckProgram(program, args) - require.NoError(t, err) -} - -func TestCheckProgramV6(t *testing.T) { - // check program v6 opcodes - require.True(t, spec.EvalMaxVersion >= 6) - - args := make([][]byte, 0) - - // bsqrt - program, err := hex.DecodeString("068001909680010ca8") - // byte 0x90; bsqrt; byte 0x0c; b== - require.NoError(t, err) - err = CheckProgram(program, args) - require.NoError(t, err) - - // divw - program, err = hex.DecodeString("06810981ecffffffffffffffff01810a9781feffffffffffffffff0112") - // int 9; int 18446744073709551596; int 10; divw; int 18446744073709551614; == - require.NoError(t, err) - err = CheckProgram(program, args) - require.NoError(t, err) - - // txn fields - program, err = hex.DecodeString("06313f1581401233003e15810a1210") - // txn StateProofPK; len; int 64; ==; gtxn 0 LastLog; len; int 10; ==; && - require.NoError(t, err) - err = CheckProgram(program, args) - require.NoError(t, err) -} diff --git a/templates/dynamicFee.go b/templates/dynamicFee.go deleted file mode 100644 index 7bb47050..00000000 --- a/templates/dynamicFee.go +++ /dev/null @@ -1,190 +0,0 @@ -package templates - -import ( - "encoding/base64" - "fmt" - - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/future" - "github.com/algorand/go-algorand-sdk/logic" - "github.com/algorand/go-algorand-sdk/transaction" - "github.com/algorand/go-algorand-sdk/types" - "golang.org/x/crypto/ed25519" -) - -// DynamicFee template representation -type DynamicFee struct { - ContractTemplate -} - -// MakeDynamicFee contract allows you to create a transaction without -// specifying the fee. The fee will be determined at the moment of -// transfer. -// -// Parameters: -// - receiver: address which is authorized to receive withdrawals -// - closeRemainder: address which will receive the balance of funds -// - amount: the maximum number of funds allowed for a single withdrawal -// - withdrawWindow: the duration of a withdrawal period -// - period: the time between a pair of withdrawal periods -// - expiryRound: the round at which the account expires -// - maxFee: maximum fee used by the withdrawal transaction -// -// Deprecated: Use TealCompile source compilation instead. -func MakeDynamicFee(receiver, closeRemainder string, amount, firstValid, lastValid uint64) (DynamicFee, error) { - leaseBytes := make([]byte, 32) - crypto.RandomBytes(leaseBytes) - leaseString := base64.StdEncoding.EncodeToString(leaseBytes) - return makeDynamicFeeWithLease(receiver, closeRemainder, leaseString, amount, firstValid, lastValid) -} - -// makeDynamicFeeWithLease is as MakeDynamicFee, but the caller can specify the lease (using b64 string) -func makeDynamicFeeWithLease(receiver, closeRemainder, lease string, amount, firstValid, lastValid uint64) (DynamicFee, error) { - const referenceProgram = "ASAFAgEHBgUmAyD+vKC7FEpaTqe0OKRoGsgObKEFvLYH/FZTJclWlfaiEyDmmpYeby1feshmB5JlUr6YI17TM2PKiJGLuck4qRW2+SB/g7Flf/H8U7ktwYFIodZd/C1LH6PWdyhK3dIAEm2QaTIEIhIzABAjEhAzAAcxABIQMwAIMQESEDEWIxIQMRAjEhAxBygSEDEJKRIQMQgkEhAxAiUSEDEEIQQSEDEGKhIQ" - referenceAsBytes, err := base64.StdEncoding.DecodeString(referenceProgram) - if err != nil { - return DynamicFee{}, err - } - receiverAddr, err := types.DecodeAddress(receiver) - if err != nil { - return DynamicFee{}, err - } - var closeRemainderAddr types.Address - if closeRemainder != "" { - closeRemainderAddr, err = types.DecodeAddress(closeRemainder) - if err != nil { - return DynamicFee{}, err - } - } - - var referenceOffsets = []uint64{ /*amount*/ 5 /*firstValid*/, 6 /*lastValid*/, 7 /*receiver*/, 11 /*closeRemainder*/, 44 /*lease*/, 76} - injectionVector := []interface{}{amount, firstValid, lastValid, receiverAddr, closeRemainderAddr, lease} - injectedBytes, err := inject(referenceAsBytes, referenceOffsets, injectionVector) - if err != nil { - return DynamicFee{}, err - } - - address := crypto.AddressFromProgram(injectedBytes) - dynamicFee := DynamicFee{ - ContractTemplate: ContractTemplate{ - address: address.String(), - program: injectedBytes, - }, - } - return dynamicFee, err -} - -// GetDynamicFeeTransactions creates and signs the secondary dynamic fee transaction, updates -// transaction fields, and signs as the fee payer; it returns both -// transactions as bytes suitable for sendRaw. -// Parameters: -// txn - main transaction from payer -// lsig - the signed logic received from the payer -// privateKey - the private key for the account that pays the fee -// fee - fee per byte for both transactions -// firstValid - first protocol round on which both transactions will be valid -// lastValid - last protocol round on which both transactions will be valid -// -// Deprecated: Use TealCompile source compilation instead. -func GetDynamicFeeTransactions(txn types.Transaction, lsig types.LogicSig, privateKey ed25519.PrivateKey, fee uint64) ([]byte, error) { - txn.Fee = types.MicroAlgos(fee) - eSize, err := transaction.EstimateSize(txn) - if err != nil { - return nil, err - } - txn.Fee = types.MicroAlgos(eSize * fee) - - if txn.Fee < transaction.MinTxnFee { - txn.Fee = transaction.MinTxnFee - } - - address := types.Address{} - copy(address[:], privateKey[ed25519.PublicKeySize:]) - genesisHash := make([]byte, 32) - copy(genesisHash[:], txn.GenesisHash[:]) - - params := types.SuggestedParams{ - Fee: types.MicroAlgos(fee), - GenesisID: txn.GenesisID, - GenesisHash: genesisHash, - FirstRoundValid: txn.FirstValid, - LastRoundValid: txn.LastValid, - FlatFee: false, - } - - feePayTxn, err := future.MakePaymentTxn(address.String(), txn.Sender.String(), uint64(txn.Fee), nil, "", params) - if err != nil { - return nil, err - } - feePayTxn.AddLease(txn.Lease, fee) - - txnGroup := []types.Transaction{feePayTxn, txn} - - updatedTxns, err := transaction.AssignGroupID(txnGroup, "") - - _, stx1Bytes, err := crypto.SignTransaction(privateKey, updatedTxns[0]) - if err != nil { - return nil, err - } - _, stx2Bytes, err := crypto.SignLogicsigTransaction(lsig, updatedTxns[1]) - if err != nil { - return nil, err - } - return append(stx1Bytes, stx2Bytes...), nil -} - -// SignDynamicFee takes in the contract bytes and returns the main transaction and signed logic needed to complete the -// transfer. These should be sent to the fee payer, who can use -// GetDynamicFeeTransactions() to update fields and create the auxiliary -// transaction. -// Parameters: -// contract - the bytearray representing the contract in question -// genesisHash - the bytearray representing the network for the txns -// -// Deprecated: Use TealCompile source compilation instead. -func SignDynamicFee(contract []byte, privateKey ed25519.PrivateKey, genesisHash []byte) (txn types.Transaction, lsig types.LogicSig, err error) { - ints, byteArrays, err := logic.ReadProgram(contract, nil) - if err != nil { - return - } - - // Convert the byteArrays[0] to receiver - var receiver types.Address //byteArrays[0] - n := copy(receiver[:], byteArrays[0]) - if n != ed25519.PublicKeySize { - err = fmt.Errorf("address generated from receiver bytes is the wrong size") - return - } - // Convert the byteArrays[1] to closeRemainderTo - var closeRemainderTo types.Address - n = copy(closeRemainderTo[:], byteArrays[1]) - if n != ed25519.PublicKeySize { - err = fmt.Errorf("address generated from closeRemainderTo bytes is the wrong size") - return - } - contractLease := byteArrays[2] - amount, firstValid, lastValid := ints[2], ints[3], ints[4] - address := types.Address{} - copy(address[:], privateKey[ed25519.PublicKeySize:]) - - fee := uint64(0) - params := types.SuggestedParams{ - Fee: types.MicroAlgos(fee), - GenesisID: "", - GenesisHash: genesisHash, - FirstRoundValid: types.Round(firstValid), - LastRoundValid: types.Round(lastValid), - FlatFee: false, - } - - txn, err = future.MakePaymentTxn(address.String(), receiver.String(), amount, nil, closeRemainderTo.String(), params) - if err != nil { - return - } - lease := [32]byte{} - copy(lease[:], contractLease) // convert from []byte to [32]byte - txn.AddLease(lease, fee) - lsig, err = crypto.MakeLogicSig(contract, nil, privateKey, crypto.MultisigAccount{}) - - return -} diff --git a/templates/hashTimeLockedContract.go b/templates/hashTimeLockedContract.go deleted file mode 100644 index 38699092..00000000 --- a/templates/hashTimeLockedContract.go +++ /dev/null @@ -1,122 +0,0 @@ -package templates - -import ( - "bytes" - "crypto/sha256" - "encoding/base64" - "fmt" - - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/logic" - "github.com/algorand/go-algorand-sdk/types" - "golang.org/x/crypto/sha3" -) - -// HTLC template representation -type HTLC struct { - ContractTemplate -} - -// MakeHTLC allows a user to receive the Algo prior to a deadline (in terms of a round) by proving a knowledge -// of a special value or to forfeit the ability to claim, returning it to the payer. -// This contract is usually used to perform cross-chained atomic swaps -// -// More formally - -// Algos can be transferred under only two circumstances: -// 1. To receiver if hash_function(arg_0) = hash_value -// 2. To owner if txn.FirstValid > expiry_round -// ... -// -// Parameters: -// - owner : string an address that can receive the asset after the expiry round -// - receiver: string address to receive Algos -// - hashFunction : string the hash function to be used (must be either sha256 or keccak256) -// - hashImage : string the hash image in base64 -// - expiryRound : uint64 the round on which the assets can be transferred back to owner -// - maxFee : uint64 the maximum fee that can be paid to the network by the account -// -// Deprecated: Use TealCompile source compilation instead. -func MakeHTLC(owner, receiver, hashFunction, hashImage string, expiryRound, maxFee uint64) (HTLC, error) { - var referenceProgram string - if hashFunction == "sha256" { - referenceProgram = "ASAECAEACSYDIOaalh5vLV96yGYHkmVSvpgjXtMzY8qIkYu5yTipFbb5IH+DsWV/8fxTuS3BgUih1l38LUsfo9Z3KErd0gASbZBpIP68oLsUSlpOp7Q4pGgayA5soQW8tgf8VlMlyVaV9qITMQEiDjEQIxIQMQcyAxIQMQgkEhAxCSgSLQEpEhAxCSoSMQIlDRAREA==" - } else if hashFunction == "keccak256" { - referenceProgram = "ASAECAEACSYDIOaalh5vLV96yGYHkmVSvpgjXtMzY8qIkYu5yTipFbb5IH+DsWV/8fxTuS3BgUih1l38LUsfo9Z3KErd0gASbZBpIP68oLsUSlpOp7Q4pGgayA5soQW8tgf8VlMlyVaV9qITMQEiDjEQIxIQMQcyAxIQMQgkEhAxCSgSLQIpEhAxCSoSMQIlDRAREA==" - } else { - return HTLC{}, fmt.Errorf("invalid hash function supplied") - } - referenceAsBytes, err := base64.StdEncoding.DecodeString(referenceProgram) - if err != nil { - return HTLC{}, err - } - ownerAddr, err := types.DecodeAddress(owner) - if err != nil { - return HTLC{}, err - } - receiverAddr, err := types.DecodeAddress(receiver) - if err != nil { - return HTLC{}, err - } - //validate hashImage - _, err = base64.StdEncoding.DecodeString(hashImage) - if err != nil { - return HTLC{}, err - } - var referenceOffsets = []uint64{ /*fee*/ 3 /*expiryRound*/, 6 /*receiver*/, 10 /*hashImage*/, 42 /*owner*/, 76} - injectionVector := []interface{}{maxFee, expiryRound, receiverAddr, hashImage, ownerAddr} - injectedBytes, err := inject(referenceAsBytes, referenceOffsets, injectionVector) - if err != nil { - return HTLC{}, err - } - - address := crypto.AddressFromProgram(injectedBytes) - htlc := HTLC{ - ContractTemplate: ContractTemplate{ - address: address.String(), - program: injectedBytes, - }, - } - return htlc, err -} - -// SignTransactionWithHTLCUnlock accepts a transaction, such as a payment, and builds the HTLC-unlocking signature around that transaction -// -// Deprecated: Use TealCompile source compilation instead. -func SignTransactionWithHTLCUnlock(program []byte, txn types.Transaction, preImageAsBase64 string) (txid string, stx []byte, err error) { - preImageAsArgument, err := base64.StdEncoding.DecodeString(preImageAsBase64) - if err != nil { - return - } - hashFunction := program[len(program)-15] - _, byteArrays, err := logic.ReadProgram(program, nil) - expectedHashImage := byteArrays[1] - if err != nil { - return - } - if hashFunction == 1 { - sha256 := sha256.Sum256(preImageAsArgument) - if !bytes.Equal(sha256[:], expectedHashImage) { - err = fmt.Errorf("sha256 hash of preimage failed to match expected hash image") - return - } - } else if hashFunction == 2 { - keccak256 := sha3.NewLegacyKeccak256() - keccak256Hash := keccak256.Sum(preImageAsArgument) - if !bytes.Equal(keccak256Hash[:], expectedHashImage) { - err = fmt.Errorf("keccak256 hash of preimage failed to match expected hash image") - } - } else { - err = fmt.Errorf("found invalid hash function %d in contract", hashFunction) - return - } - args := make([][]byte, 1) - args[0] = preImageAsArgument - var blankMultisig crypto.MultisigAccount - lsig, err := crypto.MakeLogicSig(program, args, nil, blankMultisig) - if err != nil { - return - } - txn.Receiver = types.Address{} //txn must have no receiver but MakePayment et al disallow this. - txid, stx, err = crypto.SignLogicsigTransaction(lsig, txn) - return -} diff --git a/templates/limitOrder.go b/templates/limitOrder.go deleted file mode 100644 index 0145a2dc..00000000 --- a/templates/limitOrder.go +++ /dev/null @@ -1,129 +0,0 @@ -package templates - -import ( - "encoding/base64" - - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/future" - "github.com/algorand/go-algorand-sdk/types" -) - -// LimitOrder represents a swap between Algos and an Asset at some ratio or better. -// -// Deprecated: Use TealCompile source compilation instead. -type LimitOrder struct { - ContractTemplate - assetID uint64 - owner string -} - -// GetSwapAssetsTransaction returns a group transaction array which transfer funds according to the contract's ratio -// assetAmount: amount of assets to be sent -// contract: byteform of the contract from the payer -// secretKey: secret key for signing transactions -// microAlgoAmount: number of microAlgos to transfer -// params: txn params for the transactions -// the first payment sends money (Algos) from contract to the recipient (we'll call him Buyer), closing the rest of the account to Owner -// the second payment sends money (the asset) from Buyer to the Owner -// these transactions will be rejected if they do not meet the restrictions set by the contract -// -// Deprecated: Use TealCompile source compilation instead. -func (lo LimitOrder) GetSwapAssetsTransaction(assetAmount uint64, microAlgoAmount uint64, contract, secretKey []byte, params types.SuggestedParams) ([]byte, error) { - var buyerAddress types.Address - copy(buyerAddress[:], secretKey[32:]) - contractAddress := crypto.AddressFromProgram(contract) - algosForAssets, err := future.MakePaymentTxn(contractAddress.String(), buyerAddress.String(), microAlgoAmount, nil, "", params) - if err != nil { - return nil, err - } - assetsForAlgos, err := future.MakeAssetTransferTxn(buyerAddress.String(), lo.owner, assetAmount, nil, params, "", lo.assetID) - if err != nil { - return nil, err - } - - gid, err := crypto.ComputeGroupID([]types.Transaction{algosForAssets, assetsForAlgos}) - if err != nil { - return nil, err - } - algosForAssets.Group = gid - assetsForAlgos.Group = gid - - logicSig, err := crypto.MakeLogicSig(contract, nil, nil, crypto.MultisigAccount{}) - if err != nil { - return nil, err - } - _, algosForAssetsSigned, err := crypto.SignLogicsigTransaction(logicSig, algosForAssets) - if err != nil { - return nil, err - } - _, assetsForAlgosSigned, err := crypto.SignTransaction(secretKey, assetsForAlgos) - if err != nil { - return nil, err - } - - var signedGroup []byte - signedGroup = append(signedGroup, algosForAssetsSigned...) - signedGroup = append(signedGroup, assetsForAlgosSigned...) - - return signedGroup, nil -} - -// MakeLimitOrder allows a user to exchange some number of assets for some number of algos. -// Fund the contract with some number of Algos to limit the maximum number of -// Algos you're willing to trade for some other asset. -// -// Works on two cases: -// * trading Algos for some other asset -// * closing out Algos back to the originator after a timeout -// -// trade case, a 2 transaction group: -// gtxn[0] (this txn) Algos from Me to Other -// gtxn[1] asset from Other to Me -// -// We want to get _at least_ some amount of the other asset per our Algos -// gtxn[1].AssetAmount / gtxn[0].Amount >= N / D -// === -// gtxn[1].AssetAmount * D >= gtxn[0].Amount * N -// -// close-out case: -// txn alone, close out value after timeout -// -// Parameters: -// - owner: the address to refund funds to on timeout -// - assetID: ID of the transferred asset -// - ratn: exchange rate (N asset per D Algos, or better) -// - ratd: exchange rate (N asset per D Algos, or better) -// - expiryRound: the round at which the account expires -// - minTrade: the minimum amount (of Algos) to be traded away -// - maxFee: maximum fee used by the limit order transaction -// -// Deprecated: Use TealCompile source compilation instead. -func MakeLimitOrder(owner string, assetID, ratn, ratd, expiryRound, minTrade, maxFee uint64) (LimitOrder, error) { - const referenceProgram = "ASAKAAEFAgYEBwgJCiYBIP68oLsUSlpOp7Q4pGgayA5soQW8tgf8VlMlyVaV9qITMRYiEjEQIxIQMQEkDhAyBCMSQABVMgQlEjEIIQQNEDEJMgMSEDMBECEFEhAzAREhBhIQMwEUKBIQMwETMgMSEDMBEiEHHTUCNQExCCEIHTUENQM0ATQDDUAAJDQBNAMSNAI0BA8QQAAWADEJKBIxAiEJDRAxBzIDEhAxCCISEBA=" - referenceAsBytes, err := base64.StdEncoding.DecodeString(referenceProgram) - if err != nil { - return LimitOrder{}, err - } - - var referenceOffsets = []uint64{ /*maxFee*/ 5 /*minTrade*/, 7 /*assetID*/, 9 /*ratd*/, 10 /*ratn*/, 11 /*expiryRound*/, 12 /*ownerAddr*/, 16} - ownerAddr, err := types.DecodeAddress(owner) - if err != nil { - return LimitOrder{}, err - } - injectionVector := []interface{}{maxFee, minTrade, assetID, ratd, ratn, expiryRound, ownerAddr} - injectedBytes, err := inject(referenceAsBytes, referenceOffsets, injectionVector) - if err != nil { - return LimitOrder{}, err - } - - address := crypto.AddressFromProgram(injectedBytes) - lo := LimitOrder{ - ContractTemplate: ContractTemplate{ - address: address.String(), - program: injectedBytes, - }, - owner: owner, - assetID: assetID, - } - return lo, err -} diff --git a/templates/periodicPayment.go b/templates/periodicPayment.go deleted file mode 100644 index 2ef71bb7..00000000 --- a/templates/periodicPayment.go +++ /dev/null @@ -1,122 +0,0 @@ -package templates - -import ( - "encoding/base64" - "fmt" - - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/future" - "github.com/algorand/go-algorand-sdk/logic" - "github.com/algorand/go-algorand-sdk/types" - "golang.org/x/crypto/ed25519" -) - -// PeriodicPayment template representation -// -// Deprecated: Use TealCompile source compilation instead. -type PeriodicPayment struct { - ContractTemplate -} - -// GetPeriodicPaymentWithdrawalTransaction returns a signed transaction extracting funds from the contract -// contract: the bytearray defining the contract, received from the payer -// firstValid: the first round on which the txn will be valid -// fee: the fee in microalgos per byte of the payment txn -// genesisHash: the hash representing the network for the txn -// -// Deprecated: Use TealCompile source compilation instead. -func GetPeriodicPaymentWithdrawalTransaction(contract []byte, firstValid, fee uint64, genesisHash []byte) ([]byte, error) { - address := crypto.AddressFromProgram(contract) - ints, byteArrays, err := logic.ReadProgram(contract, nil) - if err != nil { - return nil, err - } - contractLease := byteArrays[0] - // Convert the byteArrays[1] to receiver - var receiver types.Address - n := copy(receiver[:], byteArrays[1]) - if n != ed25519.PublicKeySize { - return nil, fmt.Errorf("address generated from receiver bytes is the wrong size") - } - period, withdrawWindow, amount := ints[2], ints[4], ints[5] - if firstValid%period != 0 { - return nil, fmt.Errorf("firstValid round %d was not a multiple of the contract period %d", firstValid, period) - } - lastValid := firstValid + withdrawWindow - params := types.SuggestedParams{ - Fee: types.MicroAlgos(fee), - GenesisHash: genesisHash, - FirstRoundValid: types.Round(firstValid), - LastRoundValid: types.Round(lastValid), - FlatFee: false, - } - txn, err := future.MakePaymentTxn(address.String(), receiver.String(), amount, nil, "", params) - if err != nil { - return nil, err - } - lease := [32]byte{} - copy(lease[:], contractLease) // convert from []byte to [32]byte - txn.AddLease(lease, fee) - - logicSig, err := crypto.MakeLogicSig(contract, nil, nil, crypto.MultisigAccount{}) - if err != nil { - return nil, err - } - _, signedTxn, err := crypto.SignLogicsigTransaction(logicSig, txn) - return signedTxn, err -} - -// MakePeriodicPayment allows some account to execute periodic withdrawal of funds. -// This is a contract account. -// -// This allows receiver to withdraw amount every -// period rounds for withdrawWindow after every multiple -// of period. -// -// After expiryRound, all remaining funds in the escrow -// are available to receiver. -// -// Parameters: -// - receiver: address which is authorized to receive withdrawals -// - amount: the maximum number of funds allowed for a single withdrawal -// - withdrawWindow: the duration of a withdrawal period -// - period: the time between a pair of withdrawal periods -// - expiryRound: the round at which the account expires -// - maxFee: maximum fee used by the withdrawal transaction -// -// Deprecated: Use TealCompile source compilation instead. -func MakePeriodicPayment(receiver string, amount, withdrawWindow, period, expiryRound, maxFee uint64) (PeriodicPayment, error) { - leaseBytes := make([]byte, 32) - crypto.RandomBytes(leaseBytes) - leaseString := base64.StdEncoding.EncodeToString(leaseBytes) - return makePeriodicPaymentWithLease(receiver, leaseString, amount, withdrawWindow, period, expiryRound, maxFee) -} - -// makePeriodicPaymentWithLease is as MakePeriodicPayment, but the caller can specify the lease (using b64 string) -func makePeriodicPaymentWithLease(receiver, lease string, amount, withdrawWindow, period, expiryRound, maxFee uint64) (PeriodicPayment, error) { - const referenceProgram = "ASAHAQYFAAQDByYCIAECAwQFBgcIAQIDBAUGBwgBAgMEBQYHCAECAwQFBgcIIJKvkYTkEzwJf2arzJOxERsSogG9nQzKPkpIoc4TzPTFMRAiEjEBIw4QMQIkGCUSEDEEIQQxAggSEDEGKBIQMQkyAxIxBykSEDEIIQUSEDEJKRIxBzIDEhAxAiEGDRAxCCUSEBEQ" - referenceAsBytes, err := base64.StdEncoding.DecodeString(referenceProgram) - if err != nil { - return PeriodicPayment{}, err - } - receiverAddr, err := types.DecodeAddress(receiver) - if err != nil { - return PeriodicPayment{}, err - } - - var referenceOffsets = []uint64{ /*fee*/ 4 /*period*/, 5 /*withdrawWindow*/, 7 /*amount*/, 8 /*expiryRound*/, 9 /*lease*/, 12 /*receiver*/, 46} - injectionVector := []interface{}{maxFee, period, withdrawWindow, amount, expiryRound, lease, receiverAddr} - injectedBytes, err := inject(referenceAsBytes, referenceOffsets, injectionVector) - if err != nil { - return PeriodicPayment{}, err - } - - address := crypto.AddressFromProgram(injectedBytes) - periodicPayment := PeriodicPayment{ - ContractTemplate: ContractTemplate{ - address: address.String(), - program: injectedBytes, - }, - } - return periodicPayment, err -} diff --git a/templates/split.go b/templates/split.go deleted file mode 100644 index 1582381f..00000000 --- a/templates/split.go +++ /dev/null @@ -1,167 +0,0 @@ -package templates - -import ( - "encoding/base64" - "fmt" - "math" - - "golang.org/x/crypto/ed25519" - - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/future" - "github.com/algorand/go-algorand-sdk/logic" - "github.com/algorand/go-algorand-sdk/types" -) - -// Split template representation -// -// Deprecated: Use TealCompile source compilation instead. -type Split struct { - ContractTemplate - rat1 uint64 - rat2 uint64 - receiverOne types.Address - receiverTwo types.Address -} - -//GetSplitFundsTransaction returns a group transaction array which transfer funds according to the contract's ratio -// the returned byte array is suitable for passing to SendRawTransaction -// contract: the bytecode of the contract to be used -// amount: uint64 total number of algos to be transferred (payment1_amount + payment2_amount) -// params: is typically received from algod, it defines common-to-all-txns arguments like fee and validity period -// -// Deprecated: Use TealCompile source compilation instead. -func GetSplitFundsTransaction(contract []byte, amount uint64, params types.SuggestedParams) ([]byte, error) { - ints, byteArrays, err := logic.ReadProgram(contract, nil) - if err != nil { - return nil, err - } - rat1 := ints[6] - rat2 := ints[5] - // Convert the byteArrays[0] to receiver - var receiverOne types.Address //byteArrays[0] - n := copy(receiverOne[:], byteArrays[1]) - if n != ed25519.PublicKeySize { - err = fmt.Errorf("address generated from receiver bytes is the wrong size") - return nil, err - } - // Convert the byteArrays[2] to receiverTwo - var receiverTwo types.Address - n = copy(receiverTwo[:], byteArrays[2]) - if n != ed25519.PublicKeySize { - err = fmt.Errorf("address generated from closeRemainderTo bytes is the wrong size") - return nil, err - } - - ratio := float64(rat2) / float64(rat1) - amountForReceiverOneFloat := float64(amount) / (1 + ratio) - amountForReceiverOne := uint64(math.Round(amountForReceiverOneFloat)) - amountForReceiverTwo := amount - amountForReceiverOne - if rat2*amountForReceiverOne != rat1*amountForReceiverTwo { - err = fmt.Errorf("could not split funds in a way that satisfied the contract ratio (%d * %d != %d * %d)", rat2, amountForReceiverOne, rat1, amountForReceiverTwo) - return nil, err - } - - from := crypto.AddressFromProgram(contract) - tx1, err := future.MakePaymentTxn(from.String(), receiverOne.String(), amountForReceiverOne, nil, "", params) - if err != nil { - return nil, err - } - tx2, err := future.MakePaymentTxn(from.String(), receiverTwo.String(), amountForReceiverTwo, nil, "", params) - if err != nil { - return nil, err - } - gid, err := crypto.ComputeGroupID([]types.Transaction{tx1, tx2}) - if err != nil { - return nil, err - } - tx1.Group = gid - tx2.Group = gid - - logicSig, err := crypto.MakeLogicSig(contract, nil, nil, crypto.MultisigAccount{}) - if err != nil { - return nil, err - } - _, stx1, err := crypto.SignLogicsigTransaction(logicSig, tx1) - if err != nil { - return nil, err - } - _, stx2, err := crypto.SignLogicsigTransaction(logicSig, tx2) - if err != nil { - return nil, err - } - - var signedGroup []byte - signedGroup = append(signedGroup, stx1...) - signedGroup = append(signedGroup, stx2...) - - return signedGroup, err -} - -// MakeSplit splits money sent to some account to two recipients at some ratio. -// This is a contract account. -// -// This allows either a two-transaction group, for executing a -// split, or single transaction, for closing the account. -// -// Withdrawals from this account are allowed as a group transaction which -// sends receiverOne and receiverTwo amounts with exactly the ratio of -// rat1/rat2. At least minPay must be sent to receiverOne. -// (CloseRemainderTo must be zero.) -// -// After expiryRound passes, all funds can be refunded to owner. -// -// Split ratio: -// firstRecipient_amount * rat2 == secondRecipient_amount * rat1 -// or phrased another way -// firstRecipient_amount == secondRecipient_amount * (rat1/rat2) -// -// Parameters: -// - owner: the address to refund funds to on timeout -// - receiverOne: the first recipient in the split account -// - receiverTwo: the second recipient in the split account -// - rat1: fraction determines resource split ratio -// - rat2: fraction determines resource split ratio -// - expiryRound: the round at which the account expires -// - minPay: minimum amount to be paid out of the account to receiverOne -// - maxFee: half of the maximum fee used by each split forwarding group transaction -// -// Deprecated: Use TealCompile source compilation instead. -func MakeSplit(owner, receiverOne, receiverTwo string, rat1, rat2, expiryRound, minPay, maxFee uint64) (Split, error) { - const referenceProgram = "ASAIAQUCAAYHCAkmAyCztwQn0+DycN+vsk+vJWcsoz/b7NDS6i33HOkvTpf+YiC3qUpIgHGWE8/1LPh9SGCalSN7IaITeeWSXbfsS5wsXyC4kBQ38Z8zcwWVAym4S8vpFB/c0XC6R4mnPi9EBADsPDEQIhIxASMMEDIEJBJAABkxCSgSMQcyAxIQMQglEhAxAiEEDRAiQAAuMwAAMwEAEjEJMgMSEDMABykSEDMBByoSEDMACCEFCzMBCCEGCxIQMwAIIQcPEBA=" - referenceAsBytes, err := base64.StdEncoding.DecodeString(referenceProgram) - if err != nil { - return Split{}, err - } - var referenceOffsets = []uint64{ /*fee*/ 4 /*timeout*/, 7 /*rat2*/, 8 /*rat1*/, 9 /*minPay*/, 10 /*owner*/, 14 /*receiver1*/, 47 /*receiver2*/, 80} - ownerAddr, err := types.DecodeAddress(owner) - if err != nil { - return Split{}, err - } - receiverOneAddr, err := types.DecodeAddress(receiverOne) - if err != nil { - return Split{}, err - } - receiverTwoAddr, err := types.DecodeAddress(receiverTwo) - if err != nil { - return Split{}, err - } - injectionVector := []interface{}{maxFee, expiryRound, rat2, rat1, minPay, ownerAddr, receiverOneAddr, receiverTwoAddr} - injectedBytes, err := inject(referenceAsBytes, referenceOffsets, injectionVector) - if err != nil { - return Split{}, err - } - - address := crypto.AddressFromProgram(injectedBytes) - split := Split{ - ContractTemplate: ContractTemplate{ - address: address.String(), - program: injectedBytes, - }, - rat1: rat1, - rat2: rat2, - receiverOne: receiverOneAddr, - receiverTwo: receiverTwoAddr, - } - return split, err -} diff --git a/templates/template.go b/templates/template.go deleted file mode 100644 index 1ada89fe..00000000 --- a/templates/template.go +++ /dev/null @@ -1,85 +0,0 @@ -package templates - -import ( - "encoding/base64" - "encoding/binary" - "fmt" - - "github.com/algorand/go-algorand-sdk/types" -) - -// ContractTemplate template representation -// -// Deprecated: Use TealCompile source compilation instead. -type ContractTemplate struct { - address string - program []byte -} - -// GetAddress returns the contract address -func (contract ContractTemplate) GetAddress() string { - return contract.address -} - -// GetProgram returns the program bytes -func (contract ContractTemplate) GetProgram() []byte { - return contract.program -} - -func replace(buf, newBytes []byte, offset, placeholderLength uint64) []byte { - firstChunk := make([]byte, len(buf[:offset])) - copy(firstChunk, buf[:offset]) - firstChunkAmended := append(firstChunk, newBytes...) - secondChunk := make([]byte, len(buf[(offset+placeholderLength):])) - copy(secondChunk, buf[(offset+placeholderLength):]) - return append(firstChunkAmended, secondChunk...) -} - -func inject(original []byte, offsets []uint64, values []interface{}) (result []byte, err error) { - result = original - if len(offsets) != len(values) { - err = fmt.Errorf("length of offsets %v does not match length of replacement values %v", len(offsets), len(values)) - return - } - - for i, value := range values { - decodedLength := 0 - if valueAsUint, ok := value.(uint64); ok { - // make the exact minimum buffer needed and no larger - // because otherwise there will be extra bytes inserted - sizingBuffer := make([]byte, binary.MaxVarintLen64) - decodedLength = binary.PutUvarint(sizingBuffer, valueAsUint) - fillingBuffer := make([]byte, decodedLength) - decodedLength = binary.PutUvarint(fillingBuffer, valueAsUint) - result = replace(result, fillingBuffer, offsets[i], uint64(1)) - } else if address, ok := value.(types.Address); ok { - addressLen := uint64(32) - addressBytes := make([]byte, addressLen) - copy(addressBytes, address[:]) - result = replace(result, addressBytes, offsets[i], addressLen) - } else if b64string, ok := value.(string); ok { - decodeBytes, decodeErr := base64.StdEncoding.DecodeString(b64string) - if decodeErr != nil { - err = decodeErr - return - } - // do the same thing as in the uint64 case to trim empty bytes: - // first fill one buffer to figure out the number of bytes to be written, - // then fill a second buffer of exactly the right size - sizingBuffer := make([]byte, binary.MaxVarintLen64) - numBytesWritten := binary.PutUvarint(sizingBuffer, uint64(len(decodeBytes))) - fillingBuffer := make([]byte, numBytesWritten) - binary.PutUvarint(fillingBuffer, uint64(len(decodeBytes))) // indicate length of b64 bytes - // want to write [length of b64 bytes, b64 bytes] - decodeBytes = append(fillingBuffer, decodeBytes...) - result = replace(result, decodeBytes, offsets[i], uint64(33)) - } - - if decodedLength != 0 { - for j := range offsets { - offsets[j] = offsets[j] + uint64(decodedLength) - 1 - } - } - } - return -} diff --git a/templates/templates_test.go b/templates/templates_test.go deleted file mode 100644 index d0329ede..00000000 --- a/templates/templates_test.go +++ /dev/null @@ -1,186 +0,0 @@ -package templates - -import ( - "encoding/base64" - "testing" - - "github.com/algorand/go-algorand-sdk/encoding/msgpack" - "github.com/algorand/go-algorand-sdk/future" - "github.com/algorand/go-algorand-sdk/types" - - "github.com/stretchr/testify/require" -) - -func TestSplit(t *testing.T) { - // Inputs - owner := "WO3QIJ6T4DZHBX5PWJH26JLHFSRT7W7M2DJOULPXDTUS6TUX7ZRIO4KDFY" - receivers := [2]string{"W6UUUSEAOGLBHT7VFT4H2SDATKKSG6ZBUIJXTZMSLW36YS44FRP5NVAU7U", "XCIBIN7RT4ZXGBMVAMU3QS6L5EKB7XGROC5EPCNHHYXUIBAA5Q6C5Y7NEU"} - ratn, ratd := uint64(30), uint64(100) // receiverOne gets 30/100 of whatever is sent to contract address - expiryRound := uint64(123456) - minPay := uint64(10000) - maxFee := uint64(5000000) - c, err := MakeSplit(owner, receivers[0], receivers[1], ratn, ratd, expiryRound, minPay, maxFee) - // Outputs - require.NoError(t, err) - goldenProgram := "ASAIAcCWsQICAMDEB2QekE4mAyCztwQn0+DycN+vsk+vJWcsoz/b7NDS6i33HOkvTpf+YiC3qUpIgHGWE8/1LPh9SGCalSN7IaITeeWSXbfsS5wsXyC4kBQ38Z8zcwWVAym4S8vpFB/c0XC6R4mnPi9EBADsPDEQIhIxASMMEDIEJBJAABkxCSgSMQcyAxIQMQglEhAxAiEEDRAiQAAuMwAAMwEAEjEJMgMSEDMABykSEDMBByoSEDMACCEFCzMBCCEGCxIQMwAIIQcPEBA=" - require.Equal(t, goldenProgram, base64.StdEncoding.EncodeToString(c.GetProgram())) - goldenAddress := "HDY7A4VHBWQWQZJBEMASFOUZKBNGWBMJEMUXAGZ4SPIRQ6C24MJHUZKFGY" - require.Equal(t, goldenAddress, c.GetAddress()) - goldenGenesisHash := "f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=" - genesisBytes, _ := base64.StdEncoding.DecodeString(goldenGenesisHash) - goldenStx := "gqRsc2lngaFsxM4BIAgBwJaxAgIAwMQHZB6QTiYDILO3BCfT4PJw36+yT68lZyyjP9vs0NLqLfcc6S9Ol/5iILepSkiAcZYTz/Us+H1IYJqVI3shohN55ZJdt+xLnCxfILiQFDfxnzNzBZUDKbhLy+kUH9zRcLpHiac+L0QEAOw8MRAiEjEBIwwQMgQkEkAAGTEJKBIxBzIDEhAxCCUSEDECIQQNECJAAC4zAAAzAQASMQkyAxIQMwAHKRIQMwEHKhIQMwAIIQULMwEIIQYLEhAzAAghBw8QEKN0eG6Jo2FtdM4ABJPgo2ZlZc4AId/gomZ2AaJnaMQgf4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGmjZ3JwxCBLA74bTV35FJNL1h0K9ZbRU24b4M1JRkD1YTogvvDXbqJsdmSjcmN2xCC3qUpIgHGWE8/1LPh9SGCalSN7IaITeeWSXbfsS5wsX6NzbmTEIDjx8HKnDaFoZSEjASK6mVBaawWJIylwGzyT0Rh4WuMSpHR5cGWjcGF5gqRsc2lngaFsxM4BIAgBwJaxAgIAwMQHZB6QTiYDILO3BCfT4PJw36+yT68lZyyjP9vs0NLqLfcc6S9Ol/5iILepSkiAcZYTz/Us+H1IYJqVI3shohN55ZJdt+xLnCxfILiQFDfxnzNzBZUDKbhLy+kUH9zRcLpHiac+L0QEAOw8MRAiEjEBIwwQMgQkEkAAGTEJKBIxBzIDEhAxCCUSEDECIQQNECJAAC4zAAAzAQASMQkyAxIQMwAHKRIQMwEHKhIQMwAIIQULMwEIIQYLEhAzAAghBw8QEKN0eG6Jo2FtdM4AD0JAo2ZlZc4AId/gomZ2AaJnaMQgf4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGmjZ3JwxCBLA74bTV35FJNL1h0K9ZbRU24b4M1JRkD1YTogvvDXbqJsdmSjcmN2xCC4kBQ38Z8zcwWVAym4S8vpFB/c0XC6R4mnPi9EBADsPKNzbmTEIDjx8HKnDaFoZSEjASK6mVBaawWJIylwGzyT0Rh4WuMSpHR5cGWjcGF5" - params := types.SuggestedParams{ - Fee: 10000, - FirstRoundValid: 1, - LastRoundValid: 100, - GenesisHash: genesisBytes, - } - stx, err := GetSplitFundsTransaction(c.GetProgram(), minPay*(ratd+ratn), params) - require.NoError(t, err) - require.Equal(t, goldenStx, base64.StdEncoding.EncodeToString(stx)) -} - -func TestHTLCSha256(t *testing.T) { - // Inputs - owner := "726KBOYUJJNE5J5UHCSGQGWIBZWKCBN4WYD7YVSTEXEVNFPWUIJ7TAEOPM" - receiver := "42NJMHTPFVPXVSDGA6JGKUV6TARV5UZTMPFIREMLXHETRKIVW34QFSDFRE" - hashFn := "sha256" - hashImg := "EHZhE08h/HwCIj1Qq56zYAvD/8NxJCOh5Hux+anb9V8=" - expiryRound := uint64(600000) - maxFee := uint64(1000) - c, err := MakeHTLC(owner, receiver, hashFn, hashImg, expiryRound, maxFee) - // Outputs - require.NoError(t, err) - goldenProgram := "ASAE6AcBAMDPJCYDIOaalh5vLV96yGYHkmVSvpgjXtMzY8qIkYu5yTipFbb5IBB2YRNPIfx8AiI9UKues2ALw//DcSQjoeR7sfmp2/VfIP68oLsUSlpOp7Q4pGgayA5soQW8tgf8VlMlyVaV9qITMQEiDjEQIxIQMQcyAxIQMQgkEhAxCSgSLQEpEhAxCSoSMQIlDRAREA==" - require.Equal(t, goldenProgram, base64.StdEncoding.EncodeToString(c.GetProgram())) - goldenAddress := "FBZIR3RWVT2BTGVOG25H3VAOLVD54RTCRNRLQCCJJO6SVSCT5IVDYKNCSU" - require.Equal(t, goldenAddress, c.GetAddress()) - genesisHash := "f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=" - genesisBytes, _ := base64.StdEncoding.DecodeString(genesisHash) - params := types.SuggestedParams{ - Fee: 0, - FirstRoundValid: 1, - LastRoundValid: 100, - GenesisID: "", - GenesisHash: genesisBytes, - } - txn, err := future.MakePaymentTxn(goldenAddress, receiver, 0, nil, receiver, params) - require.NoError(t, err) - preImageAsBase64 := "cHJlaW1hZ2U=" - _, stx, err := SignTransactionWithHTLCUnlock(c.GetProgram(), txn, preImageAsBase64) - require.NoError(t, err) - goldenStx := "gqRsc2lngqNhcmeRxAhwcmVpbWFnZaFsxJcBIAToBwEAwM8kJgMg5pqWHm8tX3rIZgeSZVK+mCNe0zNjyoiRi7nJOKkVtvkgEHZhE08h/HwCIj1Qq56zYAvD/8NxJCOh5Hux+anb9V8g/ryguxRKWk6ntDikaBrIDmyhBby2B/xWUyXJVpX2ohMxASIOMRAjEhAxBzIDEhAxCCQSEDEJKBItASkSEDEJKhIxAiUNEBEQo3R4boelY2xvc2XEIOaalh5vLV96yGYHkmVSvpgjXtMzY8qIkYu5yTipFbb5o2ZlZc0D6KJmdgGiZ2jEIH+DsWV/8fxTuS3BgUih1l38LUsfo9Z3KErd0gASbZBpomx2ZKNzbmTEIChyiO42rPQZmq42un3UDl1H3kZii2K4CElLvSrIU+oqpHR5cGWjcGF5" - require.Equal(t, goldenStx, base64.StdEncoding.EncodeToString(stx)) -} - -func TestHTLCKeccak256(t *testing.T) { - // Inputs - owner := "726KBOYUJJNE5J5UHCSGQGWIBZWKCBN4WYD7YVSTEXEVNFPWUIJ7TAEOPM" - receiver := "42NJMHTPFVPXVSDGA6JGKUV6TARV5UZTMPFIREMLXHETRKIVW34QFSDFRE" - hashFn := "keccak256" - hashImg := "D7d4MrvBrOSyNSmUs0kzucuJ+/9DbLkA6OOOocywoAc=" - expiryRound := uint64(600000) - maxFee := uint64(1000) - c, err := MakeHTLC(owner, receiver, hashFn, hashImg, expiryRound, maxFee) - // Outputs - require.NoError(t, err) - goldenProgram := "ASAE6AcBAMDPJCYDIOaalh5vLV96yGYHkmVSvpgjXtMzY8qIkYu5yTipFbb5IA+3eDK7wazksjUplLNJM7nLifv/Q2y5AOjjjqHMsKAHIP68oLsUSlpOp7Q4pGgayA5soQW8tgf8VlMlyVaV9qITMQEiDjEQIxIQMQcyAxIQMQgkEhAxCSgSLQIpEhAxCSoSMQIlDRAREA==" - require.Equal(t, goldenProgram, base64.StdEncoding.EncodeToString(c.GetProgram())) - goldenAddress := "3MJ6JY3P6AU4R6I2RASYSAOPNI3QMWPZ7HYXJRNRGBIAXCHAY7QZRBH5PQ" - require.Equal(t, goldenAddress, c.GetAddress()) - genesisHash := "f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=" - genesisBytes, _ := base64.StdEncoding.DecodeString(genesisHash) - params := types.SuggestedParams{ - Fee: 0, - FirstRoundValid: 1, - LastRoundValid: 100, - GenesisID: "", - GenesisHash: genesisBytes, - } - txn, err := future.MakePaymentTxn(goldenAddress, receiver, 0, nil, receiver, params) - require.NoError(t, err) - preImageAsBase64 := "cHJlaW1hZ2U=" - _, stx, err := SignTransactionWithHTLCUnlock(c.GetProgram(), txn, preImageAsBase64) - require.NoError(t, err) - goldenStx := "gqRsc2lngqNhcmeRxAhwcmVpbWFnZaFsxJcBIAToBwEAwM8kJgMg5pqWHm8tX3rIZgeSZVK+mCNe0zNjyoiRi7nJOKkVtvkgD7d4MrvBrOSyNSmUs0kzucuJ+/9DbLkA6OOOocywoAcg/ryguxRKWk6ntDikaBrIDmyhBby2B/xWUyXJVpX2ohMxASIOMRAjEhAxBzIDEhAxCCQSEDEJKBItAikSEDEJKhIxAiUNEBEQo3R4boelY2xvc2XEIOaalh5vLV96yGYHkmVSvpgjXtMzY8qIkYu5yTipFbb5o2ZlZc0D6KJmdgGiZ2jEIH+DsWV/8fxTuS3BgUih1l38LUsfo9Z3KErd0gASbZBpomx2ZKNzbmTEINsT5ONv8CnI+RqIJYkBz2o3Bln5+fF0xbEwUAuI4MfhpHR5cGWjcGF5" - require.Equal(t, goldenStx, base64.StdEncoding.EncodeToString(stx)) -} - -func TestPeriodicPayment(t *testing.T) { - // Inputs - receiver := "SKXZDBHECM6AS73GVPGJHMIRDMJKEAN5TUGMUPSKJCQ44E6M6TC2H2UJ3I" - artificialLease := "AQIDBAUGBwgBAgMEBQYHCAECAwQFBgcIAQIDBAUGBwg=" - amount := uint64(500000) - withdrawalWindow := uint64(95) - period := uint64(100) - maxFee := uint64(1000) - expiryRound := uint64(2445756) - c, err := makePeriodicPaymentWithLease(receiver, artificialLease, amount, withdrawalWindow, period, expiryRound, maxFee) - // Outputs - require.NoError(t, err) - goldenProgram := "ASAHAegHZABfoMIevKOVASYCIAECAwQFBgcIAQIDBAUGBwgBAgMEBQYHCAECAwQFBgcIIJKvkYTkEzwJf2arzJOxERsSogG9nQzKPkpIoc4TzPTFMRAiEjEBIw4QMQIkGCUSEDEEIQQxAggSEDEGKBIQMQkyAxIxBykSEDEIIQUSEDEJKRIxBzIDEhAxAiEGDRAxCCUSEBEQ" - contractBytes := c.GetProgram() - require.Equal(t, goldenProgram, base64.StdEncoding.EncodeToString(contractBytes)) - goldenAddress := "JMS3K4LSHPULANJIVQBTEDP5PZK6HHMDQS4OKHIMHUZZ6OILYO3FVQW7IY" - require.Equal(t, goldenAddress, c.GetAddress()) - goldenGenesisHash := "f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=" - genesisBytes, err := base64.StdEncoding.DecodeString(goldenGenesisHash) - require.NoError(t, err) - stx, err := GetPeriodicPaymentWithdrawalTransaction(contractBytes, 1200, 0, genesisBytes) - require.NoError(t, err) - goldenStx := "gqRsc2lngaFsxJkBIAcB6AdkAF+gwh68o5UBJgIgAQIDBAUGBwgBAgMEBQYHCAECAwQFBgcIAQIDBAUGBwggkq+RhOQTPAl/ZqvMk7ERGxKiAb2dDMo+SkihzhPM9MUxECISMQEjDhAxAiQYJRIQMQQhBDECCBIQMQYoEhAxCTIDEjEHKRIQMQghBRIQMQkpEjEHMgMSEDECIQYNEDEIJRIQERCjdHhuiaNhbXTOAAehIKNmZWXNA+iiZnbNBLCiZ2jEIH+DsWV/8fxTuS3BgUih1l38LUsfo9Z3KErd0gASbZBpomx2zQUPomx4xCABAgMEBQYHCAECAwQFBgcIAQIDBAUGBwgBAgMEBQYHCKNyY3bEIJKvkYTkEzwJf2arzJOxERsSogG9nQzKPkpIoc4TzPTFo3NuZMQgSyW1cXI76LA1KKwDMg39flXjnYOEuOUdDD0znzkLw7akdHlwZaNwYXk=" - require.Equal(t, goldenStx, base64.StdEncoding.EncodeToString(stx)) -} - -func TestDynamicFee(t *testing.T) { - // Inputs - receiver := "726KBOYUJJNE5J5UHCSGQGWIBZWKCBN4WYD7YVSTEXEVNFPWUIJ7TAEOPM" - amount := uint64(5000) - firstValid := uint64(12345) - lastValid := uint64(12346) - closeRemainder := "42NJMHTPFVPXVSDGA6JGKUV6TARV5UZTMPFIREMLXHETRKIVW34QFSDFRE" - artificialLease := "f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=" - c, err := makeDynamicFeeWithLease(receiver, closeRemainder, artificialLease, amount, firstValid, lastValid) - require.NoError(t, err) - goldenGenesisHash := "f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=" - genesisBytes, err := base64.StdEncoding.DecodeString(goldenGenesisHash) - require.NoError(t, err) - contractBytes := c.GetProgram() - require.NoError(t, err) - privateKeyOneB64 := "cv8E0Ln24FSkwDgGeuXKStOTGcze5u8yldpXxgrBxumFPYdMJymqcGoxdDeyuM8t6Kxixfq0PJCyJP71uhYT7w==" - privateKeyOne, err := base64.StdEncoding.DecodeString(privateKeyOneB64) - txn, lsig, err := SignDynamicFee(contractBytes, privateKeyOne, genesisBytes) - require.NoError(t, err) - goldenLsig := "gqFsxLEBIAUCAYgnuWC6YCYDIP68oLsUSlpOp7Q4pGgayA5soQW8tgf8VlMlyVaV9qITIOaalh5vLV96yGYHkmVSvpgjXtMzY8qIkYu5yTipFbb5IH+DsWV/8fxTuS3BgUih1l38LUsfo9Z3KErd0gASbZBpMgQiEjMAECMSEDMABzEAEhAzAAgxARIQMRYjEhAxECMSEDEHKBIQMQkpEhAxCCQSEDECJRIQMQQhBBIQMQYqEhCjc2lnxEAhLNdfdDp9Wbi0YwsEQCpP7TVHbHG7y41F4MoESNW/vL1guS+5Wj4f5V9fmM63/VKTSMFidHOSwm5o+pbV5lYH" - require.Equal(t, goldenLsig, base64.StdEncoding.EncodeToString(msgpack.Encode(lsig))) - goldenTxn := "iqNhbXTNE4ilY2xvc2XEIOaalh5vLV96yGYHkmVSvpgjXtMzY8qIkYu5yTipFbb5o2ZlZc0D6KJmds0wOaJnaMQgf4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGmibHbNMDqibHjEIH+DsWV/8fxTuS3BgUih1l38LUsfo9Z3KErd0gASbZBpo3JjdsQg/ryguxRKWk6ntDikaBrIDmyhBby2B/xWUyXJVpX2ohOjc25kxCCFPYdMJymqcGoxdDeyuM8t6Kxixfq0PJCyJP71uhYT76R0eXBlo3BheQ==" - require.Equal(t, goldenTxn, base64.StdEncoding.EncodeToString(msgpack.Encode(txn))) - privateKeyTwoB64 := "2qjz96Vj9M6YOqtNlfJUOKac13EHCXyDty94ozCjuwwriI+jzFgStFx9E6kEk1l4+lFsW4Te2PY1KV8kNcccRg==" - privateKeyTwo, err := base64.StdEncoding.DecodeString(privateKeyTwoB64) - stxns, err := GetDynamicFeeTransactions(txn, lsig, privateKeyTwo, 1234) - require.NoError(t, err) - // Outputs - goldenProgram := "ASAFAgGIJ7lgumAmAyD+vKC7FEpaTqe0OKRoGsgObKEFvLYH/FZTJclWlfaiEyDmmpYeby1feshmB5JlUr6YI17TM2PKiJGLuck4qRW2+SB/g7Flf/H8U7ktwYFIodZd/C1LH6PWdyhK3dIAEm2QaTIEIhIzABAjEhAzAAcxABIQMwAIMQESEDEWIxIQMRAjEhAxBygSEDEJKRIQMQgkEhAxAiUSEDEEIQQSEDEGKhIQ" - require.Equal(t, goldenProgram, base64.StdEncoding.EncodeToString(contractBytes)) - goldenAddress := "GCI4WWDIWUFATVPOQ372OZYG52EULPUZKI7Y34MXK3ZJKIBZXHD2H5C5TI" - require.Equal(t, goldenAddress, c.GetAddress()) - goldenStxns := "gqNzaWfEQJBNVry9qdpnco+uQzwFicUWHteYUIxwDkdHqY5Qw2Q8Fc2StrQUgN+2k8q4rC0LKrTMJQnE+mLWhZgMMJvq3QCjdHhuiqNhbXTOAAWq6qNmZWXOAATzvqJmds0wOaJnaMQgf4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGmjZ3JwxCCCVfqhCinRBXKMIq9eSrJQIXZ+7iXUTig91oGd/mZEAqJsds0wOqJseMQgf4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGmjcmN2xCCFPYdMJymqcGoxdDeyuM8t6Kxixfq0PJCyJP71uhYT76NzbmTEICuIj6PMWBK0XH0TqQSTWXj6UWxbhN7Y9jUpXyQ1xxxGpHR5cGWjcGF5gqRsc2lngqFsxLEBIAUCAYgnuWC6YCYDIP68oLsUSlpOp7Q4pGgayA5soQW8tgf8VlMlyVaV9qITIOaalh5vLV96yGYHkmVSvpgjXtMzY8qIkYu5yTipFbb5IH+DsWV/8fxTuS3BgUih1l38LUsfo9Z3KErd0gASbZBpMgQiEjMAECMSEDMABzEAEhAzAAgxARIQMRYjEhAxECMSEDEHKBIQMQkpEhAxCCQSEDECJRIQMQQhBBIQMQYqEhCjc2lnxEAhLNdfdDp9Wbi0YwsEQCpP7TVHbHG7y41F4MoESNW/vL1guS+5Wj4f5V9fmM63/VKTSMFidHOSwm5o+pbV5lYHo3R4boujYW10zROIpWNsb3NlxCDmmpYeby1feshmB5JlUr6YI17TM2PKiJGLuck4qRW2+aNmZWXOAAWq6qJmds0wOaJnaMQgf4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGmjZ3JwxCCCVfqhCinRBXKMIq9eSrJQIXZ+7iXUTig91oGd/mZEAqJsds0wOqJseMQgf4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGmjcmN2xCD+vKC7FEpaTqe0OKRoGsgObKEFvLYH/FZTJclWlfaiE6NzbmTEIIU9h0wnKapwajF0N7K4zy3orGLF+rQ8kLIk/vW6FhPvpHR5cGWjcGF5" - require.Equal(t, goldenStxns, base64.StdEncoding.EncodeToString(stxns)) -} - -func TestLimitOrder(t *testing.T) { - // Inputs - owner := "726KBOYUJJNE5J5UHCSGQGWIBZWKCBN4WYD7YVSTEXEVNFPWUIJ7TAEOPM" - assetid := uint64(12345) - ratn, ratd := uint64(30), uint64(100) - expiryRound := uint64(123456) - minTrade := uint64(10000) - maxFee := uint64(5000000) - c, err := MakeLimitOrder(owner, assetid, ratn, ratd, expiryRound, minTrade, maxFee) - // Outputs - require.NoError(t, err) - goldenProgram := "ASAKAAHAlrECApBOBLlgZB7AxAcmASD+vKC7FEpaTqe0OKRoGsgObKEFvLYH/FZTJclWlfaiEzEWIhIxECMSEDEBJA4QMgQjEkAAVTIEJRIxCCEEDRAxCTIDEhAzARAhBRIQMwERIQYSEDMBFCgSEDMBEzIDEhAzARIhBx01AjUBMQghCB01BDUDNAE0Aw1AACQ0ATQDEjQCNAQPEEAAFgAxCSgSMQIhCQ0QMQcyAxIQMQgiEhAQ" - require.Equal(t, goldenProgram, base64.StdEncoding.EncodeToString(c.GetProgram())) - goldenAddress := "LXQWT2XLIVNFS54VTLR63UY5K6AMIEWI7YTVE6LB4RWZDBZKH22ZO3S36I" - require.Equal(t, goldenAddress, c.GetAddress()) -} diff --git a/test/applications_integration_test.go b/test/applications_integration_test.go index 09f3adff..98dcd443 100644 --- a/test/applications_integration_test.go +++ b/test/applications_integration_test.go @@ -9,6 +9,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/algorand/go-algorand-sdk/transaction" "reflect" "regexp" "sort" @@ -24,7 +25,6 @@ import ( "github.com/algorand/go-algorand-sdk/client/v2/indexer" "github.com/algorand/go-algorand-sdk/crypto" sdkJson "github.com/algorand/go-algorand-sdk/encoding/json" - "github.com/algorand/go-algorand-sdk/future" "github.com/algorand/go-algorand-sdk/types" ) @@ -34,7 +34,7 @@ var tx types.Transaction var transientAccount crypto.Account var applicationId uint64 var applicationIds []uint64 -var txComposerResult future.ExecuteResult +var txComposerResult transaction.ExecuteResult func anAlgodVClientConnectedToPortWithToken(v int, host string, port int, token string) error { var err error @@ -58,7 +58,7 @@ func iCreateANewTransientAccountAndFundItWithMicroalgos(microalgos int) error { } params.Fee = types.MicroAlgos(fee) - ltxn, err := future.MakePaymentTxn(accounts[1], transientAccount.Address.String(), uint64(microalgos), note, close, params) + ltxn, err := transaction.MakePaymentTxn(accounts[1], transientAccount.Address.String(), uint64(microalgos), note, close, params) if err != nil { return err } @@ -74,7 +74,7 @@ func iCreateANewTransientAccountAndFundItWithMicroalgos(microalgos int) error { if err != nil { return err } - _, err = future.WaitForConfirmation(algodV2client, ltxid, 1, context.Background()) + _, err = transaction.WaitForConfirmation(algodV2client, ltxid, 1, context.Background()) if err != nil { return err } @@ -89,7 +89,7 @@ func iFundTheCurrentApplicationsAddress(microalgos int) error { return err } - txn, err := future.MakePaymentTxn(accounts[0], address.String(), uint64(microalgos), nil, "", params) + txn, err := transaction.MakePaymentTxn(accounts[0], address.String(), uint64(microalgos), nil, "", params) if err != nil { return err } @@ -104,7 +104,7 @@ func iFundTheCurrentApplicationsAddress(microalgos int) error { return err } - _, err = future.WaitForConfirmation(algodV2client, txid, 1, context.Background()) + _, err = transaction.WaitForConfirmation(algodV2client, txid, 1, context.Background()) return err } @@ -185,32 +185,32 @@ func iBuildAnApplicationTransaction( lSchema := types.StateSchema{NumUint: uint64(localInts), NumByteSlice: uint64(localBytes)} switch operation { case "create": - tx, err = future.MakeApplicationCreateTxWithBoxes(false, approvalP, clearP, + tx, err = transaction.MakeApplicationCreateTxWithBoxes(false, approvalP, clearP, gSchema, lSchema, uint32(extraPages), args, accs, fApp, fAssets, staticBoxes, suggestedParams, transientAccount.Address, nil, types.Digest{}, [32]byte{}, types.Address{}) case "create_optin": - tx, err = future.MakeApplicationCreateTxWithBoxes(true, approvalP, clearP, + tx, err = transaction.MakeApplicationCreateTxWithBoxes(true, approvalP, clearP, gSchema, lSchema, uint32(extraPages), args, accs, fApp, fAssets, staticBoxes, suggestedParams, transientAccount.Address, nil, types.Digest{}, [32]byte{}, types.Address{}) case "update": - tx, err = future.MakeApplicationUpdateTxWithBoxes(applicationId, args, accs, fApp, fAssets, staticBoxes, + tx, err = transaction.MakeApplicationUpdateTxWithBoxes(applicationId, args, accs, fApp, fAssets, staticBoxes, approvalP, clearP, suggestedParams, transientAccount.Address, nil, types.Digest{}, [32]byte{}, types.Address{}) case "call": - tx, err = future.MakeApplicationNoOpTxWithBoxes(applicationId, args, accs, + tx, err = transaction.MakeApplicationNoOpTxWithBoxes(applicationId, args, accs, fApp, fAssets, staticBoxes, suggestedParams, transientAccount.Address, nil, types.Digest{}, [32]byte{}, types.Address{}) case "optin": - tx, err = future.MakeApplicationOptInTxWithBoxes(applicationId, args, accs, fApp, fAssets, staticBoxes, + tx, err = transaction.MakeApplicationOptInTxWithBoxes(applicationId, args, accs, fApp, fAssets, staticBoxes, suggestedParams, transientAccount.Address, nil, types.Digest{}, [32]byte{}, types.Address{}) case "clear": - tx, err = future.MakeApplicationClearStateTxWithBoxes(applicationId, args, accs, fApp, fAssets, staticBoxes, + tx, err = transaction.MakeApplicationClearStateTxWithBoxes(applicationId, args, accs, fApp, fAssets, staticBoxes, suggestedParams, transientAccount.Address, nil, types.Digest{}, [32]byte{}, types.Address{}) case "closeout": - tx, err = future.MakeApplicationCloseOutTxWithBoxes(applicationId, args, accs, fApp, fAssets, staticBoxes, + tx, err = transaction.MakeApplicationCloseOutTxWithBoxes(applicationId, args, accs, fApp, fAssets, staticBoxes, suggestedParams, transientAccount.Address, nil, types.Digest{}, [32]byte{}, types.Address{}) case "delete": - tx, err = future.MakeApplicationDeleteTxWithBoxes(applicationId, args, accs, fApp, fAssets, staticBoxes, + tx, err = transaction.MakeApplicationDeleteTxWithBoxes(applicationId, args, accs, fApp, fAssets, staticBoxes, suggestedParams, transientAccount.Address, nil, types.Digest{}, [32]byte{}, types.Address{}) default: return fmt.Errorf("unsupported tx type: %s", operation) @@ -237,7 +237,7 @@ func iSignAndSubmitTheTransactionSavingTheTxidIfThereIsAnErrorItIs(expectedErr s } func iWaitForTheTransactionToBeConfirmed() error { - _, err := future.WaitForConfirmation(algodV2client, txid, 1, context.Background()) + _, err := transaction.WaitForConfirmation(algodV2client, txid, 1, context.Background()) if err != nil { return err } diff --git a/test/steps_test.go b/test/steps_test.go index f5842509..9a5125f5 100644 --- a/test/steps_test.go +++ b/test/steps_test.go @@ -10,6 +10,7 @@ import ( "encoding/json" "flag" "fmt" + "github.com/algorand/go-algorand-sdk/transaction" "os" "path" "reflect" @@ -29,7 +30,6 @@ import ( indexerV2 "github.com/algorand/go-algorand-sdk/client/v2/indexer" "github.com/algorand/go-algorand-sdk/crypto" "github.com/algorand/go-algorand-sdk/encoding/msgpack" - "github.com/algorand/go-algorand-sdk/future" "github.com/algorand/go-algorand-sdk/logic" "github.com/algorand/go-algorand-sdk/mnemonic" "github.com/algorand/go-algorand-sdk/types" @@ -92,12 +92,12 @@ var abiMethods []abi.Method var abiJsonString string var abiInterface abi.Interface var abiContract abi.Contract -var txComposer future.AtomicTransactionComposer -var accountTxSigner future.BasicAccountTransactionSigner +var txComposer transaction.AtomicTransactionComposer +var accountTxSigner transaction.BasicAccountTransactionSigner var methodArgs []interface{} var sigTxs [][]byte -var accountTxAndSigner future.TransactionWithSigner -var txTrace future.DryrunTxnResult +var accountTxAndSigner transaction.TransactionWithSigner +var txTrace transaction.DryrunTxnResult var trace string var sourceMap logic.SourceMap var srcMapping map[string]interface{} @@ -152,7 +152,7 @@ func initializeAccount(accountAddress string) error { return err } - txn, err = future.MakePaymentTxn(accounts[0], accountAddress, devModeInitialAmount, []byte{}, "", params) + txn, err = transaction.MakePaymentTxn(accounts[0], accountAddress, devModeInitialAmount, []byte{}, "", params) if err != nil { return err } @@ -540,7 +540,7 @@ func createMsigTxn() error { FlatFee: false, } msigaddr, _ := msig.Address() - txn, err = future.MakePaymentTxn(msigaddr.String(), to, amt, note, close, paramsToUse) + txn, err = transaction.MakePaymentTxn(msigaddr.String(), to, amt, note, close, paramsToUse) if err != nil { return err } @@ -559,7 +559,7 @@ func createMsigTxnZeroFee() error { FlatFee: true, } msigaddr, _ := msig.Address() - txn, err = future.MakePaymentTxn(msigaddr.String(), to, amt, note, close, paramsToUse) + txn, err = transaction.MakePaymentTxn(msigaddr.String(), to, amt, note, close, paramsToUse) if err != nil { return err } @@ -888,7 +888,7 @@ func defaultTxnWithAddress(iamt int, inote string, senderAddress string) error { return err } lastRound = uint64(params.FirstRoundValid) - txn, err = future.MakePaymentTxn(senderAddress, accounts[1], amt, note, "", params) + txn, err = transaction.MakePaymentTxn(senderAddress, accounts[1], amt, note, "", params) return err } @@ -936,7 +936,7 @@ func defaultMsigTxn(iamt int, inote string) error { if err != nil { return err } - txn, err = future.MakePaymentTxn(addr.String(), accounts[1], amt, note, "", params) + txn, err = transaction.MakePaymentTxn(addr.String(), accounts[1], amt, note, "", params) if err != nil { return err } @@ -1138,7 +1138,7 @@ func createTxnFlat() error { LastRoundValid: types.Round(lv), FlatFee: true, } - txn, err = future.MakePaymentTxn(a.String(), to, amt, note, close, paramsToUse) + txn, err = transaction.MakePaymentTxn(a.String(), to, amt, note, close, paramsToUse) if err != nil { return err } @@ -1235,7 +1235,7 @@ func createKeyregWithStateProof(keyregType string) (err error) { stateProofPK = "" } - txn, err = future.MakeKeyRegTxnWithStateProofKey(accounts[0], note, params, votekey, selkey, stateProofPK, votefst, votelst, votekd, nonpart) + txn, err = transaction.MakeKeyRegTxnWithStateProofKey(accounts[0], note, params, votekey, selkey, stateProofPK, votefst, votelst, votekd, nonpart) if err != nil { return err } @@ -1293,7 +1293,7 @@ func assetCreateTxnHelper(issuance int, frozenState bool) error { assetName := assetTestFixture.AssetName url := assetTestFixture.AssetURL metadataHash := assetTestFixture.AssetMetadataHash - assetCreateTxn, err := future.MakeAssetCreateTxn(creator, assetNote, params, assetIssuance, 0, frozenState, manager, reserve, freeze, clawback, unitName, assetName, url, metadataHash) + assetCreateTxn, err := transaction.MakeAssetCreateTxn(creator, assetNote, params, assetIssuance, 0, frozenState, manager, reserve, freeze, clawback, unitName, assetName, url, metadataHash) assetTestFixture.LastTransactionIssued = assetCreateTxn txn = assetCreateTxn assetTestFixture.ExpectedParams = convertTransactionAssetParamsToModelsAssetParam(assetCreateTxn.AssetParams) @@ -1322,7 +1322,7 @@ func createNoManagerAssetReconfigure() error { freeze := "" clawback := "" manager := creator // if this were "" as well, this wouldn't be a reconfigure txn, it would be a destroy txn - assetReconfigureTxn, err := future.MakeAssetConfigTxn(creator, assetNote, params, assetTestFixture.AssetIndex, manager, reserve, freeze, clawback, false) + assetReconfigureTxn, err := transaction.MakeAssetConfigTxn(creator, assetNote, params, assetTestFixture.AssetIndex, manager, reserve, freeze, clawback, false) assetTestFixture.LastTransactionIssued = assetReconfigureTxn txn = assetReconfigureTxn // update expected params @@ -1340,7 +1340,7 @@ func createAssetDestroy() error { } lastRound = uint64(params.FirstRoundValid) assetNote := []byte(nil) - assetDestroyTxn, err := future.MakeAssetDestroyTxn(creator, assetNote, params, assetTestFixture.AssetIndex) + assetDestroyTxn, err := transaction.MakeAssetDestroyTxn(creator, assetNote, params, assetTestFixture.AssetIndex) assetTestFixture.LastTransactionIssued = assetDestroyTxn txn = assetDestroyTxn // update expected params @@ -1478,7 +1478,7 @@ func createAssetAcceptanceForSecondAccount() error { } lastRound = uint64(params.FirstRoundValid) assetNote := []byte(nil) - assetAcceptanceTxn, err := future.MakeAssetAcceptanceTxn(accountToUse, assetNote, params, assetTestFixture.AssetIndex) + assetAcceptanceTxn, err := transaction.MakeAssetAcceptanceTxn(accountToUse, assetNote, params, assetTestFixture.AssetIndex) assetTestFixture.LastTransactionIssued = assetAcceptanceTxn txn = assetAcceptanceTxn return err @@ -1495,7 +1495,7 @@ func createAssetTransferTransactionToSecondAccount(amount int) error { closeAssetsTo := "" lastRound = uint64(params.FirstRoundValid) assetNote := []byte(nil) - assetAcceptanceTxn, err := future.MakeAssetTransferTxn(creator, recipient, sendAmount, assetNote, params, closeAssetsTo, assetTestFixture.AssetIndex) + assetAcceptanceTxn, err := transaction.MakeAssetTransferTxn(creator, recipient, sendAmount, assetNote, params, closeAssetsTo, assetTestFixture.AssetIndex) assetTestFixture.LastTransactionIssued = assetAcceptanceTxn txn = assetAcceptanceTxn return err @@ -1512,7 +1512,7 @@ func createAssetTransferTransactionFromSecondAccountToCreator(amount int) error closeAssetsTo := "" lastRound = uint64(params.FirstRoundValid) assetNote := []byte(nil) - assetAcceptanceTxn, err := future.MakeAssetTransferTxn(sender, recipient, sendAmount, assetNote, params, closeAssetsTo, assetTestFixture.AssetIndex) + assetAcceptanceTxn, err := transaction.MakeAssetTransferTxn(sender, recipient, sendAmount, assetNote, params, closeAssetsTo, assetTestFixture.AssetIndex) assetTestFixture.LastTransactionIssued = assetAcceptanceTxn txn = assetAcceptanceTxn return err @@ -1527,7 +1527,7 @@ func freezeTransactionHelper(target string, setting bool) error { } lastRound = uint64(params.FirstRoundValid) assetNote := []byte(nil) - assetFreezeOrUnfreezeTxn, err := future.MakeAssetFreezeTxn(assetTestFixture.Creator, assetNote, params, assetTestFixture.AssetIndex, target, setting) + assetFreezeOrUnfreezeTxn, err := transaction.MakeAssetFreezeTxn(assetTestFixture.Creator, assetNote, params, assetTestFixture.AssetIndex, target, setting) assetTestFixture.LastTransactionIssued = assetFreezeOrUnfreezeTxn txn = assetFreezeOrUnfreezeTxn return err @@ -1549,7 +1549,7 @@ func createRevocationTransaction(amount int) error { lastRound = uint64(params.FirstRoundValid) revocationAmount := uint64(amount) assetNote := []byte(nil) - assetRevokeTxn, err := future.MakeAssetRevocationTxn(assetTestFixture.Creator, accounts[1], revocationAmount, assetTestFixture.Creator, assetNote, params, assetTestFixture.AssetIndex) + assetRevokeTxn, err := transaction.MakeAssetRevocationTxn(assetTestFixture.Creator, accounts[1], revocationAmount, assetTestFixture.Creator, assetNote, params, assetTestFixture.AssetIndex) assetTestFixture.LastTransactionIssued = assetRevokeTxn txn = assetRevokeTxn return err @@ -2034,7 +2034,7 @@ func deserializeContractJson() error { } func aNewAtomicTransactionComposer() error { - txComposer = future.AtomicTransactionComposer{} + txComposer = transaction.AtomicTransactionComposer{} return nil } @@ -2071,11 +2071,11 @@ func anApplicationId(id int) error { func iMakeATransactionSignerForTheAccount(accountType string) error { if accountType == "signing" { - accountTxSigner = future.BasicAccountTransactionSigner{ + accountTxSigner = transaction.BasicAccountTransactionSigner{ Account: account, } } else if accountType == "transient" { - accountTxSigner = future.BasicAccountTransactionSigner{ + accountTxSigner = transaction.BasicAccountTransactionSigner{ Account: transientAccount, } } @@ -2242,7 +2242,7 @@ func addMethodCallHelper(accountType, strOnComplete, approvalProgram, clearProgr preparedArgs = append(preparedArgs, decodedArg) } - methodCallParams := future.AddMethodCallParams{ + methodCallParams := transaction.AddMethodCallParams{ AppID: applicationId, Method: abiMethod, MethodArgs: preparedArgs, @@ -2293,18 +2293,18 @@ func buildTheTransactionGroupWithTheComposer(errorType string) error { } func theComposerShouldHaveAStatusOf(strStatus string) error { - var status future.AtomicTransactionComposerStatus + var status transaction.AtomicTransactionComposerStatus switch strStatus { case "BUILDING": - status = future.BUILDING + status = transaction.BUILDING case "BUILT": - status = future.BUILT + status = transaction.BUILT case "SIGNED": - status = future.SIGNED + status = transaction.SIGNED case "SUBMITTED": - status = future.SUBMITTED + status = transaction.SUBMITTED case "COMMITTED": - status = future.COMMITTED + status = transaction.COMMITTED default: return fmt.Errorf("invalid status provided") } @@ -2356,13 +2356,13 @@ func iBuildAPaymentTransactionWithSenderReceiverAmountCloseRemainderTo(sender, r } var err error - txn, err = future.MakePaymentTxn(sender, receiver, uint64(amount), nil, closeTo, sugParams) + txn, err = transaction.MakePaymentTxn(sender, receiver, uint64(amount), nil, closeTo, sugParams) tx = txn return err } func iCreateATransactionWithSignerWithTheCurrentTransaction() error { - accountTxAndSigner = future.TransactionWithSigner{ + accountTxAndSigner = transaction.TransactionWithSigner{ Signer: accountTxSigner, Txn: txn, } @@ -2396,7 +2396,7 @@ func aDryrunResponseFileAndATransactionAtIndex(arg1, arg2 string) error { if err != nil { return err } - dr, err := future.NewDryrunResponseFromJson(data) + dr, err := transaction.NewDryrunResponseFromJson(data) if err != nil { return err } @@ -2409,7 +2409,7 @@ func aDryrunResponseFileAndATransactionAtIndex(arg1, arg2 string) error { } func callingAppTraceProduces(arg1 string) error { - cfg := future.DefaultStackPrinterConfig() + cfg := transaction.DefaultStackPrinterConfig() cfg.TopOfStackFirst = false trace = txTrace.GetAppCallTrace(cfg) @@ -2543,7 +2543,7 @@ func takeB64encodedBytes(b64encodedBytes string) error { } func heuristicCheckOverBytes() error { - _, sanityCheckError = crypto.MakeLogicSigAccountEscrowChecked(seeminglyProgram, nil) + _, sanityCheckError = crypto.MakeLogicSigAccountEscrow(seeminglyProgram, nil) return nil } diff --git a/test/transactions_test.go b/test/transactions_test.go index 43be3bfc..e4c9af76 100644 --- a/test/transactions_test.go +++ b/test/transactions_test.go @@ -4,11 +4,11 @@ import ( "bytes" "encoding/base64" "fmt" + "github.com/algorand/go-algorand-sdk/transaction" "strconv" "strings" "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/future" "github.com/algorand/go-algorand-sdk/mnemonic" "github.com/algorand/go-algorand-sdk/types" "github.com/cucumber/godog" @@ -67,7 +67,7 @@ func buildKeyregTransaction(sender, nonparticipation string, return fmt.Errorf("Could not parse nonparticipation value: %v", err) } - tx, err = future.MakeKeyRegTxnWithStateProofKey(sender, nil, sugParams, votePkB64, selectionPkB64, stateProofPkB64, uint64(voteFirst), uint64(voteLast), uint64(keyDilution), nonPartValue) + tx, err = transaction.MakeKeyRegTxnWithStateProofKey(sender, nil, sugParams, votePkB64, selectionPkB64, stateProofPkB64, uint64(voteFirst), uint64(voteLast), uint64(keyDilution), nonPartValue) return err } @@ -153,28 +153,28 @@ func buildLegacyAppCallTransaction( switch operation { case "create": - tx, err = future.MakeApplicationCreateTxWithBoxes(false, approvalP, clearP, + tx, err = transaction.MakeApplicationCreateTxWithBoxes(false, approvalP, clearP, gSchema, lSchema, uint32(extraPages), args, accs, fApp, fAssets, boxReferences, sugParams, senderAddr, nil, types.Digest{}, [32]byte{}, types.Address{}) case "update": - tx, err = future.MakeApplicationUpdateTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences, + tx, err = transaction.MakeApplicationUpdateTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences, approvalP, clearP, sugParams, senderAddr, nil, types.Digest{}, [32]byte{}, types.Address{}) case "call": - tx, err = future.MakeApplicationNoOpTxWithBoxes(uint64(applicationId), args, accs, + tx, err = transaction.MakeApplicationNoOpTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences, sugParams, senderAddr, nil, types.Digest{}, [32]byte{}, types.Address{}) case "optin": - tx, err = future.MakeApplicationOptInTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences, + tx, err = transaction.MakeApplicationOptInTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences, sugParams, senderAddr, nil, types.Digest{}, [32]byte{}, types.Address{}) case "clear": - tx, err = future.MakeApplicationClearStateTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences, + tx, err = transaction.MakeApplicationClearStateTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences, sugParams, senderAddr, nil, types.Digest{}, [32]byte{}, types.Address{}) case "closeout": - tx, err = future.MakeApplicationCloseOutTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences, + tx, err = transaction.MakeApplicationCloseOutTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences, sugParams, senderAddr, nil, types.Digest{}, [32]byte{}, types.Address{}) case "delete": - tx, err = future.MakeApplicationDeleteTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences, + tx, err = transaction.MakeApplicationDeleteTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences, sugParams, senderAddr, nil, types.Digest{}, [32]byte{}, types.Address{}) default: err = fmt.Errorf("Unknown opperation: %s", operation) diff --git a/future/atomicTransactionComposer.go b/transaction/atomicTransactionComposer.go similarity index 99% rename from future/atomicTransactionComposer.go rename to transaction/atomicTransactionComposer.go index dd996dc9..b50fc1c5 100644 --- a/future/atomicTransactionComposer.go +++ b/transaction/atomicTransactionComposer.go @@ -1,4 +1,4 @@ -package future +package transaction import ( "bytes" diff --git a/future/atomicTransactionComposer_test.go b/transaction/atomicTransactionComposer_test.go similarity index 99% rename from future/atomicTransactionComposer_test.go rename to transaction/atomicTransactionComposer_test.go index 55849103..faf9594f 100644 --- a/future/atomicTransactionComposer_test.go +++ b/transaction/atomicTransactionComposer_test.go @@ -1,4 +1,4 @@ -package future +package transaction import ( "testing" diff --git a/future/dryrun.go b/transaction/dryrun.go similarity index 99% rename from future/dryrun.go rename to transaction/dryrun.go index 98c49ddb..be084c31 100644 --- a/future/dryrun.go +++ b/transaction/dryrun.go @@ -1,4 +1,4 @@ -package future +package transaction import ( "bytes" diff --git a/transaction/transaction.go b/transaction/transaction.go index 5c1ba7e8..ac922da5 100644 --- a/transaction/transaction.go +++ b/transaction/transaction.go @@ -16,11 +16,27 @@ const MinTxnFee = 1000 // NumOfAdditionalBytesAfterSigning is the number of bytes added to a txn after signing it const NumOfAdditionalBytesAfterSigning = 75 +func setFee(tx types.Transaction, params types.SuggestedParams) (types.Transaction, error) { + if !params.FlatFee { + eSize, err := EstimateSize(tx) + if err != nil { + return types.Transaction{}, err + } + tx.Fee = types.MicroAlgos(eSize * uint64(params.Fee)) + if tx.Fee < MinTxnFee { + tx.Fee = MinTxnFee + } + } else { + tx.Fee = params.Fee + } + + return tx, nil +} + // MakePaymentTxn constructs a payment transaction using the passed parameters. // `from` and `to` addresses should be checksummed, human-readable addresses // fee is fee per byte as received from algod SuggestedFee API call -// Deprecated: next major version will use a Params object, see package future -func MakePaymentTxn(from, to string, fee, amount, firstRound, lastRound uint64, note []byte, closeRemainderTo, genesisID string, genesisHash []byte) (types.Transaction, error) { +func MakePaymentTxn(from, to string, amount uint64, note []byte, closeRemainderTo string, params types.SuggestedParams) (types.Transaction, error) { // Decode from address fromAddr, err := types.DecodeAddress(from) if err != nil { @@ -42,24 +58,23 @@ func MakePaymentTxn(from, to string, fee, amount, firstRound, lastRound uint64, } } - // Decode GenesisHash - if len(genesisHash) == 0 { + if len(params.GenesisHash) == 0 { return types.Transaction{}, fmt.Errorf("payment transaction must contain a genesisHash") } var gh types.Digest - copy(gh[:], genesisHash) + copy(gh[:], params.GenesisHash) // Build the transaction tx := types.Transaction{ Type: types.PaymentTx, Header: types.Header{ Sender: fromAddr, - Fee: types.MicroAlgos(fee), - FirstValid: types.Round(firstRound), - LastValid: types.Round(lastRound), + Fee: params.Fee, + FirstValid: params.FirstRoundValid, + LastValid: params.LastRoundValid, Note: note, - GenesisID: genesisID, + GenesisID: params.GenesisID, GenesisHash: gh, }, PaymentTxnFields: types.PaymentTxnFields{ @@ -69,66 +84,33 @@ func MakePaymentTxn(from, to string, fee, amount, firstRound, lastRound uint64, }, } - // Update fee - eSize, err := EstimateSize(tx) - if err != nil { - return types.Transaction{}, err - } - tx.Fee = types.MicroAlgos(eSize * fee) - - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - - return tx, nil -} - -// MakePaymentTxnWithFlatFee constructs a payment transaction using the passed parameters. -// `from` and `to` addresses should be checksummed, human-readable addresses -// fee is a flat fee -// Deprecated: next major version will use a Params object, see package future -func MakePaymentTxnWithFlatFee(from, to string, fee, amount, firstRound, lastRound uint64, note []byte, closeRemainderTo, genesisID string, genesisHash []byte) (types.Transaction, error) { - tx, err := MakePaymentTxn(from, to, fee, amount, firstRound, lastRound, note, closeRemainderTo, genesisID, genesisHash) - if err != nil { - return types.Transaction{}, err - } - tx.Fee = types.MicroAlgos(fee) - - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - - return tx, nil + return setFee(tx, params) } // MakeKeyRegTxn constructs a keyreg transaction using the passed parameters. // - account is a checksummed, human-readable address for which we register the given participation key. -// - fee is fee per byte as received from algod SuggestedFee API call. -// - firstRound is the first round this txn is valid (txn semantics unrelated to key registration) -// - lastRound is the last round this txn is valid // - note is a byte array -// - genesis id corresponds to the id of the network -// - genesis hash corresponds to the base64-encoded hash of the genesis of the network +// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period // KeyReg parameters: // - votePK is a base64-encoded string corresponding to the root participation public key // - selectionKey is a base64-encoded string corresponding to the vrf public key // - voteFirst is the first round this participation key is valid // - voteLast is the last round this participation key is valid // - voteKeyDilution is the dilution for the 2-level participation key -// Deprecated: next major version will use a Params object, see package future -func MakeKeyRegTxn(account string, feePerByte, firstRound, lastRound uint64, note []byte, genesisID string, genesisHash string, - voteKey, selectionKey string, voteFirst, voteLast, voteKeyDilution uint64) (types.Transaction, error) { +func MakeKeyRegTxn(account string, note []byte, params types.SuggestedParams, voteKey, selectionKey string, voteFirst, voteLast, voteKeyDilution uint64) (types.Transaction, error) { // Decode account address accountAddr, err := types.DecodeAddress(account) if err != nil { return types.Transaction{}, err } - ghBytes, err := byte32FromBase64(genesisHash) - if err != nil { - return types.Transaction{}, err + if len(params.GenesisHash) == 0 { + return types.Transaction{}, fmt.Errorf("key registration transaction must contain a genesisHash") } + var gh types.Digest + copy(gh[:], params.GenesisHash) + votePKBytes, err := byte32FromBase64(voteKey) if err != nil { return types.Transaction{}, err @@ -143,12 +125,12 @@ func MakeKeyRegTxn(account string, feePerByte, firstRound, lastRound uint64, not Type: types.KeyRegistrationTx, Header: types.Header{ Sender: accountAddr, - Fee: types.MicroAlgos(feePerByte), - FirstValid: types.Round(firstRound), - LastValid: types.Round(lastRound), + Fee: params.Fee, + FirstValid: params.FirstRoundValid, + LastValid: params.LastRoundValid, Note: note, - GenesisHash: types.Digest(ghBytes), - GenesisID: genesisID, + GenesisHash: gh, + GenesisID: params.GenesisID, }, KeyregTxnFields: types.KeyregTxnFields{ VotePK: types.VotePK(votePKBytes), @@ -159,65 +141,91 @@ func MakeKeyRegTxn(account string, feePerByte, firstRound, lastRound uint64, not }, } - // Update fee - eSize, err := EstimateSize(tx) - if err != nil { - return types.Transaction{}, err - } - tx.Fee = types.MicroAlgos(eSize * feePerByte) - - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - - return tx, nil + return setFee(tx, params) } -// MakeKeyRegTxnWithFlatFee constructs a keyreg transaction using the passed parameters. +// MakeKeyRegTxnWithStateProofKey constructs a keyreg transaction using the passed parameters. // - account is a checksummed, human-readable address for which we register the given participation key. -// - fee is a flat fee -// - firstRound is the first round this txn is valid (txn semantics unrelated to key registration) -// - lastRound is the last round this txn is valid // - note is a byte array -// - genesis id corresponds to the id of the network -// - genesis hash corresponds to the base64-encoded hash of the genesis of the network +// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period // KeyReg parameters: // - votePK is a base64-encoded string corresponding to the root participation public key // - selectionKey is a base64-encoded string corresponding to the vrf public key +// - stateProofPK is a base64-encoded string corresponding to the block proof public key // - voteFirst is the first round this participation key is valid // - voteLast is the last round this participation key is valid // - voteKeyDilution is the dilution for the 2-level participation key -// Deprecated: next major version will use a Params object, see package future -func MakeKeyRegTxnWithFlatFee(account string, fee, firstRound, lastRound uint64, note []byte, genesisID string, genesisHash string, - voteKey, selectionKey string, voteFirst, voteLast, voteKeyDilution uint64) (types.Transaction, error) { - tx, err := MakeKeyRegTxn(account, fee, firstRound, lastRound, note, genesisID, genesisHash, voteKey, selectionKey, voteFirst, voteLast, voteKeyDilution) +// - nonpart is an indicator marking a key registration participating or nonparticipating +func MakeKeyRegTxnWithStateProofKey(account string, note []byte, params types.SuggestedParams, voteKey, selectionKey, stateProofPK string, voteFirst, voteLast, voteKeyDilution uint64, nonpart bool) (types.Transaction, error) { + // Decode account address + accountAddr, err := types.DecodeAddress(account) if err != nil { return types.Transaction{}, err } - tx.Fee = types.MicroAlgos(fee) + if len(params.GenesisHash) == 0 { + return types.Transaction{}, fmt.Errorf("key registration transaction must contain a genesisHash") + } - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee + var gh types.Digest + copy(gh[:], params.GenesisHash) + var votePKBytes [32]byte + var selectionPKBytes [32]byte + var statePKBytes [64]byte + + if len(voteKey) > 0 { + votePKBytes, err = byte32FromBase64(voteKey) + if err != nil { + return types.Transaction{}, err + } } - return tx, nil + if len(selectionKey) > 0 { + selectionPKBytes, err = byte32FromBase64(selectionKey) + if err != nil { + return types.Transaction{}, err + } + } + + if len(stateProofPK) > 0 { + statePKBytes, err = byte64FromBase64(stateProofPK) + if err != nil { + return types.Transaction{}, err + } + } + + tx := types.Transaction{ + Type: types.KeyRegistrationTx, + Header: types.Header{ + Sender: accountAddr, + Fee: params.Fee, + FirstValid: params.FirstRoundValid, + LastValid: params.LastRoundValid, + Note: note, + GenesisHash: gh, + GenesisID: params.GenesisID, + }, + KeyregTxnFields: types.KeyregTxnFields{ + VotePK: types.VotePK(votePKBytes), + SelectionPK: types.VRFPK(selectionPKBytes), + VoteFirst: types.Round(voteFirst), + VoteLast: types.Round(voteLast), + VoteKeyDilution: voteKeyDilution, + Nonparticipation: nonpart, + StateProofPK: types.MerkleVerifier(statePKBytes), + }, + } + + return setFee(tx, params) } // MakeAssetCreateTxn constructs an asset creation transaction using the passed parameters. // - account is a checksummed, human-readable address which will send the transaction. -// - fee is fee per byte as received from algod SuggestedFee API call. -// - firstRound is the first round this txn is valid (txn semantics unrelated to the asset) -// - lastRound is the last round this txn is valid // - note is a byte array -// - genesis id corresponds to the id of the network -// - genesis hash corresponds to the base64-encoded hash of the genesis of the network +// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period // Asset creation parameters: // - see asset.go -// Deprecated: next major version will use a Params object, see package future -func MakeAssetCreateTxn(account string, feePerByte, firstRound, lastRound uint64, note []byte, genesisID, genesisHash string, - total uint64, decimals uint32, defaultFrozen bool, manager, reserve, freeze, clawback string, - unitName, assetName, url, metadataHash string) (types.Transaction, error) { +func MakeAssetCreateTxn(account string, note []byte, params types.SuggestedParams, total uint64, decimals uint32, defaultFrozen bool, manager, reserve, freeze, clawback string, unitName, assetName, url, metadataHash string) (types.Transaction, error) { var tx types.Transaction var err error @@ -280,37 +288,30 @@ func MakeAssetCreateTxn(account string, feePerByte, firstRound, lastRound uint64 } copy(tx.AssetParams.MetadataHash[:], []byte(metadataHash)) + if len(params.GenesisHash) == 0 { + return types.Transaction{}, fmt.Errorf("asset transaction must contain a genesisHash") + } + var gh types.Digest + copy(gh[:], params.GenesisHash) + // Fill in header accountAddr, err := types.DecodeAddress(account) if err != nil { return types.Transaction{}, err } - ghBytes, err := byte32FromBase64(genesisHash) - if err != nil { - return types.Transaction{}, err - } + tx.Header = types.Header{ Sender: accountAddr, - Fee: types.MicroAlgos(feePerByte), - FirstValid: types.Round(firstRound), - LastValid: types.Round(lastRound), - GenesisHash: types.Digest(ghBytes), - GenesisID: genesisID, + Fee: params.Fee, + FirstValid: params.FirstRoundValid, + LastValid: params.LastRoundValid, + GenesisHash: gh, + GenesisID: params.GenesisID, Note: note, } // Update fee - eSize, err := EstimateSize(tx) - if err != nil { - return types.Transaction{}, err - } - tx.Fee = types.MicroAlgos(eSize * feePerByte) - - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - - return tx, nil + return setFee(tx, params) } // MakeAssetConfigTxn creates a tx template for changing the @@ -321,18 +322,12 @@ func MakeAssetCreateTxn(account string, feePerByte, firstRound, lastRound uint64 // The current manager, you must specify its address again. // Parameters - // - account is a checksummed, human-readable address that will send the transaction -// - feePerByte is a fee per byte -// - firstRound is the first round this txn is valid (txn semantics unrelated to asset config) -// - lastRound is the last round this txn is valid // - note is an arbitrary byte array -// - genesis id corresponds to the id of the network -// - genesis hash corresponds to the base64-encoded hash of the genesis of the network +// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period // - index is the asset index id // - for newManager, newReserve, newFreeze, newClawback see asset.go // - strictEmptyAddressChecking: if true, disallow empty admin accounts from being set (preventing accidental disable of admin features) -// Deprecated: next major version will use a Params object, see package future -func MakeAssetConfigTxn(account string, feePerByte, firstRound, lastRound uint64, note []byte, genesisID, genesisHash string, - index uint64, newManager, newReserve, newFreeze, newClawback string, strictEmptyAddressChecking bool) (types.Transaction, error) { +func MakeAssetConfigTxn(account string, note []byte, params types.SuggestedParams, index uint64, newManager, newReserve, newFreeze, newClawback string, strictEmptyAddressChecking bool) (types.Transaction, error) { var tx types.Transaction if strictEmptyAddressChecking && (newManager == "" || newReserve == "" || newFreeze == "" || newClawback == "") { @@ -346,18 +341,19 @@ func MakeAssetConfigTxn(account string, feePerByte, firstRound, lastRound uint64 return tx, err } - ghBytes, err := byte32FromBase64(genesisHash) - if err != nil { - return types.Transaction{}, err + if len(params.GenesisHash) == 0 { + return types.Transaction{}, fmt.Errorf("asset transaction must contain a genesisHash") } + var gh types.Digest + copy(gh[:], params.GenesisHash) tx.Header = types.Header{ Sender: accountAddr, - Fee: types.MicroAlgos(feePerByte), - FirstValid: types.Round(firstRound), - LastValid: types.Round(lastRound), - GenesisHash: ghBytes, - GenesisID: genesisID, + Fee: params.Fee, + FirstValid: params.FirstRoundValid, + LastValid: params.LastRoundValid, + GenesisHash: gh, + GenesisID: params.GenesisID, Note: note, } @@ -393,24 +389,12 @@ func MakeAssetConfigTxn(account string, feePerByte, firstRound, lastRound uint64 } // Update fee - eSize, err := EstimateSize(tx) - if err != nil { - return types.Transaction{}, err - } - tx.Fee = types.MicroAlgos(eSize * feePerByte) - - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - - return tx, nil + return setFee(tx, params) } // transferAssetBuilder is a helper that builds asset transfer transactions: // either a normal asset transfer, or an asset revocation -// Deprecated: next major version will use a Params object, see package future -func transferAssetBuilder(account, recipient, closeAssetsTo, revocationTarget string, amount, feePerByte, - firstRound, lastRound uint64, note []byte, genesisID, genesisHash string, index uint64) (types.Transaction, error) { +func transferAssetBuilder(account, recipient string, amount uint64, note []byte, params types.SuggestedParams, index uint64, closeAssetsTo, revocationTarget string) (types.Transaction, error) { var tx types.Transaction tx.Type = types.AssetTransferTx @@ -419,18 +403,19 @@ func transferAssetBuilder(account, recipient, closeAssetsTo, revocationTarget st return tx, err } - ghBytes, err := byte32FromBase64(genesisHash) - if err != nil { - return types.Transaction{}, err + if len(params.GenesisHash) == 0 { + return types.Transaction{}, fmt.Errorf("asset transaction must contain a genesisHash") } + var gh types.Digest + copy(gh[:], params.GenesisHash) tx.Header = types.Header{ Sender: accountAddr, - Fee: types.MicroAlgos(feePerByte), - FirstValid: types.Round(firstRound), - LastValid: types.Round(lastRound), - GenesisHash: types.Digest(ghBytes), - GenesisID: genesisID, + Fee: params.Fee, + FirstValid: params.FirstRoundValid, + LastValid: params.LastRoundValid, + GenesisHash: gh, + GenesisID: params.GenesisID, Note: note, } @@ -461,109 +446,63 @@ func transferAssetBuilder(account, recipient, closeAssetsTo, revocationTarget st tx.AssetAmount = amount // Update fee - eSize, err := EstimateSize(tx) - if err != nil { - return types.Transaction{}, err - } - tx.Fee = types.MicroAlgos(eSize * feePerByte) - - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - - return tx, nil + return setFee(tx, params) } // MakeAssetTransferTxn creates a tx for sending some asset from an asset holder to another user // the recipient address must have previously issued an asset acceptance transaction for this asset // - account is a checksummed, human-readable address that will send the transaction and assets // - recipient is a checksummed, human-readable address what will receive the assets -// - closeAssetsTo is a checksummed, human-readable address that behaves as a close-to address for the asset transaction; the remaining assets not sent to recipient will be sent to closeAssetsTo. Leave blank for no close-to behavior. // - amount is the number of assets to send -// - feePerByte is a fee per byte -// - firstRound is the first round this txn is valid (txn semantics unrelated to asset management) -// - lastRound is the last round this txn is valid // - note is an arbitrary byte array -// - genesis id corresponds to the id of the network -// - genesis hash corresponds to the base64-encoded hash of the genesis of the network +// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period +// - closeAssetsTo is a checksummed, human-readable address that behaves as a close-to address for the asset transaction; the remaining assets not sent to recipient will be sent to closeAssetsTo. Leave blank for no close-to behavior. // - index is the asset index -// Deprecated: next major version will use a Params object, see package future -func MakeAssetTransferTxn(account, recipient, closeAssetsTo string, amount, feePerByte, firstRound, lastRound uint64, note []byte, - genesisID, genesisHash string, index uint64) (types.Transaction, error) { +func MakeAssetTransferTxn(account, recipient string, amount uint64, note []byte, params types.SuggestedParams, closeAssetsTo string, index uint64) (types.Transaction, error) { revocationTarget := "" // no asset revocation, this is normal asset transfer - return transferAssetBuilder(account, recipient, closeAssetsTo, revocationTarget, amount, feePerByte, firstRound, lastRound, - note, genesisID, genesisHash, index) + return transferAssetBuilder(account, recipient, amount, note, params, index, closeAssetsTo, revocationTarget) } // MakeAssetAcceptanceTxn creates a tx for marking an account as willing to accept the given asset // - account is a checksummed, human-readable address that will send the transaction and begin accepting the asset -// - feePerByte is a fee per byte -// - firstRound is the first round this txn is valid (txn semantics unrelated to asset management) -// - lastRound is the last round this txn is valid // - note is an arbitrary byte array -// - genesis id corresponds to the id of the network -// - genesis hash corresponds to the base64-encoded hash of the genesis of the network +// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period // - index is the asset index -// Deprecated: next major version will use a Params object, see package future -func MakeAssetAcceptanceTxn(account string, feePerByte, firstRound, lastRound uint64, note []byte, - genesisID, genesisHash string, index uint64) (types.Transaction, error) { - return MakeAssetTransferTxn(account, account, "", 0, - feePerByte, firstRound, lastRound, note, genesisID, genesisHash, index) +func MakeAssetAcceptanceTxn(account string, note []byte, params types.SuggestedParams, index uint64) (types.Transaction, error) { + return MakeAssetTransferTxn(account, account, 0, note, params, "", index) } // MakeAssetRevocationTxn creates a tx for revoking an asset from an account and sending it to another // - account is a checksummed, human-readable address; it must be the revocation manager / clawback address from the asset's parameters // - target is a checksummed, human-readable address; it is the account whose assets will be revoked // - recipient is a checksummed, human-readable address; it will receive the revoked assets -// - feePerByte is a fee per byte -// - firstRound is the first round this txn is valid (txn semantics unrelated to asset management) -// - lastRound is the last round this txn is valid -// - note is an arbitrary byte array -// - genesis id corresponds to the id of the network -// - genesis hash corresponds to the base64-encoded hash of the genesis of the network +// - amount defines the number of assets to clawback +// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period // - index is the asset index -// Deprecated: next major version will use a Params object, see package future -func MakeAssetRevocationTxn(account, target, recipient string, amount, feePerByte, firstRound, lastRound uint64, note []byte, - genesisID, genesisHash string, index uint64) (types.Transaction, error) { +func MakeAssetRevocationTxn(account, target string, amount uint64, recipient string, note []byte, params types.SuggestedParams, index uint64) (types.Transaction, error) { closeAssetsTo := "" // no close-out, this is an asset revocation - return transferAssetBuilder(account, recipient, closeAssetsTo, target, amount, feePerByte, firstRound, lastRound, - note, genesisID, genesisHash, index) + return transferAssetBuilder(account, recipient, amount, note, params, index, closeAssetsTo, target) } // MakeAssetDestroyTxn creates a tx template for destroying an asset, removing it from the record. // All outstanding asset amount must be held by the creator, and this transaction must be issued by the asset manager. // - account is a checksummed, human-readable address that will send the transaction; it also must be the asset manager -// - fee is a fee per byte -// - firstRound is the first round this txn is valid (txn semantics unrelated to asset management) -// - lastRound is the last round this txn is valid -// - genesis id corresponds to the id of the network -// - genesis hash corresponds to the base64-encoded hash of the genesis of the network +// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period // - index is the asset index -// Deprecated: next major version will use a Params object, see package future -func MakeAssetDestroyTxn(account string, feePerByte, firstRound, lastRound uint64, note []byte, genesisID, genesisHash string, - index uint64) (types.Transaction, error) { +func MakeAssetDestroyTxn(account string, note []byte, params types.SuggestedParams, index uint64) (types.Transaction, error) { // an asset destroy transaction is just a configuration transaction with AssetParams zeroed - tx, err := MakeAssetConfigTxn(account, feePerByte, firstRound, lastRound, note, genesisID, genesisHash, - index, "", "", "", "", false) - - return tx, err + return MakeAssetConfigTxn(account, note, params, index, "", "", "", "", false) } // MakeAssetFreezeTxn constructs a transaction that freezes or unfreezes an account's asset holdings // It must be issued by the freeze address for the asset // - account is a checksummed, human-readable address which will send the transaction. -// - fee is fee per byte as received from algod SuggestedFee API call. -// - firstRound is the first round this txn is valid (txn semantics unrelated to the asset) -// - lastRound is the last round this txn is valid // - note is an optional arbitrary byte array -// - genesis id corresponds to the id of the network -// - genesis hash corresponds to the base64-encoded hash of the genesis of the network +// - params is typically received from algod, it defines common-to-all-txns arguments like fee and validity period // - assetIndex is the index for tracking the asset // - target is the account to be frozen or unfrozen // - newFreezeSetting is the new state of the target account -// Deprecated: next major version will use a Params object, see package future -func MakeAssetFreezeTxn(account string, fee, firstRound, lastRound uint64, note []byte, genesisID, genesisHash string, - assetIndex uint64, target string, newFreezeSetting bool) (types.Transaction, error) { +func MakeAssetFreezeTxn(account string, note []byte, params types.SuggestedParams, assetIndex uint64, target string, newFreezeSetting bool) (types.Transaction, error) { var tx types.Transaction tx.Type = types.AssetFreezeTx @@ -573,18 +512,19 @@ func MakeAssetFreezeTxn(account string, fee, firstRound, lastRound uint64, note return tx, err } - ghBytes, err := byte32FromBase64(genesisHash) - if err != nil { - return types.Transaction{}, err + if len(params.GenesisHash) == 0 { + return types.Transaction{}, fmt.Errorf("asset transaction must contain a genesisHash") } + var gh types.Digest + copy(gh[:], params.GenesisHash) tx.Header = types.Header{ Sender: accountAddr, - Fee: types.MicroAlgos(fee), - FirstValid: types.Round(firstRound), - LastValid: types.Round(lastRound), - GenesisHash: types.Digest(ghBytes), - GenesisID: genesisID, + Fee: params.Fee, + FirstValid: params.FirstRoundValid, + LastValid: params.LastRoundValid, + GenesisHash: gh, + GenesisID: params.GenesisID, Note: note, } @@ -596,173 +536,746 @@ func MakeAssetFreezeTxn(account string, fee, firstRound, lastRound uint64, note } tx.AssetFrozen = newFreezeSetting + // Update fee - eSize, err := EstimateSize(tx) + return setFee(tx, params) +} + +// byte32FromBase64 decodes the input base64 string and outputs a +// 32 byte array, erroring if the input is the wrong length. +func byte32FromBase64(in string) (out [32]byte, err error) { + slice, err := base64.StdEncoding.DecodeString(in) if err != nil { - return types.Transaction{}, err + return } - tx.Fee = types.MicroAlgos(eSize * fee) - - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee + if len(slice) != 32 { + return out, fmt.Errorf("Input is not 32 bytes") } - - return tx, nil + copy(out[:], slice) + return } -// MakeAssetCreateTxnWithFlatFee constructs an asset creation transaction using the passed parameters. -// - account is a checksummed, human-readable address which will send the transaction. -// - fee is fee per byte as received from algod SuggestedFee API call. -// - firstRound is the first round this txn is valid (txn semantics unrelated to the asset) -// - lastRound is the last round this txn is valid -// - genesis id corresponds to the id of the network -// - genesis hash corresponds to the base64-encoded hash of the genesis of the network -// Asset creation parameters: -// - see asset.go -// Deprecated: next major version will use a Params object, see package future -func MakeAssetCreateTxnWithFlatFee(account string, fee, firstRound, lastRound uint64, note []byte, genesisID, genesisHash string, - total uint64, decimals uint32, defaultFrozen bool, manager, reserve, freeze, clawback, unitName, assetName, url, metadataHash string) (types.Transaction, error) { - tx, err := MakeAssetCreateTxn(account, fee, firstRound, lastRound, note, genesisID, genesisHash, total, decimals, defaultFrozen, manager, reserve, freeze, clawback, unitName, assetName, url, metadataHash) +// byte32FromBase64 decodes the input base64 string and outputs a +// 64 byte array, erroring if the input is the wrong length. +func byte64FromBase64(in string) (out [64]byte, err error) { + slice, err := base64.StdEncoding.DecodeString(in) if err != nil { - return types.Transaction{}, err + return } + if len(slice) != 64 { + return out, fmt.Errorf("input is not 64 bytes") + } + copy(out[:], slice) + return +} - tx.Fee = types.MicroAlgos(fee) +// - accounts lists the accounts (in addition to the sender) that may be accessed +// from the application logic. +// +// - appArgs ApplicationArgs lists some transaction-specific arguments accessible +// from application logic. +// +// - appIdx ApplicationID is the application being interacted with, or 0 if +// creating a new application. +// +// - approvalProg ApprovalProgram determines whether or not this ApplicationCall +// transaction will be approved or not. +// +// - clearProg ClearStateProgram executes when a clear state ApplicationCall +// transaction is executed. This program may not reject the +// transaction, only update state. +// +// - foreignApps lists the applications (in addition to txn.ApplicationID) whose global +// states may be accessed by this application. The access is read-only. +// +// - foreignAssets lists the assets whose global state may be accessed by this application. The access is read-only. +// +// - globalSchema GlobalStateSchema sets limits on the number of strings and +// integers that may be stored in the GlobalState. The larger these +// limits are, the larger minimum balance must be maintained inside +// the creator's account (in order to 'pay' for the state that can +// be used). The GlobalStateSchema is immutable. +// +// - localSchema LocalStateSchema sets limits on the number of strings and integers +// that may be stored in an account's LocalState for this application. +// The larger these limits are, the larger minimum balance must be +// maintained inside the account of any users who opt into this +// application. The LocalStateSchema is immutable. +// +// - extraPages ExtraProgramPages specifies the additional app program size requested in pages. +// A page is 1024 bytes. This field enables execution of app programs +// larger than the default maximum program size. +// +// - onComplete This is the faux application type used to distinguish different +// application actions. Specifically, OnCompletion specifies what +// side effects this transaction will have if it successfully makes +// it into a block. +// +// - boxes lists the boxes to be accessed during evaluation of the application +// call. This also must include the boxes accessed by inner app calls. + +// MakeApplicationCreateTx makes a transaction for creating an application (see above for args desc.) +// - optIn: true for opting in on complete, false for no-op. +// +// NOTE: if you need to use extra pages or boxes, use MakeApplicationCreateTxWithBoxes instead. +func MakeApplicationCreateTx( + optIn bool, + approvalProg []byte, + clearProg []byte, + globalSchema types.StateSchema, + localSchema types.StateSchema, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + return MakeApplicationCreateTxWithBoxes( + optIn, + approvalProg, + clearProg, + globalSchema, + localSchema, + 0, + appArgs, + accounts, + foreignApps, + foreignAssets, + nil, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) +} - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } +// MakeApplicationCreateTxWithExtraPages makes a transaction for creating an application (see above for args desc.) +// - optIn: true for opting in on complete, false for no-op. +// +// NOTE: if you need to use boxes, use MakeApplicationCreateTxWithBoxes instead. +func MakeApplicationCreateTxWithExtraPages( + optIn bool, + approvalProg []byte, + clearProg []byte, + globalSchema types.StateSchema, + localSchema types.StateSchema, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address, + extraPages uint32) (tx types.Transaction, err error) { + return MakeApplicationCreateTxWithBoxes( + optIn, + approvalProg, + clearProg, + globalSchema, + localSchema, + extraPages, + appArgs, + accounts, + foreignApps, + foreignAssets, + nil, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) +} - return tx, nil +// MakeApplicationCreateTxWithBoxes makes a transaction for creating an application (see above for args desc.) +// - optIn: true for opting in on complete, false for no-op. +func MakeApplicationCreateTxWithBoxes( + optIn bool, + approvalProg []byte, + clearProg []byte, + globalSchema types.StateSchema, + localSchema types.StateSchema, + extraPages uint32, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + appBoxReferences []types.AppBoxReference, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + + oncomp := types.NoOpOC + if optIn { + oncomp = types.OptInOC + } + + return MakeApplicationCallTxWithBoxes( + 0, + appArgs, + accounts, + foreignApps, + foreignAssets, + appBoxReferences, + oncomp, + approvalProg, + clearProg, + globalSchema, + localSchema, + extraPages, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) } -// MakeAssetConfigTxnWithFlatFee creates a tx template for changing the -// keys for an asset. An empty string means a zero key (which -// cannot be changed after becoming zero); to keep a key -// unchanged, you must specify that key. -// Deprecated: next major version will use a Params object, see package future -func MakeAssetConfigTxnWithFlatFee(account string, fee, firstRound, lastRound uint64, note []byte, genesisID, genesisHash string, - index uint64, newManager, newReserve, newFreeze, newClawback string, strictEmptyAddressChecking bool) (types.Transaction, error) { - tx, err := MakeAssetConfigTxn(account, fee, firstRound, lastRound, note, genesisID, genesisHash, - index, newManager, newReserve, newFreeze, newClawback, strictEmptyAddressChecking) - if err != nil { - return types.Transaction{}, err - } +// MakeApplicationUpdateTx makes a transaction for updating an application's programs (see above for args desc.) +// +// NOTE: if you need to use boxes, use MakeApplicationUpdateTxWithBoxes instead. +func MakeApplicationUpdateTx( + appIdx uint64, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + approvalProg []byte, + clearProg []byte, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + return MakeApplicationUpdateTxWithBoxes(appIdx, + appArgs, + accounts, + foreignApps, + foreignAssets, + nil, + approvalProg, + clearProg, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) +} - tx.Fee = types.MicroAlgos(fee) +// MakeApplicationUpdateTxWithBoxes makes a transaction for updating an application's programs (see above for args desc.) +func MakeApplicationUpdateTxWithBoxes( + appIdx uint64, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + appBoxReferences []types.AppBoxReference, + approvalProg []byte, + clearProg []byte, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + return MakeApplicationCallTxWithBoxes(appIdx, + appArgs, + accounts, + foreignApps, + foreignAssets, + appBoxReferences, + types.UpdateApplicationOC, + approvalProg, + clearProg, + emptySchema, + emptySchema, + 0, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) +} - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - return tx, nil +// MakeApplicationDeleteTx makes a transaction for deleting an application (see above for args desc.) +// +// NOTE: if you need to use boxes, use MakeApplicationDeleteTxWithBoxes instead. +func MakeApplicationDeleteTx( + appIdx uint64, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + return MakeApplicationDeleteTxWithBoxes(appIdx, + appArgs, + accounts, + foreignApps, + foreignAssets, + nil, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) } -// MakeAssetTransferTxnWithFlatFee creates a tx for sending some asset from an asset holder to another user -// the recipient address must have previously issued an asset acceptance transaction for this asset -// - account is a checksummed, human-readable address that will send the transaction and assets -// - recipient is a checksummed, human-readable address what will receive the assets -// - closeAssetsTo is a checksummed, human-readable address that behaves as a close-to address for the asset transaction; the remaining assets not sent to recipient will be sent to closeAssetsTo. Leave blank for no close-to behavior. -// - amount is the number of assets to send -// - fee is a flat fee -// - firstRound is the first round this txn is valid (txn semantics unrelated to asset management) -// - lastRound is the last round this txn is valid -// - genesis id corresponds to the id of the network -// - genesis hash corresponds to the base64-encoded hash of the genesis of the network -// - index is the asset index -func MakeAssetTransferTxnWithFlatFee(account, recipient, closeAssetsTo string, amount, fee, firstRound, lastRound uint64, note []byte, - genesisID, genesisHash string, index uint64) (types.Transaction, error) { - tx, err := MakeAssetTransferTxn(account, recipient, closeAssetsTo, amount, - fee, firstRound, lastRound, note, genesisID, genesisHash, index) - if err != nil { - return types.Transaction{}, err - } +// MakeApplicationDeleteTxWithBoxes makes a transaction for deleting an application (see above for args desc.) +func MakeApplicationDeleteTxWithBoxes( + appIdx uint64, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + appBoxReferences []types.AppBoxReference, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + return MakeApplicationCallTxWithBoxes(appIdx, + appArgs, + accounts, + foreignApps, + foreignAssets, + appBoxReferences, + types.DeleteApplicationOC, + nil, + nil, + emptySchema, + emptySchema, + 0, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) +} - tx.Fee = types.MicroAlgos(fee) +// MakeApplicationOptInTx makes a transaction for opting in to (allocating +// some account-specific state for) an application (see above for args desc.) +// +// NOTE: if you need to use boxes, use MakeApplicationOptInTxWithBoxes instead. +func MakeApplicationOptInTx( + appIdx uint64, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + return MakeApplicationOptInTxWithBoxes(appIdx, + appArgs, + accounts, + foreignApps, + foreignAssets, + nil, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) +} - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - return tx, nil +// MakeApplicationOptInTxWithBoxes makes a transaction for opting in to (allocating +// some account-specific state for) an application (see above for args desc.) +func MakeApplicationOptInTxWithBoxes( + appIdx uint64, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + appBoxReferences []types.AppBoxReference, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + return MakeApplicationCallTxWithBoxes(appIdx, + appArgs, + accounts, + foreignApps, + foreignAssets, + appBoxReferences, + types.OptInOC, + nil, + nil, + emptySchema, + emptySchema, + 0, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) } -// MakeAssetAcceptanceTxnWithFlatFee creates a tx for marking an account as willing to accept an asset -// - account is a checksummed, human-readable address that will send the transaction and begin accepting the asset -// - fee is a flat fee -// - firstRound is the first round this txn is valid (txn semantics unrelated to asset management) -// - lastRound is the last round this txn is valid -// - genesis id corresponds to the id of the network -// - genesis hash corresponds to the base64-encoded hash of the genesis of the network -// - index is the asset index -// Deprecated: next major version will use a Params object, see package future -func MakeAssetAcceptanceTxnWithFlatFee(account string, fee, firstRound, lastRound uint64, note []byte, - genesisID, genesisHash string, index uint64) (types.Transaction, error) { - tx, err := MakeAssetTransferTxnWithFlatFee(account, account, "", 0, - fee, firstRound, lastRound, note, genesisID, genesisHash, index) - return tx, err +// MakeApplicationCloseOutTx makes a transaction for closing out of +// (deallocating all account-specific state for) an application (see above for args desc.) +// +// NOTE: if you need to use boxes, use MakeApplicationCloseOutTxWithBoxes +// instead. +func MakeApplicationCloseOutTx( + appIdx uint64, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + return MakeApplicationCloseOutTxWithBoxes(appIdx, + appArgs, + accounts, + foreignApps, + foreignAssets, + nil, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) } -// MakeAssetRevocationTxnWithFlatFee creates a tx for revoking an asset from an account and sending it to another -// - account is a checksummed, human-readable address; it must be the revocation manager / clawback address from the asset's parameters -// - target is a checksummed, human-readable address; it is the account whose assets will be revoked -// - recipient is a checksummed, human-readable address; it will receive the revoked assets -// - fee is a flat fee -// - firstRound is the first round this txn is valid (txn semantics unrelated to asset management) -// - lastRound is the last round this txn is valid -// - note is an arbitrary byte array -// - genesis id corresponds to the id of the network -// - genesis hash corresponds to the base64-encoded hash of the genesis of the network -// - index is the asset index -// Deprecated: next major version will use a Params object, see package future -func MakeAssetRevocationTxnWithFlatFee(account, target, recipient string, amount, fee, firstRound, lastRound uint64, note []byte, - genesisID, genesisHash, creator string, index uint64) (types.Transaction, error) { - tx, err := MakeAssetRevocationTxn(account, target, recipient, amount, fee, firstRound, lastRound, - note, genesisID, genesisHash, index) +// MakeApplicationCloseOutTxWithBoxes makes a transaction for closing out of +// (deallocating all account-specific state for) an application (see above for args desc.) +func MakeApplicationCloseOutTxWithBoxes( + appIdx uint64, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + appBoxReferences []types.AppBoxReference, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + return MakeApplicationCallTxWithBoxes(appIdx, + appArgs, + accounts, + foreignApps, + foreignAssets, + appBoxReferences, + types.CloseOutOC, + nil, + nil, + emptySchema, + emptySchema, + 0, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) +} - if err != nil { - return types.Transaction{}, err - } +// MakeApplicationClearStateTx makes a transaction for clearing out all +// account-specific state for an application. It may not be rejected by the +// application's logic. (see above for args desc.) +// +// NOTE: if you need to use boxes, use MakeApplicationClearStateTxWithBoxes +// instead. +func MakeApplicationClearStateTx( + appIdx uint64, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + return MakeApplicationClearStateTxWithBoxes(appIdx, + appArgs, + accounts, + foreignApps, + foreignAssets, + nil, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) +} - tx.Fee = types.MicroAlgos(fee) +// MakeApplicationClearStateTxWithBoxes makes a transaction for clearing out all +// account-specific state for an application. It may not be rejected by the +// application's logic. (see above for args desc.) +func MakeApplicationClearStateTxWithBoxes( + appIdx uint64, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + appBoxReferences []types.AppBoxReference, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + return MakeApplicationCallTxWithBoxes(appIdx, + appArgs, + accounts, + foreignApps, + foreignAssets, + appBoxReferences, + types.ClearStateOC, + nil, + nil, + emptySchema, + emptySchema, + 0, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) +} - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - return tx, nil +// MakeApplicationNoOpTx makes a transaction for interacting with an existing +// application, potentially updating any account-specific local state and +// global state associated with it. (see above for args desc.) +// +// NOTE: if you need to use boxes, use MakeApplicationNoOpTxWithBoxes instead. +func MakeApplicationNoOpTx( + appIdx uint64, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + return MakeApplicationNoOpTxWithBoxes( + appIdx, + appArgs, + accounts, + foreignApps, + foreignAssets, + nil, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) } -// MakeAssetDestroyTxnWithFlatFee creates a tx template for destroying an asset, removing it from the record. -// All outstanding asset amount must be held by the creator, and this transaction must be issued by the asset manager. -// - account is a checksummed, human-readable address that will send the transaction; it also must be the asset manager -// - fee is a flat fee -// - firstRound is the first round this txn is valid (txn semantics unrelated to asset management) -// - lastRound is the last round this txn is valid -// - genesis id corresponds to the id of the network -// - genesis hash corresponds to the base64-encoded hash of the genesis of the network -// - index is the asset index -// Deprecated: next major version will use a Params object, see package future -func MakeAssetDestroyTxnWithFlatFee(account string, fee, firstRound, lastRound uint64, note []byte, genesisID, genesisHash string, - creator string, index uint64) (types.Transaction, error) { - tx, err := MakeAssetConfigTxnWithFlatFee(account, fee, firstRound, lastRound, note, genesisID, genesisHash, - index, "", "", "", "", false) - return tx, err -} - -// MakeAssetFreezeTxnWithFlatFee is as MakeAssetFreezeTxn, but taking a flat fee rather than a fee per byte. -// Deprecated: next major version will use a Params object, see package future -func MakeAssetFreezeTxnWithFlatFee(account string, fee, firstRound, lastRound uint64, note []byte, genesisID, genesisHash string, - creator string, assetIndex uint64, target string, newFreezeSetting bool) (types.Transaction, error) { - tx, err := MakeAssetFreezeTxn(account, fee, firstRound, lastRound, note, genesisID, genesisHash, - assetIndex, target, newFreezeSetting) +// MakeApplicationNoOpTxWithBoxes makes a transaction for interacting with an +// existing application, potentially updating any account-specific local state +// and global state associated with it. (see above for args desc.) +func MakeApplicationNoOpTxWithBoxes( + appIdx uint64, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + appBoxReferences []types.AppBoxReference, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + return MakeApplicationCallTxWithBoxes( + appIdx, + appArgs, + accounts, + foreignApps, + foreignAssets, + appBoxReferences, + types.NoOpOC, + nil, + nil, + emptySchema, + emptySchema, + 0, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) +} + +// MakeApplicationCallTx is a helper for the above ApplicationCall +// transaction constructors. A fully custom ApplicationCall transaction may +// be constructed using this method. (see above for args desc.) +// +// NOTE: if you need to use boxes or extra program pages, use +// MakeApplicationCallTxWithBoxes instead. +func MakeApplicationCallTx( + appIdx uint64, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + onCompletion types.OnCompletion, + approvalProg []byte, + clearProg []byte, + globalSchema types.StateSchema, + localSchema types.StateSchema, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + return MakeApplicationCallTxWithBoxes( + appIdx, + appArgs, + accounts, + foreignApps, + foreignAssets, + nil, + onCompletion, + approvalProg, + clearProg, + globalSchema, + localSchema, + 0, + sp, + sender, + note, + group, + lease, + rekeyTo, + ) +} + +// MakeApplicationCallTxWithExtraPages sets the ExtraProgramPages on an existing +// application call transaction. +// +// Consider using MakeApplicationCallTxWithBoxes instead if you wish to assign +// the extra pages value at creation. +func MakeApplicationCallTxWithExtraPages( + txn types.Transaction, extraPages uint32) (types.Transaction, error) { + txn.ExtraProgramPages = extraPages + return txn, nil +} + +// MakeApplicationCallTxWithBoxes is a helper for the above ApplicationCall +// transaction constructors. A fully custom ApplicationCall transaction may +// be constructed using this method. (see above for args desc.) +func MakeApplicationCallTxWithBoxes( + appIdx uint64, + appArgs [][]byte, + accounts []string, + foreignApps []uint64, + foreignAssets []uint64, + appBoxReferences []types.AppBoxReference, + onCompletion types.OnCompletion, + approvalProg []byte, + clearProg []byte, + globalSchema types.StateSchema, + localSchema types.StateSchema, + extraPages uint32, + sp types.SuggestedParams, + sender types.Address, + note []byte, + group types.Digest, + lease [32]byte, + rekeyTo types.Address) (tx types.Transaction, err error) { + tx.Type = types.ApplicationCallTx + tx.ApplicationID = types.AppIndex(appIdx) + tx.OnCompletion = onCompletion + + tx.ApplicationArgs = appArgs + tx.Accounts, err = parseTxnAccounts(accounts) if err != nil { - return types.Transaction{}, err + return tx, err } - tx.Fee = types.MicroAlgos(fee) + tx.ForeignApps = parseTxnForeignApps(foreignApps) + tx.ForeignAssets = parseTxnForeignAssets(foreignAssets) + tx.BoxReferences, err = parseBoxReferences(appBoxReferences, foreignApps, appIdx) + if err != nil { + return tx, err + } + + tx.ApprovalProgram = approvalProg + tx.ClearStateProgram = clearProg + tx.LocalStateSchema = localSchema + tx.GlobalStateSchema = globalSchema + tx.ExtraProgramPages = extraPages + + var gh types.Digest + copy(gh[:], sp.GenesisHash) - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee + tx.Header = types.Header{ + Sender: sender, + Fee: sp.Fee, + FirstValid: sp.FirstRoundValid, + LastValid: sp.LastRoundValid, + Note: note, + GenesisID: sp.GenesisID, + GenesisHash: gh, + Group: group, + Lease: lease, + RekeyTo: rekeyTo, } - return tx, nil + + // Update fee + return setFee(tx, sp) } // AssignGroupID computes and return list of transactions with Group field set. @@ -794,16 +1307,68 @@ func EstimateSize(txn types.Transaction) (uint64, error) { return uint64(len(msgpack.Encode(txn))) + NumOfAdditionalBytesAfterSigning, nil } -// byte32FromBase64 decodes the input base64 string and outputs a -// 32 byte array, erroring if the input is the wrong length. -func byte32FromBase64(in string) (out [32]byte, err error) { - slice, err := base64.StdEncoding.DecodeString(in) - if err != nil { - return +func parseTxnAccounts(accounts []string) (parsed []types.Address, err error) { + for _, acct := range accounts { + addr, err := types.DecodeAddress(acct) + if err != nil { + return nil, err + } + parsed = append(parsed, addr) } - if len(slice) != 32 { - return out, fmt.Errorf("Input is not 32 bytes") + return +} + +func parseTxnForeignApps(foreignApps []uint64) (parsed []types.AppIndex) { + for _, aidx := range foreignApps { + parsed = append(parsed, types.AppIndex(aidx)) } - copy(out[:], slice) return } + +func parseTxnForeignAssets(foreignAssets []uint64) (parsed []types.AssetIndex) { + for _, aidx := range foreignAssets { + parsed = append(parsed, types.AssetIndex(aidx)) + } + return +} + +func parseBoxReferences(abrs []types.AppBoxReference, foreignApps []uint64, curAppID uint64) (parsed []types.BoxReference, err error) { + for _, abr := range abrs { + // there are a few unintuitive details to the parsing: + // 1. the AppID of the box must either be in the foreign apps array or + // equal to 0, which references the current app. + // 2. if the box references the current app by its appID rather than 0 AND + // the current appID is explicitly provided in the foreign apps array + // then ForeignAppIdx should be set to its index in the array. + br := types.BoxReference{Name: abr.Name} + found := false + + if abr.AppID == 0 { + found = true + br.ForeignAppIdx = 0 + } else { + for idx, appID := range foreignApps { + if appID == abr.AppID { + found = true + br.ForeignAppIdx = uint64(idx + 1) + break + } + } + } + + if !found && abr.AppID == curAppID { + found = true + br.ForeignAppIdx = 0 + } + + if !found { + return nil, fmt.Errorf("the app id %d provided for this box is not in the foreignApps array", abr.AppID) + } + + parsed = append(parsed, br) + } + + return +} + +var emptySchema = types.StateSchema{} diff --git a/future/transactionSigner.go b/transaction/transactionSigner.go similarity index 99% rename from future/transactionSigner.go rename to transaction/transactionSigner.go index 4f908585..d6a39a6b 100644 --- a/future/transactionSigner.go +++ b/transaction/transactionSigner.go @@ -1,4 +1,4 @@ -package future +package transaction import ( "encoding/json" diff --git a/future/transactionSigner_test.go b/transaction/transactionSigner_test.go similarity index 99% rename from future/transactionSigner_test.go rename to transaction/transactionSigner_test.go index 916552cd..78a1b820 100644 --- a/future/transactionSigner_test.go +++ b/transaction/transactionSigner_test.go @@ -1,4 +1,4 @@ -package future +package transaction import ( "crypto/ed25519" diff --git a/transaction/transaction_test.go b/transaction/transaction_test.go index ca6df9af..5bdfe687 100644 --- a/transaction/transaction_test.go +++ b/transaction/transaction_test.go @@ -4,12 +4,11 @@ import ( "encoding/base64" "testing" - "github.com/stretchr/testify/require" - "github.com/algorand/go-algorand-sdk/crypto" "github.com/algorand/go-algorand-sdk/encoding/msgpack" "github.com/algorand/go-algorand-sdk/mnemonic" "github.com/algorand/go-algorand-sdk/types" + "github.com/stretchr/testify/require" ) func byteFromBase64(s string) []byte { @@ -26,6 +25,15 @@ func byte32ArrayFromBase64(s string) (out [32]byte) { return } +func byte64ArrayFromBase64(s string) (out [64]byte) { + slice := byteFromBase64(s) + if len(slice) != 64 { + panic("wrong length: input slice not 64 bytes") + } + copy(out[:], slice) + return +} + func TestMakePaymentTxn(t *testing.T) { const fromAddress = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU" const toAddress = "PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI" @@ -34,13 +42,21 @@ func TestMakePaymentTxn(t *testing.T) { const golden = "gqNzaWfEQPhUAZ3xkDDcc8FvOVo6UinzmKBCqs0woYSfodlmBMfQvGbeUx3Srxy3dyJDzv7rLm26BRv9FnL2/AuT7NYfiAWjdHhui6NhbXTNA+ilY2xvc2XEIEDpNJKIJWTLzpxZpptnVCaJ6aHDoqnqW2Wm6KRCH/xXo2ZlZc0EmKJmds0wsqNnZW6sZGV2bmV0LXYzMy4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds00mqRub3RlxAjqABVHQ2y/lqNyY3bEIHts4k/rW6zAsWTinCIsV/X2PcOH1DkEglhBHF/hD3wCo3NuZMQg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGkdHlwZaNwYXk=" gh := byteFromBase64("JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=") - txn, err := MakePaymentTxn(fromAddress, toAddress, 4, 1000, 12466, 13466, byteFromBase64("6gAVR0Nsv5Y="), "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA", "devnet-v33.0", gh) + params := types.SuggestedParams{ + Fee: 4, + FirstRoundValid: 12466, + LastRoundValid: 13466, + GenesisID: "devnet-v33.0", + GenesisHash: gh, + } + txn, err := MakePaymentTxn(fromAddress, toAddress, 1000, byteFromBase64("6gAVR0Nsv5Y="), "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA", params) require.NoError(t, err) key, err := mnemonic.ToPrivateKey(mn) require.NoError(t, err) id, bytes, err := crypto.SignTransaction(key, txn) + require.NoError(t, err) stxBytes := byteFromBase64(golden) require.Equal(t, stxBytes, bytes) @@ -52,10 +68,14 @@ func TestMakePaymentTxn(t *testing.T) { func TestMakePaymentTxn2(t *testing.T) { const fromAddress = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU" const toAddress = "PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI" - - _, err := MakePaymentTxn(fromAddress, toAddress, 4, 1000, 12466, 13466, byteFromBase64("6gAVR0Nsv5Y="), "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA", "devnet-v33.0", []byte{}) + params := types.SuggestedParams{ + Fee: 4, + FirstRoundValid: 12466, + LastRoundValid: 13466, + GenesisID: "devnet-v33.0", + } + _, err := MakePaymentTxn(fromAddress, toAddress, 1000, byteFromBase64("6gAVR0Nsv5Y="), "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA", params) require.Error(t, err) - } func TestMakePaymentTxnWithLease(t *testing.T) { @@ -65,9 +85,15 @@ func TestMakePaymentTxnWithLease(t *testing.T) { const mn = "advice pudding treat near rule blouse same whisper inner electric quit surface sunny dismiss leader blood seat clown cost exist hospital century reform able sponsor" const golden = "gqNzaWfEQOMmFSIKsZvpW0txwzhmbgQjxv6IyN7BbV5sZ2aNgFbVcrWUnqPpQQxfPhV/wdu9jzEPUU1jAujYtcNCxJ7ONgejdHhujKNhbXTNA+ilY2xvc2XEIEDpNJKIJWTLzpxZpptnVCaJ6aHDoqnqW2Wm6KRCH/xXo2ZlZc0FLKJmds0wsqNnZW6sZGV2bmV0LXYzMy4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds00mqJseMQgAQIDBAECAwQBAgMEAQIDBAECAwQBAgMEAQIDBAECAwSkbm90ZcQI6gAVR0Nsv5ajcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEIOfw+E0GgR358xyNh4sRVfRnHVGhhcIAkIZn9ElYcGihpHR5cGWjcGF5" gh := byteFromBase64("JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=") - + params := types.SuggestedParams{ + Fee: 4, + FirstRoundValid: 12466, + LastRoundValid: 13466, + GenesisID: "devnet-v33.0", + GenesisHash: gh, + } lease := [32]byte{1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4} - txn, err := MakePaymentTxn(fromAddress, toAddress, 4, 1000, 12466, 13466, byteFromBase64("6gAVR0Nsv5Y="), "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA", "devnet-v33.0", gh) + txn, err := MakePaymentTxn(fromAddress, toAddress, 1000, byteFromBase64("6gAVR0Nsv5Y="), "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA", params) require.NoError(t, err) txn.AddLease(lease, 4) require.NoError(t, err) @@ -76,6 +102,7 @@ func TestMakePaymentTxnWithLease(t *testing.T) { require.NoError(t, err) id, stxBytes, err := crypto.SignTransaction(key, txn) + require.NoError(t, err) goldenBytes := byteFromBase64(golden) require.Equal(t, goldenBytes, stxBytes) @@ -118,8 +145,14 @@ func TestKeyRegTxn(t *testing.T) { func TestMakeKeyRegTxn(t *testing.T) { const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" - tx, err := MakeKeyRegTxn(addr, 10, 322575, 323575, []byte{45, 67}, "", "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", - "Kv7QI7chi1y6axoy+t7wzAVpePqRq/rkjzWh/RMYyLo=", "bPgrv4YogPcdaUAxrt1QysYZTVyRAuUMD4zQmCu9llc=", 10000, 10111, 11) + ghAsArray := byte32ArrayFromBase64("SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=") + params := types.SuggestedParams{ + Fee: 10, + FirstRoundValid: 322575, + LastRoundValid: 323575, + GenesisHash: ghAsArray[:], + } + tx, err := MakeKeyRegTxn(addr, []byte{45, 67}, params, "Kv7QI7chi1y6axoy+t7wzAVpePqRq/rkjzWh/RMYyLo=", "bPgrv4YogPcdaUAxrt1QysYZTVyRAuUMD4zQmCu9llc=", 10000, 10111, 11) require.NoError(t, err) a, err := types.DecodeAddress(addr) @@ -146,19 +179,88 @@ func TestMakeKeyRegTxn(t *testing.T) { require.Equal(t, expKeyRegTxn, tx) } +func TestMakeKeyRegTxnWithStateProofKey(t *testing.T) { + const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" + ghAsArray := byte32ArrayFromBase64("SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=") + params := types.SuggestedParams{ + Fee: 10, + FirstRoundValid: 322575, + LastRoundValid: 323575, + GenesisHash: ghAsArray[:], + } + // nonparticipation + tx, err := MakeKeyRegTxnWithStateProofKey(addr, []byte{45, 67}, params, "", "", "", 0, 0, 0, true) + require.NoError(t, err) + a, err := types.DecodeAddress(addr) + require.NoError(t, err) + expKeyRegTxn := types.Transaction{ + Type: types.KeyRegistrationTx, + Header: types.Header{ + Sender: a, + Fee: 2020, + FirstValid: 322575, + LastValid: 323575, + Note: []byte{45, 67}, + GenesisHash: byte32ArrayFromBase64("SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="), + GenesisID: "", + }, + KeyregTxnFields: types.KeyregTxnFields{ + Nonparticipation: true, + }, + } + require.Equal(t, expKeyRegTxn, tx) + + // online + stateProof := "mYR0GVEObMTSNdsKM6RwYywHYPqVDqg3E4JFzxZOreH9NU8B+tKzUanyY8AQ144hETgSMX7fXWwjBdHz6AWk9w==" + tx, err = MakeKeyRegTxnWithStateProofKey(addr, []byte{45, 67}, params, "Kv7QI7chi1y6axoy+t7wzAVpePqRq/rkjzWh/RMYyLo=", "bPgrv4YogPcdaUAxrt1QysYZTVyRAuUMD4zQmCu9llc=", stateProof, 10000, 10111, 11, false) + require.NoError(t, err) + + a, err = types.DecodeAddress(addr) + require.NoError(t, err) + expKeyRegTxn = types.Transaction{ + Type: types.KeyRegistrationTx, + Header: types.Header{ + Sender: a, + Fee: 3800, + FirstValid: 322575, + LastValid: 323575, + Note: []byte{45, 67}, + GenesisHash: byte32ArrayFromBase64("SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="), + GenesisID: "", + }, + KeyregTxnFields: types.KeyregTxnFields{ + VotePK: byte32ArrayFromBase64("Kv7QI7chi1y6axoy+t7wzAVpePqRq/rkjzWh/RMYyLo="), + SelectionPK: byte32ArrayFromBase64("bPgrv4YogPcdaUAxrt1QysYZTVyRAuUMD4zQmCu9llc="), + VoteFirst: 10000, + VoteLast: 10111, + VoteKeyDilution: 11, + Nonparticipation: false, + StateProofPK: byte64ArrayFromBase64(stateProof), + }, + } + require.Equal(t, expKeyRegTxn, tx) +} + func TestMakeAssetCreateTxn(t *testing.T) { const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" const defaultFrozen = false const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" + ghAsArray := byte32ArrayFromBase64(genesisHash) const total = 100 const reserve = addr const freeze = addr const clawback = addr const unitName = "tst" const assetName = "testcoin" - const testURL = "websitewebsitewebsitewebsitewebsitewebsitewebsitewebsitewebsitewebsitewebsitewebsitewebsitewebsi" //96 characters + const testURL = "website" const metadataHash = "fACPO4nRgO55j1ndAK3W6Sgc4APkcyFh" - tx, err := MakeAssetCreateTxn(addr, 10, 322575, 323575, nil, "", genesisHash, total, 0, defaultFrozen, addr, reserve, freeze, clawback, unitName, assetName, testURL, metadataHash) + params := types.SuggestedParams{ + Fee: 10, + FirstRoundValid: 322575, + LastRoundValid: 323575, + GenesisHash: ghAsArray[:], + } + tx, err := MakeAssetCreateTxn(addr, nil, params, total, 0, defaultFrozen, addr, reserve, freeze, clawback, unitName, assetName, testURL, metadataHash) require.NoError(t, err) a, err := types.DecodeAddress(addr) @@ -167,7 +269,7 @@ func TestMakeAssetCreateTxn(t *testing.T) { Type: types.AssetConfigTx, Header: types.Header{ Sender: a, - Fee: 4920, + Fee: 4020, FirstValid: 322575, LastValid: 323575, GenesisHash: byte32ArrayFromBase64(genesisHash), @@ -192,7 +294,8 @@ func TestMakeAssetCreateTxn(t *testing.T) { private, err := mnemonic.ToPrivateKey(addrSK) require.NoError(t, err) _, newStxBytes, err := crypto.SignTransaction(private, tx) - signedGolden := "gqNzaWfEQCPNXED15sdMwiSxl9K4LALy5brxBpnOtBurPK2TAtjXpxKQqN9flVtjxP0GGYVUjNx/Sez0W4v1CSU9FhYSUgOjdHhuh6RhcGFyiaJhbcQgZkFDUE80blJnTzU1ajFuZEFLM1c2U2djNEFQa2N5RmiiYW6odGVzdGNvaW6iYXXZYHdlYnNpdGV3ZWJzaXRld2Vic2l0ZXdlYnNpdGV3ZWJzaXRld2Vic2l0ZXdlYnNpdGV3ZWJzaXRld2Vic2l0ZXdlYnNpdGV3ZWJzaXRld2Vic2l0ZXdlYnNpdGV3ZWJzaaFjxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFmxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFtxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFyxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aF0ZKJ1bqN0c3SjZmVlzRM4omZ2zgAE7A+iZ2jEIEhjtRiks8hOyBDyLU8QgcsPcfBZp6wg3sYvf3DlCToiomx2zgAE7/ejc25kxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aR0eXBlpGFjZmc=" + require.NoError(t, err) + signedGolden := "gqNzaWfEQEDd1OMRoQI/rzNlU4iiF50XQXmup3k5czI9hEsNqHT7K4KsfmA/0DUVkbzOwtJdRsHS8trm3Arjpy9r7AXlbAujdHhuh6RhcGFyiaJhbcQgZkFDUE80blJnTzU1ajFuZEFLM1c2U2djNEFQa2N5RmiiYW6odGVzdGNvaW6iYXWnd2Vic2l0ZaFjxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFmxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFtxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFyxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aF0ZKJ1bqN0c3SjZmVlzQ+0omZ2zgAE7A+iZ2jEIEhjtRiks8hOyBDyLU8QgcsPcfBZp6wg3sYvf3DlCToiomx2zgAE7/ejc25kxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aR0eXBlpGFjZmc=" require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) } @@ -200,6 +303,7 @@ func TestMakeAssetCreateTxnWithDecimals(t *testing.T) { const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" const defaultFrozen = false const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" + ghAsArray := byte32ArrayFromBase64(genesisHash) const total = 100 const decimals = 1 const reserve = addr @@ -209,7 +313,13 @@ func TestMakeAssetCreateTxnWithDecimals(t *testing.T) { const assetName = "testcoin" const testURL = "website" const metadataHash = "fACPO4nRgO55j1ndAK3W6Sgc4APkcyFh" - tx, err := MakeAssetCreateTxn(addr, 10, 322575, 323575, nil, "", genesisHash, total, decimals, defaultFrozen, addr, reserve, freeze, clawback, unitName, assetName, testURL, metadataHash) + params := types.SuggestedParams{ + Fee: 10, + FirstRoundValid: 322575, + LastRoundValid: 323575, + GenesisHash: ghAsArray[:], + } + tx, err := MakeAssetCreateTxn(addr, nil, params, total, decimals, defaultFrozen, addr, reserve, freeze, clawback, unitName, assetName, testURL, metadataHash) require.NoError(t, err) a, err := types.DecodeAddress(addr) @@ -244,6 +354,7 @@ func TestMakeAssetCreateTxnWithDecimals(t *testing.T) { private, err := mnemonic.ToPrivateKey(addrSK) require.NoError(t, err) _, newStxBytes, err := crypto.SignTransaction(private, tx) + require.NoError(t, err) signedGolden := "gqNzaWfEQCj5xLqNozR5ahB+LNBlTG+d0gl0vWBrGdAXj1ibsCkvAwOsXs5KHZK1YdLgkdJecQiWm4oiZ+pm5Yg0m3KFqgqjdHhuh6RhcGFyiqJhbcQgZkFDUE80blJnTzU1ajFuZEFLM1c2U2djNEFQa2N5RmiiYW6odGVzdGNvaW6iYXWnd2Vic2l0ZaFjxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aJkYwGhZsQgCfvSdiwI+Gxa5r9t16epAd5mdddQ4H6MXHaYZH224f2hbcQgCfvSdiwI+Gxa5r9t16epAd5mdddQ4H6MXHaYZH224f2hcsQgCfvSdiwI+Gxa5r9t16epAd5mdddQ4H6MXHaYZH224f2hdGSidW6jdHN0o2ZlZc0P3KJmds4ABOwPomdoxCBIY7UYpLPITsgQ8i1PEIHLD3HwWaesIN7GL39w5Qk6IqJsds4ABO/3o3NuZMQgCfvSdiwI+Gxa5r9t16epAd5mdddQ4H6MXHaYZH224f2kdHlwZaRhY2Zn" require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) } @@ -251,13 +362,19 @@ func TestMakeAssetCreateTxnWithDecimals(t *testing.T) { func TestMakeAssetConfigTxn(t *testing.T) { const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" + ghAsArray := byte32ArrayFromBase64(genesisHash) const manager = addr const reserve = addr const freeze = addr const clawback = addr const assetIndex = 1234 - tx, err := MakeAssetConfigTxn(addr, 10, 322575, 323575, nil, "", genesisHash, - assetIndex, manager, reserve, freeze, clawback, false) + params := types.SuggestedParams{ + Fee: 10, + FirstRoundValid: 322575, + LastRoundValid: 323575, + GenesisHash: ghAsArray[:], + } + tx, err := MakeAssetConfigTxn(addr, nil, params, assetIndex, manager, reserve, freeze, clawback, false) require.NoError(t, err) a, err := types.DecodeAddress(addr) @@ -287,6 +404,7 @@ func TestMakeAssetConfigTxn(t *testing.T) { private, err := mnemonic.ToPrivateKey(addrSK) require.NoError(t, err) _, newStxBytes, err := crypto.SignTransaction(private, tx) + require.NoError(t, err) signedGolden := "gqNzaWfEQBBkfw5n6UevuIMDo2lHyU4dS80JCCQ/vTRUcTx5m0ivX68zTKyuVRrHaTbxbRRc3YpJ4zeVEnC9Fiw3Wf4REwejdHhuiKRhcGFyhKFjxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFmxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFtxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aFyxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aRjYWlkzQTSo2ZlZc0NSKJmds4ABOwPomdoxCBIY7UYpLPITsgQ8i1PEIHLD3HwWaesIN7GL39w5Qk6IqJsds4ABO/3o3NuZMQgCfvSdiwI+Gxa5r9t16epAd5mdddQ4H6MXHaYZH224f2kdHlwZaRhY2Zn" require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) } @@ -294,24 +412,37 @@ func TestMakeAssetConfigTxn(t *testing.T) { func TestMakeAssetConfigTxnStrictChecking(t *testing.T) { const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" + ghAsArray := byte32ArrayFromBase64(genesisHash) const manager = addr const reserve = addr const freeze = "" const clawback = addr const assetIndex = 1234 - _, err := MakeAssetConfigTxn(addr, 10, 322575, 323575, nil, "", genesisHash, - assetIndex, manager, reserve, freeze, clawback, true) + params := types.SuggestedParams{ + Fee: 10, + FirstRoundValid: 322575, + LastRoundValid: 323575, + GenesisHash: ghAsArray[:], + } + _, err := MakeAssetConfigTxn(addr, nil, params, assetIndex, manager, reserve, freeze, clawback, true) require.Error(t, err) } func TestMakeAssetDestroyTxn(t *testing.T) { const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" + ghAsArray := byte32ArrayFromBase64(genesisHash) const creator = addr const assetIndex = 1 const firstValidRound = 322575 const lastValidRound = 323575 - tx, err := MakeAssetDestroyTxn(creator, 10, firstValidRound, lastValidRound, nil, "", genesisHash, assetIndex) + params := types.SuggestedParams{ + Fee: 10, + FirstRoundValid: firstValidRound, + LastRoundValid: lastValidRound, + GenesisHash: ghAsArray[:], + } + tx, err := MakeAssetDestroyTxn(creator, nil, params, assetIndex) require.NoError(t, err) a, err := types.DecodeAddress(creator) @@ -336,6 +467,7 @@ func TestMakeAssetDestroyTxn(t *testing.T) { private, err := mnemonic.ToPrivateKey(addrSK) require.NoError(t, err) _, newStxBytes, err := crypto.SignTransaction(private, tx) + require.NoError(t, err) signedGolden := "gqNzaWfEQBSP7HtzD/Lvn4aVvaNpeR4T93dQgo4LvywEwcZgDEoc/WVl3aKsZGcZkcRFoiWk8AidhfOZzZYutckkccB8RgGjdHhuh6RjYWlkAaNmZWXNB1iiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv96NzbmTEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pHR5cGWkYWNmZw==" require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) } @@ -343,12 +475,19 @@ func TestMakeAssetDestroyTxn(t *testing.T) { func TestMakeAssetFreezeTxn(t *testing.T) { const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" + ghAsArray := byte32ArrayFromBase64(genesisHash) const assetIndex = 1 const firstValidRound = 322575 const lastValidRound = 323576 const freezeSetting = true const target = addr - tx, err := MakeAssetFreezeTxn(addr, 10, firstValidRound, lastValidRound, nil, "", genesisHash, assetIndex, target, freezeSetting) + params := types.SuggestedParams{ + Fee: 10, + FirstRoundValid: firstValidRound, + LastRoundValid: lastValidRound, + GenesisHash: ghAsArray[:], + } + tx, err := MakeAssetFreezeTxn(addr, nil, params, assetIndex, target, freezeSetting) require.NoError(t, err) a, err := types.DecodeAddress(addr) @@ -374,6 +513,7 @@ func TestMakeAssetFreezeTxn(t *testing.T) { private, err := mnemonic.ToPrivateKey(addrSK) require.NoError(t, err) _, newStxBytes, err := crypto.SignTransaction(private, tx) + require.NoError(t, err) signedGolden := "gqNzaWfEQAhru5V2Xvr19s4pGnI0aslqwY4lA2skzpYtDTAN9DKSH5+qsfQQhm4oq+9VHVj7e1rQC49S28vQZmzDTVnYDQGjdHhuiaRhZnJ6w6RmYWRkxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aRmYWlkAaNmZWXNCRqiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv+KNzbmTEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pHR5cGWkYWZyeg==" require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) } @@ -385,14 +525,19 @@ func TestMakeAssetTransferTxn(t *testing.T) { const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" + ghAsArray := byte32ArrayFromBase64(genesisHash) const sender, recipient, closeAssetsTo = addr, addr, addr const assetIndex = 1 const firstValidRound = 322575 const lastValidRound = 323576 const amountToSend = 1 - - tx, err := MakeAssetTransferTxn(sender, recipient, closeAssetsTo, amountToSend, 10, firstValidRound, - lastValidRound, nil, "", genesisHash, assetIndex) + params := types.SuggestedParams{ + Fee: 10, + FirstRoundValid: firstValidRound, + LastRoundValid: lastValidRound, + GenesisHash: ghAsArray[:], + } + tx, err := MakeAssetTransferTxn(sender, recipient, amountToSend, nil, params, closeAssetsTo, assetIndex) require.NoError(t, err) sendAddr, err := types.DecodeAddress(sender) @@ -435,12 +580,17 @@ func TestMakeAssetTransferTxn(t *testing.T) { func TestMakeAssetAcceptanceTxn(t *testing.T) { const sender = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" + ghAsArray := byte32ArrayFromBase64(genesisHash) const assetIndex = 1 const firstValidRound = 322575 const lastValidRound = 323575 - - tx, err := MakeAssetAcceptanceTxn(sender, 10, firstValidRound, - lastValidRound, nil, "", genesisHash, assetIndex) + params := types.SuggestedParams{ + Fee: 10, + FirstRoundValid: firstValidRound, + LastRoundValid: lastValidRound, + GenesisHash: ghAsArray[:], + } + tx, err := MakeAssetAcceptanceTxn(sender, nil, params, assetIndex) require.NoError(t, err) sendAddr, err := types.DecodeAddress(sender) @@ -469,6 +619,7 @@ func TestMakeAssetAcceptanceTxn(t *testing.T) { private, err := mnemonic.ToPrivateKey(addrSK) require.NoError(t, err) _, newStxBytes, err := crypto.SignTransaction(private, tx) + require.NoError(t, err) signedGolden := "gqNzaWfEQJ7q2rOT8Sb/wB0F87ld+1zMprxVlYqbUbe+oz0WM63FctIi+K9eYFSqT26XBZ4Rr3+VTJpBE+JLKs8nctl9hgijdHhuiKRhcmN2xCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aNmZWXNCOiiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv96NzbmTEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pHR5cGWlYXhmZXKkeGFpZAE=" require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) } @@ -476,14 +627,20 @@ func TestMakeAssetAcceptanceTxn(t *testing.T) { func TestMakeAssetRevocationTransaction(t *testing.T) { const addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4" const genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" + ghAsArray := byte32ArrayFromBase64(genesisHash) const revoker, recipient, revoked = addr, addr, addr const assetIndex = 1 const firstValidRound = 322575 const lastValidRound = 323575 const amountToSend = 1 - tx, err := MakeAssetRevocationTxn(revoker, revoked, recipient, amountToSend, 10, firstValidRound, - lastValidRound, nil, "", genesisHash, assetIndex) + params := types.SuggestedParams{ + Fee: 10, + FirstRoundValid: firstValidRound, + LastRoundValid: lastValidRound, + GenesisHash: ghAsArray[:], + } + tx, err := MakeAssetRevocationTxn(revoker, revoked, amountToSend, recipient, nil, params, assetIndex) require.NoError(t, err) sendAddr, err := types.DecodeAddress(revoker) @@ -520,10 +677,107 @@ func TestMakeAssetRevocationTransaction(t *testing.T) { private, err := mnemonic.ToPrivateKey(addrSK) require.NoError(t, err) _, newStxBytes, err := crypto.SignTransaction(private, tx) + require.NoError(t, err) signedGolden := "gqNzaWfEQHsgfEAmEHUxLLLR9s+Y/yq5WeoGo/jAArCbany+7ZYwExMySzAhmV7M7S8+LBtJalB4EhzEUMKmt3kNKk6+vAWjdHhuiqRhYW10AaRhcmN2xCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aRhc25kxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aNmZWXNCqqiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv96NzbmTEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pHR5cGWlYXhmZXKkeGFpZAE=" require.EqualValues(t, newStxBytes, byteFromBase64(signedGolden)) } +func TestMakeApplicationCallTx(t *testing.T) { + const fee = 1000 + const firstRound = 2063137 + const genesisID = "devnet-v1.0" + genesisHash := byteFromBase64("sC3P7e2SdbqKJK0tbiCdK9tdSpbe6XeCGKdoNzmlj0E=") + + params := types.SuggestedParams{ + Fee: fee, + FirstRoundValid: firstRound, + LastRoundValid: firstRound + 1000, + GenesisHash: genesisHash, + GenesisID: genesisID, + FlatFee: true, + } + note := byteFromBase64("8xMCTuLQ810=") + program := []byte{1, 32, 1, 1, 34} + args := make([][]byte, 2) + args[0] = []byte("123") + args[1] = []byte("456") + foreignApps := make([]uint64, 1) + foreignApps[0] = 10 + foreignAssets := foreignApps + gSchema := types.StateSchema{NumUint: uint64(1), NumByteSlice: uint64(1)} + lSchema := types.StateSchema{NumUint: uint64(1), NumByteSlice: uint64(1)} + extraPages := uint32(2) + addr := make([]string, 1) + addr[0] = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU" + boxReferences := make([]types.AppBoxReference, 3) + boxReferences[0] = types.AppBoxReference{AppID: 2, Name: []byte("box_name")} + boxReferences[1] = types.AppBoxReference{AppID: 10, Name: []byte("box_name")} + boxReferences[2] = types.AppBoxReference{AppID: 10, Name: []byte("box_name2")} + + tx, err := MakeApplicationCallTxWithBoxes(2, args, addr, foreignApps, foreignAssets, boxReferences, types.NoOpOC, program, program, gSchema, lSchema, extraPages, params, types.Address{}, note, types.Digest{}, [32]byte{}, types.Address{}) + require.NoError(t, err) + require.EqualValues(t, 2, tx.ExtraProgramPages) + + // verify that the correct app index was calculated + require.EqualValues(t, 0, tx.BoxReferences[0].ForeignAppIdx) + require.EqualValues(t, 1, tx.BoxReferences[1].ForeignAppIdx) + require.EqualValues(t, 1, tx.BoxReferences[2].ForeignAppIdx) + + // the current app can also be referenced with AppID = 0 + boxReferences[0].AppID = 0 + tx, err = MakeApplicationCallTxWithBoxes(2, args, addr, foreignApps, foreignAssets, boxReferences, types.NoOpOC, program, program, gSchema, lSchema, extraPages, params, types.Address{}, note, types.Digest{}, [32]byte{}, types.Address{}) + require.NoError(t, err) + require.EqualValues(t, 0, tx.BoxReferences[0].ForeignAppIdx) + require.EqualValues(t, 1, tx.BoxReferences[1].ForeignAppIdx) + require.EqualValues(t, 1, tx.BoxReferences[2].ForeignAppIdx) + + // if the current app's ID is provided explicitly AND is present in the foreignApps array + // then the index in the array should be returned rather than the usual value of 0 + boxReferences[0].AppID = 2 + foreignApps = append(foreignApps, 2) + tx, err = MakeApplicationCallTxWithBoxes(2, args, addr, foreignApps, foreignAssets, boxReferences, types.NoOpOC, program, program, gSchema, lSchema, extraPages, params, types.Address{}, note, types.Digest{}, [32]byte{}, types.Address{}) + require.NoError(t, err) + require.EqualValues(t, 2, tx.BoxReferences[0].ForeignAppIdx) + require.EqualValues(t, 1, tx.BoxReferences[1].ForeignAppIdx) + require.EqualValues(t, 1, tx.BoxReferences[2].ForeignAppIdx) +} + +func TestMakeApplicationCallTxInvalidBoxes(t *testing.T) { + const fee = 1000 + const firstRound = 2063137 + const genesisID = "devnet-v1.0" + genesisHash := byteFromBase64("sC3P7e2SdbqKJK0tbiCdK9tdSpbe6XeCGKdoNzmlj0E=") + + params := types.SuggestedParams{ + Fee: fee, + FirstRoundValid: firstRound, + LastRoundValid: firstRound + 1000, + GenesisHash: genesisHash, + GenesisID: genesisID, + FlatFee: true, + } + note := byteFromBase64("8xMCTuLQ810=") + program := []byte{1, 32, 1, 1, 34} + args := make([][]byte, 2) + args[0] = []byte("123") + args[1] = []byte("456") + foreignApps := make([]uint64, 1) + foreignApps[0] = 10 + foreignAssets := foreignApps + gSchema := types.StateSchema{NumUint: uint64(1), NumByteSlice: uint64(1)} + lSchema := types.StateSchema{NumUint: uint64(1), NumByteSlice: uint64(1)} + extraPages := uint32(2) + addr := make([]string, 1) + addr[0] = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU" + boxReferences := make([]types.AppBoxReference, 3) + boxReferences[0] = types.AppBoxReference{AppID: 2, Name: []byte("box_name")} + boxReferences[1] = types.AppBoxReference{AppID: 10, Name: []byte("box_name")} + boxReferences[2] = types.AppBoxReference{AppID: 11, Name: []byte("box_name")} + + _, err := MakeApplicationCallTxWithBoxes(2, args, addr, foreignApps, foreignAssets, boxReferences, types.NoOpOC, program, program, gSchema, lSchema, extraPages, params, types.Address{}, note, types.Digest{}, [32]byte{}, types.Address{}) + require.Error(t, err, "the app id 10 provided for this box is not in the foreignApps array") +} + func TestComputeGroupID(t *testing.T) { // compare regular transactions created in SDK with 'goal clerk send' result // compare transaction group created in SDK with 'goal clerk group' result @@ -535,19 +789,29 @@ func TestComputeGroupID(t *testing.T) { genesisHash := byteFromBase64("sC3P7e2SdbqKJK0tbiCdK9tdSpbe6XeCGKdoNzmlj0E=") const firstRound1 = 710399 + params1 := types.SuggestedParams{ + Fee: fee, + FirstRoundValid: firstRound1, + LastRoundValid: firstRound1 + 1000, + GenesisHash: genesisHash, + GenesisID: genesisID, + FlatFee: true, + } note1 := byteFromBase64("wRKw5cJ0CMo=") - tx1, err := MakePaymentTxnWithFlatFee( - fromAddress, toAddress, fee, amount, firstRound1, firstRound1+1000, - note1, "", genesisID, genesisHash, - ) + tx1, err := MakePaymentTxn(fromAddress, toAddress, amount, note1, "", params1) require.NoError(t, err) const firstRound2 = 710515 + params2 := types.SuggestedParams{ + Fee: fee, + FirstRoundValid: firstRound2, + LastRoundValid: firstRound2 + 1000, + GenesisHash: genesisHash, + GenesisID: genesisID, + FlatFee: true, + } note2 := byteFromBase64("dBlHI6BdrIg=") - tx2, err := MakePaymentTxnWithFlatFee( - fromAddress, toAddress, fee, amount, firstRound2, firstRound2+1000, - note2, "", genesisID, genesisHash, - ) + tx2, err := MakePaymentTxn(fromAddress, toAddress, amount, note2, "", params2) require.NoError(t, err) const goldenTx1 = "gaN0eG6Ko2FtdM0H0KNmZWXNA+iiZnbOAArW/6NnZW6rZGV2bmV0LXYxLjCiZ2jEILAtz+3tknW6iiStLW4gnSvbXUqW3ul3ghinaDc5pY9Bomx2zgAK2uekbm90ZcQIwRKw5cJ0CMqjcmN2xCCj8AKs8kPYlx63ppj1w5410qkMRGZ9FYofNYPXxGpNLKNzbmTEIKPwAqzyQ9iXHremmPXDnjXSqQxEZn0Vih81g9fEak0spHR5cGWjcGF5" @@ -560,6 +824,7 @@ func TestComputeGroupID(t *testing.T) { require.Equal(t, byteFromBase64(goldenTx2), msgpack.Encode(stx2)) gid, err := crypto.ComputeGroupID([]types.Transaction{tx1, tx2}) + require.NoError(t, err) // goal clerk group sets Group to every transaction and concatenate them in output file // simulating that behavior here @@ -574,7 +839,7 @@ func TestComputeGroupID(t *testing.T) { require.Equal(t, byteFromBase64(goldenTxg), txg) - // check AssignGroupID, do not validate correctness of Group field calculation + // check transaction.AssignGroupID, do not validate correctness of Group field calculation result, err := AssignGroupID([]types.Transaction{tx1, tx2}, "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4") require.NoError(t, err) require.Equal(t, 0, len(result)) @@ -592,7 +857,6 @@ func TestLogicSig(t *testing.T) { // validate LogicSig signed transaction against goal const fromAddress = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU" const toAddress = "PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI" - const referenceTxID = "5FJDJD5LMZC3EHUYYJNH5I23U4X6H2KXABNDGPIL557ZMJ33GZHQ" const mn = "advice pudding treat near rule blouse same whisper inner electric quit surface sunny dismiss leader blood seat clown cost exist hospital century reform able sponsor" const fee = 1000 const amount = 2000 @@ -601,10 +865,15 @@ func TestLogicSig(t *testing.T) { genesisHash := byteFromBase64("sC3P7e2SdbqKJK0tbiCdK9tdSpbe6XeCGKdoNzmlj0E=") note := byteFromBase64("8xMCTuLQ810=") - tx, err := MakePaymentTxnWithFlatFee( - fromAddress, toAddress, fee, amount, firstRound, firstRound+1000, - note, "", genesisID, genesisHash, - ) + params := types.SuggestedParams{ + Fee: fee, + FirstRoundValid: firstRound, + LastRoundValid: firstRound + 1000, + GenesisHash: genesisHash, + GenesisID: genesisID, + FlatFee: true, + } + tx, err := MakePaymentTxn(fromAddress, toAddress, amount, note, "", params) require.NoError(t, err) // goal clerk send -o tx3 -a 2000 --fee 1000 -d ~/.algorand -w test -L sig.lsig --argb64 MTIz --argb64 NDU2 \ @@ -617,20 +886,172 @@ func TestLogicSig(t *testing.T) { args[0] = []byte("123") args[1] = []byte("456") key, err := mnemonic.ToPrivateKey(mn) - var pk crypto.MultisigAccount require.NoError(t, err) - lsig, err := crypto.MakeLogicSig(program, args, key, pk) + lsig, err := crypto.MakeLogicSigAccountDelegated(program, args, key) require.NoError(t, err) - _, stxBytes, err := crypto.SignLogicsigTransaction(lsig, tx) + _, stxBytes, err := crypto.SignLogicSigAccountTransaction(lsig, tx) require.NoError(t, err) require.Equal(t, byteFromBase64(golden), stxBytes) +} - sender, err := types.DecodeAddress(fromAddress) - require.NoError(t, err) +func TestFee(t *testing.T) { + testcases := []struct { + name string + flatFee bool + fee types.MicroAlgos + expected types.MicroAlgos + }{ + { + name: "Use flat fee", + flatFee: true, + fee: 1001, + expected: 1001, + }, + { + name: "Flat fee does not get overridden with min fee", + flatFee: true, + fee: 999, + expected: 999, + }, + { + name: "Estimated fee overridden with min fee", + flatFee: false, + fee: 1, + expected: 1000, + }, + { + name: "Flat fee set to 0", + flatFee: true, + fee: 0, + expected: 0, + }, + } + addr := types.Address{}.String() + for _, testcase := range testcases { + t.Run(testcase.name, func(t *testing.T) { + var tx types.Transaction + var err error + + params := types.SuggestedParams{ + FlatFee: testcase.flatFee, + Fee: testcase.fee, + FirstRoundValid: 1, + LastRoundValid: 1001, + GenesisHash: byteFromBase64("JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI="), + } + + tx, err = MakeAssetTransferTxn(addr, addr, 1, nil, params, "", 1) + require.NoError(t, err) + require.Equal(t, testcase.expected, tx.Fee) + + tx, err = MakeAssetAcceptanceTxn(addr, nil, params, 1) + require.NoError(t, err) + require.Equal(t, testcase.expected, tx.Fee) + + tx, err = MakeAssetRevocationTxn(addr, addr, 1, addr, nil, params, 1) + require.NoError(t, err) + require.Equal(t, testcase.expected, tx.Fee) + + tx, err = MakeAssetDestroyTxn(addr, nil, params, 1) + require.NoError(t, err) + require.Equal(t, testcase.expected, tx.Fee) + + tx, err = MakeAssetCreateTxn(addr, nil, params, 1, 1, false, addr, addr, addr, addr, "", "", "", "") + require.NoError(t, err) + require.Equal(t, testcase.expected, tx.Fee) + + tx, err = MakeAssetConfigTxn(addr, nil, params, 1, addr, addr, addr, addr, false) + require.NoError(t, err) + require.Equal(t, testcase.expected, tx.Fee) + + tx, err = MakeAssetFreezeTxn(addr, nil, params, 1, addr, true) + require.NoError(t, err) + require.Equal(t, testcase.expected, tx.Fee) + }) + } +} + +func TestParseBoxReferences(t *testing.T) { - verified := crypto.VerifyLogicSig(lsig, sender) - require.True(t, verified) + genWithAppId := func(appId uint64) types.AppBoxReference { + return types.AppBoxReference{appId, []byte("example")} + } + + genWithNewAppId := func() types.AppBoxReference { + return types.AppBoxReference{0, []byte("example")} + } + t.Run("appIndexExists", func(t *testing.T) { + appId := uint64(7) + abr := genWithAppId(appId) + + brs, err := parseBoxReferences( + []types.AppBoxReference{abr}, + []uint64{1, 3, 4, appId}, + appId-1) + require.NoError(t, err) + require.Equal(t, + []types.BoxReference{{ + ForeignAppIdx: uint64(4), + Name: abr.Name}}, + brs) + }) + + t.Run("appIndexDoesNotExist", func(t *testing.T) { + appId := uint64(7) + abr := genWithAppId(appId) + + _, err := parseBoxReferences( + []types.AppBoxReference{abr}, + []uint64{1, 3, 4}, + appId-1) + require.Error(t, err) + }) + + t.Run("newAppId", func(t *testing.T) { + abr := genWithNewAppId() + + brs, err := parseBoxReferences( + []types.AppBoxReference{abr}, + []uint64{}, + uint64(1)) + require.NoError(t, err) + require.Equal(t, + []types.BoxReference{{ + ForeignAppIdx: uint64(0), + Name: abr.Name}}, + brs) + }) + + t.Run("fallbackToCurrentApp", func(t *testing.T) { + // Mirrors priority search in goal from `cmd/goal/application.go::translateBoxRefs`. + appId := uint64(7) + abr := genWithAppId(appId) + + // Prefer foreign apps index when present. + brs, err := parseBoxReferences( + []types.AppBoxReference{abr}, + []uint64{1, 3, 4, appId}, + appId) + require.NoError(t, err) + require.Equal(t, + []types.BoxReference{{ + ForeignAppIdx: uint64(4), + Name: abr.Name}}, + brs) + + // Fallback to current app when absent from foreign apps. + brs, err = parseBoxReferences( + []types.AppBoxReference{abr}, + []uint64{1, 3, 4}, + appId) + require.NoError(t, err) + require.Equal(t, + []types.BoxReference{{ + ForeignAppIdx: uint64(0), + Name: abr.Name}}, + brs) + }) } diff --git a/future/waitForConfirmation.go b/transaction/waitForConfirmation.go similarity index 98% rename from future/waitForConfirmation.go rename to transaction/waitForConfirmation.go index 31975125..3c7e7baf 100644 --- a/future/waitForConfirmation.go +++ b/transaction/waitForConfirmation.go @@ -1,4 +1,4 @@ -package future +package transaction import ( "context" From d80305ac6bdcbdff175c179753109569be7d87b9 Mon Sep 17 00:00:00 2001 From: Michael Diamant Date: Fri, 16 Dec 2022 15:10:39 -0500 Subject: [PATCH 5/8] Add LogicSig usage disclaimer (#457) --- types/signature.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/types/signature.go b/types/signature.go index c51cbe17..6af9f9a9 100644 --- a/types/signature.go +++ b/types/signature.go @@ -43,6 +43,8 @@ func (msig MultisigSig) Blank() bool { // LogicSig is signed by an account, allowing delegation of operations. // OR // LogicSig defines a contract account. +// +// LogicSig cannot sign transactions in all cases. Instead, use LogicSigAccount as a safe, general purpose signing mechanism. Since LogicSig does not track the provided signature's public key, LogicSig cannot sign transactions when delegated to a non-multisig account _and_ the sender is not the delegating account. type LogicSig struct { _struct struct{} `codec:",omitempty,omitemptyarray"` From 30dfc64efa0d5e113ae9ed78e87f926992749c27 Mon Sep 17 00:00:00 2001 From: Michael Diamant Date: Fri, 16 Dec 2022 17:26:23 -0500 Subject: [PATCH 6/8] v2: Restore MakeLogicSigAccountEscrowChecked (#458) --- crypto/account.go | 4 ++-- crypto/account_test.go | 4 ++-- crypto/crypto_test.go | 2 +- test/steps_test.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crypto/account.go b/crypto/account.go index bc849eb3..dc8ccf9b 100644 --- a/crypto/account.go +++ b/crypto/account.go @@ -187,9 +187,9 @@ type LogicSigAccount struct { SigningKey ed25519.PublicKey `codec:"sigkey"` } -// MakeLogicSigAccountEscrow creates a new escrow LogicSigAccount. +// MakeLogicSigAccountEscrowChecked creates a new escrow LogicSigAccount. // The address of this account will be a hash of its program. -func MakeLogicSigAccountEscrow(program []byte, args [][]byte) (LogicSigAccount, error) { +func MakeLogicSigAccountEscrowChecked(program []byte, args [][]byte) (LogicSigAccount, error) { lsig, err := makeLogicSig(program, args, nil, MultisigAccount{}) if err != nil { return LogicSigAccount{}, err diff --git a/crypto/account_test.go b/crypto/account_test.go index 907a59bf..7e4fdf20 100644 --- a/crypto/account_test.go +++ b/crypto/account_test.go @@ -167,7 +167,7 @@ func TestMakeLogicSigAccount(t *testing.T) { } t.Run("Escrow", func(t *testing.T) { - lsigAccount, err := MakeLogicSigAccountEscrow(program, args) + lsigAccount, err := MakeLogicSigAccountEscrowChecked(program, args) require.NoError(t, err) require.Equal(t, program, lsigAccount.Lsig.Logic) @@ -351,7 +351,7 @@ func TestLogicSigAccount_Address(t *testing.T) { } t.Run("no sig", func(t *testing.T) { - lsigAccount, err := MakeLogicSigAccountEscrow(program, args) + lsigAccount, err := MakeLogicSigAccountEscrowChecked(program, args) require.NoError(t, err) expectedAddr, err := types.DecodeAddress("6Z3C3LDVWGMX23BMSYMANACQOSINPFIRF77H7N3AWJZYV6OH6GWTJKVMXY") diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index f9c2a20b..014e09b2 100644 --- a/crypto/crypto_test.go +++ b/crypto/crypto_test.go @@ -618,7 +618,7 @@ func TestSignLogicSigAccountTransaction(t *testing.T) { } t.Run("no sig", func(t *testing.T) { - lsigAccount, err := MakeLogicSigAccountEscrow(program, args) + lsigAccount, err := MakeLogicSigAccountEscrowChecked(program, args) require.NoError(t, err) programAddr, err := types.DecodeAddress("6Z3C3LDVWGMX23BMSYMANACQOSINPFIRF77H7N3AWJZYV6OH6GWTJKVMXY") diff --git a/test/steps_test.go b/test/steps_test.go index 9a5125f5..d1254ef1 100644 --- a/test/steps_test.go +++ b/test/steps_test.go @@ -2543,7 +2543,7 @@ func takeB64encodedBytes(b64encodedBytes string) error { } func heuristicCheckOverBytes() error { - _, sanityCheckError = crypto.MakeLogicSigAccountEscrow(seeminglyProgram, nil) + _, sanityCheckError = crypto.MakeLogicSigAccountEscrowChecked(seeminglyProgram, nil) return nil } From 7590afc86aa7be7e381ae5e6c86dfacc3b44b290 Mon Sep 17 00:00:00 2001 From: Michael Diamant Date: Mon, 19 Dec 2022 09:41:57 -0500 Subject: [PATCH 7/8] v2: Prepare module for v2 release (#456) --- auction/auction.go | 2 +- client/kmd/common.go | 2 +- client/kmd/kmd.go | 2 +- client/kmd/requests.go | 2 +- client/kmd/responses.go | 2 +- client/kmd/wrappers.go | 4 +-- .../v2/algod/accountApplicationInformation.go | 4 +-- client/v2/algod/accountAssetInformation.go | 4 +-- client/v2/algod/accountInformation.go | 4 +-- client/v2/algod/algod.go | 4 +-- client/v2/algod/blockRaw.go | 2 +- client/v2/algod/dryrun.go | 4 +-- client/v2/algod/getApplicationBoxByName.go | 4 +-- client/v2/algod/getApplicationBoxes.go | 4 +-- client/v2/algod/getApplicationByID.go | 4 +-- client/v2/algod/getAssetByID.go | 4 +-- client/v2/algod/getBlock.go | 6 ++--- client/v2/algod/getBlockHash.go | 4 +-- client/v2/algod/getGenesis.go | 2 +- client/v2/algod/getLedgerStateDelta.go | 4 +-- client/v2/algod/getLightBlockHeaderProof.go | 4 +-- client/v2/algod/getPendingTransactions.go | 6 ++--- .../algod/getPendingTransactionsByAddress.go | 6 ++--- client/v2/algod/getStateProof.go | 4 +-- client/v2/algod/getStatus.go | 4 +-- client/v2/algod/getSupply.go | 4 +-- client/v2/algod/getSyncRound.go | 4 +-- client/v2/algod/getTransactionProof.go | 4 +-- client/v2/algod/getVersion.go | 4 +-- client/v2/algod/healthCheck.go | 2 +- .../v2/algod/pendingTransactionInformation.go | 6 ++--- client/v2/algod/rawTransaction.go | 4 +-- client/v2/algod/setSyncRound.go | 2 +- client/v2/algod/tealCompile.go | 4 +-- client/v2/algod/tealDisassemble.go | 4 +-- client/v2/algod/tealDryrun.go | 6 ++--- client/v2/algod/transactionParams.go | 6 ++--- client/v2/algod/unsetSyncRound.go | 2 +- client/v2/algod/waitForBlock.go | 4 +-- client/v2/common/common.go | 4 +-- client/v2/common/models/block_response.go | 2 +- client/v2/common/models/dryrun_request.go | 2 +- .../models/pending_transaction_response.go | 2 +- .../models/pending_transactions_response.go | 2 +- client/v2/indexer/indexer.go | 2 +- .../v2/indexer/lookupAccountAppLocalStates.go | 4 +-- client/v2/indexer/lookupAccountAssets.go | 4 +-- client/v2/indexer/lookupAccountByID.go | 4 +-- .../lookupAccountCreatedApplications.go | 4 +-- .../v2/indexer/lookupAccountCreatedAssets.go | 4 +-- .../v2/indexer/lookupAccountTransactions.go | 4 +-- .../lookupApplicationBoxByIDandName.go | 4 +-- client/v2/indexer/lookupApplicationByID.go | 4 +-- .../v2/indexer/lookupApplicationLogsByID.go | 4 +-- client/v2/indexer/lookupAssetBalances.go | 4 +-- client/v2/indexer/lookupAssetByID.go | 4 +-- client/v2/indexer/lookupAssetTransactions.go | 4 +-- client/v2/indexer/lookupBlock.go | 4 +-- client/v2/indexer/lookupTransaction.go | 4 +-- client/v2/indexer/makeHealthCheck.go | 4 +-- client/v2/indexer/searchForAccounts.go | 4 +-- .../v2/indexer/searchForApplicationBoxes.go | 4 +-- client/v2/indexer/searchForApplications.go | 4 +-- client/v2/indexer/searchForAssets.go | 4 +-- client/v2/indexer/searchForTransactions.go | 4 +-- crypto/account.go | 2 +- crypto/account_test.go | 4 +-- crypto/crypto.go | 4 +-- crypto/crypto_test.go | 6 ++--- examples/gen-addresses/main.go | 10 +++---- go.mod | 3 +-- go.sum | 1 - mnemonic/helpers.go | 2 +- mnemonic/mnemonic_test.go | 4 +-- test/algodclientv2_test.go | 6 ++--- test/applications_integration_test.go | 16 ++++++------ test/applications_unit_test.go | 6 ++--- test/indexer_unit_test.go | 2 +- test/responses_unit_test.go | 10 +++---- test/steps_test.go | 26 +++++++++---------- test/transactions_test.go | 8 +++--- test/utilities.go | 4 +-- transaction/atomicTransactionComposer.go | 10 +++---- transaction/atomicTransactionComposer_test.go | 6 ++--- transaction/dryrun.go | 8 +++--- transaction/transaction.go | 6 ++--- transaction/transactionSigner.go | 4 +-- transaction/transactionSigner_test.go | 6 ++--- transaction/transaction_test.go | 8 +++--- transaction/waitForConfirmation.go | 6 ++--- types/basics.go | 2 +- types/basics_test.go | 2 +- 92 files changed, 206 insertions(+), 208 deletions(-) diff --git a/auction/auction.go b/auction/auction.go index 0ea6b620..3d220f8d 100644 --- a/auction/auction.go +++ b/auction/auction.go @@ -1,7 +1,7 @@ package auction import ( - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/types" ) // MakeBid constructs a bid using the passed parameters. `bidderAddress` and diff --git a/client/kmd/common.go b/client/kmd/common.go index 7db18c90..b4c251fc 100644 --- a/client/kmd/common.go +++ b/client/kmd/common.go @@ -1,7 +1,7 @@ package kmd import ( - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/types" ) // APIV1Wallet is the API's representation of a wallet diff --git a/client/kmd/kmd.go b/client/kmd/kmd.go index cb34c394..48cc8c5d 100644 --- a/client/kmd/kmd.go +++ b/client/kmd/kmd.go @@ -6,7 +6,7 @@ import ( "net/http" "time" - "github.com/algorand/go-algorand-sdk/encoding/json" + "github.com/algorand/go-algorand-sdk/v2/encoding/json" ) const ( diff --git a/client/kmd/requests.go b/client/kmd/requests.go index 8e570032..94eeedcf 100644 --- a/client/kmd/requests.go +++ b/client/kmd/requests.go @@ -3,7 +3,7 @@ package kmd import ( "golang.org/x/crypto/ed25519" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/types" ) // DefaultWalletDriver is the wallet backend that kmd will use by default diff --git a/client/kmd/responses.go b/client/kmd/responses.go index ee4fc9de..d6ad03f6 100644 --- a/client/kmd/responses.go +++ b/client/kmd/responses.go @@ -5,7 +5,7 @@ import ( "golang.org/x/crypto/ed25519" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/types" ) // APIV1Response is the interface that all API V1 responses must satisfy diff --git a/client/kmd/wrappers.go b/client/kmd/wrappers.go index cf8f1142..255fabaf 100644 --- a/client/kmd/wrappers.go +++ b/client/kmd/wrappers.go @@ -3,8 +3,8 @@ package kmd import ( "golang.org/x/crypto/ed25519" - "github.com/algorand/go-algorand-sdk/encoding/msgpack" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/encoding/msgpack" + "github.com/algorand/go-algorand-sdk/v2/types" ) // Version returns a VersionResponse containing a list of kmd API versions diff --git a/client/v2/algod/accountApplicationInformation.go b/client/v2/algod/accountApplicationInformation.go index ee2edf22..6988ee50 100644 --- a/client/v2/algod/accountApplicationInformation.go +++ b/client/v2/algod/accountApplicationInformation.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // AccountApplicationInformationParams contains all of the query parameters for url serialization. diff --git a/client/v2/algod/accountAssetInformation.go b/client/v2/algod/accountAssetInformation.go index 28298c9e..997c978b 100644 --- a/client/v2/algod/accountAssetInformation.go +++ b/client/v2/algod/accountAssetInformation.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // AccountAssetInformationParams contains all of the query parameters for url serialization. diff --git a/client/v2/algod/accountInformation.go b/client/v2/algod/accountInformation.go index 44ef753a..f601bb76 100644 --- a/client/v2/algod/accountInformation.go +++ b/client/v2/algod/accountInformation.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // AccountInformationParams contains all of the query parameters for url serialization. diff --git a/client/v2/algod/algod.go b/client/v2/algod/algod.go index d38b6315..73cb5f30 100644 --- a/client/v2/algod/algod.go +++ b/client/v2/algod/algod.go @@ -3,8 +3,8 @@ package algod import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) const authHeader = "X-Algo-API-Token" diff --git a/client/v2/algod/blockRaw.go b/client/v2/algod/blockRaw.go index 711f687d..3c1e8992 100644 --- a/client/v2/algod/blockRaw.go +++ b/client/v2/algod/blockRaw.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" ) // GetBlockParams defines parameters for GetBlock. diff --git a/client/v2/algod/dryrun.go b/client/v2/algod/dryrun.go index 89531e26..96c1807b 100644 --- a/client/v2/algod/dryrun.go +++ b/client/v2/algod/dryrun.go @@ -3,8 +3,8 @@ package algod import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // TealDryRun /v2/teal/dryrun diff --git a/client/v2/algod/getApplicationBoxByName.go b/client/v2/algod/getApplicationBoxByName.go index 0fc8f2af..1058fd40 100644 --- a/client/v2/algod/getApplicationBoxByName.go +++ b/client/v2/algod/getApplicationBoxByName.go @@ -5,8 +5,8 @@ import ( "encoding/base64" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // GetApplicationBoxByNameParams contains all of the query parameters for url serialization. diff --git a/client/v2/algod/getApplicationBoxes.go b/client/v2/algod/getApplicationBoxes.go index c5a49d8d..70b40f8b 100644 --- a/client/v2/algod/getApplicationBoxes.go +++ b/client/v2/algod/getApplicationBoxes.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // GetApplicationBoxesParams contains all of the query parameters for url serialization. diff --git a/client/v2/algod/getApplicationByID.go b/client/v2/algod/getApplicationByID.go index 351ff4c0..eb5798e9 100644 --- a/client/v2/algod/getApplicationByID.go +++ b/client/v2/algod/getApplicationByID.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // GetApplicationByID given a application ID, it returns application information diff --git a/client/v2/algod/getAssetByID.go b/client/v2/algod/getAssetByID.go index ae5643b6..ab1443d2 100644 --- a/client/v2/algod/getAssetByID.go +++ b/client/v2/algod/getAssetByID.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // GetAssetByID given a asset ID, it returns asset information including creator, diff --git a/client/v2/algod/getBlock.go b/client/v2/algod/getBlock.go index bcc63505..9ae92460 100644 --- a/client/v2/algod/getBlock.go +++ b/client/v2/algod/getBlock.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/types" ) // BlockParams contains all of the query parameters for url serialization. diff --git a/client/v2/algod/getBlockHash.go b/client/v2/algod/getBlockHash.go index cf034e30..7b9836c6 100644 --- a/client/v2/algod/getBlockHash.go +++ b/client/v2/algod/getBlockHash.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // GetBlockHash get the block hash for the block on the given round. diff --git a/client/v2/algod/getGenesis.go b/client/v2/algod/getGenesis.go index 9ee87127..0c75975f 100644 --- a/client/v2/algod/getGenesis.go +++ b/client/v2/algod/getGenesis.go @@ -3,7 +3,7 @@ package algod import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" ) // GetGenesis returns the entire genesis file in json. diff --git a/client/v2/algod/getLedgerStateDelta.go b/client/v2/algod/getLedgerStateDelta.go index eda780e0..f10040d6 100644 --- a/client/v2/algod/getLedgerStateDelta.go +++ b/client/v2/algod/getLedgerStateDelta.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // GetLedgerStateDelta get ledger deltas for a round. diff --git a/client/v2/algod/getLightBlockHeaderProof.go b/client/v2/algod/getLightBlockHeaderProof.go index 66888891..edbdff0e 100644 --- a/client/v2/algod/getLightBlockHeaderProof.go +++ b/client/v2/algod/getLightBlockHeaderProof.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // GetLightBlockHeaderProof gets a proof for a given light block header inside a diff --git a/client/v2/algod/getPendingTransactions.go b/client/v2/algod/getPendingTransactions.go index 509ecb31..12fb19e8 100644 --- a/client/v2/algod/getPendingTransactions.go +++ b/client/v2/algod/getPendingTransactions.go @@ -3,9 +3,9 @@ package algod import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/types" ) // PendingTransactionsParams contains all of the query parameters for url serialization. diff --git a/client/v2/algod/getPendingTransactionsByAddress.go b/client/v2/algod/getPendingTransactionsByAddress.go index d4765b3c..8f2f80e2 100644 --- a/client/v2/algod/getPendingTransactionsByAddress.go +++ b/client/v2/algod/getPendingTransactionsByAddress.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/types" ) // PendingTransactionsByAddressParams contains all of the query parameters for url serialization. diff --git a/client/v2/algod/getStateProof.go b/client/v2/algod/getStateProof.go index be65cd11..851b626a 100644 --- a/client/v2/algod/getStateProof.go +++ b/client/v2/algod/getStateProof.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // GetStateProof get a state proof that covers a given round diff --git a/client/v2/algod/getStatus.go b/client/v2/algod/getStatus.go index 7bbec8b5..2966eeef 100644 --- a/client/v2/algod/getStatus.go +++ b/client/v2/algod/getStatus.go @@ -3,8 +3,8 @@ package algod import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // Status gets the current node status. diff --git a/client/v2/algod/getSupply.go b/client/v2/algod/getSupply.go index 513e57d5..dac8aa32 100644 --- a/client/v2/algod/getSupply.go +++ b/client/v2/algod/getSupply.go @@ -3,8 +3,8 @@ package algod import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // Supply get the current supply reported by the ledger. diff --git a/client/v2/algod/getSyncRound.go b/client/v2/algod/getSyncRound.go index 37a15f20..c92f5b5f 100644 --- a/client/v2/algod/getSyncRound.go +++ b/client/v2/algod/getSyncRound.go @@ -3,8 +3,8 @@ package algod import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // GetSyncRound gets the minimum sync round for the ledger. diff --git a/client/v2/algod/getTransactionProof.go b/client/v2/algod/getTransactionProof.go index 2f62b5b1..d3a5fad5 100644 --- a/client/v2/algod/getTransactionProof.go +++ b/client/v2/algod/getTransactionProof.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // GetTransactionProofParams contains all of the query parameters for url serialization. diff --git a/client/v2/algod/getVersion.go b/client/v2/algod/getVersion.go index 31e5f893..ad4484fc 100644 --- a/client/v2/algod/getVersion.go +++ b/client/v2/algod/getVersion.go @@ -3,8 +3,8 @@ package algod import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // Versions retrieves the supported API versions, binary build versions, and diff --git a/client/v2/algod/healthCheck.go b/client/v2/algod/healthCheck.go index df0ba1d9..fbfe2a1f 100644 --- a/client/v2/algod/healthCheck.go +++ b/client/v2/algod/healthCheck.go @@ -3,7 +3,7 @@ package algod import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" ) // HealthCheck returns OK if healthy. diff --git a/client/v2/algod/pendingTransactionInformation.go b/client/v2/algod/pendingTransactionInformation.go index 3ccb2e4f..c6212e45 100644 --- a/client/v2/algod/pendingTransactionInformation.go +++ b/client/v2/algod/pendingTransactionInformation.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/types" ) // PendingTransactionInformationParams contains all of the query parameters for url serialization. diff --git a/client/v2/algod/rawTransaction.go b/client/v2/algod/rawTransaction.go index 6815604e..1c8ed7a4 100644 --- a/client/v2/algod/rawTransaction.go +++ b/client/v2/algod/rawTransaction.go @@ -4,8 +4,8 @@ import ( "context" "strings" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // SendRawTransaction broadcasts a raw transaction to the network. diff --git a/client/v2/algod/setSyncRound.go b/client/v2/algod/setSyncRound.go index 9292b7b2..8f5004a4 100644 --- a/client/v2/algod/setSyncRound.go +++ b/client/v2/algod/setSyncRound.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" ) // SetSyncRound sets the minimum sync round on the ledger. diff --git a/client/v2/algod/tealCompile.go b/client/v2/algod/tealCompile.go index c503ad7e..cb9b050d 100644 --- a/client/v2/algod/tealCompile.go +++ b/client/v2/algod/tealCompile.go @@ -3,8 +3,8 @@ package algod import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // TealCompileParams contains all of the query parameters for url serialization. diff --git a/client/v2/algod/tealDisassemble.go b/client/v2/algod/tealDisassemble.go index 6f2bf48b..2711b1dd 100644 --- a/client/v2/algod/tealDisassemble.go +++ b/client/v2/algod/tealDisassemble.go @@ -3,8 +3,8 @@ package algod import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // TealDisassemble given the program bytes, return the TEAL source code in plain diff --git a/client/v2/algod/tealDryrun.go b/client/v2/algod/tealDryrun.go index 2299b2cd..7e5538cd 100644 --- a/client/v2/algod/tealDryrun.go +++ b/client/v2/algod/tealDryrun.go @@ -3,9 +3,9 @@ package algod import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" - "github.com/algorand/go-algorand-sdk/encoding/msgpack" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/encoding/msgpack" ) // TealDryrun executes TEAL program(s) in context and returns debugging information diff --git a/client/v2/algod/transactionParams.go b/client/v2/algod/transactionParams.go index fe237662..7bf4403c 100644 --- a/client/v2/algod/transactionParams.go +++ b/client/v2/algod/transactionParams.go @@ -3,9 +3,9 @@ package algod import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/types" ) // SuggestedParams get parameters for constructing a new transaction diff --git a/client/v2/algod/unsetSyncRound.go b/client/v2/algod/unsetSyncRound.go index 601350c8..70973920 100644 --- a/client/v2/algod/unsetSyncRound.go +++ b/client/v2/algod/unsetSyncRound.go @@ -3,7 +3,7 @@ package algod import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" ) // UnsetSyncRound unset the ledger sync round. diff --git a/client/v2/algod/waitForBlock.go b/client/v2/algod/waitForBlock.go index 70ff9ebd..70435f39 100644 --- a/client/v2/algod/waitForBlock.go +++ b/client/v2/algod/waitForBlock.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // StatusAfterBlock waits for a block to appear after round {round} and returns the diff --git a/client/v2/common/common.go b/client/v2/common/common.go index 5108e567..0851848b 100644 --- a/client/v2/common/common.go +++ b/client/v2/common/common.go @@ -10,8 +10,8 @@ import ( "net/http" "net/url" - "github.com/algorand/go-algorand-sdk/encoding/json" - "github.com/algorand/go-algorand-sdk/encoding/msgpack" + "github.com/algorand/go-algorand-sdk/v2/encoding/json" + "github.com/algorand/go-algorand-sdk/v2/encoding/msgpack" "github.com/google/go-querystring/query" ) diff --git a/client/v2/common/models/block_response.go b/client/v2/common/models/block_response.go index b63fd2e4..8783c395 100644 --- a/client/v2/common/models/block_response.go +++ b/client/v2/common/models/block_response.go @@ -1,6 +1,6 @@ package models -import "github.com/algorand/go-algorand-sdk/types" +import "github.com/algorand/go-algorand-sdk/v2/types" // BlockResponse encoded block object. type BlockResponse struct { diff --git a/client/v2/common/models/dryrun_request.go b/client/v2/common/models/dryrun_request.go index c6c40d6c..f7c50a2b 100644 --- a/client/v2/common/models/dryrun_request.go +++ b/client/v2/common/models/dryrun_request.go @@ -1,6 +1,6 @@ package models -import "github.com/algorand/go-algorand-sdk/types" +import "github.com/algorand/go-algorand-sdk/v2/types" // DryrunRequest request data type for dryrun endpoint. Given the Transactions and // simulated ledger state upload, run TEAL scripts and return debugging diff --git a/client/v2/common/models/pending_transaction_response.go b/client/v2/common/models/pending_transaction_response.go index a3721584..e8dd79e7 100644 --- a/client/v2/common/models/pending_transaction_response.go +++ b/client/v2/common/models/pending_transaction_response.go @@ -1,6 +1,6 @@ package models -import "github.com/algorand/go-algorand-sdk/types" +import "github.com/algorand/go-algorand-sdk/v2/types" // PendingTransactionResponse details about a pending transaction. If the // transaction was recently confirmed, includes confirmation details like the round diff --git a/client/v2/common/models/pending_transactions_response.go b/client/v2/common/models/pending_transactions_response.go index b8a22bf7..951a6275 100644 --- a/client/v2/common/models/pending_transactions_response.go +++ b/client/v2/common/models/pending_transactions_response.go @@ -1,6 +1,6 @@ package models -import "github.com/algorand/go-algorand-sdk/types" +import "github.com/algorand/go-algorand-sdk/v2/types" // PendingTransactionsResponse a potentially truncated list of transactions // currently in the node's transaction pool. You can compute whether or not the diff --git a/client/v2/indexer/indexer.go b/client/v2/indexer/indexer.go index 6bfb86c8..a3d9f9fa 100644 --- a/client/v2/indexer/indexer.go +++ b/client/v2/indexer/indexer.go @@ -3,7 +3,7 @@ package indexer import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" ) const authHeader = "X-Indexer-API-Token" diff --git a/client/v2/indexer/lookupAccountAppLocalStates.go b/client/v2/indexer/lookupAccountAppLocalStates.go index 8dbfb403..2a5a0be0 100644 --- a/client/v2/indexer/lookupAccountAppLocalStates.go +++ b/client/v2/indexer/lookupAccountAppLocalStates.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // LookupAccountAppLocalStatesParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/lookupAccountAssets.go b/client/v2/indexer/lookupAccountAssets.go index 596181db..be011ef0 100644 --- a/client/v2/indexer/lookupAccountAssets.go +++ b/client/v2/indexer/lookupAccountAssets.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // LookupAccountAssetsParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/lookupAccountByID.go b/client/v2/indexer/lookupAccountByID.go index 930c5116..b29ca23f 100644 --- a/client/v2/indexer/lookupAccountByID.go +++ b/client/v2/indexer/lookupAccountByID.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // LookupAccountByIDParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/lookupAccountCreatedApplications.go b/client/v2/indexer/lookupAccountCreatedApplications.go index 4852d251..7b1dbe5d 100644 --- a/client/v2/indexer/lookupAccountCreatedApplications.go +++ b/client/v2/indexer/lookupAccountCreatedApplications.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // LookupAccountCreatedApplicationsParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/lookupAccountCreatedAssets.go b/client/v2/indexer/lookupAccountCreatedAssets.go index d28f384c..58fb1332 100644 --- a/client/v2/indexer/lookupAccountCreatedAssets.go +++ b/client/v2/indexer/lookupAccountCreatedAssets.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // LookupAccountCreatedAssetsParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/lookupAccountTransactions.go b/client/v2/indexer/lookupAccountTransactions.go index c7b6aa09..e1bb6fbf 100644 --- a/client/v2/indexer/lookupAccountTransactions.go +++ b/client/v2/indexer/lookupAccountTransactions.go @@ -6,8 +6,8 @@ import ( "fmt" "time" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // LookupAccountTransactionsParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/lookupApplicationBoxByIDandName.go b/client/v2/indexer/lookupApplicationBoxByIDandName.go index 344b3070..f1fada46 100644 --- a/client/v2/indexer/lookupApplicationBoxByIDandName.go +++ b/client/v2/indexer/lookupApplicationBoxByIDandName.go @@ -5,8 +5,8 @@ import ( "encoding/base64" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // LookupApplicationBoxByIDAndNameParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/lookupApplicationByID.go b/client/v2/indexer/lookupApplicationByID.go index 7e03f3f2..ab46d64c 100644 --- a/client/v2/indexer/lookupApplicationByID.go +++ b/client/v2/indexer/lookupApplicationByID.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // LookupApplicationByIDParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/lookupApplicationLogsByID.go b/client/v2/indexer/lookupApplicationLogsByID.go index ea416f46..be6be0f0 100644 --- a/client/v2/indexer/lookupApplicationLogsByID.go +++ b/client/v2/indexer/lookupApplicationLogsByID.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // LookupApplicationLogsByIDParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/lookupAssetBalances.go b/client/v2/indexer/lookupAssetBalances.go index 7e2e845a..33595ec3 100644 --- a/client/v2/indexer/lookupAssetBalances.go +++ b/client/v2/indexer/lookupAssetBalances.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // LookupAssetBalancesParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/lookupAssetByID.go b/client/v2/indexer/lookupAssetByID.go index d020277c..4ffbd674 100644 --- a/client/v2/indexer/lookupAssetByID.go +++ b/client/v2/indexer/lookupAssetByID.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // LookupAssetByIDParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/lookupAssetTransactions.go b/client/v2/indexer/lookupAssetTransactions.go index 6ded451c..5890dd49 100644 --- a/client/v2/indexer/lookupAssetTransactions.go +++ b/client/v2/indexer/lookupAssetTransactions.go @@ -6,8 +6,8 @@ import ( "fmt" "time" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // LookupAssetTransactionsParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/lookupBlock.go b/client/v2/indexer/lookupBlock.go index 6f2f931b..1f1881c0 100644 --- a/client/v2/indexer/lookupBlock.go +++ b/client/v2/indexer/lookupBlock.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // LookupBlockParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/lookupTransaction.go b/client/v2/indexer/lookupTransaction.go index 99c6e8da..af1f69c7 100644 --- a/client/v2/indexer/lookupTransaction.go +++ b/client/v2/indexer/lookupTransaction.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // LookupTransaction lookup a single transaction. diff --git a/client/v2/indexer/makeHealthCheck.go b/client/v2/indexer/makeHealthCheck.go index 03b2df73..2678fded 100644 --- a/client/v2/indexer/makeHealthCheck.go +++ b/client/v2/indexer/makeHealthCheck.go @@ -3,8 +3,8 @@ package indexer import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // HealthCheck returns 200 if healthy. diff --git a/client/v2/indexer/searchForAccounts.go b/client/v2/indexer/searchForAccounts.go index 8085430d..175600e4 100644 --- a/client/v2/indexer/searchForAccounts.go +++ b/client/v2/indexer/searchForAccounts.go @@ -3,8 +3,8 @@ package indexer import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // SearchAccountsParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/searchForApplicationBoxes.go b/client/v2/indexer/searchForApplicationBoxes.go index 4f05e68e..6b353f5e 100644 --- a/client/v2/indexer/searchForApplicationBoxes.go +++ b/client/v2/indexer/searchForApplicationBoxes.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // SearchForApplicationBoxesParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/searchForApplications.go b/client/v2/indexer/searchForApplications.go index dc29e96f..3cfe444d 100644 --- a/client/v2/indexer/searchForApplications.go +++ b/client/v2/indexer/searchForApplications.go @@ -3,8 +3,8 @@ package indexer import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // SearchForApplicationsParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/searchForAssets.go b/client/v2/indexer/searchForAssets.go index ea014aa5..0b8383f6 100644 --- a/client/v2/indexer/searchForAssets.go +++ b/client/v2/indexer/searchForAssets.go @@ -3,8 +3,8 @@ package indexer import ( "context" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // SearchForAssetsParams contains all of the query parameters for url serialization. diff --git a/client/v2/indexer/searchForTransactions.go b/client/v2/indexer/searchForTransactions.go index b57c0fa4..04a18556 100644 --- a/client/v2/indexer/searchForTransactions.go +++ b/client/v2/indexer/searchForTransactions.go @@ -5,8 +5,8 @@ import ( "encoding/base64" "time" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // SearchForTransactionsParams contains all of the query parameters for url serialization. diff --git a/crypto/account.go b/crypto/account.go index dc8ccf9b..82cc23ea 100644 --- a/crypto/account.go +++ b/crypto/account.go @@ -7,7 +7,7 @@ import ( "golang.org/x/crypto/ed25519" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/types" ) // prefix for multisig transaction signing diff --git a/crypto/account_test.go b/crypto/account_test.go index 7e4fdf20..2af5c840 100644 --- a/crypto/account_test.go +++ b/crypto/account_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/crypto/ed25519" - "github.com/algorand/go-algorand-sdk/mnemonic" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/mnemonic" + "github.com/algorand/go-algorand-sdk/v2/types" ) func TestGenerateAccount(t *testing.T) { diff --git a/crypto/crypto.go b/crypto/crypto.go index ee0ba4d0..3bf84658 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -12,8 +12,8 @@ import ( "golang.org/x/crypto/ed25519" - "github.com/algorand/go-algorand-sdk/encoding/msgpack" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/encoding/msgpack" + "github.com/algorand/go-algorand-sdk/v2/types" ) // txidPrefix is prepended to a transaction when computing its txid diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index 014e09b2..8102f275 100644 --- a/crypto/crypto_test.go +++ b/crypto/crypto_test.go @@ -9,9 +9,9 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/crypto/ed25519" - "github.com/algorand/go-algorand-sdk/encoding/msgpack" - "github.com/algorand/go-algorand-sdk/mnemonic" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/encoding/msgpack" + "github.com/algorand/go-algorand-sdk/v2/mnemonic" + "github.com/algorand/go-algorand-sdk/v2/types" ) func makeTestMultisigAccount(t *testing.T) (MultisigAccount, ed25519.PrivateKey, ed25519.PrivateKey, ed25519.PrivateKey) { diff --git a/examples/gen-addresses/main.go b/examples/gen-addresses/main.go index 99e4c1ee..90301ee6 100644 --- a/examples/gen-addresses/main.go +++ b/examples/gen-addresses/main.go @@ -4,13 +4,13 @@ import ( "bytes" "context" "fmt" - "github.com/algorand/go-algorand-sdk/transaction" + "github.com/algorand/go-algorand-sdk/v2/transaction" "strings" - "github.com/algorand/go-algorand-sdk/client/kmd" - "github.com/algorand/go-algorand-sdk/client/v2/algod" - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/client/kmd" + "github.com/algorand/go-algorand-sdk/v2/client/v2/algod" + "github.com/algorand/go-algorand-sdk/v2/crypto" + "github.com/algorand/go-algorand-sdk/v2/types" ) // CHANGE ME diff --git a/go.mod b/go.mod index 54db4f60..65a611ac 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/algorand/go-algorand-sdk +module github.com/algorand/go-algorand-sdk/v2 go 1.17 @@ -14,6 +14,5 @@ require ( require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) diff --git a/go.sum b/go.sum index fca639dc..0f3bc5b1 100644 --- a/go.sum +++ b/go.sum @@ -32,7 +32,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/mnemonic/helpers.go b/mnemonic/helpers.go index 6cd7bba2..d320c7e8 100644 --- a/mnemonic/helpers.go +++ b/mnemonic/helpers.go @@ -3,7 +3,7 @@ package mnemonic import ( "golang.org/x/crypto/ed25519" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/types" ) // FromPrivateKey is a helper that converts an ed25519 private key to a diff --git a/mnemonic/mnemonic_test.go b/mnemonic/mnemonic_test.go index 1160b01f..23e0c71e 100644 --- a/mnemonic/mnemonic_test.go +++ b/mnemonic/mnemonic_test.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/require" - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/crypto" + "github.com/algorand/go-algorand-sdk/v2/types" ) func TestGenerateAndRecovery(t *testing.T) { diff --git a/test/algodclientv2_test.go b/test/algodclientv2_test.go index f429c489..030f2ce5 100644 --- a/test/algodclientv2_test.go +++ b/test/algodclientv2_test.go @@ -6,9 +6,9 @@ import ( "encoding/base64" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/algod" - modelsV2 "github.com/algorand/go-algorand-sdk/client/v2/common/models" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/client/v2/algod" + modelsV2 "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/types" "github.com/cucumber/godog" ) diff --git a/test/applications_integration_test.go b/test/applications_integration_test.go index 98dcd443..df33926b 100644 --- a/test/applications_integration_test.go +++ b/test/applications_integration_test.go @@ -9,7 +9,7 @@ import ( "encoding/json" "errors" "fmt" - "github.com/algorand/go-algorand-sdk/transaction" + "github.com/algorand/go-algorand-sdk/v2/transaction" "reflect" "regexp" "sort" @@ -19,13 +19,13 @@ import ( "github.com/cucumber/godog" - "github.com/algorand/go-algorand-sdk/abi" - "github.com/algorand/go-algorand-sdk/client/v2/algod" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" - "github.com/algorand/go-algorand-sdk/client/v2/indexer" - "github.com/algorand/go-algorand-sdk/crypto" - sdkJson "github.com/algorand/go-algorand-sdk/encoding/json" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/abi" + "github.com/algorand/go-algorand-sdk/v2/client/v2/algod" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/indexer" + "github.com/algorand/go-algorand-sdk/v2/crypto" + sdkJson "github.com/algorand/go-algorand-sdk/v2/encoding/json" + "github.com/algorand/go-algorand-sdk/v2/types" ) var algodV2client *algod.Client diff --git a/test/applications_unit_test.go b/test/applications_unit_test.go index 060a5af2..6fd19d8c 100644 --- a/test/applications_unit_test.go +++ b/test/applications_unit_test.go @@ -6,9 +6,9 @@ import ( "github.com/cucumber/godog" - "github.com/algorand/go-algorand-sdk/client/v2/algod" - "github.com/algorand/go-algorand-sdk/client/v2/indexer" - "github.com/algorand/go-algorand-sdk/encoding/msgpack" + "github.com/algorand/go-algorand-sdk/v2/client/v2/algod" + "github.com/algorand/go-algorand-sdk/v2/client/v2/indexer" + "github.com/algorand/go-algorand-sdk/v2/encoding/msgpack" ) func feeFieldIsInTxn() error { diff --git a/test/indexer_unit_test.go b/test/indexer_unit_test.go index 74b9b7c8..4e9f915e 100644 --- a/test/indexer_unit_test.go +++ b/test/indexer_unit_test.go @@ -6,7 +6,7 @@ import ( "fmt" "strings" - "github.com/algorand/go-algorand-sdk/client/v2/indexer" + "github.com/algorand/go-algorand-sdk/v2/client/v2/indexer" "github.com/cucumber/godog" ) diff --git a/test/responses_unit_test.go b/test/responses_unit_test.go index 34cb0e13..c98c234b 100644 --- a/test/responses_unit_test.go +++ b/test/responses_unit_test.go @@ -8,11 +8,11 @@ import ( "github.com/cucumber/godog" - "github.com/algorand/go-algorand-sdk/client/v2/algod" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" - "github.com/algorand/go-algorand-sdk/client/v2/indexer" - "github.com/algorand/go-algorand-sdk/encoding/json" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/client/v2/algod" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/indexer" + "github.com/algorand/go-algorand-sdk/v2/encoding/json" + "github.com/algorand/go-algorand-sdk/v2/types" ) var algodC *algod.Client diff --git a/test/steps_test.go b/test/steps_test.go index d1254ef1..7945182a 100644 --- a/test/steps_test.go +++ b/test/steps_test.go @@ -10,7 +10,7 @@ import ( "encoding/json" "flag" "fmt" - "github.com/algorand/go-algorand-sdk/transaction" + "github.com/algorand/go-algorand-sdk/v2/transaction" "os" "path" "reflect" @@ -21,18 +21,18 @@ import ( "golang.org/x/crypto/ed25519" - "github.com/algorand/go-algorand-sdk/abi" - "github.com/algorand/go-algorand-sdk/auction" - "github.com/algorand/go-algorand-sdk/client/kmd" - algodV2 "github.com/algorand/go-algorand-sdk/client/v2/algod" - commonV2 "github.com/algorand/go-algorand-sdk/client/v2/common" - modelsV2 "github.com/algorand/go-algorand-sdk/client/v2/common/models" - indexerV2 "github.com/algorand/go-algorand-sdk/client/v2/indexer" - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/encoding/msgpack" - "github.com/algorand/go-algorand-sdk/logic" - "github.com/algorand/go-algorand-sdk/mnemonic" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/abi" + "github.com/algorand/go-algorand-sdk/v2/auction" + "github.com/algorand/go-algorand-sdk/v2/client/kmd" + algodV2 "github.com/algorand/go-algorand-sdk/v2/client/v2/algod" + commonV2 "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + modelsV2 "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" + indexerV2 "github.com/algorand/go-algorand-sdk/v2/client/v2/indexer" + "github.com/algorand/go-algorand-sdk/v2/crypto" + "github.com/algorand/go-algorand-sdk/v2/encoding/msgpack" + "github.com/algorand/go-algorand-sdk/v2/logic" + "github.com/algorand/go-algorand-sdk/v2/mnemonic" + "github.com/algorand/go-algorand-sdk/v2/types" "github.com/cucumber/godog" "github.com/cucumber/godog/colors" ) diff --git a/test/transactions_test.go b/test/transactions_test.go index e4c9af76..8d8925ce 100644 --- a/test/transactions_test.go +++ b/test/transactions_test.go @@ -4,13 +4,13 @@ import ( "bytes" "encoding/base64" "fmt" - "github.com/algorand/go-algorand-sdk/transaction" + "github.com/algorand/go-algorand-sdk/v2/transaction" "strconv" "strings" - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/mnemonic" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/crypto" + "github.com/algorand/go-algorand-sdk/v2/mnemonic" + "github.com/algorand/go-algorand-sdk/v2/types" "github.com/cucumber/godog" "golang.org/x/crypto/ed25519" diff --git a/test/utilities.go b/test/utilities.go index 2f647474..6f64822c 100644 --- a/test/utilities.go +++ b/test/utilities.go @@ -13,8 +13,8 @@ import ( "sort" "strings" - sdk_json "github.com/algorand/go-algorand-sdk/encoding/json" - "github.com/algorand/go-algorand-sdk/encoding/msgpack" + sdk_json "github.com/algorand/go-algorand-sdk/v2/encoding/json" + "github.com/algorand/go-algorand-sdk/v2/encoding/msgpack" ) func VerifyResponse(expectedFile string, actual string) error { diff --git a/transaction/atomicTransactionComposer.go b/transaction/atomicTransactionComposer.go index b50fc1c5..beab0a53 100644 --- a/transaction/atomicTransactionComposer.go +++ b/transaction/atomicTransactionComposer.go @@ -6,11 +6,11 @@ import ( "errors" "fmt" - "github.com/algorand/go-algorand-sdk/abi" - "github.com/algorand/go-algorand-sdk/client/v2/algod" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/abi" + "github.com/algorand/go-algorand-sdk/v2/client/v2/algod" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/crypto" + "github.com/algorand/go-algorand-sdk/v2/types" ) // abiReturnHash is the 4-byte prefix for logged return values, from https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0004.md#standard-format diff --git a/transaction/atomicTransactionComposer_test.go b/transaction/atomicTransactionComposer_test.go index faf9594f..6982a6e3 100644 --- a/transaction/atomicTransactionComposer_test.go +++ b/transaction/atomicTransactionComposer_test.go @@ -3,9 +3,9 @@ package transaction import ( "testing" - "github.com/algorand/go-algorand-sdk/abi" - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/abi" + "github.com/algorand/go-algorand-sdk/v2/crypto" + "github.com/algorand/go-algorand-sdk/v2/types" "github.com/stretchr/testify/require" ) diff --git a/transaction/dryrun.go b/transaction/dryrun.go index be084c31..606d6715 100644 --- a/transaction/dryrun.go +++ b/transaction/dryrun.go @@ -9,10 +9,10 @@ import ( "strings" "text/tabwriter" - "github.com/algorand/go-algorand-sdk/client/v2/algod" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/client/v2/algod" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/crypto" + "github.com/algorand/go-algorand-sdk/v2/types" ) const ( diff --git a/transaction/transaction.go b/transaction/transaction.go index ac922da5..fe437ce0 100644 --- a/transaction/transaction.go +++ b/transaction/transaction.go @@ -5,9 +5,9 @@ import ( "encoding/base64" "fmt" - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/encoding/msgpack" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/crypto" + "github.com/algorand/go-algorand-sdk/v2/encoding/msgpack" + "github.com/algorand/go-algorand-sdk/v2/types" ) // MinTxnFee is v5 consensus params, in microAlgos diff --git a/transaction/transactionSigner.go b/transaction/transactionSigner.go index d6a39a6b..62843a46 100644 --- a/transaction/transactionSigner.go +++ b/transaction/transactionSigner.go @@ -3,8 +3,8 @@ package transaction import ( "encoding/json" - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/crypto" + "github.com/algorand/go-algorand-sdk/v2/types" ) /** diff --git a/transaction/transactionSigner_test.go b/transaction/transactionSigner_test.go index 78a1b820..e1340b30 100644 --- a/transaction/transactionSigner_test.go +++ b/transaction/transactionSigner_test.go @@ -4,9 +4,9 @@ import ( "crypto/ed25519" "testing" - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/mnemonic" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/crypto" + "github.com/algorand/go-algorand-sdk/v2/mnemonic" + "github.com/algorand/go-algorand-sdk/v2/types" "github.com/stretchr/testify/require" ) diff --git a/transaction/transaction_test.go b/transaction/transaction_test.go index 5bdfe687..298d1a55 100644 --- a/transaction/transaction_test.go +++ b/transaction/transaction_test.go @@ -4,10 +4,10 @@ import ( "encoding/base64" "testing" - "github.com/algorand/go-algorand-sdk/crypto" - "github.com/algorand/go-algorand-sdk/encoding/msgpack" - "github.com/algorand/go-algorand-sdk/mnemonic" - "github.com/algorand/go-algorand-sdk/types" + "github.com/algorand/go-algorand-sdk/v2/crypto" + "github.com/algorand/go-algorand-sdk/v2/encoding/msgpack" + "github.com/algorand/go-algorand-sdk/v2/mnemonic" + "github.com/algorand/go-algorand-sdk/v2/types" "github.com/stretchr/testify/require" ) diff --git a/transaction/waitForConfirmation.go b/transaction/waitForConfirmation.go index 3c7e7baf..0150c769 100644 --- a/transaction/waitForConfirmation.go +++ b/transaction/waitForConfirmation.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "github.com/algorand/go-algorand-sdk/client/v2/algod" - "github.com/algorand/go-algorand-sdk/client/v2/common" - "github.com/algorand/go-algorand-sdk/client/v2/common/models" + "github.com/algorand/go-algorand-sdk/v2/client/v2/algod" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common" + "github.com/algorand/go-algorand-sdk/v2/client/v2/common/models" ) // `WaitForConfirmation` waits for a pending transaction to be accepted by the network diff --git a/types/basics.go b/types/basics.go index f5456e04..37ff4672 100644 --- a/types/basics.go +++ b/types/basics.go @@ -4,7 +4,7 @@ import ( "encoding/base64" "math" - "github.com/algorand/go-algorand-sdk/encoding/msgpack" + "github.com/algorand/go-algorand-sdk/v2/encoding/msgpack" "golang.org/x/crypto/ed25519" ) diff --git a/types/basics_test.go b/types/basics_test.go index 364e98b5..ad91de34 100644 --- a/types/basics_test.go +++ b/types/basics_test.go @@ -4,7 +4,7 @@ import ( "testing" "encoding/base64" - "github.com/algorand/go-algorand-sdk/encoding/msgpack" + "github.com/algorand/go-algorand-sdk/v2/encoding/msgpack" "github.com/stretchr/testify/require" ) From 112d3b03b95a4e0dc86e76df79eee776999bb1e7 Mon Sep 17 00:00:00 2001 From: Jack Smith Date: Tue, 3 Jan 2023 11:02:21 -0800 Subject: [PATCH 8/8] Updated CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc4d30c8..4bf232f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ * Remove v1 algod API (client/algod) due to API end-of-life (2022-12-01). Instead, use v2 algod API (client/v2/algod). * Remove unused generated types: `CatchpointAbortResponse`, `CatchpointStartResponse`. +**Full Changelog**: https://github.com/algorand/go-algorand-sdk/compare/v1.24.0...v2.0.0 + # 1.24.0 ## What's Changed ### Bugfixes