From 10f6e6b291cd35b0bb3018e02bf615d88f38f710 Mon Sep 17 00:00:00 2001 From: kanishka Date: Wed, 19 Apr 2023 20:51:11 +0530 Subject: [PATCH 01/65] add ParachainHostValidators to runtime --- dot/interfaces.go | 1 + dot/state/interfaces.go | 1 + dot/types/parachain.go | 39 ++++++++++++++++++++ lib/blocktree/interfaces.go | 1 + lib/runtime/constants.go | 2 ++ lib/runtime/wasmer/exports.go | 18 ++++++++++ lib/runtime/wasmer/exports_test.go | 58 ++++++++++++++++++++++++++++++ 7 files changed, 120 insertions(+) create mode 100644 dot/types/parachain.go diff --git a/dot/interfaces.go b/dot/interfaces.go index a9255d0d3c..0665a83182 100644 --- a/dot/interfaces.go +++ b/dot/interfaces.go @@ -75,4 +75,5 @@ type runtimeInterface interface { GrandpaSubmitReportEquivocationUnsignedExtrinsic( equivocationProof types.GrandpaEquivocationProof, keyOwnershipProof types.GrandpaOpaqueKeyOwnershipProof, ) error + ParachainHostValidators() ([]types.Validator, error) } diff --git a/dot/state/interfaces.go b/dot/state/interfaces.go index f12e2e24d3..2306b610b7 100644 --- a/dot/state/interfaces.go +++ b/dot/state/interfaces.go @@ -100,6 +100,7 @@ type Runtime interface { GrandpaSubmitReportEquivocationUnsignedExtrinsic( equivocationProof types.GrandpaEquivocationProof, keyOwnershipProof types.GrandpaOpaqueKeyOwnershipProof, ) error + ParachainHostValidators() ([]types.Validator, error) } // BabeConfigurer returns the babe configuration of the runtime. diff --git a/dot/types/parachain.go b/dot/types/parachain.go new file mode 100644 index 0000000000..274d047fe1 --- /dev/null +++ b/dot/types/parachain.go @@ -0,0 +1,39 @@ +package types + +import ( + "github.com/ChainSafe/gossamer/lib/crypto" + "github.com/ChainSafe/gossamer/lib/crypto/sr25519" +) + +// ValidatorID represents a validator ID +type ValidatorID [sr25519.PublicKeyLength]byte + +type Validator struct { + Key crypto.PublicKey +} + +// FromRawSr25519 sets the Validator given ValidatorID. It converts the byte representations of +// the authority public keys into a sr25519.PublicKey. +func (a *Validator) FromRawSr25519(id ValidatorID) error { + key, err := sr25519.NewPublicKey(id[:]) + if err != nil { + return err + } + + a.Key = key + return nil +} + +// ValidatorIDToValidator turns a slice of ValidatorID into a slice of Validator +func ValidatorIDToValidator(ids []ValidatorID) ([]Validator, error) { + validators := make([]Validator, len(ids)) + for i, r := range ids { + validators[i] = Validator{} + err := validators[i].FromRawSr25519(r) + if err != nil { + return nil, err + } + } + + return validators, nil +} diff --git a/lib/blocktree/interfaces.go b/lib/blocktree/interfaces.go index 3a4480e170..caf74708c1 100644 --- a/lib/blocktree/interfaces.go +++ b/lib/blocktree/interfaces.go @@ -46,4 +46,5 @@ type Runtime interface { GrandpaSubmitReportEquivocationUnsignedExtrinsic( equivocationProof types.GrandpaEquivocationProof, keyOwnershipProof types.GrandpaOpaqueKeyOwnershipProof, ) error + ParachainHostValidators() ([]types.Validator, error) } diff --git a/lib/runtime/constants.go b/lib/runtime/constants.go index c4ea384d3c..9800af5d21 100644 --- a/lib/runtime/constants.go +++ b/lib/runtime/constants.go @@ -61,4 +61,6 @@ const ( TransactionPaymentCallAPIQueryCallInfo = "TransactionPaymentCallApi_query_call_info" // TransactionPaymentCallAPIQueryCallFeeDetails returns call query call fee details TransactionPaymentCallAPIQueryCallFeeDetails = "TransactionPaymentCallApi_query_call_fee_details" + // ParachainHostValidators is the runtime API call ParachainHost_validators + ParachainHostValidators = "ParachainHost_validators" ) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index b7298cb574..573ca7a2e1 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -327,6 +327,24 @@ func (in *Instance) GrandpaSubmitReportEquivocationUnsignedExtrinsic( return nil } +// ParachainHostValidators Returns the validator set at the current state. +// The specified validators are responsible for backing parachains for the current state. +func (in *Instance) ParachainHostValidators() ([]types.Validator, error) { + ret, err := in.Exec(runtime.ParachainHostValidators, []byte{}) + if err != nil { + return nil, err + } + fmt.Println("ret", ret) + + var gar []types.ValidatorID + err = scale.Unmarshal(ret, &gar) + if err != nil { + return nil, err + } + + return types.ValidatorIDToValidator(gar) +} + func (in *Instance) RandomSeed() {} //nolint:revive func (in *Instance) OffchainWorker() {} //nolint:revive func (in *Instance) GenerateSessionKeys() {} //nolint:revive diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index ab4bda60b8..0639b1339f 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -15,6 +15,7 @@ import ( "github.com/ChainSafe/gossamer/internal/log" "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/crypto/ed25519" + "github.com/ChainSafe/gossamer/lib/crypto/sr25519" "github.com/ChainSafe/gossamer/lib/genesis" "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/lib/runtime/storage" @@ -1190,3 +1191,60 @@ func TestInstance_GrandpaSubmitReportEquivocationUnsignedExtrinsic(t *testing.T) err = runtime.GrandpaSubmitReportEquivocationUnsignedExtrinsic(equivocationProof, opaqueKeyOwnershipProof) require.NoError(t, err) } + +func TestInstance_ParachainHostValidators_NodeRuntime(t *testing.T) { + tt := trie.NewEmptyTrie() + + value, err := common.HexToBytes("0x0108eea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d714103640100000000000000b64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d7170100000000000000") //nolint:lll + require.NoError(t, err) + + key := common.MustHexToBytes(genesis.GrandpaAuthoritiesKeyHex) + tt.Put(key, value) + + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + + auths, err := rt.ParachainHostValidators() + require.NoError(t, err) + + authABytes, _ := common.HexToBytes("0xeea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d71410364") + authBBytes, _ := common.HexToBytes("0xb64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d717") + + authA, _ := sr25519.NewPublicKey(authABytes) + authB, _ := sr25519.NewPublicKey(authBBytes) + + expected := []types.Validator{ + {Key: authA}, + {Key: authB}, + } + + require.Equal(t, expected, auths) +} + +func TestInstance_ParachainHostValidators_PolkadotRuntime(t *testing.T) { + tt := trie.NewEmptyTrie() + + value, err := common.HexToBytes("0x0108eea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d714103640100000000000000b64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d7170100000000000000") //nolint:lll + require.NoError(t, err) + + key := common.MustHexToBytes(genesis.GrandpaAuthoritiesKeyHex) + tt.Put(key, value) + + rt := NewTestInstanceWithTrie(t, runtime.POLKADOT_RUNTIME_v0929, tt) + + auths, err := rt.ParachainHostValidators() + t.Logf("auths: %v", auths) + require.NoError(t, err) + + authABytes, _ := common.HexToBytes("0xeea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d71410364") + authBBytes, _ := common.HexToBytes("0xb64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d717") + + authA, _ := sr25519.NewPublicKey(authABytes) + authB, _ := sr25519.NewPublicKey(authBBytes) + + expected := []types.Validator{ + {Key: authA}, + {Key: authB}, + } + + require.Equal(t, expected, auths) +} From 0b78f375b298a54706524569c81188eda7c377de Mon Sep 17 00:00:00 2001 From: kanishka Date: Mon, 24 Apr 2023 12:12:51 +0530 Subject: [PATCH 02/65] add ParachainHostValidatorGroups to runtime --- dot/types/parachain.go | 21 +++++++++++ lib/runtime/constants.go | 2 ++ lib/runtime/wasmer/exports.go | 18 +++++++++- lib/runtime/wasmer/exports_test.go | 58 ------------------------------ 4 files changed, 40 insertions(+), 59 deletions(-) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 274d047fe1..b63de2aafd 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -8,6 +8,7 @@ import ( // ValidatorID represents a validator ID type ValidatorID [sr25519.PublicKeyLength]byte +// Validator represents a validator type Validator struct { Key crypto.PublicKey } @@ -37,3 +38,23 @@ func ValidatorIDToValidator(ids []ValidatorID) ([]Validator, error) { return validators, nil } + +// ValidatorIndex represents a validator index +type ValidatorIndex uint32 + +// GroupRotationInfo represents the group rotation info +type GroupRotationInfo struct { + // SessionStartBlock is the block number at which the session started + SessionStartBlock uint64 `scale:"1"` + // GroupRotationFrequency indicates how often groups rotate. 0 means never. + GroupRotationFrequency uint64 `scale:"2"` + // Now indicates the current block number. + Now uint64 `scale:"3"` +} + +type ValidatorGroups struct { + // Validators is an array the validator set Ids + Validators [][]ValidatorIndex `scale:"1"` + // GroupRotationInfo is the group rotation info + GroupRotationInfo GroupRotationInfo `scale:"2"` +} diff --git a/lib/runtime/constants.go b/lib/runtime/constants.go index 9800af5d21..47cd9fced4 100644 --- a/lib/runtime/constants.go +++ b/lib/runtime/constants.go @@ -63,4 +63,6 @@ const ( TransactionPaymentCallAPIQueryCallFeeDetails = "TransactionPaymentCallApi_query_call_fee_details" // ParachainHostValidators is the runtime API call ParachainHost_validators ParachainHostValidators = "ParachainHost_validators" + // ParachainHostValidatorGroups is the runtime API call ParachainHost_validator_groups + ParachainHostValidatorGroups = "ParachainHost_validator_groups" ) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 573ca7a2e1..d3afa7980d 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -334,7 +334,6 @@ func (in *Instance) ParachainHostValidators() ([]types.Validator, error) { if err != nil { return nil, err } - fmt.Println("ret", ret) var gar []types.ValidatorID err = scale.Unmarshal(ret, &gar) @@ -345,6 +344,23 @@ func (in *Instance) ParachainHostValidators() ([]types.Validator, error) { return types.ValidatorIDToValidator(gar) } +// ParachainHostValidatorGroups Returns the validator groups used during the current session. +// The validators in the groups are referred to by the validator set Id. +func (in *Instance) ParachainHostValidatorGroups() (*types.ValidatorGroups, error) { + ret, err := in.Exec(runtime.ParachainHostValidatorGroups, []byte{}) + if err != nil { + return nil, err + } + + var validatorGroups types.ValidatorGroups + err = scale.Unmarshal(ret, &validatorGroups) + if err != nil { + return nil, err + } + + return &validatorGroups, nil +} + func (in *Instance) RandomSeed() {} //nolint:revive func (in *Instance) OffchainWorker() {} //nolint:revive func (in *Instance) GenerateSessionKeys() {} //nolint:revive diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index 0639b1339f..ab4bda60b8 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -15,7 +15,6 @@ import ( "github.com/ChainSafe/gossamer/internal/log" "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/crypto/ed25519" - "github.com/ChainSafe/gossamer/lib/crypto/sr25519" "github.com/ChainSafe/gossamer/lib/genesis" "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/lib/runtime/storage" @@ -1191,60 +1190,3 @@ func TestInstance_GrandpaSubmitReportEquivocationUnsignedExtrinsic(t *testing.T) err = runtime.GrandpaSubmitReportEquivocationUnsignedExtrinsic(equivocationProof, opaqueKeyOwnershipProof) require.NoError(t, err) } - -func TestInstance_ParachainHostValidators_NodeRuntime(t *testing.T) { - tt := trie.NewEmptyTrie() - - value, err := common.HexToBytes("0x0108eea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d714103640100000000000000b64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d7170100000000000000") //nolint:lll - require.NoError(t, err) - - key := common.MustHexToBytes(genesis.GrandpaAuthoritiesKeyHex) - tt.Put(key, value) - - rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) - - auths, err := rt.ParachainHostValidators() - require.NoError(t, err) - - authABytes, _ := common.HexToBytes("0xeea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d71410364") - authBBytes, _ := common.HexToBytes("0xb64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d717") - - authA, _ := sr25519.NewPublicKey(authABytes) - authB, _ := sr25519.NewPublicKey(authBBytes) - - expected := []types.Validator{ - {Key: authA}, - {Key: authB}, - } - - require.Equal(t, expected, auths) -} - -func TestInstance_ParachainHostValidators_PolkadotRuntime(t *testing.T) { - tt := trie.NewEmptyTrie() - - value, err := common.HexToBytes("0x0108eea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d714103640100000000000000b64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d7170100000000000000") //nolint:lll - require.NoError(t, err) - - key := common.MustHexToBytes(genesis.GrandpaAuthoritiesKeyHex) - tt.Put(key, value) - - rt := NewTestInstanceWithTrie(t, runtime.POLKADOT_RUNTIME_v0929, tt) - - auths, err := rt.ParachainHostValidators() - t.Logf("auths: %v", auths) - require.NoError(t, err) - - authABytes, _ := common.HexToBytes("0xeea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d71410364") - authBBytes, _ := common.HexToBytes("0xb64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d717") - - authA, _ := sr25519.NewPublicKey(authABytes) - authB, _ := sr25519.NewPublicKey(authBBytes) - - expected := []types.Validator{ - {Key: authA}, - {Key: authB}, - } - - require.Equal(t, expected, auths) -} From f1a035d75cdd37d846bb58cab70b99dc6cffe1ac Mon Sep 17 00:00:00 2001 From: kanishka Date: Mon, 24 Apr 2023 13:56:42 +0530 Subject: [PATCH 03/65] add ParachainHostAvailabilityCores to runtime --- dot/types/parachain.go | 113 ++++++++++++++++++++++++++++++++++ lib/runtime/constants.go | 2 + lib/runtime/wasmer/exports.go | 20 ++++++ 3 files changed, 135 insertions(+) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index b63de2aafd..2277bc0568 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -1,8 +1,11 @@ package types import ( + "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/crypto" "github.com/ChainSafe/gossamer/lib/crypto/sr25519" + "github.com/ChainSafe/gossamer/pkg/scale" + "github.com/centrifuge/go-substrate-rpc-client/v4/types" ) // ValidatorID represents a validator ID @@ -58,3 +61,113 @@ type ValidatorGroups struct { // GroupRotationInfo is the group rotation info GroupRotationInfo GroupRotationInfo `scale:"2"` } + +// + +// ParaID The ID of a para scheduled. +type ParaID uint32 + +// GroupIndex The unique (during session) index of a validator group. +type GroupIndex uint32 + +// CollatorID represents a collator ID +type CollatorID [sr25519.PublicKeyLength]byte + +// Collator represents a collator +type Collator struct { + Key crypto.PublicKey +} + +// CollatorSignature is the signature on a candidate's block data signed by a collator. +type CollatorSignature [sr25519.SignatureLength]byte + +// ValidationCodeHash is the blake2-256 hash of the validation code bytes. +type ValidationCodeHash common.Hash + +// CandidateDescriptor is a unique descriptor of the candidate receipt. +type CandidateDescriptor struct { + // The ID of the para this is a candidate for. + ParaID uint32 `scale:"1"` + + // RelayParent is the hash of the relay-chain block this should be executed in + // the context of. + // NOTE: the fact that the hash includes this value means that code depends + // on this for deduplication. Removing this field is likely to break things. + RelayParent common.Hash `scale:"2"` + + // Collator is the collator's relay-chain account ID + Collator sr25519.PublicKey `scale:"3"` + + // PersistedValidationDataHash is the blake2-256 hash of the persisted validation data. This is extra data derived from + // relay-chain state which may vary based on bitfields included before the candidate. + // Thus, it cannot be derived entirely from the relay-parent. + PersistedValidationDataHash common.Hash `scale:"4"` + + // PovHash is the hash of the `pov-block`. + PovHash common.Hash `scale:"5"` + // ErasureRoot is the root of a block's erasure encoding Merkle tree. + ErasureRoot common.Hash `scale:"6"` + + // Signature on blake2-256 of components of this receipt: + // The parachain index, the relay parent, the validation data hash, and the `pov_hash`. + // this is basically sr25519::Signature + Signature CollatorSignature `scale:"7"` + + // ParaHead is the hash of the para header that is being generated by this candidate. + ParaHead common.Hash `scale:"8"` + // ValidationCodeHash is the blake2-256 hash of the validation code bytes. + ValidationCodeHash ValidationCodeHash `scale:"9"` +} + +// ScheduledCore Information about a core which is currently occupied. +type ScheduledCore struct { + // The ID of a para scheduled. + ParaID ParaID + // The collator required to author the block, if any. + Collator *Collator +} + +// OccupiedCore Information about a core which is currently occupied. +type OccupiedCore struct { + // NOTE: this has no ParaId as it can be deduced from the candidate descriptor. + // If this core is freed by availability, this is the assignment that is next up on this + // core, if any. None if there is nothing queued for this core. + NextUpOnAvailable *ScheduledCore `scale:"1"` + // The relay-chain block number this began occupying the core at. + OccupiedSince types.BlockNumber `scale:"2"` + // The relay-chain block this will time-out at, if any. + TimeoutAt types.BlockNumber `scale:"3"` + // If this core is freed by being timed-out, this is the assignment that is next up on this + // core. None if there is nothing queued for this core or there is no possibility of timing + // out. + NextUpOnTimeOut *ScheduledCore `scale:"4"` + // A bitfield with 1 bit for each validator in the set. `1` bits mean that the corresponding + // validators has attested to availability on-chain. A 2/3+ majority of `1` bits means that + // this will be available. + // TODO: this should be a bitvec + Availability []byte `scale:"5"` + // The group assigned to distribute availability pieces of this candidate. + GroupResponsible GroupIndex `scale:"6"` + // The hash of the candidate occupying the core. + CandidateHash common.Hash `scale:"7"` + // The descriptor of the candidate occupying the core. + CandidateDescriptor types.CandidateDescriptor `scale:"8"` +} + +type Occupied scale.VaryingDataType + +func (Occupied) Index() uint { + return 0 +} + +type Scheduled scale.VaryingDataType + +func (Scheduled) Index() uint { + return 1 +} + +type Free scale.VaryingDataType + +func (Free) Index() uint { + return 2 +} diff --git a/lib/runtime/constants.go b/lib/runtime/constants.go index 47cd9fced4..0cd145a235 100644 --- a/lib/runtime/constants.go +++ b/lib/runtime/constants.go @@ -65,4 +65,6 @@ const ( ParachainHostValidators = "ParachainHost_validators" // ParachainHostValidatorGroups is the runtime API call ParachainHost_validator_groups ParachainHostValidatorGroups = "ParachainHost_validator_groups" + // ParachainHostAvailabilityCores is the runtime API call ParachainHost_availability_cores + ParachainHostAvailabilityCores = "ParachainHost_availability_cores" ) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index d3afa7980d..32c4aaba88 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -361,6 +361,26 @@ func (in *Instance) ParachainHostValidatorGroups() (*types.ValidatorGroups, erro return &validatorGroups, nil } +// ParachainHostAvailabilityCores Returns information on all availability cores +func (in *Instance) ParachainHostAvailabilityCores() (any, error) { + ret, err := in.Exec(runtime.ParachainHostAvailabilityCores, []byte{}) + if err != nil { + return nil, err + } + + availabilityCores, err := scale.NewVaryingDataType(types.Scheduled{}, types.Occupied{}, types.Free{}) + if err != nil { + return nil, err + } + + err = scale.Unmarshal(ret, &availabilityCores) + if err != nil { + return nil, err + } + + return availabilityCores, nil +} + func (in *Instance) RandomSeed() {} //nolint:revive func (in *Instance) OffchainWorker() {} //nolint:revive func (in *Instance) GenerateSessionKeys() {} //nolint:revive From e31c9568a6a834f2c7b4270644a7566f19a64a33 Mon Sep 17 00:00:00 2001 From: kanishka Date: Mon, 24 Apr 2023 15:30:13 +0530 Subject: [PATCH 04/65] fix CoreState enum --- dot/types/parachain.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 2277bc0568..0c41904c1d 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -154,13 +154,13 @@ type OccupiedCore struct { CandidateDescriptor types.CandidateDescriptor `scale:"8"` } -type Occupied scale.VaryingDataType +type Occupied OccupiedCore func (Occupied) Index() uint { return 0 } -type Scheduled scale.VaryingDataType +type Scheduled ScheduledCore func (Scheduled) Index() uint { return 1 From 99588716b57d09c557e3761fd0071538607ceb98 Mon Sep 17 00:00:00 2001 From: kanishka Date: Mon, 24 Apr 2023 15:46:13 +0530 Subject: [PATCH 05/65] cleanup --- dot/types/parachain.go | 42 +++++++++++++++++++++++++++++++++-- lib/runtime/wasmer/exports.go | 2 +- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 0c41904c1d..339a08c7f9 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -1,6 +1,8 @@ package types import ( + "fmt" + "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/crypto" "github.com/ChainSafe/gossamer/lib/crypto/sr25519" @@ -62,8 +64,6 @@ type ValidatorGroups struct { GroupRotationInfo GroupRotationInfo `scale:"2"` } -// - // ParaID The ID of a para scheduled. type ParaID uint32 @@ -154,20 +154,58 @@ type OccupiedCore struct { CandidateDescriptor types.CandidateDescriptor `scale:"8"` } +// Occupied Core information about a core which is currently occupied. type Occupied OccupiedCore +// Index returns the index func (Occupied) Index() uint { return 0 } +// Scheduled Core information about a core which is currently scheduled. type Scheduled ScheduledCore +// Index returns the index func (Scheduled) Index() uint { return 1 } +// Free Core information about a core which is currently free. type Free scale.VaryingDataType +// Index returns the index func (Free) Index() uint { return 2 } + +// CoreState represents the state of a particular availability core. +type CoreState scale.VaryingDataType + +// Set will set a VaryingDataTypeValue using the underlying VaryingDataType +func (va *CoreState) Set(val scale.VaryingDataTypeValue) (err error) { + // cast to VaryingDataType to use VaryingDataType.Set method + vdt := scale.VaryingDataType(*va) + err = vdt.Set(val) + if err != nil { + return fmt.Errorf("setting value to varying data type: %w", err) + } + // store original ParentVDT with VaryingDataType that has been set + *va = CoreState(vdt) + return nil +} + +// Value returns the value from the underlying VaryingDataType +func (va *CoreState) Value() (scale.VaryingDataTypeValue, error) { + vdt := scale.VaryingDataType(*va) + return vdt.Value() +} + +// NewCoreState returns a new CoreState +func NewCoreState() (CoreState, error) { + vdt, err := scale.NewVaryingDataType(Occupied{}, Scheduled{}, Free{}) + if err != nil { + return CoreState{}, fmt.Errorf("failed to create varying data type: %w", err) + } + + return CoreState(vdt), nil +} diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 32c4aaba88..cb62aaacf3 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -368,7 +368,7 @@ func (in *Instance) ParachainHostAvailabilityCores() (any, error) { return nil, err } - availabilityCores, err := scale.NewVaryingDataType(types.Scheduled{}, types.Occupied{}, types.Free{}) + availabilityCores, err := types.NewCoreState() if err != nil { return nil, err } From dff1140fd641576c55582d4159bd49aa30fdfa72 Mon Sep 17 00:00:00 2001 From: kanishka Date: Mon, 24 Apr 2023 15:54:49 +0530 Subject: [PATCH 06/65] add ParachainHostCheckValidationOutputs --- dot/types/parachain.go | 30 ++++++++++++++++++++++++++++++ lib/runtime/constants.go | 2 ++ lib/runtime/wasmer/exports.go | 28 ++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 339a08c7f9..2e6f26b098 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -209,3 +209,33 @@ func NewCoreState() (CoreState, error) { return CoreState(vdt), nil } + +type UpwardMessage []byte + +// OutboundHrmpMessage is an HRMP message seen from the perspective of a sender. +type OutboundHrmpMessage struct { + Recipient uint32 `scale:"1"` + Data []byte `scale:"2"` +} + +// ValidationCode is Parachain validation code. +type ValidationCode []byte + +// headData is Parachain head data included in the chain. +type headData []byte + +// CandidateCommitments are Commitments made in a `CandidateReceipt`. Many of these are outputs of validation. +type CandidateCommitments struct { + // Messages destined to be interpreted by the Relay chain itself. + UpwardMessages []UpwardMessage `scale:"1"` + // Horizontal messages sent by the parachain. + HorizontalMessages []OutboundHrmpMessage `scale:"2"` + // New validation code. + NewValidationCode *ValidationCode `scale:"3"` + // The head-data produced as a result of execution. + HeadData headData `scale:"4"` + // The number of messages processed from the DMQ. + ProcessedDownwardMessages uint32 `scale:"5"` + // The mark which specifies the block number up to which all inbound HRMP messages are processed. + HrmpWatermark uint32 `scale:"6"` +} diff --git a/lib/runtime/constants.go b/lib/runtime/constants.go index 0cd145a235..0f023f4e73 100644 --- a/lib/runtime/constants.go +++ b/lib/runtime/constants.go @@ -67,4 +67,6 @@ const ( ParachainHostValidatorGroups = "ParachainHost_validator_groups" // ParachainHostAvailabilityCores is the runtime API call ParachainHost_availability_cores ParachainHostAvailabilityCores = "ParachainHost_availability_cores" + // ParachainHostCheckValidationOutputs is the runtime API call ParachainHost_check_validation_outputs + ParachainHostCheckValidationOutputs = "ParachainHost_check_validation_outputs" ) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index cb62aaacf3..d4e8a8fde3 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -381,6 +381,34 @@ func (in *Instance) ParachainHostAvailabilityCores() (any, error) { return availabilityCores, nil } +// ParachainHostCheckValidationOutputs Checks the validation outputs of a candidate. +// Returns true if the candidate is valid. +func (in *Instance) ParachainHostCheckValidationOutputs(parachainID types.ParaID, outputs types.CandidateCommitments) (bool, error) { + buffer := bytes.NewBuffer(nil) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(parachainID) + if err != nil { + return false, fmt.Errorf("error while encoding parachainID: %w", err) + } + err = encoder.Encode(outputs) + if err != nil { + return false, fmt.Errorf("error while encoding outputs: %w", err) + } + + encodedPersistedValidationData, err := in.Exec(runtime.ParachainHostCheckValidationOutputs, buffer.Bytes()) + if err != nil { + return false, fmt.Errorf("error while executing runtime: %w", err) + } + + var isValid bool + err = scale.Unmarshal(encodedPersistedValidationData, &isValid) + if err != nil { + return false, fmt.Errorf("error while scale decoding: %w", err) + } + + return isValid, nil +} + func (in *Instance) RandomSeed() {} //nolint:revive func (in *Instance) OffchainWorker() {} //nolint:revive func (in *Instance) GenerateSessionKeys() {} //nolint:revive From eacdd106296be88cd093fde18ec568882af936ea Mon Sep 17 00:00:00 2001 From: kanishka Date: Mon, 24 Apr 2023 16:03:59 +0530 Subject: [PATCH 07/65] add ParachainHostSessionIndexForChild --- dot/types/parachain.go | 4 ++++ lib/runtime/constants.go | 2 ++ lib/runtime/wasmer/exports.go | 16 ++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 2e6f26b098..85ea2dfb6a 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -210,6 +210,7 @@ func NewCoreState() (CoreState, error) { return CoreState(vdt), nil } +// UpwardMessage A message from a parachain to its Relay Chain. type UpwardMessage []byte // OutboundHrmpMessage is an HRMP message seen from the perspective of a sender. @@ -239,3 +240,6 @@ type CandidateCommitments struct { // The mark which specifies the block number up to which all inbound HRMP messages are processed. HrmpWatermark uint32 `scale:"6"` } + +// SessionIndex is a session index. +type SessionIndex uint32 diff --git a/lib/runtime/constants.go b/lib/runtime/constants.go index 0f023f4e73..39205fd188 100644 --- a/lib/runtime/constants.go +++ b/lib/runtime/constants.go @@ -69,4 +69,6 @@ const ( ParachainHostAvailabilityCores = "ParachainHost_availability_cores" // ParachainHostCheckValidationOutputs is the runtime API call ParachainHost_check_validation_outputs ParachainHostCheckValidationOutputs = "ParachainHost_check_validation_outputs" + // ParachainHostSessionIndexForChild is the runtime API call ParachainHost_session_index_for_child + ParachainHostSessionIndexForChild = "ParachainHost_session_index_for_child" ) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index d4e8a8fde3..d617c3996e 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -409,6 +409,22 @@ func (in *Instance) ParachainHostCheckValidationOutputs(parachainID types.ParaID return isValid, nil } +// ParachainHostSessionIndexForChild Returns the session index that is expected at the child of a block. +func (in *Instance) ParachainHostSessionIndexForChild() (types.SessionIndex, error) { + ret, err := in.Exec(runtime.ParachainHostSessionIndexForChild, []byte{}) + if err != nil { + return 0, err + } + + var sessionIndex types.SessionIndex + err = scale.Unmarshal(ret, &sessionIndex) + if err != nil { + return 0, err + } + + return sessionIndex, nil +} + func (in *Instance) RandomSeed() {} //nolint:revive func (in *Instance) OffchainWorker() {} //nolint:revive func (in *Instance) GenerateSessionKeys() {} //nolint:revive From 58ef4ef19590b0468551c9e13ca0511b077b3a2f Mon Sep 17 00:00:00 2001 From: kanishka Date: Mon, 24 Apr 2023 16:18:50 +0530 Subject: [PATCH 08/65] add ParachainHostCandidatePendingAvailability --- dot/types/parachain.go | 10 +++++++++- lib/runtime/constants.go | 2 ++ lib/runtime/wasmer/exports.go | 23 +++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 85ea2dfb6a..20f3291334 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -151,7 +151,7 @@ type OccupiedCore struct { // The hash of the candidate occupying the core. CandidateHash common.Hash `scale:"7"` // The descriptor of the candidate occupying the core. - CandidateDescriptor types.CandidateDescriptor `scale:"8"` + CandidateDescriptor CandidateDescriptor `scale:"8"` } // Occupied Core information about a core which is currently occupied. @@ -243,3 +243,11 @@ type CandidateCommitments struct { // SessionIndex is a session index. type SessionIndex uint32 + +// CommittedCandidateReceipt A candidate-receipt with commitments directly included. +type CommittedCandidateReceipt struct { + // The candidate descriptor. + Descriptor CandidateDescriptor `scale:"1"` + // The commitments made by the parachain. + Commitments CandidateCommitments `scale:"2"` +} diff --git a/lib/runtime/constants.go b/lib/runtime/constants.go index 39205fd188..191163916c 100644 --- a/lib/runtime/constants.go +++ b/lib/runtime/constants.go @@ -71,4 +71,6 @@ const ( ParachainHostCheckValidationOutputs = "ParachainHost_check_validation_outputs" // ParachainHostSessionIndexForChild is the runtime API call ParachainHost_session_index_for_child ParachainHostSessionIndexForChild = "ParachainHost_session_index_for_child" + // ParachainHostCandidatePendingAvailability is the runtime API call ParachainHost_candidate_pending_availability + ParachainHostCandidatePendingAvailability = "ParachainHost_candidate_pending_availability" ) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index d617c3996e..d915b87a76 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -425,6 +425,29 @@ func (in *Instance) ParachainHostSessionIndexForChild() (types.SessionIndex, err return sessionIndex, nil } +// ParachainHostCandidatePendingAvailability Returns the receipt of a candidate pending availability for any parachain assigned to an occupied availability core. +func (in *Instance) ParachainHostCandidatePendingAvailability(parachainID types.ParaID) (*types.CommittedCandidateReceipt, error) { + buffer := bytes.NewBuffer(nil) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(parachainID) + if err != nil { + return nil, fmt.Errorf("error while encoding parachainID: %w", err) + } + + encodedCandidateReceipt, err := in.Exec(runtime.ParachainHostCandidatePendingAvailability, buffer.Bytes()) + if err != nil { + return nil, fmt.Errorf("error while executing runtime: %w", err) + } + + var candidateReceipt types.CommittedCandidateReceipt + err = scale.Unmarshal(encodedCandidateReceipt, &candidateReceipt) + if err != nil { + return nil, fmt.Errorf("error while scale decoding: %w", err) + } + + return &candidateReceipt, nil +} + func (in *Instance) RandomSeed() {} //nolint:revive func (in *Instance) OffchainWorker() {} //nolint:revive func (in *Instance) GenerateSessionKeys() {} //nolint:revive From e7792013ad4e002f68104470be26976333a37d50 Mon Sep 17 00:00:00 2001 From: kanishka Date: Mon, 24 Apr 2023 17:31:46 +0530 Subject: [PATCH 09/65] add ParachainHostSessionInfo --- dot/types/parachain.go | 38 +++++++++++++++++++++++++++++++++++ lib/runtime/constants.go | 2 ++ lib/runtime/wasmer/exports.go | 23 +++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 20f3291334..ec0ef2dd28 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -251,3 +251,41 @@ type CommittedCandidateReceipt struct { // The commitments made by the parachain. Commitments CandidateCommitments `scale:"2"` } + +// AssignmentID The public key of a keypair used by a validator for determining assignments +// to approve included parachain candidates. +type AssignmentID sr25519.PublicKey + +// SessionInfo Information about validator sets of a session. +type SessionInfo struct { + // All the validators actively participating in parachain consensus. + // Indices are into the broader validator set. + ActiveValidatorIndices []ValidatorIndex `scale:"1"` + // A secure random seed for the session, gathered from BABE. + RandomSeed [32]byte `scale:"2"` + // The amount of sessions to keep for disputes. + DisputePeriod SessionIndex `scale:"3"` + // Validators in canonical ordering. + Validators map[ValidatorIndex]ValidatorID `scale:"4"` + // Validators' authority discovery keys for the session in canonical ordering. + DiscoveryKeys []Authority `scale:"5"` + // The assignment keys for validators. + AssignmentKeys []AssignmentID `scale:"6"` + // Validators in shuffled ordering - these are the validator groups as produced + // by the `Scheduler` module for the session and are typically referred to by + // `GroupIndex`. + ValidatorGroups map[GroupIndex][]ValidatorIndex `scale:"7"` + // The number of availability cores used by the protocol during this session. + NCores uint32 `scale:"8"` + // The zeroth delay tranche width. + ZerothDelayTrancheWidth uint32 `scale:"9"` + // The number of samples we do of `relay_vrf_modulo`. + RelayVRFModuloSamples uint32 `scale:"10"` + // The number of delay tranches in total. + NDelayTranches uint32 `scale:"11"` + // How many slots (BABE / SASSAFRAS) must pass before an assignment is considered a + // no-show. + NoShowSlots uint32 `scale:"12"` + // The number of validators needed to approve a block. + NeededApprovals uint32 `scale:"13"` +} diff --git a/lib/runtime/constants.go b/lib/runtime/constants.go index 191163916c..d37ed0f497 100644 --- a/lib/runtime/constants.go +++ b/lib/runtime/constants.go @@ -73,4 +73,6 @@ const ( ParachainHostSessionIndexForChild = "ParachainHost_session_index_for_child" // ParachainHostCandidatePendingAvailability is the runtime API call ParachainHost_candidate_pending_availability ParachainHostCandidatePendingAvailability = "ParachainHost_candidate_pending_availability" + // ParachainHostSessionInfo is the runtime API call ParachainHost_session_info + ParachainHostSessionInfo = "ParachainHost_session_info" ) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index d915b87a76..11e8e0e014 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -448,6 +448,29 @@ func (in *Instance) ParachainHostCandidatePendingAvailability(parachainID types. return &candidateReceipt, nil } +// ParachainHostSessionInfo Returns the session info of the given session, if available. +func (in *Instance) ParachainHostSessionInfo(sessionIndex types.SessionIndex) (*types.SessionInfo, error) { + buffer := bytes.NewBuffer(nil) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(sessionIndex) + if err != nil { + return nil, fmt.Errorf("error while encoding sessionIndex: %w", err) + } + + encodedSessionInfo, err := in.Exec(runtime.ParachainHostSessionInfo, buffer.Bytes()) + if err != nil { + return nil, fmt.Errorf("error while executing runtime: %w", err) + } + + var sessionInfo types.SessionInfo + err = scale.Unmarshal(encodedSessionInfo, &sessionInfo) + if err != nil { + return nil, fmt.Errorf("error while scale decoding: %w", err) + } + + return &sessionInfo, nil +} + func (in *Instance) RandomSeed() {} //nolint:revive func (in *Instance) OffchainWorker() {} //nolint:revive func (in *Instance) GenerateSessionKeys() {} //nolint:revive From 5c8f0f82eeb9ebee0739713f899cb77b01f9c69d Mon Sep 17 00:00:00 2001 From: kanishka Date: Mon, 24 Apr 2023 18:44:36 +0530 Subject: [PATCH 10/65] add InboundHrmpChannelsContents and DMQContents --- dot/types/parachain.go | 24 ++++++++++++++++++ lib/runtime/constants.go | 4 +++ lib/runtime/wasmer/exports.go | 47 +++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index ec0ef2dd28..9db90ed2a2 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -10,6 +10,8 @@ import ( "github.com/centrifuge/go-substrate-rpc-client/v4/types" ) +type BlockNumber uint32 + // ValidatorID represents a validator ID type ValidatorID [sr25519.PublicKeyLength]byte @@ -289,3 +291,25 @@ type SessionInfo struct { // The number of validators needed to approve a block. NeededApprovals uint32 `scale:"13"` } + +// DownwardMessage A message sent from the relay-chain down to a parachain. +type DownwardMessage []byte + +// InboundDownwardMessage A wrapped version of `DownwardMessage`. The difference is that it has attached the block number when +// the message was sent. +type InboundDownwardMessage struct { + // The block number at which these messages were put into the downward message queue. + SentAt BlockNumber `scale:"1"` + // The actual downward message to processes. + Message DownwardMessage `scale:"2"` +} + +// InboundHrmpMessage An HRMP message seen from the perspective of a recipient. +type InboundHrmpMessage struct { + // The block number at which this message was sent. + // Specifically, it is the block number at which the candidate that sends this message was + // enacted. + SentAt BlockNumber `scale:"1"` + // The message payload. + Message []byte `scale:"2"` +} diff --git a/lib/runtime/constants.go b/lib/runtime/constants.go index d37ed0f497..c1b1f70234 100644 --- a/lib/runtime/constants.go +++ b/lib/runtime/constants.go @@ -75,4 +75,8 @@ const ( ParachainHostCandidatePendingAvailability = "ParachainHost_candidate_pending_availability" // ParachainHostSessionInfo is the runtime API call ParachainHost_session_info ParachainHostSessionInfo = "ParachainHost_session_info" + // ParachainHostDMQContents is the runtime API call ParachainHost_dmq_contents + ParachainHostDMQContents = "ParachainHost_dmq_contents" + //ParachainHostInboundHrmpChannelsContents is the runtime API call ParachainHost_inbound_hrmp_channels_contents + ParachainHostInboundHrmpChannelsContents = "ParachainHost_inbound_hrmp_channels_contents" ) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 11e8e0e014..7467529a9b 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -471,6 +471,53 @@ func (in *Instance) ParachainHostSessionInfo(sessionIndex types.SessionIndex) (* return &sessionInfo, nil } +// ParachainHostDMQContents Returns all the pending inbound messages in the downward message queue for a given parachain. +func (in *Instance) ParachainHostDMQContents(parachainID types.ParaID) ([]types.DownwardMessage, error) { + buffer := bytes.NewBuffer(nil) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(parachainID) + if err != nil { + return nil, fmt.Errorf("error while encoding parachainID: %w", err) + } + + encodedDownwardMessages, err := in.Exec(runtime.ParachainHostDMQContents, buffer.Bytes()) + if err != nil { + return nil, fmt.Errorf("error while executing runtime: %w", err) + } + + var downwardMessages []types.DownwardMessage + err = scale.Unmarshal(encodedDownwardMessages, &downwardMessages) + if err != nil { + return nil, fmt.Errorf("error while scale decoding: %w", err) + } + + return downwardMessages, nil +} + +// ParachainHostInboundHrmpChannelsContents Returns the contents of all channels addressed to the given recipient. +// Channels that have no messages in them are also included. +func (in *Instance) ParachainHostInboundHrmpChannelsContents(recipient types.ParaID) ([]types.InboundHrmpMessage, error) { + buffer := bytes.NewBuffer(nil) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(recipient) + if err != nil { + return nil, fmt.Errorf("error while encoding recipient: %w", err) + } + + encodedInboundHrmpMessages, err := in.Exec(runtime.ParachainHostInboundHrmpChannelsContents, buffer.Bytes()) + if err != nil { + return nil, fmt.Errorf("error while executing runtime: %w", err) + } + + var inboundHrmpMessages []types.InboundHrmpMessage + err = scale.Unmarshal(encodedInboundHrmpMessages, &inboundHrmpMessages) + if err != nil { + return nil, fmt.Errorf("error while scale decoding: %w", err) + } + + return inboundHrmpMessages, nil +} + func (in *Instance) RandomSeed() {} //nolint:revive func (in *Instance) OffchainWorker() {} //nolint:revive func (in *Instance) GenerateSessionKeys() {} //nolint:revive From 8baa4e6fd5943ec80e6b99391246ab82baab6f9f Mon Sep 17 00:00:00 2001 From: kanishka Date: Tue, 25 Apr 2023 18:36:53 +0530 Subject: [PATCH 11/65] add IndexVec --- dot/types/parachain.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 9db90ed2a2..78906548a6 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -258,6 +258,18 @@ type CommittedCandidateReceipt struct { // to approve included parachain candidates. type AssignmentID sr25519.PublicKey +// IndexedValidator A validator with its index. +type IndexedValidator struct { + Index ValidatorIndex `scale:"-"` + Validator Validator `scale:"2"` +} + +// IndexedValidatorGroup A validator group with its group index. +type IndexedValidatorGroup struct { + GroupIndex []GroupIndex `scale:"-"` + Validators []ValidatorIndex `scale:"2"` +} + // SessionInfo Information about validator sets of a session. type SessionInfo struct { // All the validators actively participating in parachain consensus. @@ -268,7 +280,7 @@ type SessionInfo struct { // The amount of sessions to keep for disputes. DisputePeriod SessionIndex `scale:"3"` // Validators in canonical ordering. - Validators map[ValidatorIndex]ValidatorID `scale:"4"` + Validators []IndexedValidator `scale:"4"` // Validators' authority discovery keys for the session in canonical ordering. DiscoveryKeys []Authority `scale:"5"` // The assignment keys for validators. @@ -276,7 +288,7 @@ type SessionInfo struct { // Validators in shuffled ordering - these are the validator groups as produced // by the `Scheduler` module for the session and are typically referred to by // `GroupIndex`. - ValidatorGroups map[GroupIndex][]ValidatorIndex `scale:"7"` + ValidatorGroups []IndexedValidatorGroup `scale:"7"` // The number of availability cores used by the protocol during this session. NCores uint32 `scale:"8"` // The zeroth delay tranche width. From e41710b107686d424c496aebed4ccd52de5e5fd3 Mon Sep 17 00:00:00 2001 From: kanishka Date: Wed, 26 Apr 2023 12:49:43 +0530 Subject: [PATCH 12/65] add ParachainHostCandidateEvents --- dot/types/parachain.go | 75 +++++++++++++++++++++++++++++++++++ lib/runtime/constants.go | 2 + lib/runtime/wasmer/exports.go | 25 +++++++++++- 3 files changed, 100 insertions(+), 2 deletions(-) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 78906548a6..6d1f0fca8d 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -325,3 +325,78 @@ type InboundHrmpMessage struct { // The message payload. Message []byte `scale:"2"` } + +// CandidateReceipt A receipt for a parachain candidate. +type CandidateReceipt struct { + // The candidate descriptor. + Descriptor CandidateDescriptor `scale:"1"` + // The candidate event. + CommitmentsHash common.Hash `scale:"2"` +} + +// HeadData Parachain head data included in the chain. +type HeadData []byte + +// CoreIndex The unique (during session) index of a core. +type CoreIndex uint32 + +// CandidateBacked This candidate receipt was backed in the most recent block. +// This includes the core index the candidate is now occupying. +type CandidateBacked scale.VaryingDataType + +// Index returns the VaryingDataType Index +func (CandidateBacked) Index() uint { + return 0 +} + +// CandidateIncluded This candidate receipt was included and became a parablock at the most recent block. +// This includes the core index the candidate was occupying as well as the group responsible +// for backing the candidate. +type CandidateIncluded scale.VaryingDataType + +// Index returns the VaryingDataType Index +func (CandidateIncluded) Index() uint { + return 1 +} + +// CandidateTimedOut A candidate that timed out. +// / This candidate receipt was not made available in time and timed out. +// / This includes the core index the candidate was occupying. +type CandidateTimedOut scale.VaryingDataType + +// Index returns the VaryingDataType Index +func (CandidateTimedOut) Index() uint { + return 2 +} + +// CandidateEvent A candidate event. +type CandidateEvent scale.VaryingDataType + +// Set will set a VaryingDataTypeValue using the underlying VaryingDataType +func (va *CandidateEvent) Set(val scale.VaryingDataTypeValue) (err error) { + // cast to VaryingDataType to use VaryingDataType.Set method + vdt := scale.VaryingDataType(*va) + err = vdt.Set(val) + if err != nil { + return fmt.Errorf("setting value to varying data type: %w", err) + } + // store original ParentVDT with VaryingDataType that has been set + *va = CandidateEvent(vdt) + return nil +} + +// Value returns the value from the underlying VaryingDataType +func (va *CandidateEvent) Value() (scale.VaryingDataTypeValue, error) { + vdt := scale.VaryingDataType(*va) + return vdt.Value() +} + +// NewCandidateEventVDT returns a new CandidateEvent VaryingDataType +func NewCandidateEventVDT() (scale.VaryingDataType, error) { + vdt, err := scale.NewVaryingDataType(CandidateBacked{}, CandidateIncluded{}, CandidateTimedOut{}) + if err != nil { + return scale.VaryingDataType{}, fmt.Errorf("failed to create varying data type: %w", err) + } + + return vdt, nil +} diff --git a/lib/runtime/constants.go b/lib/runtime/constants.go index c1b1f70234..d123b4bc1d 100644 --- a/lib/runtime/constants.go +++ b/lib/runtime/constants.go @@ -73,6 +73,8 @@ const ( ParachainHostSessionIndexForChild = "ParachainHost_session_index_for_child" // ParachainHostCandidatePendingAvailability is the runtime API call ParachainHost_candidate_pending_availability ParachainHostCandidatePendingAvailability = "ParachainHost_candidate_pending_availability" + // ParachainHostCandidateEvents is the runtime API call ParachainHost_candidate_events + ParachainHostCandidateEvents = "ParachainHost_candidate_events" // ParachainHostSessionInfo is the runtime API call ParachainHost_session_info ParachainHostSessionInfo = "ParachainHost_session_info" // ParachainHostDMQContents is the runtime API call ParachainHost_dmq_contents diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 7467529a9b..e98f6d18e5 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -362,7 +362,7 @@ func (in *Instance) ParachainHostValidatorGroups() (*types.ValidatorGroups, erro } // ParachainHostAvailabilityCores Returns information on all availability cores -func (in *Instance) ParachainHostAvailabilityCores() (any, error) { +func (in *Instance) ParachainHostAvailabilityCores() (*types.CoreState, error) { ret, err := in.Exec(runtime.ParachainHostAvailabilityCores, []byte{}) if err != nil { return nil, err @@ -378,7 +378,7 @@ func (in *Instance) ParachainHostAvailabilityCores() (any, error) { return nil, err } - return availabilityCores, nil + return &availabilityCores, nil } // ParachainHostCheckValidationOutputs Checks the validation outputs of a candidate. @@ -448,6 +448,27 @@ func (in *Instance) ParachainHostCandidatePendingAvailability(parachainID types. return &candidateReceipt, nil } +// ParachainHostCandidateEvents Returns an array of candidate events that occurred within the latest state. +func (in *Instance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + ret, err := in.Exec(runtime.ParachainHostCandidateEvents, []byte{}) + if err != nil { + return nil, err + } + + candidateEvent, err := types.NewCandidateEventVDT() + if err != nil { + return nil, err + } + + candidateEvents := scale.NewVaryingDataTypeSlice(candidateEvent) + err = scale.Unmarshal(ret, &candidateEvents) + if err != nil { + return nil, err + } + + return &candidateEvents, nil +} + // ParachainHostSessionInfo Returns the session info of the given session, if available. func (in *Instance) ParachainHostSessionInfo(sessionIndex types.SessionIndex) (*types.SessionInfo, error) { buffer := bytes.NewBuffer(nil) From e9df9aa2b7f6d9be67e9c1068d1f9e201e097f5b Mon Sep 17 00:00:00 2001 From: kanishka Date: Wed, 26 Apr 2023 13:53:14 +0530 Subject: [PATCH 13/65] fix vdt --- dot/types/parachain.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 6d1f0fca8d..f15b21f98c 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -342,7 +342,12 @@ type CoreIndex uint32 // CandidateBacked This candidate receipt was backed in the most recent block. // This includes the core index the candidate is now occupying. -type CandidateBacked scale.VaryingDataType +type CandidateBacked struct { + CandidateReceipt CandidateReceipt `scale:"1"` + HeadData HeadData `scale:"2"` + CoreIndex CoreIndex `scale:"3"` + GroupIndex GroupIndex `scale:"4"` +} // Index returns the VaryingDataType Index func (CandidateBacked) Index() uint { @@ -352,7 +357,12 @@ func (CandidateBacked) Index() uint { // CandidateIncluded This candidate receipt was included and became a parablock at the most recent block. // This includes the core index the candidate was occupying as well as the group responsible // for backing the candidate. -type CandidateIncluded scale.VaryingDataType +type CandidateIncluded struct { + CandidateReceipt CandidateReceipt `scale:"1"` + HeadData HeadData `scale:"2"` + CoreIndex CoreIndex `scale:"3"` + GroupIndex GroupIndex `scale:"4"` +} // Index returns the VaryingDataType Index func (CandidateIncluded) Index() uint { @@ -362,7 +372,11 @@ func (CandidateIncluded) Index() uint { // CandidateTimedOut A candidate that timed out. // / This candidate receipt was not made available in time and timed out. // / This includes the core index the candidate was occupying. -type CandidateTimedOut scale.VaryingDataType +type CandidateTimedOut struct { + CandidateReceipt CandidateReceipt `scale:"1"` + HeadData HeadData `scale:"2"` + CoreIndex CoreIndex `scale:"3"` +} // Index returns the VaryingDataType Index func (CandidateTimedOut) Index() uint { From c4d15e4dc993fc9dc0a400c12c072c4e966527fd Mon Sep 17 00:00:00 2001 From: kanishka Date: Thu, 27 Apr 2023 17:30:49 +0530 Subject: [PATCH 14/65] add `state_call` and fix test --- dot/rpc/modules/state.go | 36 ++++++++++++++++++++++----- tests/rpc/rpc_05-state_test.go | 15 +++++++++--- tests/utils/rpc/request.go | 45 ++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 9 deletions(-) diff --git a/dot/rpc/modules/state.go b/dot/rpc/modules/state.go index 6266dfcd8e..9a41203e13 100644 --- a/dot/rpc/modules/state.go +++ b/dot/rpc/modules/state.go @@ -23,7 +23,7 @@ type StateGetReadProofRequest struct { // StateCallRequest holds json fields type StateCallRequest struct { Method string `json:"method"` - Data []byte `json:"data"` + Data string `json:"params"` Block *common.Hash `json:"block"` } @@ -86,7 +86,7 @@ type StateStorageQueryAtRequest struct { type StateStorageKeysQuery [][]byte // StateCallResponse holds json fields -type StateCallResponse []byte +type StateCallResponse string // StateKeysResponse field to store the state keys type StateKeysResponse [][]byte @@ -245,10 +245,34 @@ func (sm *StateModule) GetPairs(_ *http.Request, req *StatePairRequest, res *Sta return nil } -// Call isn't implemented properly yet. -func (sm *StateModule) Call(_ *http.Request, _ *StateCallRequest, _ *StateCallResponse) error { - _ = sm.networkAPI - _ = sm.storageAPI +// Call makes a call to the runtime. +func (sm *StateModule) Call(_ *http.Request, req *StateCallRequest, res *StateCallResponse) error { + rt, err := sm.blockAPI.GetRuntime(sm.blockAPI.BestBlockHash()) + if err != nil { + return err + } + + requestData, err := common.HexToBytes(req.Data) + if err != nil { + return fmt.Errorf("cannot convert hex data %s to bytes: %w", req.Data, err) + } + + switch req.Method { + case runtime.CoreVersion: + version, err := rt.Exec(runtime.CoreVersion, requestData) + if err != nil { + return err + } + *res = StateCallResponse(common.BytesToHex(version)) + case runtime.CoreInitializeBlock: + + case runtime.Metadata: + metadata, err := rt.Exec(runtime.Metadata, requestData) + if err != nil { + return err + } + *res = StateCallResponse(common.BytesToHex(metadata)) + } return nil } diff --git a/tests/rpc/rpc_05-state_test.go b/tests/rpc/rpc_05-state_test.go index ec91343d34..d2f51fc2d6 100644 --- a/tests/rpc/rpc_05-state_test.go +++ b/tests/rpc/rpc_05-state_test.go @@ -10,6 +10,8 @@ import ( "time" "github.com/ChainSafe/gossamer/dot/rpc/modules" + "github.com/ChainSafe/gossamer/lib/runtime" + "github.com/ChainSafe/gossamer/lib/common" libutils "github.com/ChainSafe/gossamer/lib/utils" "github.com/ChainSafe/gossamer/tests/utils/config" @@ -34,10 +36,17 @@ func TestStateRPCResponseValidation(t *testing.T) { //nolint:tparallel t.Run("state_call", func(t *testing.T) { t.Parallel() - const params = `["", "","0x580d77a9136035a0bc3c3cd86286172f7f81291164c5914266073a30466fba21"]` - var response modules.StateCallResponse + const params = `["Core_version", "0x"]` + var response runtime.Version - fetchWithTimeout(ctx, t, "state_call", params, &response) + ctx, cancel := context.WithTimeout(ctx, time.Second) + defer cancel() + endpoint := rpc.NewEndpoint(node.RPCPort()) + data, err := rpc.Post(ctx, endpoint, "state_call", params) + require.NoError(t, err) + + err = rpc.DecodeScale(data, &response) + require.NoError(t, err) // TODO assert stateCallResponse }) diff --git a/tests/utils/rpc/request.go b/tests/utils/rpc/request.go index 4e76e39871..c136a9facf 100644 --- a/tests/utils/rpc/request.go +++ b/tests/utils/rpc/request.go @@ -57,6 +57,7 @@ var ( ) // Decode decodes []body into the target interface. +// It assumes that the response.Result is a JSON-encoded value. func Decode(body []byte, target interface{}) error { decoder := json.NewDecoder(bytes.NewReader(body)) decoder.DisallowUnknownFields() @@ -93,6 +94,50 @@ func Decode(body []byte, target interface{}) error { return nil } +// DecodeScale decodes []body into the target interface. +// It assumes that the response.Result is a SCALE-encoded value. +func DecodeScale(body []byte, target interface{}) error { + decoder := json.NewDecoder(bytes.NewReader(body)) + decoder.DisallowUnknownFields() + + var response ServerResponse + err := decoder.Decode(&response) + if err != nil { + return fmt.Errorf("cannot decode response: %s: %w", + string(body), err) + } + + if response.Version != "2.0" { + return fmt.Errorf("%w: %s", ErrResponseVersion, response.Version) + } + + if response.Error != nil { + return fmt.Errorf("%w: %s (error code %d)", + ErrResponseError, response.Error.Message, response.Error.ErrorCode) + } + + var result string + err = json.Unmarshal(response.Result, &result) + if err != nil { + return fmt.Errorf("cannot decode response result: %s: %w", + string(response.Result), err) + } + + scaleRawMessage, err := common.HexToBytes(result) + if err != nil { + return fmt.Errorf("cannot convert to bytes: %s: %w", + result, err) + } + + err = scale.Unmarshal(scaleRawMessage, target) + if err != nil { + return fmt.Errorf("cannot decode response result: %s: %w", + string(response.Result), err) + } + + return nil +} + // NewEndpoint returns http://localhost: func NewEndpoint(port string) string { return "http://localhost:" + port From 586a2aeff53c76ebf3493edaa8bb9beb39103b0d Mon Sep 17 00:00:00 2001 From: kanishka Date: Thu, 27 Apr 2023 17:53:43 +0530 Subject: [PATCH 15/65] cleanup --- dot/rpc/modules/state.go | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/dot/rpc/modules/state.go b/dot/rpc/modules/state.go index 9a41203e13..b4b1c2590f 100644 --- a/dot/rpc/modules/state.go +++ b/dot/rpc/modules/state.go @@ -252,27 +252,17 @@ func (sm *StateModule) Call(_ *http.Request, req *StateCallRequest, res *StateCa return err } - requestData, err := common.HexToBytes(req.Data) + request, err := common.HexToBytes(req.Data) if err != nil { return fmt.Errorf("cannot convert hex data %s to bytes: %w", req.Data, err) } - switch req.Method { - case runtime.CoreVersion: - version, err := rt.Exec(runtime.CoreVersion, requestData) - if err != nil { - return err - } - *res = StateCallResponse(common.BytesToHex(version)) - case runtime.CoreInitializeBlock: - - case runtime.Metadata: - metadata, err := rt.Exec(runtime.Metadata, requestData) - if err != nil { - return err - } - *res = StateCallResponse(common.BytesToHex(metadata)) + response, err := rt.Exec(req.Method, request) + if err != nil { + return err } + + *res = StateCallResponse(common.BytesToHex(response)) return nil } From 97d410e2fc7b92d5b79438544a859ce8f862d4ad Mon Sep 17 00:00:00 2001 From: kanishka Date: Thu, 27 Apr 2023 17:56:37 +0530 Subject: [PATCH 16/65] cleanup --- dot/rpc/modules/state.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dot/rpc/modules/state.go b/dot/rpc/modules/state.go index b4b1c2590f..c3a19f27c5 100644 --- a/dot/rpc/modules/state.go +++ b/dot/rpc/modules/state.go @@ -23,7 +23,7 @@ type StateGetReadProofRequest struct { // StateCallRequest holds json fields type StateCallRequest struct { Method string `json:"method"` - Data string `json:"params"` + Params string `json:"params"` Block *common.Hash `json:"block"` } @@ -252,9 +252,9 @@ func (sm *StateModule) Call(_ *http.Request, req *StateCallRequest, res *StateCa return err } - request, err := common.HexToBytes(req.Data) + request, err := common.HexToBytes(req.Params) if err != nil { - return fmt.Errorf("cannot convert hex data %s to bytes: %w", req.Data, err) + return fmt.Errorf("cannot convert hex data %s to bytes: %w", req.Params, err) } response, err := rt.Exec(req.Method, request) From be9037c32151e43d701e213c1ce5b7a691c56c2b Mon Sep 17 00:00:00 2001 From: kanishka Date: Thu, 27 Apr 2023 18:23:54 +0530 Subject: [PATCH 17/65] fix tests --- dot/rpc/modules/state_test.go | 18 ++++++++++++++++-- tests/rpc/rpc_05-state_test.go | 6 +++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/dot/rpc/modules/state_test.go b/dot/rpc/modules/state_test.go index 792e4edc0e..c95f22605d 100644 --- a/dot/rpc/modules/state_test.go +++ b/dot/rpc/modules/state_test.go @@ -20,6 +20,8 @@ import ( "net/http" "testing" + "github.com/ChainSafe/gossamer/lib/runtime/wasmer" + "github.com/ChainSafe/gossamer/dot/rpc/modules/mocks" testdata "github.com/ChainSafe/gossamer/dot/rpc/modules/test_data" "github.com/ChainSafe/gossamer/dot/types" @@ -283,12 +285,24 @@ func TestStateModuleGetKeysPaged(t *testing.T) { // Implement Tests once function is implemented func TestCall(t *testing.T) { ctrl := gomock.NewController(t) + testHash := common.NewHash([]byte{0x01, 0x02}) + rt := wasmer.NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) mockNetworkAPI := mocks.NewMockNetworkAPI(ctrl) mockStorageAPI := mocks.NewMockStorageAPI(ctrl) - sm := NewStateModule(mockNetworkAPI, mockStorageAPI, nil, nil) + mockBlockAPI := mocks.NewMockBlockAPI(ctrl) + mockBlockAPI.EXPECT().BestBlockHash().Return(testHash) + mockBlockAPI.EXPECT().GetRuntime(gomock.Any()).Return(rt, nil) + + sm := NewStateModule(mockNetworkAPI, mockStorageAPI, nil, mockBlockAPI) - err := sm.Call(nil, nil, nil) + req := &StateCallRequest{ + Method: "Core_version", + Params: "0x", + Block: &testHash, + } + var res StateCallResponse + err := sm.Call(nil, req, &res) assert.NoError(t, err) } diff --git a/tests/rpc/rpc_05-state_test.go b/tests/rpc/rpc_05-state_test.go index d2f51fc2d6..e8cf240005 100644 --- a/tests/rpc/rpc_05-state_test.go +++ b/tests/rpc/rpc_05-state_test.go @@ -39,10 +39,10 @@ func TestStateRPCResponseValidation(t *testing.T) { //nolint:tparallel const params = `["Core_version", "0x"]` var response runtime.Version - ctx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() + rpcCtx, rpcCancel := context.WithTimeout(ctx, time.Second) + rpcCancel() endpoint := rpc.NewEndpoint(node.RPCPort()) - data, err := rpc.Post(ctx, endpoint, "state_call", params) + data, err := rpc.Post(rpcCtx, endpoint, "state_call", params) require.NoError(t, err) err = rpc.DecodeScale(data, &response) From 7d9bcc3ce2aeda1d174578c1ce99e63e18ecb3c0 Mon Sep 17 00:00:00 2001 From: kanishka Date: Thu, 27 Apr 2023 18:39:29 +0530 Subject: [PATCH 18/65] fix test --- tests/rpc/rpc_05-state_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/rpc/rpc_05-state_test.go b/tests/rpc/rpc_05-state_test.go index e8cf240005..1c6429aa63 100644 --- a/tests/rpc/rpc_05-state_test.go +++ b/tests/rpc/rpc_05-state_test.go @@ -39,8 +39,8 @@ func TestStateRPCResponseValidation(t *testing.T) { //nolint:tparallel const params = `["Core_version", "0x"]` var response runtime.Version - rpcCtx, rpcCancel := context.WithTimeout(ctx, time.Second) - rpcCancel() + rpcCtx, rpcCancel := context.WithTimeout(ctx, 10*time.Second) + defer rpcCancel() endpoint := rpc.NewEndpoint(node.RPCPort()) data, err := rpc.Post(rpcCtx, endpoint, "state_call", params) require.NoError(t, err) From c0c413e38ebb1524fe0fdead3d485c67946f60e4 Mon Sep 17 00:00:00 2001 From: kanishka Date: Thu, 27 Apr 2023 18:52:53 +0530 Subject: [PATCH 19/65] cleanup --- dot/rpc/modules/state.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dot/rpc/modules/state.go b/dot/rpc/modules/state.go index c3a19f27c5..57cac43f2e 100644 --- a/dot/rpc/modules/state.go +++ b/dot/rpc/modules/state.go @@ -85,7 +85,7 @@ type StateStorageQueryAtRequest struct { // StateStorageKeysQuery field to store storage keys type StateStorageKeysQuery [][]byte -// StateCallResponse holds json fields +// StateCallResponse holds the result of the call type StateCallResponse string // StateKeysResponse field to store the state keys From 0c0150671e9fd7bcd826bfa7ea4d400d204058ba Mon Sep 17 00:00:00 2001 From: kanishka Date: Thu, 27 Apr 2023 19:20:54 +0530 Subject: [PATCH 20/65] cleanup --- dot/rpc/modules/state_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dot/rpc/modules/state_test.go b/dot/rpc/modules/state_test.go index c95f22605d..c053733d3a 100644 --- a/dot/rpc/modules/state_test.go +++ b/dot/rpc/modules/state_test.go @@ -282,7 +282,9 @@ func TestStateModuleGetKeysPaged(t *testing.T) { } } -// Implement Tests once function is implemented +// TestCall tests the state_call. +// TODO: cover more cases in Zombienet tests +// https://github.com/ChainSafe/gossamer/issues/3229 func TestCall(t *testing.T) { ctrl := gomock.NewController(t) testHash := common.NewHash([]byte{0x01, 0x02}) From 6c5e32acfad34d0e6636b5c1e9600f0eac42d896 Mon Sep 17 00:00:00 2001 From: kanishka Date: Thu, 27 Apr 2023 20:52:34 +0530 Subject: [PATCH 21/65] use blockHash if present --- dot/rpc/modules/state.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dot/rpc/modules/state.go b/dot/rpc/modules/state.go index 57cac43f2e..b5e74a86e6 100644 --- a/dot/rpc/modules/state.go +++ b/dot/rpc/modules/state.go @@ -247,7 +247,12 @@ func (sm *StateModule) GetPairs(_ *http.Request, req *StatePairRequest, res *Sta // Call makes a call to the runtime. func (sm *StateModule) Call(_ *http.Request, req *StateCallRequest, res *StateCallResponse) error { - rt, err := sm.blockAPI.GetRuntime(sm.blockAPI.BestBlockHash()) + var blockHash = sm.blockAPI.BestBlockHash() + if req.Block != nil { + blockHash = *req.Block + } + + rt, err := sm.blockAPI.GetRuntime(blockHash) if err != nil { return err } From 80d30aaa6feaec1ecfeaf8bab21efe7d75f52e23 Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 28 Apr 2023 01:45:53 +0530 Subject: [PATCH 22/65] cleanup --- dot/rpc/modules/state_test.go | 2 +- tests/rpc/rpc_05-state_test.go | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/dot/rpc/modules/state_test.go b/dot/rpc/modules/state_test.go index c053733d3a..bdfcdf39d5 100644 --- a/dot/rpc/modules/state_test.go +++ b/dot/rpc/modules/state_test.go @@ -294,7 +294,7 @@ func TestCall(t *testing.T) { mockStorageAPI := mocks.NewMockStorageAPI(ctrl) mockBlockAPI := mocks.NewMockBlockAPI(ctrl) mockBlockAPI.EXPECT().BestBlockHash().Return(testHash) - mockBlockAPI.EXPECT().GetRuntime(gomock.Any()).Return(rt, nil) + mockBlockAPI.EXPECT().GetRuntime(common.Hash{}).Return(rt, nil) sm := NewStateModule(mockNetworkAPI, mockStorageAPI, nil, mockBlockAPI) diff --git a/tests/rpc/rpc_05-state_test.go b/tests/rpc/rpc_05-state_test.go index 1c6429aa63..b549077b51 100644 --- a/tests/rpc/rpc_05-state_test.go +++ b/tests/rpc/rpc_05-state_test.go @@ -47,8 +47,6 @@ func TestStateRPCResponseValidation(t *testing.T) { //nolint:tparallel err = rpc.DecodeScale(data, &response) require.NoError(t, err) - - // TODO assert stateCallResponse }) t.Run("state_getKeysPaged", func(t *testing.T) { From a1441ec68665933050287ebd239e8b26d3287376 Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 28 Apr 2023 01:51:11 +0530 Subject: [PATCH 23/65] fix unit test --- dot/rpc/modules/state_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dot/rpc/modules/state_test.go b/dot/rpc/modules/state_test.go index bdfcdf39d5..f0a97e723e 100644 --- a/dot/rpc/modules/state_test.go +++ b/dot/rpc/modules/state_test.go @@ -294,7 +294,7 @@ func TestCall(t *testing.T) { mockStorageAPI := mocks.NewMockStorageAPI(ctrl) mockBlockAPI := mocks.NewMockBlockAPI(ctrl) mockBlockAPI.EXPECT().BestBlockHash().Return(testHash) - mockBlockAPI.EXPECT().GetRuntime(common.Hash{}).Return(rt, nil) + mockBlockAPI.EXPECT().GetRuntime(testHash).Return(rt, nil) sm := NewStateModule(mockNetworkAPI, mockStorageAPI, nil, mockBlockAPI) From 0ddd6a378888325bf2b441e2e0e27e53069fe8c7 Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 28 Apr 2023 10:25:15 +0530 Subject: [PATCH 24/65] cleanup --- dot/rpc/modules/state.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dot/rpc/modules/state.go b/dot/rpc/modules/state.go index b5e74a86e6..42a76c31ea 100644 --- a/dot/rpc/modules/state.go +++ b/dot/rpc/modules/state.go @@ -247,8 +247,10 @@ func (sm *StateModule) GetPairs(_ *http.Request, req *StatePairRequest, res *Sta // Call makes a call to the runtime. func (sm *StateModule) Call(_ *http.Request, req *StateCallRequest, res *StateCallResponse) error { - var blockHash = sm.blockAPI.BestBlockHash() - if req.Block != nil { + var blockHash common.Hash + if req.Block == nil { + blockHash = sm.blockAPI.BestBlockHash() + } else { blockHash = *req.Block } From 28bd3405669a0783908d2f3fc2473a07624ae259 Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 28 Apr 2023 10:43:52 +0530 Subject: [PATCH 25/65] fix test --- dot/rpc/modules/state_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/dot/rpc/modules/state_test.go b/dot/rpc/modules/state_test.go index f0a97e723e..bf5dd3567e 100644 --- a/dot/rpc/modules/state_test.go +++ b/dot/rpc/modules/state_test.go @@ -301,7 +301,6 @@ func TestCall(t *testing.T) { req := &StateCallRequest{ Method: "Core_version", Params: "0x", - Block: &testHash, } var res StateCallResponse err := sm.Call(nil, req, &res) From 780a11b34c622a6b1b1a394386de3a4f8a1c0770 Mon Sep 17 00:00:00 2001 From: kanishka Date: Tue, 2 May 2023 13:38:49 +0530 Subject: [PATCH 26/65] address review comments --- dot/rpc/modules/state.go | 6 +++--- dot/rpc/modules/state_test.go | 4 ++-- tests/rpc/rpc_05-state_test.go | 2 ++ tests/utils/rpc/request.go | 16 +++++++--------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/dot/rpc/modules/state.go b/dot/rpc/modules/state.go index 42a76c31ea..742b023f6f 100644 --- a/dot/rpc/modules/state.go +++ b/dot/rpc/modules/state.go @@ -256,17 +256,17 @@ func (sm *StateModule) Call(_ *http.Request, req *StateCallRequest, res *StateCa rt, err := sm.blockAPI.GetRuntime(blockHash) if err != nil { - return err + return fmt.Errorf("get runtime: %w", err) } request, err := common.HexToBytes(req.Params) if err != nil { - return fmt.Errorf("cannot convert hex data %s to bytes: %w", req.Params, err) + return fmt.Errorf("convert hex to bytes: %w", err) } response, err := rt.Exec(req.Method, request) if err != nil { - return err + return fmt.Errorf("runtime exec: %w", err) } *res = StateCallResponse(common.BytesToHex(response)) diff --git a/dot/rpc/modules/state_test.go b/dot/rpc/modules/state_test.go index bf5dd3567e..3d7a3d6d55 100644 --- a/dot/rpc/modules/state_test.go +++ b/dot/rpc/modules/state_test.go @@ -283,8 +283,8 @@ func TestStateModuleGetKeysPaged(t *testing.T) { } // TestCall tests the state_call. -// TODO: cover more cases in Zombienet tests -// https://github.com/ChainSafe/gossamer/issues/3229 +// TODO: Improve runtime tests +// https://github.com/ChainSafe/gossamer/issues/3234 func TestCall(t *testing.T) { ctrl := gomock.NewController(t) testHash := common.NewHash([]byte{0x01, 0x02}) diff --git a/tests/rpc/rpc_05-state_test.go b/tests/rpc/rpc_05-state_test.go index b549077b51..2291eff77c 100644 --- a/tests/rpc/rpc_05-state_test.go +++ b/tests/rpc/rpc_05-state_test.go @@ -33,6 +33,8 @@ func TestStateRPCResponseValidation(t *testing.T) { //nolint:tparallel getBlockHashCancel() require.NoError(t, err) + // TODO: Improve runtime tests + // https://github.com/ChainSafe/gossamer/issues/3234 t.Run("state_call", func(t *testing.T) { t.Parallel() diff --git a/tests/utils/rpc/request.go b/tests/utils/rpc/request.go index c136a9facf..7225559c89 100644 --- a/tests/utils/rpc/request.go +++ b/tests/utils/rpc/request.go @@ -57,7 +57,7 @@ var ( ) // Decode decodes []body into the target interface. -// It assumes that the response.Result is a JSON-encoded value. +// It assumes that the response.Result is an optional JSON-encoded value. func Decode(body []byte, target interface{}) error { decoder := json.NewDecoder(bytes.NewReader(body)) decoder.DisallowUnknownFields() @@ -96,7 +96,7 @@ func Decode(body []byte, target interface{}) error { // DecodeScale decodes []body into the target interface. // It assumes that the response.Result is a SCALE-encoded value. -func DecodeScale(body []byte, target interface{}) error { +func DecodeScale(body []byte, target any) error { decoder := json.NewDecoder(bytes.NewReader(body)) decoder.DisallowUnknownFields() @@ -119,20 +119,18 @@ func DecodeScale(body []byte, target interface{}) error { var result string err = json.Unmarshal(response.Result, &result) if err != nil { - return fmt.Errorf("cannot decode response result: %s: %w", + return fmt.Errorf("decode response result: %s: %w", string(response.Result), err) } - scaleRawMessage, err := common.HexToBytes(result) + resultBytes, err := common.HexToBytes(result) if err != nil { - return fmt.Errorf("cannot convert to bytes: %s: %w", - result, err) + return fmt.Errorf("convert hex to bytes: %w", err) } - err = scale.Unmarshal(scaleRawMessage, target) + err = scale.Unmarshal(resultBytes, target) if err != nil { - return fmt.Errorf("cannot decode response result: %s: %w", - string(response.Result), err) + return fmt.Errorf("decode response result: %w", err) } return nil From 462ac39135bd9b4983d923e8dc1138a66a44eb5d Mon Sep 17 00:00:00 2001 From: kanishka Date: Tue, 2 May 2023 19:18:55 +0530 Subject: [PATCH 27/65] cleanup DecodeScale --- tests/utils/rpc/request.go | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/tests/utils/rpc/request.go b/tests/utils/rpc/request.go index 7225559c89..7bcdd49838 100644 --- a/tests/utils/rpc/request.go +++ b/tests/utils/rpc/request.go @@ -97,30 +97,10 @@ func Decode(body []byte, target interface{}) error { // DecodeScale decodes []body into the target interface. // It assumes that the response.Result is a SCALE-encoded value. func DecodeScale(body []byte, target any) error { - decoder := json.NewDecoder(bytes.NewReader(body)) - decoder.DisallowUnknownFields() - - var response ServerResponse - err := decoder.Decode(&response) - if err != nil { - return fmt.Errorf("cannot decode response: %s: %w", - string(body), err) - } - - if response.Version != "2.0" { - return fmt.Errorf("%w: %s", ErrResponseVersion, response.Version) - } - - if response.Error != nil { - return fmt.Errorf("%w: %s (error code %d)", - ErrResponseError, response.Error.Message, response.Error.ErrorCode) - } - var result string - err = json.Unmarshal(response.Result, &result) + err := Decode(body, &result) if err != nil { - return fmt.Errorf("decode response result: %s: %w", - string(response.Result), err) + return fmt.Errorf("decode body: %w", err) } resultBytes, err := common.HexToBytes(result) @@ -130,7 +110,7 @@ func DecodeScale(body []byte, target any) error { err = scale.Unmarshal(resultBytes, target) if err != nil { - return fmt.Errorf("decode response result: %w", err) + return fmt.Errorf("decode result: %w", err) } return nil From cb49d8f422c70fbe410b7bdfb3da31fc34d323b1 Mon Sep 17 00:00:00 2001 From: kanishka Date: Tue, 2 May 2023 20:27:08 +0530 Subject: [PATCH 28/65] cleanup --- tests/rpc/rpc_05-state_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rpc/rpc_05-state_test.go b/tests/rpc/rpc_05-state_test.go index 2291eff77c..d4bbaed40e 100644 --- a/tests/rpc/rpc_05-state_test.go +++ b/tests/rpc/rpc_05-state_test.go @@ -39,7 +39,6 @@ func TestStateRPCResponseValidation(t *testing.T) { //nolint:tparallel t.Parallel() const params = `["Core_version", "0x"]` - var response runtime.Version rpcCtx, rpcCancel := context.WithTimeout(ctx, 10*time.Second) defer rpcCancel() @@ -47,6 +46,7 @@ func TestStateRPCResponseValidation(t *testing.T) { //nolint:tparallel data, err := rpc.Post(rpcCtx, endpoint, "state_call", params) require.NoError(t, err) + var response runtime.Version err = rpc.DecodeScale(data, &response) require.NoError(t, err) }) From 94206ca54bfc23afd3c857aeeca303bcdb0883e2 Mon Sep 17 00:00:00 2001 From: kanishka Date: Wed, 3 May 2023 12:24:08 +0530 Subject: [PATCH 29/65] add tests for parachain types --- dot/types/parachain.go | 8 ++-- dot/types/parachain_test.go | 87 +++++++++++++++++++++++++++++++++++ lib/runtime/wasmer/exports.go | 6 +-- 3 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 dot/types/parachain_test.go diff --git a/dot/types/parachain.go b/dot/types/parachain.go index f15b21f98c..222e20adfe 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -52,15 +52,15 @@ type ValidatorIndex uint32 // GroupRotationInfo represents the group rotation info type GroupRotationInfo struct { // SessionStartBlock is the block number at which the session started - SessionStartBlock uint64 `scale:"1"` + SessionStartBlock uint32 `scale:"1"` // GroupRotationFrequency indicates how often groups rotate. 0 means never. - GroupRotationFrequency uint64 `scale:"2"` + GroupRotationFrequency uint32 `scale:"2"` // Now indicates the current block number. - Now uint64 `scale:"3"` + Now uint32 `scale:"3"` } type ValidatorGroups struct { - // Validators is an array the validator set Ids + // Validators is an array of validator set Ids Validators [][]ValidatorIndex `scale:"1"` // GroupRotationInfo is the group rotation info GroupRotationInfo GroupRotationInfo `scale:"2"` diff --git a/dot/types/parachain_test.go b/dot/types/parachain_test.go new file mode 100644 index 0000000000..ce6eb35aac --- /dev/null +++ b/dot/types/parachain_test.go @@ -0,0 +1,87 @@ +package types + +import ( + "testing" + + "github.com/ChainSafe/gossamer/pkg/scale" + + "github.com/stretchr/testify/require" + + "github.com/ChainSafe/gossamer/lib/common" +) + +func Test_Validators(t *testing.T) { + t.Parallel() + + expected := []common.Address{ + "5Do5qUFfEp5CcAfdcYSj3ZyPzQcbgtTMYZozyD4VCMF4gzDb", + "5CP9KEeF9V3eyTWEStEKQyi6grLsUgEZRqHVcTTm5PbL5CWF", + "5DqujH7PVLVLE7czPhx1gNohVCPUQ5TfhqJ8wKLcZH3zjKd1", + "5Fjd1oQRcLBfEjCVyqhDK2WTEhZ5srNU3LCVB8f52PLytLs8", + "5FRz16eLxHdvCtPfZXpNW5Cn1k61tKTLVrNH36jmAeurMtzp", + "5ExvT1sWmnt2DL5KJp7QnKXsMmx2AH5YMWmGvdkrGq2ycLHd", + "5GjySVgQVLKiA3UG3bJrUHb2Q9PNvFuSBXpUb9vo5arg4jw8", + "5Fxu9xhgqcxTtTQL1HJcLqQpYhj6B4a1Usn1LtYkc7qGry7K", + "5G1BUGa4iCLLQGgypZeeUThiLk2S9Y1Yy7ddpNhPLrgYf6kj", + "5HGRWRdLehaFbJ3zczdfgHhubCygs1bME8yLc4MWidqDwPkj", + "5HBuwTWAzV1LEReH8ohsWRUeCx5ykb3CkCa2GNJKHozQ3hcK", + "5Gj5kpJCbX5oQXRTv6insZeMtMCEptqJ2A5vB5gHsdBgwYJp", + "5Fhe8H4XeYdvV31FVfxKAivKcDw9g5EMnm7oWCunnFfrxEip", + "5CFPSw1J5S9eNyUoh1oceF3inj1zPsV8csiBzR63WZrrf6sq", + "5GBV6ye2TkgNTn9ctjVx4dfxfRQYV1pcPwxrR9ARTTya7Bwc", + "5DLNXbTdnVqoHK2rhskA27e9qxVQvk1GeY1rwxn5kzBf757w", + "5EyBuSrUhLx5prt47u7R4djuhAaenABPTNVruDcVEK7K574Y", + } + resultHex := "0x444c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e368589360e101de266b8f5f05431dcaf63ecd936988cc348a271f42519bef19df1e9af7f4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57ecee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237ac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a" + resultBytes, err := common.HexToBytes(resultHex) + require.NoError(t, err) + + var validatorIDs []ValidatorID + err = scale.Unmarshal(resultBytes, &validatorIDs) + require.NoError(t, err) + + var validators []Validator + validators, err = ValidatorIDToValidator(validatorIDs) + require.NoError(t, err) + + var addresses []common.Address + for _, v := range validators { + addresses = append(addresses, v.Key.Address()) + } + require.Equal(t, expected, addresses) + + encoded, err := scale.Marshal(validatorIDs) + require.NoError(t, err) + require.Equal(t, resultHex, common.BytesToHex(encoded)) +} + +func Test_ValidatorGroup(t *testing.T) { + t.Parallel() + + expected := ValidatorGroups{ + Validators: [][]ValidatorIndex{{0, 1, 2, 3, 4, 5}, {6, 7, 8, 9, 10, 11}, {12, 13, 14, 15, 16}}, + GroupRotationInfo: GroupRotationInfo{ + SessionStartBlock: 15657314, + GroupRotationFrequency: 10, + Now: 15657556, + }, + } + + result := "0x0c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f0000001000000062e9ee000a00000054eaee00" + resultBytes, err := common.HexToBytes(result) + require.NoError(t, err) + + validatorGroups := ValidatorGroups{ + Validators: [][]ValidatorIndex{}, + GroupRotationInfo: GroupRotationInfo{}, + } + err = scale.Unmarshal(resultBytes, &validatorGroups) + require.NoError(t, err) + + require.Equal(t, expected, validatorGroups) + + encoded, err := scale.Marshal(validatorGroups) + require.NoError(t, err) + + require.Equal(t, result, common.BytesToHex(encoded)) +} diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index e98f6d18e5..3f7b260a66 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -335,13 +335,13 @@ func (in *Instance) ParachainHostValidators() ([]types.Validator, error) { return nil, err } - var gar []types.ValidatorID - err = scale.Unmarshal(ret, &gar) + var validatorIDs []types.ValidatorID + err = scale.Unmarshal(ret, &validatorIDs) if err != nil { return nil, err } - return types.ValidatorIDToValidator(gar) + return types.ValidatorIDToValidator(validatorIDs) } // ParachainHostValidatorGroups Returns the validator groups used during the current session. From 629d7e8ae05cb4e6313764b6cce76a9371ed30c6 Mon Sep 17 00:00:00 2001 From: kanishka Date: Wed, 3 May 2023 13:46:30 +0530 Subject: [PATCH 30/65] fix availability-cores and add tests --- dot/types/parachain.go | 34 +++++++++++--------------- dot/types/parachain_test.go | 45 +++++++++++++++++++++++++++++++++++ lib/runtime/wasmer/exports.go | 5 ++-- 3 files changed, 62 insertions(+), 22 deletions(-) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 222e20adfe..19e29d2132 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -121,14 +121,6 @@ type CandidateDescriptor struct { ValidationCodeHash ValidationCodeHash `scale:"9"` } -// ScheduledCore Information about a core which is currently occupied. -type ScheduledCore struct { - // The ID of a para scheduled. - ParaID ParaID - // The collator required to author the block, if any. - Collator *Collator -} - // OccupiedCore Information about a core which is currently occupied. type OccupiedCore struct { // NOTE: this has no ParaId as it can be deduced from the candidate descriptor. @@ -156,19 +148,21 @@ type OccupiedCore struct { CandidateDescriptor CandidateDescriptor `scale:"8"` } -// Occupied Core information about a core which is currently occupied. -type Occupied OccupiedCore - // Index returns the index -func (Occupied) Index() uint { +func (OccupiedCore) Index() uint { return 0 } -// Scheduled Core information about a core which is currently scheduled. -type Scheduled ScheduledCore +// ScheduledCore Information about a core which is currently occupied. +type ScheduledCore struct { + // The ID of a para scheduled. + ParaID ParaID + // The collator required to author the block, if any. + Collator *Collator +} // Index returns the index -func (Scheduled) Index() uint { +func (ScheduledCore) Index() uint { return 1 } @@ -202,14 +196,14 @@ func (va *CoreState) Value() (scale.VaryingDataTypeValue, error) { return vdt.Value() } -// NewCoreState returns a new CoreState -func NewCoreState() (CoreState, error) { - vdt, err := scale.NewVaryingDataType(Occupied{}, Scheduled{}, Free{}) +// NewCoreStateVDT returns a new CoreState VaryingDataType +func NewCoreStateVDT() (scale.VaryingDataType, error) { + vdt, err := scale.NewVaryingDataType(OccupiedCore{}, ScheduledCore{}, Free{}) if err != nil { - return CoreState{}, fmt.Errorf("failed to create varying data type: %w", err) + return scale.VaryingDataType{}, fmt.Errorf("failed to create varying data type: %w", err) } - return CoreState(vdt), nil + return vdt, nil } // UpwardMessage A message from a parachain to its Relay Chain. diff --git a/dot/types/parachain_test.go b/dot/types/parachain_test.go index ce6eb35aac..876a29445b 100644 --- a/dot/types/parachain_test.go +++ b/dot/types/parachain_test.go @@ -1,3 +1,6 @@ +// Copyright 2023 ChainSafe Systems (ON) +// SPDX-License-Identifier: LGPL-3.0-only + package types import ( @@ -10,6 +13,7 @@ import ( "github.com/ChainSafe/gossamer/lib/common" ) +// Test_Validators tests the scale encoding and decoding of a Validator struct func Test_Validators(t *testing.T) { t.Parallel() @@ -55,6 +59,7 @@ func Test_Validators(t *testing.T) { require.Equal(t, resultHex, common.BytesToHex(encoded)) } +// Test_ValidatorGroup tests the validator group encoding and decoding. func Test_ValidatorGroup(t *testing.T) { t.Parallel() @@ -85,3 +90,43 @@ func Test_ValidatorGroup(t *testing.T) { require.Equal(t, result, common.BytesToHex(encoded)) } + +// Test_AvailabilityCoresScheduled tests the CoreState VDT with ScheduledCore encoding and decoding. +// TODO: cover it for other CoreState variants +func Test_AvailabilityCoresScheduled(t *testing.T) { + t.Parallel() + + result := "0x0c01e80300000001e90300000001ea03000000" + resultBytes, err := common.HexToBytes(result) + require.NoError(t, err) + + availabilityCoreVDT, err := NewCoreStateVDT() + require.NoError(t, err) + availabilityCores := scale.NewVaryingDataTypeSlice(availabilityCoreVDT) + err = scale.Unmarshal(resultBytes, &availabilityCores) + require.NoError(t, err) + + vdt, err := NewCoreStateVDT() + require.NoError(t, err) + expected := scale.NewVaryingDataTypeSlice(vdt) + err = expected.Add( + ScheduledCore{ + ParaID: 1000, + Collator: nil, + }, + ScheduledCore{ + ParaID: 1001, + Collator: nil, + }, + ScheduledCore{ + ParaID: 1002, + Collator: nil, + }, + ) + require.NoError(t, err) + require.Equal(t, expected, availabilityCores) + + encoded, err := scale.Marshal(availabilityCores) + require.NoError(t, err) + require.Equal(t, result, common.BytesToHex(encoded)) +} diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 3f7b260a66..3f5d782e4f 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -362,16 +362,17 @@ func (in *Instance) ParachainHostValidatorGroups() (*types.ValidatorGroups, erro } // ParachainHostAvailabilityCores Returns information on all availability cores -func (in *Instance) ParachainHostAvailabilityCores() (*types.CoreState, error) { +func (in *Instance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { ret, err := in.Exec(runtime.ParachainHostAvailabilityCores, []byte{}) if err != nil { return nil, err } - availabilityCores, err := types.NewCoreState() + coreStateVDT, err := types.NewCoreStateVDT() if err != nil { return nil, err } + availabilityCores := scale.NewVaryingDataTypeSlice(coreStateVDT) err = scale.Unmarshal(ret, &availabilityCores) if err != nil { From 0e4190b83424abf657533da4b9da878b7e70ca08 Mon Sep 17 00:00:00 2001 From: kanishka Date: Wed, 3 May 2023 13:50:22 +0530 Subject: [PATCH 31/65] add session-index tests --- dot/types/parachain_test.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/dot/types/parachain_test.go b/dot/types/parachain_test.go index 876a29445b..da3401c2e3 100644 --- a/dot/types/parachain_test.go +++ b/dot/types/parachain_test.go @@ -130,3 +130,22 @@ func Test_AvailabilityCoresScheduled(t *testing.T) { require.NoError(t, err) require.Equal(t, result, common.BytesToHex(encoded)) } + +// TestSessionIndex tests the SessionIndex encoding and decoding. +func TestSessionIndex(t *testing.T) { + t.Parallel() + + result := "0x0f690000" + resultBytes, err := common.HexToBytes(result) + require.NoError(t, err) + + var sessionIndex SessionIndex + err = scale.Unmarshal(resultBytes, &sessionIndex) + require.NoError(t, err) + + require.Equal(t, SessionIndex(26895), sessionIndex) + + encoded, err := scale.Marshal(sessionIndex) + require.NoError(t, err) + require.Equal(t, result, common.BytesToHex(encoded)) +} From 0f7d8572c79d956134569bfe50928fe066eea4b9 Mon Sep 17 00:00:00 2001 From: kanishka Date: Wed, 3 May 2023 21:23:46 +0530 Subject: [PATCH 32/65] fix err --- dot/types/parachain.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 19e29d2132..005f555e25 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -200,7 +200,7 @@ func (va *CoreState) Value() (scale.VaryingDataTypeValue, error) { func NewCoreStateVDT() (scale.VaryingDataType, error) { vdt, err := scale.NewVaryingDataType(OccupiedCore{}, ScheduledCore{}, Free{}) if err != nil { - return scale.VaryingDataType{}, fmt.Errorf("failed to create varying data type: %w", err) + return scale.VaryingDataType{}, fmt.Errorf("create varying data type: %w", err) } return vdt, nil @@ -329,10 +329,14 @@ type CandidateReceipt struct { } // HeadData Parachain head data included in the chain. -type HeadData []byte +type HeadData struct { + Data []byte `scale:"1"` +} // CoreIndex The unique (during session) index of a core. -type CoreIndex uint32 +type CoreIndex struct { + Index uint32 `scale:"1"` +} // CandidateBacked This candidate receipt was backed in the most recent block. // This includes the core index the candidate is now occupying. @@ -354,7 +358,7 @@ func (CandidateBacked) Index() uint { type CandidateIncluded struct { CandidateReceipt CandidateReceipt `scale:"1"` HeadData HeadData `scale:"2"` - CoreIndex CoreIndex `scale:"3"` + CoreIndex uint32 `scale:"-"` GroupIndex GroupIndex `scale:"4"` } @@ -403,7 +407,7 @@ func (va *CandidateEvent) Value() (scale.VaryingDataTypeValue, error) { func NewCandidateEventVDT() (scale.VaryingDataType, error) { vdt, err := scale.NewVaryingDataType(CandidateBacked{}, CandidateIncluded{}, CandidateTimedOut{}) if err != nil { - return scale.VaryingDataType{}, fmt.Errorf("failed to create varying data type: %w", err) + return scale.VaryingDataType{}, fmt.Errorf("create varying data type: %w", err) } return vdt, nil From e36bd979cc8149de33dbf66982137d3467fa4687 Mon Sep 17 00:00:00 2001 From: kanishka Date: Thu, 4 May 2023 19:01:54 +0530 Subject: [PATCH 33/65] add tests --- dot/types/parachain.go | 16 ++-- dot/types/parachain_test.go | 141 ++++++++++++++++++++++++++++++------ 2 files changed, 128 insertions(+), 29 deletions(-) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 005f555e25..119394af2e 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -98,7 +98,7 @@ type CandidateDescriptor struct { RelayParent common.Hash `scale:"2"` // Collator is the collator's relay-chain account ID - Collator sr25519.PublicKey `scale:"3"` + Collator CollatorID `scale:"3"` // PersistedValidationDataHash is the blake2-256 hash of the persisted validation data. This is extra data derived from // relay-chain state which may vary based on bitfields included before the candidate. @@ -228,7 +228,7 @@ type CandidateCommitments struct { // Horizontal messages sent by the parachain. HorizontalMessages []OutboundHrmpMessage `scale:"2"` // New validation code. - NewValidationCode *ValidationCode `scale:"3"` + NewValidationCode ValidationCode `scale:"3"` // The head-data produced as a result of execution. HeadData headData `scale:"4"` // The number of messages processed from the DMQ. @@ -255,12 +255,12 @@ type AssignmentID sr25519.PublicKey // IndexedValidator A validator with its index. type IndexedValidator struct { Index ValidatorIndex `scale:"-"` - Validator Validator `scale:"2"` + Validator []ValidatorID `scale:"2"` } // IndexedValidatorGroup A validator group with its group index. type IndexedValidatorGroup struct { - GroupIndex []GroupIndex `scale:"-"` + GroupIndex []GroupIndex `scale:"1"` Validators []ValidatorIndex `scale:"2"` } @@ -270,15 +270,15 @@ type SessionInfo struct { // Indices are into the broader validator set. ActiveValidatorIndices []ValidatorIndex `scale:"1"` // A secure random seed for the session, gathered from BABE. - RandomSeed [32]byte `scale:"2"` + RandomSeed [32]uint8 `scale:"2"` // The amount of sessions to keep for disputes. DisputePeriod SessionIndex `scale:"3"` // Validators in canonical ordering. Validators []IndexedValidator `scale:"4"` // Validators' authority discovery keys for the session in canonical ordering. - DiscoveryKeys []Authority `scale:"5"` + DiscoveryKeys []byte `scale:"5"` // The assignment keys for validators. - AssignmentKeys []AssignmentID `scale:"6"` + AssignmentKeys []byte `scale:"6"` // Validators in shuffled ordering - these are the validator groups as produced // by the `Scheduler` module for the session and are typically referred to by // `GroupIndex`. @@ -317,7 +317,7 @@ type InboundHrmpMessage struct { // enacted. SentAt BlockNumber `scale:"1"` // The message payload. - Message []byte `scale:"2"` + Data []byte `scale:"2"` } // CandidateReceipt A receipt for a parachain candidate. diff --git a/dot/types/parachain_test.go b/dot/types/parachain_test.go index da3401c2e3..28a88a3579 100644 --- a/dot/types/parachain_test.go +++ b/dot/types/parachain_test.go @@ -17,6 +17,18 @@ import ( func Test_Validators(t *testing.T) { t.Parallel() + resultHex := "0x444c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e368589360e101de266b8f5f05431dcaf63ecd936988cc348a271f42519bef19df1e9af7f4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57ecee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237ac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a" + resultBytes, err := common.HexToBytes(resultHex) + require.NoError(t, err) + + var validatorIDs []ValidatorID + err = scale.Unmarshal(resultBytes, &validatorIDs) + require.NoError(t, err) + + var validators []Validator + validators, err = ValidatorIDToValidator(validatorIDs) + require.NoError(t, err) + expected := []common.Address{ "5Do5qUFfEp5CcAfdcYSj3ZyPzQcbgtTMYZozyD4VCMF4gzDb", "5CP9KEeF9V3eyTWEStEKQyi6grLsUgEZRqHVcTTm5PbL5CWF", @@ -36,18 +48,6 @@ func Test_Validators(t *testing.T) { "5DLNXbTdnVqoHK2rhskA27e9qxVQvk1GeY1rwxn5kzBf757w", "5EyBuSrUhLx5prt47u7R4djuhAaenABPTNVruDcVEK7K574Y", } - resultHex := "0x444c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e368589360e101de266b8f5f05431dcaf63ecd936988cc348a271f42519bef19df1e9af7f4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57ecee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237ac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a" - resultBytes, err := common.HexToBytes(resultHex) - require.NoError(t, err) - - var validatorIDs []ValidatorID - err = scale.Unmarshal(resultBytes, &validatorIDs) - require.NoError(t, err) - - var validators []Validator - validators, err = ValidatorIDToValidator(validatorIDs) - require.NoError(t, err) - var addresses []common.Address for _, v := range validators { addresses = append(addresses, v.Key.Address()) @@ -63,15 +63,6 @@ func Test_Validators(t *testing.T) { func Test_ValidatorGroup(t *testing.T) { t.Parallel() - expected := ValidatorGroups{ - Validators: [][]ValidatorIndex{{0, 1, 2, 3, 4, 5}, {6, 7, 8, 9, 10, 11}, {12, 13, 14, 15, 16}}, - GroupRotationInfo: GroupRotationInfo{ - SessionStartBlock: 15657314, - GroupRotationFrequency: 10, - Now: 15657556, - }, - } - result := "0x0c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f0000001000000062e9ee000a00000054eaee00" resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -83,6 +74,14 @@ func Test_ValidatorGroup(t *testing.T) { err = scale.Unmarshal(resultBytes, &validatorGroups) require.NoError(t, err) + expected := ValidatorGroups{ + Validators: [][]ValidatorIndex{{0, 1, 2, 3, 4, 5}, {6, 7, 8, 9, 10, 11}, {12, 13, 14, 15, 16}}, + GroupRotationInfo: GroupRotationInfo{ + SessionStartBlock: 15657314, + GroupRotationFrequency: 10, + Now: 15657556, + }, + } require.Equal(t, expected, validatorGroups) encoded, err := scale.Marshal(validatorGroups) @@ -149,3 +148,103 @@ func TestSessionIndex(t *testing.T) { require.NoError(t, err) require.Equal(t, result, common.BytesToHex(encoded)) } + +// TestCommittedCandidateReceipt tests the CommittedCandidateReceipt encoding and decoding. +func TestCommittedCandidateReceipt(t *testing.T) { + t.Parallel() + + result := "0x01e9030000328b2b271db466af1870b5918aa43aec671de9803aeadf75013d3c78de35ceea84b5c6e57a116cba4148aaad37fbfc3edc54e7728b5192a40391d9c8ef33bc40e0a84b429996989d65526edda87a56b79f51b98cbeb347ce22a356cc7da02e38ab0e77029716d6a3e8b45e3ac27c623c347f28d433926a7f762cf0018484f58e505b19ef3223929a5ac8e2f17e5add18665a164f002b806899329b25c8da3be76c5664eb273bc0dbc3016d1304e53fc86b20d4d3583c4b72599ffe4386aa7060c9e6f1ad9699ddcc8f2bbe324c882cba6307b47e991cff013ffc307cc7d3e4831efb8e925358db3e93e466f6238871a8a29a6028279db855f0eed3fe4d7705f2dcc6cda49b51efbe0fd184b974074d1258ca9f15b9fccfedc35b7dee6e1ab9e9000000e902bc8e637ddab3bc69db43a62181e9a5807647ae518b205161b1beb25cc72bb441a6dc4600cd7190aaa808a47ac7c2cce73922a0cdde3fc639969c76d5ab44566e25e5fee50cc06625cdc46c76bd0bf8c046308022fe7b2cfd31859fcab2c7d84a2b208b1b080661757261206f495c0800000000056175726101012cd5b2805efcf8f0d7a35e05a9b3582df5af3cab0c912af9a56e83a10a42ef56b4feea6347c7c862c71ad66e0a6296cb6e46cdf10baf65dc89315f2768fd4f8100000000a18fea00" + resultBytes, err := common.HexToBytes(result) + require.NoError(t, err) + + var c *CommittedCandidateReceipt + err = scale.Unmarshal(resultBytes, &c) + require.NoError(t, err) + + // TODO: assert the fields + + encoded, err := scale.Marshal(c) + require.NoError(t, err) + require.Equal(t, result, common.BytesToHex(encoded)) +} + +// TestSessionInfo tests the SessionInfo encoding and decoding. +// TODO: fix the test +func TestSessionInfo(t *testing.T) { + t.Parallel() + + result := "0x0121035000000040000000d70000003b000000f40000000b0100009200000078000000ea00000027000000ad000000cd000000b6000000220000001f00000010000000fe000000a100000037000000e0000000f000000054000000450000003d000000380000001b0100005900000047000000aa000000160100004a000000d5000000ee0000003a000000d2000000df00000002010000d90000001f0100006e000000f9000000d00000001301000006010000bc0000006d0000005c0000001d010000b800000000010000190000004f00000015000000180000007d00000006000000250100008c0000003f000000fa00000004000000560000001e0000008b000000b20000005d000000bb00000035000000f7000000ba00000075000000fc000000090000006f00000055000000eb000000b70000000d000000800000007f000000a6000000070100007100000033000000c800000073000000f300000017010000fb000000b400000001010000890000002601000019010000290000002701000021000000f6000000a90000008d000000040100000e0000007b000000c3000000a2000000cc00000062000000de0000002f000000310000000c01000074000000e900000024000000970000009e000000480000003c0000002001000066000000210100004b0000001b000000900000006700000049000000e50000002b0000001a010000e3000000980000004d00000005010000ed000000810000006a0000000b000000cf0000007a000000a80000001c0100001c000000950000002800000083000000d300000043000000c5000000dd0000003200000061000000fd0000000c00000026000000d100000003010000000000001a000000230100002401000012000000130000005800000091000000230000003e000000460000000d01000042000000ec000000a400000082000000a000000052000000d40000002d000000be0000000a0000005300000011010000d8000000a700000014010000390000009f0000005b0000003600000068000000930000002a00000007000000f5000000db0000001e01000018010000690000008e0000001d00000077000000da0000002a5c9458a86c0fdf9dbbb3a601b73ffdfe2e4286b19590105f3cca519368a49e060000002103703579df75d2c2dd3d53003f55ebbefeb59446d476d0a722ef8ed1954fae9d6d887163920530fb937e8f1da96a7b61d25d5fa5ec340d6a0081b79371bba84602b20cb56c26ed93ec124e1c74118106d1185564c7c13d79440adac261a32fa066280f6162242be89d139d52f449e2bad667d7d974cb80d0edbce7237185b114755034e95e2ceeaae78df5568d0fb779511c7eaa4bf3bd4c93666161489f0ce15e9a434cba271bd56cc40fa8e08ab8837da8abd274e7db6da8551e11cb14ce154d0a2a458b11deeca8a708cb12b8212da06449f7c8136862b0bf11fd368d00143e6a98b861ac1f6182a14bd30adcc699cf22e900d5f51711e7d41bba4928de23519a149b9b68af793ab31f83f500126e0fffa71469e78e22e754f3b49db1dbe6316e07945d95fb46ef5346bb3a502da9f005d1cdc956e1b96258fba48dc793f50b3256f3f643ebc6300f32561a0a5583813bb3b42844d1ad3d3779a438771a295e18cea89823eaf4f9d332f3a74ee2d88e19b321a311b45f095b05c82f4366c0093cd4a621e6146ee5e441e904aec79a734da3675970cde7793608ba482602ce2b306daa91a5a25590d2290fd262d40f239f87d37e1c03a2494035a42961db2f33701058e68510bdf68a3678d32145780e13c29b88fe77b27440bdf3ea9762a639dc3a5a9fa2b1bed2a4a48fb21792b44c5772f888132d414d13a98bb5bbbbd70a46b3d1cb07cfb8d2e13fa9158734dc2bd1ea554fd3032bdbf9e9871d29370602d8e45f1d6d02c43c3e38d6e7871f18ee80f60415adc76fdf4c8ad2c67ac7d116f02a182d14b38906ce1f4693cd9b87d0369e6af514cf7ec91455b26cd4c0d71b5604f6624a20179a00fb5dc8ba0bee359255702c162c85d72496ca031266554deafbe5a4ba60e2abfaf17f7f730e43bba40e7102e6c75c08f27403fb9761d874167e6d847ad207f3a1221ce1f958946317e77ba146d16aa7bd82810c5e913c4d76c4d221bfc6da82c7055e469a1405eca842b4b8efd101e984a2482e526ecb08482cdc214f825dc7085e54a984230a753d66d08425f9763f52f8f689111202601e0560d2b374b7d6e1380b6b88ee8ef92cdde7edbd9a48d66f5e219840a1155898dd787757d12ae0629612152b863116a5e2d0e204011b12b06101158fe1fb7230930357b8b54ce94dfac3276daca91ccbab9b944bdd9754fb27d2b786427b304a3487dc0c46f976d352e5e152e120d2d23774f921583d1f2c128f7cf9f66529e2379c7f13349fbdd0d6a65918797b977a5509f31930b09dd62983e0609dba11c42afa68950568131a449e70574ae0f45f28b87210c1ff7df1adee5576d039500ab779ad711947b3faf071e6ef46aedbdb33aea5a26510057e8439e09abcb0321e282ef8862f121223f6aa19fc1f929106d7a916747f21e1973eec1e8c5b7f78b61bf2c4723c0ffac961d2a54b44eed88f74076eacb58b8d0f208588ba2b435428e15975e20c0f4dee26bbd12317df11d4135edba1eb865bdd6111af6d27693b347964127e9d8bcd119989a92646c80886c2eb8440c87dd7dd94437873a3ce28cedcb9f27c114aecd7c8860d96145cb226ea5dc9139419533886dfe6e340f023d49f031c94d9c3b33494849eb9682c0311b3c283b17373f18b9ca02d94e2c05cf8187c36919c9d3bb5bb42f9539f8fca2040717cb0c409c58991b5bd2945f15400af2466b5e4a434ad5ef602a77f311fa22300a5a6ebf03bdcc04f92fdf0da3cfaf06927382cf7d52882c7033a6baccc329b4d4cf4f8b6cb592eb9065c3fde133667fd3b0c5fdf2c30cccdd640a7297da408b6aff82ee9651f889910fda9f24c06859e71b51c3b67b9be211ab3dd2de59e860d8757616c4398fd9273e6320e4d569159331192c6b6949dee038eac8ee723d32f77f049cdb4542083249db6127522500f189af22d09cf00c8851df6c4ac122134f428b24be25e12914c8bde527ce059357312bfd525317b4f93e5eee1de639872edfaec9d2a320a6fac04d61051e41161e6df14443df6eadfb3c5ad5228291d1383cdaaef20c9cc8125f7952f24645c3b5a2e17df20f698507190332c6951d761c5f46e0dcf997c7337c0bb7e5434cc7903dcaaeddb2bd99fd6b36ab15fc32ee001bd1d95e87020019f7c88be2ef63d466d1560353a2cfa849afbcbcc86cdaa057bd819895d4e90820b8bf9db7bc4bc688653010a7720d44168b4552bf75974219788ac1cf3fb440c67ff692d49b27ddf8cb39d72e9fc00e6165f43fd61812f9dce895b0d89329d2b870a91d0282a345983fe177ea7b18090fcb028cc41c1c4020feb6b80f807d4b5c8a4756c4b72ca569751b32be145716eac8ee5e731a1db2b1dae4b9023b05876077cdd78089a53c2f9f5f55bd687e359ef37196cd288fcd1a14adf6cad53c6704445a1f121d614110699b5642a4b726cbcb74bee77642ec7b4f17b06db88ee461848ead17cfcd9b0171f73154a0734c1cc95ae552d9f3180d7d64e8b50d3837b14b5afd222aafd3f8056d3462eda0083ac22241db692c4671249a14a04c2f0a2959aab4126dc96b44d66194bb8d466903d20f3f7b04217c3b5ec66111c325ff76450954665d669fa5f68e69276919abd026fad265d5062567425e3f2d364960dfbdbcfd3417afcd4713265cfd83dd24d3bfdba3d67384f32e4ce357fd88c4586d3abffbd33d2ebb6671ff854613aa3ad169250e037aadbf0ea14c87982d7382f09c7b8c967e24208a0bbbb7035130798abba24cab205d22443e8973817b685f13c9012b97c38a1fdd2dbd3f5ce02f08fd3858799ee6a994c48cc1db6d713d6eea3dfd4a93590f0a210318068c2a90f4dc4f2e114cb83367e561d811e18c30a6c2d7c8a7272128714ed41e3d13b8aad0d076b7ad34af4946866f552568eadd3d3582b4c4f50f286ac449dbc94282864e76dac48fb9bce48124189d2d45e2b2e16b8084c022b3405a94626a6d3cecc0492a268e974e9864826f8745403fbb98f55bf45c0b62002d1ae50abf4787916aa4d35e41d807f88e32460fb084187b4070c3a7331f92f6ad32f9b9aff185ae19ac28f3032c96ffd8fe3dd72cd0446f9e0098ed3a2fe2d56aee499b2dffa90a79b118a646aec6b79e6766dc25665db73a98e173fa6381a484d1bff4961f87c7ff6a6a68beac9264665f87ba1a5fab9802f1cd729391a711af7dc55da09babaf097d1304b4cde14562506f4db4897644895324b542d8f5778f186de80c5d2d0669404118ff1591ff141a606e05e2835889a5f42a32e9a1ff4e91b06cf4e6f6ecf77590356fa1773c014185bdf5a44972e03576c477fa731925f1d69f20b9d9cbdec900346fb9dfc869c696b3614062e5716ab0a579ca33fb429d0687fef75f26e5503379a61920777ef1f254af024922e382dd19e752e699e2c6f01ad57676c99bcf413211db6d82b36c39b441d65b0d7ed4c5aa0bf24050658f8f3a64ec6949a26916ae2cd976fe531947a9c9e93e6d587bac746cb08264eed0663b1d15bcbf9e99c372c041ef118de7d179c68899a645a0fa0983b473ef81c50a41863194537aa28f805d69280250c97b5c4f913d4030f8110085b200cc802ed675571cba95d42bfe5c3394fb7ad5778ddc436f407fcce0ea0eb427c0ada5bd7647f8d8388c2b4dbc138e36b8679284eadc49370ce0a16a4e0be28804b88c40cc8b84d75f043545a46bc8124a169ccaa40158b1f60915817f5f22ccb75f6c138e9e4061b3a799bf7987ef5c820c1e534df298f3328e1093c5d0758d434ea33c3da5b7189094e98315abff23fb4044c5d78633336658dd5e47e973ade4d8a7477bdafa88e49f5c8cd88fbcbc1724d8e227935eabce71ec303d832c4ab27106827b00917fd22c6b8e62eda5e130344c9214f2565b92ddcd6b6edfa18e95fd4d65053a5ef2ab1152c72f3b15d4f24d4bced3b7e277735eb49450dd867c115a4572a284f0f812d5fcedd8983f24df41875dac1ed854f1bd126b4d76c416e54b48268cf5d93c19d1969468b3fa94ba9f249b0c9464c6635728a2d3fac3d123472d3ac8b4dbb4b6a02692af692160b113da09d4ae9f0464c5522b7236a59b70d98b499a9c38970f6f3dbee7e6220ee0e12a582a76ae036347816baa6cd7c9a7bcc90ef1acebf194c7b9820968e554e2ec4d34346eedf80cacdafcdbf118a3f15a47238af22f221626e9a03a6005a06e53ea9554fed6ae199c0b84c769d4731709662caa1a29ff92ad66794001cfaaebbdf4071f4db6d74ee767ba59cca4cb36c0828f0bfffc49973cd14329675728a2d243102ab486601f1581b1e741bb5c775de464459b18deeea6f02d5882e80a8696b00c9f703da84bc5769921053ecc7494e8c22d93dbca83c05bc5222ae72b85617956f04eded477369ec95312c7c783564a615616a60f11f3faf3b83415d572e0c7db6bed9aa119aa6372f6eb7ecbc01cc3ceec15a5af2b64d5a43ae54fcccd31ddabe95461fdcb5be506267404ba432b0cfe1745dd408f6dfa0ceaa1780ad4ae1747a8912a589a754ed86373a08ff557a99adb8191a2eab2473283f387361100853b1eb98eb69959d8802d730bbde3d969ae5d9d6efa40c6255ec4b27b0a4752d7f4068163116e76cd0d4041c471431de365e70f8503654e384a4524c1c16900873792541ef023019a68f62250b7c21865b996d545865beeef3b84ab62610764825db06457340d99d3051903a759b4a68a25e2913e0d6e61521809ccd9dbead6b71744771c25d31cfec9c4ca5ac0c21765478a56c4b3708da965c36dac2e8caca9398d50bff836219540b179bae76671077a01e7352b7f4ea4faa4d7176fb75dd9c99844a76a8d042a48c5f76a34a2cc056df4318d12a052ab505db7d06dfe03767eb5f46cf0d271393db1db2516c52a0d9c323ea08a0551f96c28b05ac0c7b0e338cc5004bac22d06feea5a8f5c0011619ab90bff00f89ea8055f0d7d45f8c8aa9c04b7fc1d06468837c6c563a6529c414ad7aab917306d30209c502394c169a698d1461eb23ba81dcf998bafb3635aa091181db267cc8ff6c5201acaad6fc2c3a2cd18eb729ad0c1526c6c348e3308e650f7e08ac882d65fb09141fc5c7d252da9b1d8ca2ae311752ddce97713722aa0b27274712eaaf13c959cb84495856b51b71d066d3d4a346b37d3e2d587a0bee13fa85260215c5235169fea113546e7b4aa7a1c936c47a14e81d3df912601ab2a1fefc7a956231a446a575db2e31f7c084c2945094f3927519617d7b913712061f1060d5207533b44b4977f128acd44bfe1bfe235f2f4b2d042a87c7da4d1d82faebc67455d17caf2247f2b470db6bd8917913635bb8e41582ff0e06d22f092a27a84cd2398fd21f533281bc0d6ed0ea6c50fc7077add24dba8eb41b43670ca2fe2f72540e18669d0e534dc562fa03af53b90a8003e7e355849dc2c489082f4408b86991f7ff8f5676ee81ee9b44be90d067969cfdf6a95d4004396be34c5c80fc5fd10948cd231f68ec00397e22a19042578431aad63546679e72efa3cc61b40ef939e553ef7b366ae8d3b1da893ecef71a2bad32e39e7597b1a664d5393c34d4c6438f429028ba64818bedeff64b1db1ebdd89f2c2b2fe3336942a03036bb46bbbb430df46c7c792d3a23c29de2dd7189892b1a28742091213c56139b20a408b1d453ae31f699e53904605cfdbaa72639138cea3e544258e0484a5322163ba846878e4f157741703bb4c3ab4f3ff2e9b99916624a9965a4256d893c84e150ed18130a0ed0513b2a2bfa7ed6c9090cb350983746b1936c6a92f7304a70054a82cfd0a101c80974526db2868471fe3b84d802610a5effddb0a1d84f03f276afc2dfec5fc9e062cce0b84af38f1aa1e0aa8cdf197da7df8abd786a47a3c7861108b830844381b9efb92625d7333f62f5ed580f29c83cc232fbadf64439cdb32e2ca7cc3abf450897e2c320b9595850ce89fc41da36cac7c2ca9b135daeab148645771381f31a42a1e0bca62f752fb49e8d2a49f942cd48a03129a709e763d23547b4c766e40db6b1685c455de210347c5757ebb7d463d1910eb70fb290b5c7b8afa23b3c8f159391a3ffb6dda5ce3c9f6b40f25c1dc7a742186b7b693f30111c4b778017656b9a7d69d3e69159852f38adf971f5a25df65f9950e97411c1c3638c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e85297eeab48cb88c51118ced6c65368c5197ec7f014c443b47d898627cdb77813514782e505e29567f9cd04ef52e106d671e5591af83fa3a5475e6dc2ede9ef7f03f70d2ffd3b72525806a645e5abd09a51d257c30dcf016435c114d26d3d3be17085809bbd7c01492cb4105e4fbb173650c3586f94af7b6d9ad2835f62872e7ba4f5cac0ffa042ee550a3bf70d380dc032d11eabe311e0796c5143341600ef62664ce534070da425ee9c583103b7a1df8603d6dc9b08dc3692d6ca6a831c93b822cae73975ffedd91e81d8d6d9dd6c865356ae655ad1d55fa4a3e3641d2e2b3d12582942ab79f74656a8f51ab8c1b088f33ddfa20992eaaae491dc3dfff9742fe32263ad657e55682de826f6137dedd2d246971fd8c5d318034940160fc179efa6306b888519767218eed7b884fb221f597a2d4edb69c094961ace2e65a7e40913c5edbe8dcd591d30511a0fc08bc5172ff58ff98fa848387b25f99205361348105107c0623b54b469b13f24fb30d9556087096c900413e5f1229b844ef0fbd8846b0acf62c24bb58eeb0a71365ba5f890a594cc046a483d9b306a487ea4eb5e80518913d34cc4d0c2b0602803371bb33f5946fe6f4a44388a05bdfa02226be6f176c36aa9c0762a59eada83c70e1049d5d09f7f7304c465f2ff56dbe21687ece20e60838991dfc86f6a774c295cbde7fc208880cbe0a02c4434d31b7532976f66f2270467b0c03fcfd8bac09473161c6eba9c25369a853193b472eb2f113a3d333806eb5dcaff87a28d25de336e240731a375be04c4bbff6be6a5ba4f1042a06706432533fdbdd1a739c62733cb36ac48c821dcb0311978f1027bc1e39d4c8964e42c2279a99ce0b66cb06a5005dc6061a241edfd1860476cc03abf527f668971cfeba93ce0a747704cdb63a6affc76d6e6753469532256f29226d97566bc7de00903f1b40303c03067b48189de899eca5f2a7d8081ef4c3ebfc8aa305dac4637758c1f97d369f4290e38a09b7187c55dbc2c6c180d278cde597075ba0fbd0a1262c19794d20de22edc9c4c1514f4f4e29ac16e6b421d3620ec6545f737100f01372e1be0414087552630274f329a465cb85e625d3bd3121ba7df904a753cdc70b5215aab350a03f5371cefeca57c3685e2cae8845673073c0d89e3f654e206c1bce5d949162cbc728667ecce548da5efe0448823e928463418342d41883dc6e2030f93bce6916b6b78ce4f7d550c39c7947c6860502333717d541fdb6697ab4472078921751764a4d5caf9a2ed29c0bc7c5ede2cfc5460155d4818f3bd211e3389e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712160bb493e536e83addf98be8cb2a0158cf18c6d5ba06ab586a2cb56cf1ad4cd09c81fafe5d47c4ee373a54a64d267c497c59f4c15077374317b91566d44c82f74b8d2a3c1187b96dbac7ec6ee71a9c9ae3713acb168a8f0e325d22fa6be66e74e4c29c11128e193f06c866e165662d903d9f799508e617920d786ebf75acd26743c50b2fab9b87f1a6228df23e9507c90bec51b8e3be978b526c0e0c7704c7334181e6b71b981059fa265cd76422e52fe175db6983c6ebdd0fea1a3075166b92936da4573a6c20044052b270916290b13a30adf3a821b467c4038a14026badd09ae9fcd9ab8a7020a1f967780a1ef49b13b40fc3cfd208e29f4d5d5ee9bb63c5f7cbe0f373967eabbe8b5f5302ca7d7d9ecd763d3d2dd4c28896f14e730098c443ea7825552b7f76db8f2ba2fce0e546d7e7abab7d59e7afee2bfe438bad60919a6c2006ee64daae1fc0dc0cb5473b35b338c934cd957a64e7ee970385650c342c6eda549af9f0787a7331fdc24174026c49bbc00a20cd9d723f6e172988b462990932c5bbb2666927583b8a8aa64f7480ce8d8705c0b2ec53fb39584b660481d148f2b835556a0c8d3b51ae0e823655bd4aa20fdadc6b4189de9f32cf228870000b9032129790c24e593457de03f1950c427a6958487a0a8b3cad21f7581e43d26552839c17a5dbf3b2f90875abc9959553b320da9f07f1392fa3065315a8b17c2d3f9f9f499e04d2f27dbe47ffbce115afd1bac9fe116ce7fae719325e4082436da9dac450b4c23405b4f93953b74b11815f0f0cd45d2022d4ecf6a320eda1ae232d9f4c8884a9f53a999e8ce7a27f68e9108a4fde15bc51a350774c22b2a147a599c3e8a28ad44c5e3677254b2587f269e73d370d0c04d267092a52274844ae8c13e37a4d00135dbe7699d91507f5a53a7b8ed36a3be29cb2fddab9f7a286c78f2db2e0d3736589c38da969e8ccdd8e175040e25af8bcbea5a5c0568c9c624744c3b91b676828a5f884e79d9c02d6f23ec246c3a1a8adcfa9dc1e531a9a5317ce213846134673a8addd69befcd121e08a53cebe9fff3b872a7debfffc96611264105f794545152cfbff9151899b846773cd928403d11400e4d514e5f703d408c33a12a32c203715ebd7b2e9f574c733d0197fb36f2587028614be990caa70aa02f9a012221d644717e2f1361ddfd9e6b5d0043f3a47eeffab15e43d7d45e1ff8d720c75db2894a9a2746ccba83bbae55c0a99b821a41db37b0011d12a01a6018d3fcd225254bfac8ee7f94e5f505496773b69c49697eb79ef8523530c55511d816c065e65b3583c8309e3465db95b458d0b42619e1ea75ca546e966d761c5394cc6b2efa21cfcaf122e7524a35dcded808306c042e70bab6298ade3ad80d33b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411da504b6dbcce848e56c21d870a965f61bc53894462a6997e78f55f20ebf32f8f4de37ae23e707c1df21527ba79fb2c6cb074d51ed0b90e361b2cbda0637c074415c3e585eeb7d466f7e38b980536e62c00fd3dc5c703c3bbd721c9491e6eb85c32a44664e74f116e47c0991afa7bc43d0b4aaf085d205ced8ea01235b224e9e2a57569eb394a00dd88f01a451ade235d634484a9c56c595224495874fbdbdfdc1e9329e2e155aa2dd16ed173f806fb4531de44350ea0f1ce530bf0199d2a4e5912a042c88235eb7ebc41513cb9d42bfef2e56ab0a86eba53150cdf24f8ca5429b6c5590a786a922fad3ae1f8e6ef534f341aa4ca800700499532dd0d9436fb24c1b1b5ebb74bbc3f5ea7cc6eb966a566123ce03005a73c0294531cdb87e6f4e95a51514a49f30a2a2f680daeab96ba080e9436779e88da9f35f1df28aa84992e99a0b3a836e898f478234d26fc7d8bf866a6a308f8f7cdaab738bc98b879669911a26e05965e7b4c7ef5319c98707e231a82bafbbc639a8613ba2d4f22584de53740c421e7f92dcd88622e35e35994021fd95c368ce30d455831b8d7b5431f33a7327d87f69b187cd620e910289b9d5c2704d332359fce4040b4978eb1527e743dc1526b7a3b02d5edba566f82d3f949278d4d0660165857965f123b1ff5aa680a62c36d972bf0421adc4a00cd631414f1cbecb646e0008529253e9c0169822efb33cbea69d9e769a9b465041255b591fe2708f1193c6a0d7e83e929c167d0f672a6c8c62c3e73695bc27a72c21d264daa0d40c012083c581e4a0dfc7f168b722b23736d3b2112224e3432e605d698c7809f9599544725f3bbd89e076742a2e33631e1c33a7f530505af5bd7347c366ee21d089ea4ef1f48acfe1bb6d6c340aecd66660d3a60f115c98e714b9ca80bb1bfbe16704fb841cbfb0bedad90d8ee5106d21a44c8d3067a4034b5d6101af80d9a2970f3443536302525e41dceba23d8862004e1f947c0be485986af1fefb306419c6fc3cc203303517dedafea231dd90856d62fa40d6ad22c0bd13811d9555f4b2adb0f639cf7ace8468db36e557c1e1176e42f7de325ac001c0d50c4d27c15248ae2023cbc52e2ee969b16fbef249ee2542a27e810f57d102788527c3e274dddc99f094edf73a09544cf3f162573d6da479d65e0318bcca6caafcefeb3452d68d6197c8ea0b26b971962e201405c4c157651e202a49166a5e267724e5bbd0d9efe57d34d8cd7a2e536cc7aee14f127260657849008fc52de08473191d53f8cff9c54059406398e89683d41db5ca287bb379e421d77953121b3efeb10cd44d504b5cf47a9807dacce8eb24d53ce62e1458353e9052ee1ea8f6f1a8fd7b2262bfb86110b06210c25e7fac37b49198155c24719e961df7e2cd5aa3f816fe8950ecc0c2c9838fbf68bca5d4955de8719bb6cf7972c623880702eed40e35aadcfcf6b09f67040effbeddd2b22af32c2978da711f6ea75184c3c36dcddad7c1a570d4167525f3f53d8d39ebaf2d239bc1f9e7572c9c2de89a454439ff9ddadea199ac62ed47b9326a4a08c06859dc6aa56cf5af62a0fe07efe8476c462860a01a5e4180a4de0249f05648c23f8e6e3bc49809eb27cc08d547840066bb56916d9bb9761e05133fd18a68324492ad7b9f9caa166803782939a3e4f8394ef0f1c9a8f811a7f5ea333cadd30d3404352aedbd7a2a7430f46dacd30ba7bc9797085a143f0fcdd6b0c7ffdde124bace833b758ee4ddfe50f261ebad3748d4e586cf4bb52da7a9c3a306113046efec9210cdac01dd254b6f5e30cb812643fc1d2857c220dcb944c423397264da353d5131d0c70933d72b55360d771b7d982561ac136d24b714920430c4110bcd961e12bdee0f47545d9a50c20e2c4e3989890f61c5b1df09c72d8a70b5e5a161c0077f73c816b17f59d95372ccb9ad0332fc9b36d3a24c6173a23014f684d0f1666b8331d108ff33986354b6edef3369e8da5f707e530fcf611301be6bab8187386d130d1f8c94e5c3602e0ac63a273f4213225773647e8a739187223eaf5c9f0f2e3d1b12e229fa77e65b9880b245038d021948c6700d89443c09f207b9da66d2ec05e1c567a8ae5fe502d4d02ae9d39b49dafea09bc363a28395b90f0c0482be2642d693c65b1dabd51d38cdf73e322686f01341d26623c2491c6340204508a421b5978d8f7f698b473ad8db813d1070487f577a18b9e163ed125ed818c0d13dde40503a10ed6c8d3e6ab231b7a7a68d58e125aada1bdc72c94363a3d8c1e3ff72da6102d37790dbdd11064da00b79d78901da2b568d1dfd70c58eaab561cb0dce9ec88d17684a783d36067bba03c1df0cbc3cfea77b39ee77b49d8b425455e45a27a245c1963853bd3532ed1f9d70028c2001ede3fb28ac4db0b0215889cb331f8bc637d8cd27d44435e0e4451bfef8b6e07bc00ff6fe17cdd12d45db9f816cace50b0682291a8dc25726a39cb65fb8a0456f4f5380b87473b2c6d3ae6c36664af57171130202317f5686635f0474f0fe3f7138dbd0c961b000d0c14707c9c3037792e2b59632bef200ecea24e409eec05550dd35c62be25a1612ab90b268015b40eaed9fa0717aab7604a659bb00f067a95adcff05c08c3250b864efeb0c75aec01b50d32d909a2a0b8e0595ca52e08fe5b0d37ac52bda3dc4c8a0b7d3e9d1812d5530ebcf9df0ca53581d176f5b8f880047f3803efbbcd442b7f8b1fe158353183f03d3f6acf468659eb30a9abe2de835e3229d8c3cd6b00e936d5339b325684a5c483b15420e123ca6b7893cfcd6ddb8a9ff65313caf6456f2ad2188feb5ba8dc102539e94beba5882614bbdd5de594a31b66107f0476d8e0f3e2f9b858634451f0fc2222e24db6608ca6874a522c58bc897c403a860cd5d05b731add09f9e24a465d0da6417d000a4533e0224cd2cf5426a5cdcab8c30caba2a0a36831bce623b526cac663bf76f4816a0ad32ac3690b658c96cc6e09d9510a57c8e28f32220210108791a15aa0d3a2cdcb143ba3e7fa41dccf5534c6fd36ef91187d55e35dac9d3925ac08e2c22c246361396ba03e69055b5347faa6c1cb9929766e4f2a7b41911e25448678f4856d131b61a171c4554591d3c74fbc8fb899600114d3a61951d7af36bb8e6460b88c1cfeb3f21e0b94d5a12f2615ed49cf7d67abf18a93af7ba649cd0ac29680d4a2e1e42195049ba8878f1d05a2e30251a57f7f4662d4bbe42ecc98b7399c13a52690fc3626bb5c1a0757a19226c7db6e42ec243932a2503b9b257fa271f933e58407803a283c989035fccba4ccbe481464529a8697f4057982aca7f3e9f8f5f429a69d97e299e3570c43db128086a548346eddf38a8fd24e270d954e57a425ada9a7597e0b1d1e880416c0a36fd5d9a8a1a0e277025e81af122c541ead22d788cc9567892bccaa9f0d0d4410a411d42de63d1e2908e4ebbcafdb25c1a4ee002aa63a6245db826d277bf7bed80169db1bccdc7a3eb0ae7852317a5fb2628982a7067757484a42e2e39a2c58cf41f683c3646c0e993fdb61ba33306f7524ee273dcbcfb064b2f296cbed17603820bbd3a5e93ec52e82e67ab2760735d2fc91512a677170aa190a675a10256c484c6d7ec374539b6a4e2cf91347b6a7ce07f7e3d5804d109d88647def7d8362b09e103f65285c88ff5ac9329ca40a9c29dca4e07de3bfa39f84a9545268f1b04c23b04556d7648e368e30e4c593f9c74a4dee34eaa146708071810254fb2b5fd49243a64bc29a6cf8638150988ebd9756b917719cc9bb55d2b8d2766660c370803b4aa4e0b87e1b76ea667faa2a9c43e861729499eb19a6e461dc5fcce21ea03fdc88fe1a67bdd4b67671794d5348a1b481ad45e5810293b5345958abc5f84808fd97351d481e6809e00bee6538408aea7c6c0744ac7db719c3be3a8a8fb077e5aaa181f69f89547570b88ecaba644b0c8623f799c809855b617cec1498a8e2313908d070839a80574b129b24245eded44df2d130474feb95e86dd6e211cd2e6f65ced4fbfff3817ccb8c25dae508502d4df393b2e85eadf3fb86959768990ad2c8625a553c4d920338ebe25de23761c08510255447c7d787652ba7c318efbd758620236476ecd6df6abc2cadf3488c7e6416c12269e3d114a73a0229bbc06b4f53b1f5c0ca2198e418a49af03440d375ae7c76e860ff18be0bfcefdb413d281ebc034b8b5f8722b041e90ec772e1e9449f61650b8a2bb40ce3658b1d71c42e68495a5504986f38696e56ba0fc2df70182a5b11f247f876b27b3d89aa71714f55561cbdd0ebbc4b24d39b044ca3e3ef42bf8f63b2ef6d9024f2194253e89d0ed237b1903f89dc510bbdfd982b518c3576659cd397e37db2ce13f8b1b0cc42acf317bf5a8f948dd3977725de1590421117c9ffd00602470f3e49488451e5d7bce797a71126028547bbf44dddd6bba9f67d53b9c20e8afbc8632efb5aabfcaa6e749cd45043ecb13046ce3209fa85ef21441ec2d1a120b53fc4e51e100e83a51da1239f64947e10f158bc42d10a3b20a366b431137d004e87da3ee9342f44b433ff1b8535e3f1928f927eaf8bdf52e31c5894673178a3ae897ec528be2ca7c977eca6cfc08a00266e96fd43a723fc7226b66aaa86f2864f98b6fd26bbf80abe1a9ecef909810ecefd129f3a73bd3296a2999b9bb45f2574cb85143f66a0bc2ff2a9811e62cca6fe559c14e606a1c9ac2753af2050d3a8f81e4731205cf0af72285f08cdaf87f9cda4cd3c7c7d51bce592ea15d692ee694c399bc8bd5f07c0db8fab186d5ee762d33a5debc1902bed79a68d8420d068878e367fea06978192e6e69d4b8acadd42ac1133fb3a9e9e1dc50e281254144bacd43a231dadc4f4116e333fc9f88fbcb64abea30e650a11ac56a1988eca45902fcf424a1223968027d877793bf9f4636cdba3b47dfac921296a818d1b0882170641d3606bc050e0383940f0e25880e6b183b137ab86e3ddd52a0ea7024db4446b4988c5f282984edae2a11e1a4a4a1dcf28583c092c331aeb08799f8cff204fa2810bfcd09e53dad5f37258fa86f46560785713ec711c9f5ab98c631bb3e3b92f097884bc8751c88ee126bd1f3682449da8181bc9cc5b90f0bd9dce1cb0d1966bb15bdd7b78a1138b7927890dffd8b76a9385fabcc2a5fbf454fbeacc8e61f0c5b2ab0a4db4d0a259bc517898153957166f01726a25d2012da74a8fcfec1043c1d970403cebabf7a1af318743767411fda52e046b2fdbee1680978da2f6641dc5012547ee806376f3ffab1e2780f491f33a0cb355ea6b677c4ea1b54ab6e561ed96024055de5d02392688133abeee6aa2f4d3048df6efbb7e64a6aa902b811a674b0b9ebcc31efa34cdc88d6209367d7c9cb38d96a9ceb0b51e8e23643996556171e270fec0156069e8006f48956683abccd1427e3ec9df93abc4fbee9170eaad8190353d85860814a81887509424d72a79cef1534ea7655db318a424d6a03868b391a7c49dbde0913228107a7795db90a5e3e91e505d9922c2914d7755e0c56d25ea4e37f9ed5c7988835ca83818b75c344d06ea03e6dd7e582c6afdc5e0cc2dc395f40b62b11adfb0a552412447e35ac364bee1f8ce0ad23a72daad149442cf0be27858cf5b7eccaec2b6d06a107b676e9fd7e573066e9155fede55c357a90b980074580512dc2e7d3e2b87a063a5da17648602d66ed743cf227b0ef5a34fc4458e5fe418d5a7ed1c33878563e44403bf194507c93079ff9105b433e6078b2b9bb22f1c69337d131a4c91c2b70f1b45fa522eb556b7960f937e6fba63e1a50c687afb0416d584561da16f22ecb1d016076358d918b6d5ef2246424b5051872ddffd8c30b482d9c34b428ed5eaa2fe80cc4b5b4f603f714bc42e0efe338188a7dfb0be6f66f395cfd85bde8b957d8285328c303d001bf5a98fb9f26e6051a1e43dc9142274e0b70a75a903791928a1bfcec374626d3c6136c409de439066c5887221563f3ead0d53f19846cb8c3345403ba3f7209d78da91196896a687824e4e6047dd8e85212633fba991cea2364c746d0ec558d0fdfd64f2ca44bcc9763c26b68e2002ea0633e6c3d7484493771c50eeb727d6fcea84ed9c26bdaddaf73d676c3554c66ecb08ee954d3de09ddaa2e3d11f5fa4f9d4c89cbdce2c3accd6f38c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e8529eab3c9bc2858788c7077ea13728eed4debededfd07f1672798856c3a055a134014b924dfc217dbc5b9b44e89d25f35314db49b096287a77d1734d0f8f8d16846281439426e64348199839d84de5c3d2441a5dd9c75bd064c1385ca083cd1df6e72e42327ed298ddac2fc87c59442d545b0ff476caed9e785f2bed1bff26b033312dd6bdedd4ded92b9647ecd2ce31eda2a6f5a4ef9df833b9b4c70ec0924a92a3c6761b167ab56948265b496cb7529b01cc4e53c3cd9a39384643996beac7e7e841eb0fdbd766a1e860249639928c27ea49a3d1b2bc02bb95c9663eb07e0232ba0ede4e40a7b352f38ccd532d1a416ffb5207d68c2b7b3a6cfd957d7efa5b7143abe63296589646fa4fd48c7d15548b46fe4f60435bf69fb31260205482eab02b276cf5c2ddbf28d010e2a6976cf03488c0d1d11c5c1f9b23d7ac44ed221724bd0d505f36fdd6c1f2f87ae7f7b7d2a84caf41d8db3d926a728904ffc98ade11410e880b38007beeaff985e007a1460051bb827ffb24970b0fbf79cde0264cf02d08eca7f936f1a8a1fd902a4395ac8be7312d9eaf784c761cb1354dd40baf30138d361ef8d4cbc840dbcc9336d9348f3cbd51fcb6541da05bb0cf039edbb5e203845b97698e2511195a1fbb646bd896dad04547a95f1941a1df510c4f799006284dcacf83ad61a2b13644eba1c459299b7a92a42c735c24fe9a4b2e2e9fd6a0070c84f2e19c4aa5a2610030e19ea4093bd118f72e066ba44693db5cef94f390532d3fdefa1807e6bf9c14050d63d2c37bf357802a7d8e813baee24cefa76b229a035f7c6b0546f536c07cfd7a2d8e3be9ac2c7b7e854ebf59eaeda5edad7dc23eadaa7ee423a19ddf921117a558f52bc7238e74738f6b182f284404461dbbf5b9ac11dd9ca793e7d4ad05cfe205d6ba0969f8e965d571cfbf51f54a8e3317b795c76523eec774719d38f8ecbbb192bc298fdca9b0a9304386b0791c671fa441dee797d349e052a0edd93134d2a7c57ee3fdacad7f8e00de15fee3a091b2c8e51faba26ef3daab055a97199108ceea0d3b0dfee6ef4f8ad55f1eca9c15771251dce196dfdef45901abfd0236327e527b7b5a90085cadf18125f106358211b47259e193b2d7bd2a55e7e715c64e67d0be4b76086d9cc31c11ec35caeb68634eb556c5a293370fec522d61149c7bb09bd4256e55a71487db84f95cffaefd2c4a3054e528241405f8618bcc663a513318815f67de9a13e6786615542b715d6d2bb3dc44c310feaea7537b2040a1c0668b795fde4c9ef029aebc5a58ddf0dd100da729e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd93257121305908aceeb3388deb21c5ceaa4c1dae6b8ef3ef9ccfca9bc6523b609bcddd0bc210cfc2275da1aba94d5bd2b963fbd80dda7a9c8ff88271f152875d7cccd66404e095e1dcee94fdf133c53e148690e813cbf3a049c76d2e098135864a11fc370cf33eead0be3cea163831560bf46c98931a1dd530301d054fad074fb22e5d6a923ef8cdfac92e83ce444c9a2b61fe92d6043d108129649a3c6ea306c5d9db7ba6740f6b046ac8d7b77f5451a405975c2588b5b82cfb70843359010be8b7f328f8bf480b21d5fcfdf7c0ed21b4968982c3b4798fe04b9e9462fe2bd8fb6c511bc0d4fd794bc886625c783228e520fde1dbed723fc9779bef796e04307444ff32882e89471f99ad0b367c55273a7a4a3dfff10ea4c7816a44c1cad69137741b64d4c2addda665d13fc93f613f8de4ae6526a7ec8bcc418d9d190bff5fb2bf8a576c7aa614ce9faa7901f55f64b0b0bf1c084f52e7069e5bf1097a9889ff977307061399848cc96c7a631da2855f503865eb732fd4e5c3976571cde050a1777e67a4b8c95221524a3c23c6b5401c00b5030ac5fc9d0a0463ad9e34009a00ad426ac296fc0f38221dca15bbd3ad95092e6a4f38b8ef8e9f3b9992d57409c7833c0e3c2e6ab0c7a26dd2cad7646133b739b24e20159d38cb2e11faad8ea1743054178c642ebb1fcbeccda9a1e3aed8762eaf0d9ed97308e08e7489424c321f49af5f2caf02567c87ef2729ac221651de0efa7ccc8de802d0ced1036b68b51868bd36ac7ce8054384aa6a10b17928e57abda181dd6caed22f35fdc74e5fa8cbc8520b3a414b00e01850a90adb945205173ed44279aeb17ca7ebf9a239d5f6ecc9306a0074af6bb1098b22b21e3b9d12bfcf4ba0ee5e9c3cf8820ef6061d10c3648d73b8c0ff0094b6feeb0707b5cd61797ca034755fa42aab8c5c9e245157f5425f5d9c43b10c831d840579f3fb8ab975e36f52ddbb4fef464e8bc62f5bb730fbfe5332c4252393c6cb8e07655646eca309a1481552ecbd9569e94a0cbb6905c4571720adc754722bc8f182a697c43e34c44782ead62b2b4d01ed046ac0d7187fdf4e1ea75d41bd9ef4da3a7a5ee404600a4880f8915d2a0d4943210c8e5e71277e7fa6aea2e843cde25869445dce969fda78091938b3cfdd6f1ab376e62e9f94ff04a8336309a4f867baccec1e6369b73bdf4b757c1049448f4bb3999ee0d8ffcf00c6d22bb9a4502c3b263699d0ea24baa448b12d24f501412d09da75d99714c91406d47dbbbde1bdb9b1bfa8dab1989c600610422ddba5fabd57a54dc955ccfc7e00bc1f800f46d8c06a9861b5ebb82ee710a67a28a410942c343c5385210af2239444d4186539c1983075c1100c45b2a80ec93371fb04da55a70d7e4064542210b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d66f5b305293c5ce2538e4d8e773a6d51cb10adc0c50d9b9cba83e8429a2e2e1e628b901883b088d7b9dedc64dc86f636e337839c21edf802b526c26346ff314a86f8e7ead704ea80c6fabc0641fdb53599f2e2532b2733e93514058b042af10b86a8ecbd7b1a217342e937037c0bebc6a026371b85698d124c09998e5a531b6c98d2853047a428891a431d89979492f261809be176ccc6f09660d5cd4b624f33faa2a0487a29d08064960b2068be68c3c830254caee33d9436053af9fd02847472a558406365b77652cb2bd1ccf651da71b0b22bf789af3d24014217fea74522c87f228bd61350ac8ebe6922fbe3db9b1f1c95cc6fad66daca76115c222bee07689e5192515b7b99cfd14d624ea54dbe5eea6c8f22b59babc3c6a3ce22286f1a7e98797f7d5a383fdf3eba7a9d9f91ef76bca8a1f5e028013db30143acb3e550a812ae8f2fcfcbfd6b8ae693e1ea88c730469e018cc7c303389843f05d67ee133a524e56e2044349643bea61e7d9d3ae3dc19e660d754e6cac3fa4f24ae46d7990bb3badda6ebe181dbf2e7a2b6d1983b75388ed410c04105e5790c0ece24b0e2e85194adb91496335138d5815f82e01ebc93b757c1ff94620f3a87ef48ca064f0d2434a7152607d997781ffdbd8987c5b14b6f20449493fdab89717e43a141592305be0faf22877173da64f6bb647b3a636b831df365b7c3394915ca6209d756e01ef99a3542549cacdede905e8e8304ad6d95f6d04b85fceb7e28499ac16104eb13b75b149505ccf56ad08a10df211eba48ffd7a2d0d42a1bd943dcc12f86efe3fdf6285d91ddb739bc5c2481ed4d77589febde82e624d0af0ff9796e59932d858087e220893ac87e5b5203582ed469929c865ca6e35cafc0886f8e5a9f813d471496a02cc87ca65544c0ef979e7f4c1f0a7269e3eb21fea4e0d91ec4fe86be49b18cc3d5ecb36f4a8dfd602319507ba7dade07e22ca3a895e9ce0a2f59d7f441bd6bd7dd64756c6cb272ce5ea2a934c56dec8f3be010f8ea74cc61f20d130221c6faa48e432e6ad29d22301073d3dcd3dad319399258dae99d20eb634bd697482ad1abb0ef6ca6488989637ea1d44a918f062b169f1b802c9ee6d05a2fe348e76d655032dad5ed688567ea02cd741c0f1684f271e1e6f57e70339d949187fc02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c24169cc5ed830203c45863ffda2b704a0bfc77cd4cbaf3279e937c9415d47635c23544512e70a1dd7110e04b778646d4f7b399d36712e40bd06a6907f25046639e4fe0bac941c2e9591a1af974b9d7ed718ae8c2c5246458375efb92aa04a645b615ac131413580ad09206331a67387cdfbf12cee28aab9a8b0aefc03d6d1f2fde7000c82090e61c34b4675c01815b7e25a1fd09d2fc60f60ec1f3f435096790681ce4bc1869026d0ca9966cfa34a5506577dd7eaa826a1dbd86bf3e8ae5fe73cd59f45e5edff6c3c216a16d4b6539790325daae1a6400ee446c2b4fd1852c409d43c22a3f4b757aa0ea308743fdaa83feb2bba825098346ef0ec8a0a752833e2a5fbed2bab603e428eba5d241504949b6d4c4f02b543fd709a15be42ee92b6bd37baa61bc2904832a15e7077176451dbb49a688cf55649c5637bab364126c473c492c09b76fc9de21fd95de63f8e5b0276a7fe25efa62bedecf69ceb278c8309d1ca641fe2f9f61c57dd21ffc4ea32c8ac547bcbe01fa01634d739c86d75ff0681db6ba6b02f41eb730989a90ffe2f8948b98eda9bb5bdaddacaba1ac1877ea8c775ccae18338cd298c2ce4780f31255dd1321fbd0dbb6f8f64f321e0e0b665130b58ecfa2acaff06cdc5d550de264d6d61988290e84649f3faef516f21a36b40345c681a841ce65fe1848e33fe6c929cfdb09181ed6f10f9b5d42b079890c93f6c407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71d8885a58a341f31387950a999ec683cac9de2d53d8eced4cf1a4e76d753dcf20026074c387dc5714b8038735a05a39459797ad1f591aede76adbce55e99ed94a4ed5f55ec45727a57e2d8d6914f6d2acffb17b9515d347ba045067502a0b14022a269560e0d95cb168c7097ea8eccca5aecb328a24b1eda37bdb600fffb212178ec0923744a6402d58d7d738f233ce9b64b6a9f1dbfeec1505db36c5a06eab7366740f5785cf6b88326cc3136f3e677ee943c7f1c1ec6da6591f72d17c667479c47074d544333068438bbce32a53bc0117d123ddb9718eb62baa88f7a7bc78677686eed59f920597a10643f36f40b821f85fc2e6b62569c88b32189a52966c52f011fb08ba33475f7e9b64397ce8355542f0d31bebdb5238414fbc41ab88fe2a7e3af5596f09c8a333cc19880d51fcd11a73c7b8eb1b02485903f9c3b3d15b56ac304e37b46e43a844db9b7bcda351e09ad1efc57db99dc2a7c12e553ca9a604e463c7df481005fcaa51f86223229d9aa3f1dc10b0bc97f9814eedae2d1a0d4824b5eaccc793902c3f48b7529b6d116f4e7418406b6dfcabf008b65268d1b375fe932b8407f5434fc3b4165e5c0bdaac4887eddb7102cbe8be428b09c8d43979e83eb30dfa3dd91753614a811769d6a564e5e2b27c43c70d7497a0834ea96e50a61b0015878e7e28903dbcdb802b63c5e6c895e2619c6511dfa0723fc48f796982580e61b8d0dc0c1652fcb6ad0fe74186d4f30f931ded5712a16e9724b9993c5c832c850ec9d476fa68c807d36d09edf0c1eb9b2995a3812cec5092b90c4c72a842dc9eca0e5774a6374ed583ce8605795f084731e95e368d039b6ac539d614924eb791afc0aacb141b54f0d75fcde46e4682e806926114b2ec7ee5a1a5626a3a00a72c2f0fd68497472feb62d2481dfa1ae93b14895fd3773d48635738847ddeffde56148294271b50d17c8ecfec51791fde88bb15b07ef5a9f0f13b9ee20cee21322f3a6fd0783089d9dd32a9344cb0a89e9746bd35c0bc36f37afacb5e3590a7bfeb5fd893b53578b04160e3162b0aae5d6f67dfcb75abbcf01b2ebb10694cb91586856f0f35245f0b614af51a8ec9de0c16b4c52d4a722b1c44424e2837fa47643df9b11a50e4f6f2c820c284d4c147481412e5e4945115040df8151123dcbbcf3aa3616297725b2ea6ce68ade3be8d490a0839ff1ad65f6cdc9f3b410424c41b6ccc361bdd655dbd0f0a5b5e7c86fb1bf779a912921794e17746c37f40309c890258c6702ea0943d8a32748f67d8dfa4a29fd85282d949f1cff5faba2722a8f95b4c20b4a2545baa5879a817128101c28cc253f3a7a73cb74f0c43d60924cc7c0c46b93aa96c8e69afd833d5c5f4ee23346e35053b1fa6044421208a5fb0a75847a0e9f3e97824f457206271c9147e2862e8728b4d69cbe84e785d9260bc6104bd6770c69d9e19769899be4884707e9fe7a4cc7460577ac05769874d16a6a7bcef3064eafe8855f607996bf06eb728978f6535d6bf0b089bfc0be52105b8daa8790dd2fda2c3493f33b66804385212b1c3747f61ba6de535688b2ec24dd2c7ee29fd05b5cab4d8ea4b8868446d4562a8b2d6f182d818b448b165d8497a2849b441c4f0a26462ef0a1dc6f963cd36adbc02c0a0f040b662e314819eb236dc6adcb19ffaa9366908510f4e29ea59a98726597eb3f2bb8cad776a1f6b5065d440ada739faad77e82f68b346adcded75163d50f3a0a6ffac67559c3c72d87c96c35481c26a024016382c63d0c393e3fd7dccc91275dc3a610a95f0c63bb8553034a4c23a5fe2e1a82fe0b885d736e57a0883291961a087a2719664020a574c20e4764775b18b4c0668fa3ca1e9183ed8e57c30c211e97e7cfdc685e6c082449a1fcf68fc3da9660e86c1189f879b8c9cb6611d57d470765dec4c3514243009d8ac7ad5aa36f30863234f789eb1d0092f42deb6ca72061146b920d71b45770090680e74933520624041ba2cca522af3caf37c267991f7910e042e5800632d66d021a519c3d7a9c5614710da694bc1e1b7d5cfe40931ce3f0e1f35d253566b236c7b8a1064cbfd234f3e26fcd14b1eb52a0b46a47e8a8d38027bb3fa2cba9471b63489fe6ca5926a30f68d89fea2985c600a9114516a6c29aa1a9a390358ae1146ce84fba254aa25005dd08c988f4dbdcc3dc795d3487566e587f8f99fa6d222603fe0045e0a581002149e02f12f72a340fcd78d5723d10b6869cb54bc64940d6cbeabce345363e57dc45931c6bf8f278f704cf252234e0e580741af38024e153c2f2d4af59046fba73c6d72ca8cc525648416b9b2143dac665457204258b81bf0097f3dac95ce491ef6f07d89dd7a409b0f13475eeef708fbb0cac0f200cd312103944d2868c4978492fa514359fd3ca4231f9a3b7689833643ca183622e8cd963918c07625bf860ec2281a5fb55025fce0f79d2e3f09168907c20bc34dc2d4b34d5cd5b78bbbf06900f74bbcb83754b0860f97e0d40bfaa956dbad7103f938255f7a45f5b334202ec3bdf629961bee8974b2e756e4c7b638ddcb558e8b8fe0e8021c85fbe0c8b8739b8b1079d14900f8469f5ec613ec65576c6773608f36e062331a5e94b4f5c4a1b124898399f3db554636f854464f232ee1a6f169100dd180195a6eff150ba89382577e8770a15e32faf075697770f85fe1067c8f5841d37c6988ba4efdf07ae6c46e9c2d1e726de30e53229ba4428ffaf8aa05391454b4e41234534af2f0c4e38ba3617ddd1c70bbd23365639fa7cd5f191861c7fbed74a80914c06cdef71226f89708e71ef9c6ab3d95def2dd7f487e42efa411f4eb05a33b78f83a80e6764aa6f07eaa4e22d1741ed853c68c6ab19999edb739487eaaee49a422102fe32fed2c73c7d5490f536ba5a7e96691c8c0bc34dd1f6ae02690a438e419c40c9cd26869e6ce0e3e2e6e1db4a35037625efc1ee4aa2d6a26530c3417b05113ccb3c725993fb28e76ac53f00b9ed3ab5f6912e0786fc1138fdd9eb43bde42db08d3a2ae3363169cf1de0faac09b586e3da4527c94f3e773341a31864c76f31fc1f72c9a86eccbe29a1060e2a5b0d6abf7c452613018b69e8385b7ab50e468bd570a388c6eda0d4b98552d27b9aacca2bcdf7f90b75243f624e0181f20901a6c759e4cffd958b68736a9a1ee2ebdff616811e63d43b100947549aef12a1858ca58ee54562ddd8ce1604479185664a744017e539e3a7737b7eba00d767562c6ee73a704bbd52bd17331679914ef0e5a5888b9e2cb6448263a75c0585d56342263a48a5cd916d64a902dcca41efa763e77935265e3b2d8164fc8d819762a7ca74dd548b3c5d98e4f70c9a85d29ddd2296fa1cb8be37e5d8701af88c70c55d65c6b0300db4259152800ab8a88f85e276b32399f0746cdbfd93182863a850dd68496b94fdfed16540c30b13d0d7e65a4ff1bb1b73ae867b96e7c912b00ff6ae02a488e8df0f2c1a026bdcb1c9e5e273773626b603e9c7ff6b9bf0beb5a573cd8dbc6cb60997da70aa06d0db39d1dba72c0eb35a773994dfb1cc3447614540d0eecf2766560b1c77937fcec07555c995ffa2eb97e7bed217c46cc798a407a05a8e2b2f015072895fe33d26bdf621bc4357610234e563f1f6dbf1584d21aac7bdcf47bce5b008b72eb8b01e183285e635da5eaf069358ab0142d54b28f30bc599e460dbd802cd49164665229340e29a14dcadf345f493f00ebe1d829515c6528f61a6ff498c1bd104b004ad09211420e761faab5c193746843ffac77b8387414dc4b5aa9706a54c576dd1caad7fb29bdca6dbbce5cac2eb1e65d89633e3dfa6040b63fe6d05a67a51e96b309235a66e1114494d37a75e8a285828f0d6dc61161c47f0780f95ab40533a28771af010a3866c099cbe7de1b5ba926757ff2ebc73544e1b21418fc96c9b11246ec54148661fd7515be3636f5d3fb5e2723cfb1a725b43c10323e2df2841c9f221b061b01baf702df0c335e0932977ab4978260fb37c2a1f4c8869fd97e805ab0157b6325650d1e03909ae85ae3751e582cd823db5380ac9496d1d015ec2b28839d5daa888718cde30870f8fac9282e4471182b911196817ee864c2396b7b2a9f349d959b6fae1d66ec9104ff9c942f030e65a8aa549866470e32cbb4e38b8c0bc430bacb0ad6aa1c372776f812b941ab4297ee1468b2a296fc8053d12508a47fa99f2cbd5b7fcea38d04fb896e5421661613af2b533ec2bb28c57cf7d9a02708e13edbc55df986cc4b1711bcc75d1ce872b9d48e260ea1878a5d7f6f7f964340f6da824c0e74e6d6990cf0707ac8f1dc11924bfa5c1ca130af9ee39ddd16c4d9cdccc036856f84eda4ab17cc28106323024c8e72663a41b5a85c0e978d30601e32bfa02697f9eab6f756a1d83440c49028baa4607d6a339aaedb6cdac744b85af70456c65c9025b86a7426169cda4490dc7f20d022ea6edb9107df7695cf745e061c1c8b98f078d88f50881eda8dea89dc75b6633fa44303147839275ddbe891c2ce4f93b4e51ba2a2709de73de8b659f9ad0d8a6aaecf1e5de8f4724004d7a92a652474b63824c30f8027de4f9b98386208a27001b41fcd121741e20510209b0740cb89c118f190cae98339b07e65df9cc9dd126b2ae3538a4d0985c9e7b52c5de7e5787b3109845cc803314d2b6d9692ed5e2e0adebbc148a87ab25752ca0e8aaae7558ebeb7d98955066e38ec3fe38a00b7606128b4a3ba320237b20444e34f94f2c8f9d5e0173b28a2dea1a88f7e40403b11375e8fcf6841f2e94ebd740f848a2b4e72c31c7a21aea6ae8917400c81d43bb522a417c3a364675ca3cb6a8235ce24cfc39325150995dd367ebed4e2adba7efd67bef767d681dba2b2af833aada512c7f867dbe6e01b2a7eb49c7b6e50bb8d9e6c728d9a044cfc98d6435f5a73643ddfa896ed51671f0a76359ad302d329a7d64886437478cf402887d5021d87404431bbc0b7780e1746b73747f7c01d7f6f141012dca88d721016b8b21871289774455306da42ae89e9c762a2ec58a22a96eb5356336537e0ff56854b097b976be07974484f59b0626729a1f672e146de5ac57b4ae5233ea7370c02412b04da5cecbbb9154f804dc0c8e74e2ac9daca31a3b872ca80ef8c5a7f17dda7b9554e659d2b24c2373f3dcd7473bf12aefe152f200333c87b090fc60e3aed8773a753b992935e33d35c92f1055f2a5261bfecb98b27031686e69b2e843937643581a8b3a670e34bb0bf9850ccc4dd1b4be267775b18608af4d2400c18023b5de425d219f9efcafb72aa555fd994cf9f67ebeb5de47b6ab4577184b74582b4774b8ddc3f186fdab84f01e0f988b74bacfe932f46aa7023100538397589fa07b331c10ff03ffcf5cac1691840ba63344882cad3a161b13520417266880fc4c2de2e2d5c0529af712ef5570db2121f86419a0e63c1da3d2000d9eb5c85c76bb728eafd2dfdcf41599f816c32951d724e3b41f921317cd41c60ab0ec43fca15dc14d5312371e0b26d5cf58477961dbd96fcdf2b31d78c450fee02ee85779a0ee900ad2e02300ecc774f73ec419fdd15546141233308dd4e051c826ce665878ade3dace990e64ecfb1ba367f4c3c0a61d4aa1dad084d5c32793e97f57984a6c431796df3d153e6b310d25c37fd451bb16e2ed028aa7b09e42e20b4eb5a03fe8157f3d4be0998c98bc7320ba91b9729b9b466fb2595a1ab4000a4063793ddb24833d15dbabd24ec4e2bc0eb73436b0f08b9a562503729ab644180185bd09edd014de26223b5f1a82e054dfebb79336d891b767f8be214f88151c6e7cf8783284c7b1adbc75d8f414979d725fdc7c0dc5d013e0ee51879df8a5e3451595f904e1bcc1ecaffb327a9375f9f09251fd12a66f7cbd6faf86fe902439e0ea0f5bfff13843f2b4a2067c577278af1558bddd481e153602c11d5c81a42dcd5ccdb01ea371454f8fc228aeab0a651b71316bb9e4303f24b0faeda606521c4625ad1221843515f2b55467cd591a16e91a5a119431c0a40030412724be545aeec5145d93ca5215998b118cd43fe6f953be84cdf704bda68dec68fb14c3e642079b36172d8392420362d0ff639df122d90c48bfb4463a941f942309e768527e8b207b02674157f4b2fac359d2595191b18223ef8d7a62f203c30dfb407d3016e2942de95012f636a769b665370660d2906c68900072fc9e5cd13b24490f424e0bd98aef19726d7d2749d8f316b798b87ac700de86806c0586e96d5fa35d9085a6313b77aea6326c8a3ce609b67aa4b2de89a10da711cc35cf593e91f701a0f0ae752dca9264748a313dc53b63231d29e9fad3bf5e6ec9134177e105125ee61b888aab2d6eeaaac9b63e99b4554c617848d6d4addd41ff261a14972bbae7427f40cfc7286e8ef47f58ac239e46d974a0e0ac57679f6c0497e0f15419f8c0b3e563ee5edebece3368fcbf345b930c92fca7072eceb55222b960c5f7e0fd54d5842383c5e1385b87afd269b475a6fde0ffb7bd90e239d010036426a9102aab37b309f130f7d93dc434d02fa0318a7a63dcb6fc7a8cccb8eb8452ee3c1cb6540517e9f6bc9f832332e4fd732cd54f8e33896323ca2a6642d7bd30c4c8b9d4afd1c5e7822263c75b2709c939073244489a929410cd8eaf39549a7f7e39808fb4311a03477bcfddddd9319bcfa6de112cd37ab5040bc19e0b3a52f039a6ba60d20459884cef69623c717e7aade3c1f270584fa38cd0d9b6a56045e318ec49ba8a961ba754247a7319d29a2d250be22ad5e7494d649b11898276a964aafd01459781202fa7e77dcb212548e7028b56cec34b508d478e84034a501e5f67aae930c2a56aae7bb0cc818fc18b6ffff18592e8e8671eb94ceb0c2e15b33f9f54415cc9e625abed39d47633eeccd98be10042d5d03d852c5bd930a89f0ce256a9332521f282813a5a6c2f9facd2659c39efa1ea822a53b4dc428a9521c954e669dbb9bda2e94add842eb339426c7a1f44fe90370fb00c10664c8f2c9515800831c45fb524866c2be38a68a4f8d2cb06766b1cec3242cf191ff9ecec987893588a89b042c208cc9770c48d2480ca83a7762d7aa8eefc4ee180600d3620aed0414847a2198747821b006346ba2ff93226fdd08d92fe2e8c22014ee9c389db737f3d5d8201f0c8657bf91d13f2dd4f1bb6adc1d6da398e1d9b2a4884c63631d46aeeac4ca734882dbf7453254ccefe535131d857e9baf418f9a77afae84446c06762d62ad302db644f122be630c593c15b16fb21e9cab0fc7b0140c981652059d2310ea20e46356d8e06152648b0c9f937d26c08490a5752ece4b16ced9ed97d75143de35326baed933b6c623a04853e8e76cab3219c59d5ed56410b366482128627181b5aa4e3a3e9bfddd01b73c36c624ee4eb5eb445009a0fdc7dc15c08a48c83927500e0d887106b8f07b427790d1cf4a2713ad56af6e1e1629ef93edf14348535e50013dee7757f605a7b0d7d518a7751ffc17479ef2cdbec637e4bfb3dad4d8993a553d081a31120746c200d8748f031b9b010d21fe20a80c69f06959feee4de31337320a5ef93a98dbe72b55880c843da199106393fa4db8a6f659207f6f419b31a6784e2a1e946483bdda59d530949954fc0d7e42afce9454b6faa5b7575f6fa1d23712d8f0e3c51c77bd269f51b501bc3056358b894a4efd94d6f3ab31c60a2e6d42f843678d2baab7d571b1ee2a585968e65e63f91974d5da580edb472af08b1b03921ad08b16ec25a554a5a4c3a354078b7e7715d29df11eeaa50531e726323a7fb657d9c44d701faefea31ce086fb59618c914224c48d1b1d5820f67bc528d05e42f8781052403fc0abb1c201272cdef98963450211e46b0c280f8c83b25e371bd827a1b3dd1a3cd1ff4732a3826ac5a468c6464286aca145027df161442843524a009a4c3e5a8732003fe7a21d212e1e7743a8206fdec564f55b413d7376785610f820389a6e253f09f99692ffc4359b494a30096a3eb8a5b97c3aba02933a370e7d5bf068b765dd5f6fad73b66753452a03b21933d2625a570e8f1406fb81781c698336cca9cda4ce660b4873e19098521277c6167a5090ebc2df903b9e6827ceec7f1352a57bf84ff4eb62099a8875cc61b06d7c3dc6094fe96948c881c60e4e395013f2599efd1c800bb1a8d30d5f57f82ac1df5056e7ab4b9b21cf69a979c218ebff5e25bba8d563f5640c602a33208b632d59f14fe714bb407af7e74472209faffa3a3f224d1457e0b6f2a055f4d64621658f227698a5d5bc7734739677dadbceae2cfabe8d2263210ff6c07f3d44f26d82b51679c57bfe223732829a7b9e91280ec090176d08d5f9606dd24a835c71171595de9e3c0c54c6a0ce7a9a159c415bb13419d4c73469ba912eb7d346b91629642940f117e1aa50a09fd5dd482a69b1d98b990ab979c98b9a66995d1665017790168ae8b5dd1608ad0bf62c35a8e27969e0a4642d03481c477ea3219946b9e8b8b1271dd6fbc2da017b45d321bc46c0d63e2847067350555940f33ffa238dc7137ea04ecb81d9abc5b068794738c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e8529d833c6d57f623b8f0c8ed846045cf44fea32bcbe0bc04e118f3922c6a45c890eac97e3090de6829cacf681651f2a2c95582f40369321aa9e4b9b4e8a4c731f31cc38779f9c7b1a6ca93f2c4f6d04a6b0f3e699c8a40511a2e3b9fb7f897266172ad643c8a692b2345d538097d284c68b6a92f1e9843fc3a4ffba593dd95df36e7ee4eeeb4e3410a8326cab9ea1eb95213475d669589cc8b1331ccc7d65eed95506d4426e3ecd0cb1d069420ecad77d65acb51c0b03ed6634f1ec46f4caed7e1b1c7033c6986d616077de809dad1e4c7dcf3060175b19babe4609a5601f5a7a286caa34d62c1fee27f253562286a466c2b2f91a711cbfaebc527f705bc8bc73510a1f9b915d9b65deb6f9add45e7b03240fec592fd59851a1fced2bf84b59977c3ca84536e7b0ef7109b756252405947adb4dfeaf4712a116940f296667427b1c783daaa9274a0ebb267618be37418eb65bd822d1caac9f77229bb6c60962c5158659d275728fa84b319c357eb867b9d18aa4d4759a8665c3b8375644d168f97e7ef28d1fe4a0ee885dea9edf31e01e23e896796b8fcdecd44b4b180dc7e02617a269b553a28177388c3c4176ee50e6721a43aebf52959252f937914ea9352669c269f1e31a344f8884e5ae3450628689e6356669e7a94e43ea1ac65578a8a21d06171703bf6509b7691a28cbda6929bb1f6de818b314d73bc1fc97fa5cb16c34b64c2aaa0a1986e68954e4ca7b5784088392fda54f4dfbac75e454458e01583d22d254e33b7c35d78ed4f76db5578f07a6c1bcb7dc46199c567c4a61f84c574f3ebc10064373d6227daca15f68a54710eea722a4c7ac9d8cb34c289634b7a83122011136c8b42a837199b6425a68b53f9ea56033d30bd62b1cddd8482f91d74f6173676ee3296563205563eb39965933d33ea5a591c45af07f0eee2272ef67238e7a55035403dd1cc7efcbd204360f01748ddb5d64095b865b5e45633f14727c5eaaf6ca123d995b8841ebcc8faf301ab032da70d4684b15e2042a59b4c1a333ea50f1aa4ca2c2c57af4783c613dfe8392229ee5fdf145d7506ef3d9e559246590c4864aa19ea70edc3be719cf9bdb22bd454500833be9d6eb25db42bc9c9c2b3e15f10cbbbf8faac4a982da16a236850a2ef22deaf688924420288cc4d4a7164a33f70273ba18c23050e010109645dd600bbb52809754ddeaf668a72b443d636cde95375caf3e05b69ec9d53a3c3d46d2c269274d4c297ea4c1849854c73f6fccbd1da5cbc533bd0779c44f05aa802aac65e825ab3ca5f8cf80e76032355f2d9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd932571219c3cb77d7a563214f32cae5c3ab5a379198c36ac46ef0f151a21bb0db55720417e475ac343e5f8f85b776ea6276755f5d9069447d01bf34604c0389a5a80b7684ad20d2069c15633ca011354afd94f15a0c1d2ea3a3f77e17ce258d8febd0a7358463ea4005ea0f83e358d15a789493bea81664169d09e26df8e8e3a2361e622da442aa4ea276a4e1cad5e196a6945f4f9feb7e434a747a9244eab3dce1ed953f2218fc25708efa7679c23d318c33cdbfce6be7e9125002352d34948fa8b3a67683e701c397f4118ddc67c11ade82127f6d66ca2b4137aa4876cf62bc50a20398cf64b22197ab966b1a20a098fe08768b0f5e53e25c71864a657cb42ea209e75c2201fa9b4088faae5a11d0cf74aac72f94c6cb592c2c5d6846f380d5b80202232d554abf826a19340bd0f7c5984343cb49e89936f55f2256bfc32871448794e94549ff4abc33e994c97fcdab7b3f9b270389c498899a27ca0ad92d3bcf54640c0627cbe29ee4dba357fe561619ed221c9654cc767444663abcc31edb5c66f03eee45a13503e7009cbd62d9c747fe2e8a878b4160957eb1d7ee5994382077c2ba8704ed2503421465b1e68c51817ae25727b7b72f3817febe4ec7451fc241d77109b0b4e62ec3cdb59588eef72c1b430d0640b7298820ece3c60f289be7f6c0af834a3195e89e19ae67d96b45a0bee0beb3ec45595def5f6e8fc37ba73c0515e0ec72e68159e3a59b6311dca75e37ce70329997f97069f11df50dfcfd9f0527d5ef1b407254c56d5f6f501e2d9e85d7095d7ca960a0d2c59c6f00607d66b987e1c7fb016c01016f8225393bfbb03533db594d4e1f289484f7c5eaf4babc9ff199ebe55cea3a137ac99ed39ca64c7a264e417f9bc026e5ca91a6479d8789e4638387358534d37a9b2bc6b9ec84bbcda7f2f8fc16f848423e1dae978e729d4886fc68b21dc5c90176d0dcce1c75866cc21365d383ca485c8e2e8165a264849897efaf86a2d30c068ff63e9fd065e1f84362827c46ccb49a8ec04049d1e04db6f7b50c79104f025b46d5d86e159a01e0c67310a000fc9782d29768a5b4994d46148021da4d5bf1c36ad11120ff11768b55bace7b6ca92e943d0ebd040ec7580e86094a3d569b23ef56bb4f4fcbb7b488503e0c59b287b368ed13913e7ec7d6f296df0b6a53e8785a5b3392bb92c3a0e904b1c0e100735390c8676dd2da11747fd6086f667481a70f2f2bfb352943af0492be82236a48bfd7bf8107bc6adc3928d492016aa2a13c0e05dabd3e3754bbf0e87775ff06bdca2da1382448fbabfde077584256e12aea7e877a8b9b5cbcc01119aa6a8e732f551d99dfa4fc239739c0c1d2404ee5da87e1864c313fc86fe52b02e33ec1103f9f0b7d829ab967b443bbf46b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411dac140000000001000000020000000300000004000000140500000006000000070000000800000009000000140a0000000b0000000c0000000d0000000e000000140f0000001000000011000000120000001300000014140000001500000016000000170000001800000014190000001a0000001b0000001c0000001d000000141e0000001f0000002000000021000000220000001423000000240000002500000026000000270000001428000000290000002a0000002b0000002c000000142d0000002e0000002f0000003000000031000000143200000033000000340000003500000036000000143700000038000000390000003a0000003b000000143c0000003d0000003e0000003f0000004000000014410000004200000043000000440000004500000014460000004700000048000000490000004a000000144b0000004c0000004d0000004e0000004f000000145000000051000000520000005300000054000000145500000056000000570000005800000059000000145a0000005b0000005c0000005d0000005e000000145f0000006000000061000000620000006300000014640000006500000066000000670000006800000014690000006a0000006b0000006c0000006d000000146e0000006f0000007000000071000000720000001473000000740000007500000076000000770000001478000000790000007a0000007b0000007c000000147d0000007e0000007f0000008000000081000000148200000083000000840000008500000086000000148700000088000000890000008a0000008b000000108c0000008d0000008e0000008f000000109000000091000000920000009300000010940000009500000096000000970000001098000000990000009a0000009b000000109c0000009d0000009e0000009f00000010a0000000a1000000a2000000a300000010a4000000a5000000a6000000a700000010a8000000a9000000aa000000ab00000010ac000000ad000000ae000000af00000010b0000000b1000000b2000000b300000010b4000000b5000000b6000000b700000010b8000000b9000000ba000000bb00000010bc000000bd000000be000000bf00000010c0000000c1000000c2000000c300000010c4000000c5000000c6000000c70000002b000000000000002800000059000000020000001e000000" + resultBytes, err := common.HexToBytes(result) + require.NoError(t, err) + + var sessionInfo *SessionInfo + err = scale.Unmarshal(resultBytes, &sessionInfo) + require.NoError(t, err) + + //require.Equal(t, SessionInfo{}, sessionInfo) + + encoded, err := scale.Marshal(sessionInfo) + require.NoError(t, err) + require.Equal(t, result, common.BytesToHex(encoded)) +} + +// TestInboundHrmpMessage tests the scale encoding of an InboundHrmpMessage +func TestInboundHrmpMessage(t *testing.T) { + t.Parallel() + + result := "0x28e803000000d007000000d207000000d407000000db07000000ee07000000f007000000f207000000f307000000fe07000000" + resultBytes, err := common.HexToBytes(result) + require.NoError(t, err) + + var msg []InboundHrmpMessage + err = scale.Unmarshal(resultBytes, &msg) + require.NoError(t, err) + + expected := []InboundHrmpMessage{ + { + SentAt: 1000, + Data: []byte{}, + }, + { + SentAt: 2000, + Data: []byte{}, + }, + { + SentAt: 2002, + Data: []byte{}, + }, + { + SentAt: 2004, + Data: []byte{}, + }, + { + SentAt: 2011, + Data: []byte{}, + }, + { + SentAt: 2030, + Data: []byte{}, + }, + { + SentAt: 2032, + Data: []byte{}, + }, + { + SentAt: 2034, + Data: []byte{}, + }, + { + SentAt: 2035, + Data: []byte{}, + }, + { + SentAt: 2046, + Data: []byte{}, + }, + } + require.Equal(t, expected, msg) + + encoded, err := scale.Marshal(msg) + require.NoError(t, err) + require.Equal(t, result, common.BytesToHex(encoded)) +} From 5cfd8098de22ef226a277307ba4581e4f5fff85f Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 5 May 2023 00:18:32 +0530 Subject: [PATCH 34/65] fix tests --- dot/rpc/modules/state_test.go | 5 +++++ tests/rpc/rpc_05-state_test.go | 5 ++++- tests/utils/rpc/request.go | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/dot/rpc/modules/state_test.go b/dot/rpc/modules/state_test.go index 3d7a3d6d55..5d08318071 100644 --- a/dot/rpc/modules/state_test.go +++ b/dot/rpc/modules/state_test.go @@ -19,6 +19,9 @@ import ( "errors" "net/http" "testing" + "unsafe" + + "github.com/stretchr/testify/require" "github.com/ChainSafe/gossamer/lib/runtime/wasmer" @@ -305,6 +308,8 @@ func TestCall(t *testing.T) { var res StateCallResponse err := sm.Call(nil, req, &res) assert.NoError(t, err) + + require.Greater(t, int(unsafe.Sizeof(res)), 0) //nolint:staticcheck } func TestStateModuleGetMetadata(t *testing.T) { diff --git a/tests/rpc/rpc_05-state_test.go b/tests/rpc/rpc_05-state_test.go index d4bbaed40e..4bc5d2791a 100644 --- a/tests/rpc/rpc_05-state_test.go +++ b/tests/rpc/rpc_05-state_test.go @@ -8,6 +8,7 @@ import ( "fmt" "testing" "time" + "unsafe" "github.com/ChainSafe/gossamer/dot/rpc/modules" "github.com/ChainSafe/gossamer/lib/runtime" @@ -47,8 +48,10 @@ func TestStateRPCResponseValidation(t *testing.T) { //nolint:tparallel require.NoError(t, err) var response runtime.Version - err = rpc.DecodeScale(data, &response) + err = rpc.DecodeScaleUnmarshal(data, &response) require.NoError(t, err) + + require.Greater(t, int(unsafe.Sizeof(response)), 0) //nolint:staticcheck }) t.Run("state_getKeysPaged", func(t *testing.T) { diff --git a/tests/utils/rpc/request.go b/tests/utils/rpc/request.go index 7bcdd49838..c79a0d0bc8 100644 --- a/tests/utils/rpc/request.go +++ b/tests/utils/rpc/request.go @@ -94,9 +94,9 @@ func Decode(body []byte, target interface{}) error { return nil } -// DecodeScale decodes []body into the target interface. +// DecodeScaleUnmarshal decodes []body into the result. // It assumes that the response.Result is a SCALE-encoded value. -func DecodeScale(body []byte, target any) error { +func DecodeScaleUnmarshal(body []byte, target any) error { var result string err := Decode(body, &result) if err != nil { From 1748902b4a79ef5cd2db3addc01ffe67cc9d1d74 Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 5 May 2023 00:47:42 +0530 Subject: [PATCH 35/65] fix tests --- dot/rpc/modules/state_test.go | 6 +----- tests/rpc/rpc_05-state_test.go | 3 +-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/dot/rpc/modules/state_test.go b/dot/rpc/modules/state_test.go index 5d08318071..a216d5d844 100644 --- a/dot/rpc/modules/state_test.go +++ b/dot/rpc/modules/state_test.go @@ -19,9 +19,6 @@ import ( "errors" "net/http" "testing" - "unsafe" - - "github.com/stretchr/testify/require" "github.com/ChainSafe/gossamer/lib/runtime/wasmer" @@ -308,8 +305,7 @@ func TestCall(t *testing.T) { var res StateCallResponse err := sm.Call(nil, req, &res) assert.NoError(t, err) - - require.Greater(t, int(unsafe.Sizeof(res)), 0) //nolint:staticcheck + assert.NotEmpty(t, res) } func TestStateModuleGetMetadata(t *testing.T) { diff --git a/tests/rpc/rpc_05-state_test.go b/tests/rpc/rpc_05-state_test.go index 4bc5d2791a..6e039bd3f5 100644 --- a/tests/rpc/rpc_05-state_test.go +++ b/tests/rpc/rpc_05-state_test.go @@ -8,7 +8,6 @@ import ( "fmt" "testing" "time" - "unsafe" "github.com/ChainSafe/gossamer/dot/rpc/modules" "github.com/ChainSafe/gossamer/lib/runtime" @@ -51,7 +50,7 @@ func TestStateRPCResponseValidation(t *testing.T) { //nolint:tparallel err = rpc.DecodeScaleUnmarshal(data, &response) require.NoError(t, err) - require.Greater(t, int(unsafe.Sizeof(response)), 0) //nolint:staticcheck + require.NotEqualf(t, 0, len(response.SpecName), "response must not be empty") //nolint:staticcheck }) t.Run("state_getKeysPaged", func(t *testing.T) { From b571bad5167e6523eaa7fa2128eb5bd8924176cb Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 5 May 2023 00:52:33 +0530 Subject: [PATCH 36/65] fix lint --- tests/rpc/rpc_05-state_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rpc/rpc_05-state_test.go b/tests/rpc/rpc_05-state_test.go index 6e039bd3f5..ba58886428 100644 --- a/tests/rpc/rpc_05-state_test.go +++ b/tests/rpc/rpc_05-state_test.go @@ -50,7 +50,7 @@ func TestStateRPCResponseValidation(t *testing.T) { //nolint:tparallel err = rpc.DecodeScaleUnmarshal(data, &response) require.NoError(t, err) - require.NotEqualf(t, 0, len(response.SpecName), "response must not be empty") //nolint:staticcheck + require.NotEqualf(t, 0, len(response.SpecName), "response must not be empty") }) t.Run("state_getKeysPaged", func(t *testing.T) { From 13b80a001d6e8d7c9d9d030bdc1d7574634ccf54 Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 5 May 2023 13:34:25 +0530 Subject: [PATCH 37/65] add test --- dot/types/parachain.go | 21 ++++++++++++--------- dot/types/parachain_test.go | 23 ++++++++++++++++++++++- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 119394af2e..5fdcdd8496 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -250,12 +250,12 @@ type CommittedCandidateReceipt struct { // AssignmentID The public key of a keypair used by a validator for determining assignments // to approve included parachain candidates. -type AssignmentID sr25519.PublicKey +type AssignmentID [32]byte // IndexedValidator A validator with its index. type IndexedValidator struct { - Index ValidatorIndex `scale:"-"` - Validator []ValidatorID `scale:"2"` + Index []ValidatorIndex `scale:"-"` + Validator []ValidatorID `scale:"2"` } // IndexedValidatorGroup A validator group with its group index. @@ -264,25 +264,28 @@ type IndexedValidatorGroup struct { Validators []ValidatorIndex `scale:"2"` } +// AuthorityDiscoveryID An authority discovery key. +type AuthorityDiscoveryID [32]byte + // SessionInfo Information about validator sets of a session. type SessionInfo struct { // All the validators actively participating in parachain consensus. // Indices are into the broader validator set. ActiveValidatorIndices []ValidatorIndex `scale:"1"` // A secure random seed for the session, gathered from BABE. - RandomSeed [32]uint8 `scale:"2"` + RandomSeed [32]byte `scale:"2"` // The amount of sessions to keep for disputes. DisputePeriod SessionIndex `scale:"3"` // Validators in canonical ordering. - Validators []IndexedValidator `scale:"4"` + Validators []ValidatorID `scale:"4"` // Validators' authority discovery keys for the session in canonical ordering. - DiscoveryKeys []byte `scale:"5"` + DiscoveryKeys []AuthorityDiscoveryID `scale:"5"` // The assignment keys for validators. - AssignmentKeys []byte `scale:"6"` + AssignmentKeys []AssignmentID `scale:"6"` // Validators in shuffled ordering - these are the validator groups as produced // by the `Scheduler` module for the session and are typically referred to by // `GroupIndex`. - ValidatorGroups []IndexedValidatorGroup `scale:"7"` + ValidatorGroups []ValidatorIndex `scale:"7"` // The number of availability cores used by the protocol during this session. NCores uint32 `scale:"8"` // The zeroth delay tranche width. @@ -358,7 +361,7 @@ func (CandidateBacked) Index() uint { type CandidateIncluded struct { CandidateReceipt CandidateReceipt `scale:"1"` HeadData HeadData `scale:"2"` - CoreIndex uint32 `scale:"-"` + CoreIndex uint32 `scale:"3"` GroupIndex GroupIndex `scale:"4"` } diff --git a/dot/types/parachain_test.go b/dot/types/parachain_test.go index 28a88a3579..134056c42a 100644 --- a/dot/types/parachain_test.go +++ b/dot/types/parachain_test.go @@ -173,7 +173,7 @@ func TestCommittedCandidateReceipt(t *testing.T) { func TestSessionInfo(t *testing.T) { t.Parallel() - result := "0x0121035000000040000000d70000003b000000f40000000b0100009200000078000000ea00000027000000ad000000cd000000b6000000220000001f00000010000000fe000000a100000037000000e0000000f000000054000000450000003d000000380000001b0100005900000047000000aa000000160100004a000000d5000000ee0000003a000000d2000000df00000002010000d90000001f0100006e000000f9000000d00000001301000006010000bc0000006d0000005c0000001d010000b800000000010000190000004f00000015000000180000007d00000006000000250100008c0000003f000000fa00000004000000560000001e0000008b000000b20000005d000000bb00000035000000f7000000ba00000075000000fc000000090000006f00000055000000eb000000b70000000d000000800000007f000000a6000000070100007100000033000000c800000073000000f300000017010000fb000000b400000001010000890000002601000019010000290000002701000021000000f6000000a90000008d000000040100000e0000007b000000c3000000a2000000cc00000062000000de0000002f000000310000000c01000074000000e900000024000000970000009e000000480000003c0000002001000066000000210100004b0000001b000000900000006700000049000000e50000002b0000001a010000e3000000980000004d00000005010000ed000000810000006a0000000b000000cf0000007a000000a80000001c0100001c000000950000002800000083000000d300000043000000c5000000dd0000003200000061000000fd0000000c00000026000000d100000003010000000000001a000000230100002401000012000000130000005800000091000000230000003e000000460000000d01000042000000ec000000a400000082000000a000000052000000d40000002d000000be0000000a0000005300000011010000d8000000a700000014010000390000009f0000005b0000003600000068000000930000002a00000007000000f5000000db0000001e01000018010000690000008e0000001d00000077000000da0000002a5c9458a86c0fdf9dbbb3a601b73ffdfe2e4286b19590105f3cca519368a49e060000002103703579df75d2c2dd3d53003f55ebbefeb59446d476d0a722ef8ed1954fae9d6d887163920530fb937e8f1da96a7b61d25d5fa5ec340d6a0081b79371bba84602b20cb56c26ed93ec124e1c74118106d1185564c7c13d79440adac261a32fa066280f6162242be89d139d52f449e2bad667d7d974cb80d0edbce7237185b114755034e95e2ceeaae78df5568d0fb779511c7eaa4bf3bd4c93666161489f0ce15e9a434cba271bd56cc40fa8e08ab8837da8abd274e7db6da8551e11cb14ce154d0a2a458b11deeca8a708cb12b8212da06449f7c8136862b0bf11fd368d00143e6a98b861ac1f6182a14bd30adcc699cf22e900d5f51711e7d41bba4928de23519a149b9b68af793ab31f83f500126e0fffa71469e78e22e754f3b49db1dbe6316e07945d95fb46ef5346bb3a502da9f005d1cdc956e1b96258fba48dc793f50b3256f3f643ebc6300f32561a0a5583813bb3b42844d1ad3d3779a438771a295e18cea89823eaf4f9d332f3a74ee2d88e19b321a311b45f095b05c82f4366c0093cd4a621e6146ee5e441e904aec79a734da3675970cde7793608ba482602ce2b306daa91a5a25590d2290fd262d40f239f87d37e1c03a2494035a42961db2f33701058e68510bdf68a3678d32145780e13c29b88fe77b27440bdf3ea9762a639dc3a5a9fa2b1bed2a4a48fb21792b44c5772f888132d414d13a98bb5bbbbd70a46b3d1cb07cfb8d2e13fa9158734dc2bd1ea554fd3032bdbf9e9871d29370602d8e45f1d6d02c43c3e38d6e7871f18ee80f60415adc76fdf4c8ad2c67ac7d116f02a182d14b38906ce1f4693cd9b87d0369e6af514cf7ec91455b26cd4c0d71b5604f6624a20179a00fb5dc8ba0bee359255702c162c85d72496ca031266554deafbe5a4ba60e2abfaf17f7f730e43bba40e7102e6c75c08f27403fb9761d874167e6d847ad207f3a1221ce1f958946317e77ba146d16aa7bd82810c5e913c4d76c4d221bfc6da82c7055e469a1405eca842b4b8efd101e984a2482e526ecb08482cdc214f825dc7085e54a984230a753d66d08425f9763f52f8f689111202601e0560d2b374b7d6e1380b6b88ee8ef92cdde7edbd9a48d66f5e219840a1155898dd787757d12ae0629612152b863116a5e2d0e204011b12b06101158fe1fb7230930357b8b54ce94dfac3276daca91ccbab9b944bdd9754fb27d2b786427b304a3487dc0c46f976d352e5e152e120d2d23774f921583d1f2c128f7cf9f66529e2379c7f13349fbdd0d6a65918797b977a5509f31930b09dd62983e0609dba11c42afa68950568131a449e70574ae0f45f28b87210c1ff7df1adee5576d039500ab779ad711947b3faf071e6ef46aedbdb33aea5a26510057e8439e09abcb0321e282ef8862f121223f6aa19fc1f929106d7a916747f21e1973eec1e8c5b7f78b61bf2c4723c0ffac961d2a54b44eed88f74076eacb58b8d0f208588ba2b435428e15975e20c0f4dee26bbd12317df11d4135edba1eb865bdd6111af6d27693b347964127e9d8bcd119989a92646c80886c2eb8440c87dd7dd94437873a3ce28cedcb9f27c114aecd7c8860d96145cb226ea5dc9139419533886dfe6e340f023d49f031c94d9c3b33494849eb9682c0311b3c283b17373f18b9ca02d94e2c05cf8187c36919c9d3bb5bb42f9539f8fca2040717cb0c409c58991b5bd2945f15400af2466b5e4a434ad5ef602a77f311fa22300a5a6ebf03bdcc04f92fdf0da3cfaf06927382cf7d52882c7033a6baccc329b4d4cf4f8b6cb592eb9065c3fde133667fd3b0c5fdf2c30cccdd640a7297da408b6aff82ee9651f889910fda9f24c06859e71b51c3b67b9be211ab3dd2de59e860d8757616c4398fd9273e6320e4d569159331192c6b6949dee038eac8ee723d32f77f049cdb4542083249db6127522500f189af22d09cf00c8851df6c4ac122134f428b24be25e12914c8bde527ce059357312bfd525317b4f93e5eee1de639872edfaec9d2a320a6fac04d61051e41161e6df14443df6eadfb3c5ad5228291d1383cdaaef20c9cc8125f7952f24645c3b5a2e17df20f698507190332c6951d761c5f46e0dcf997c7337c0bb7e5434cc7903dcaaeddb2bd99fd6b36ab15fc32ee001bd1d95e87020019f7c88be2ef63d466d1560353a2cfa849afbcbcc86cdaa057bd819895d4e90820b8bf9db7bc4bc688653010a7720d44168b4552bf75974219788ac1cf3fb440c67ff692d49b27ddf8cb39d72e9fc00e6165f43fd61812f9dce895b0d89329d2b870a91d0282a345983fe177ea7b18090fcb028cc41c1c4020feb6b80f807d4b5c8a4756c4b72ca569751b32be145716eac8ee5e731a1db2b1dae4b9023b05876077cdd78089a53c2f9f5f55bd687e359ef37196cd288fcd1a14adf6cad53c6704445a1f121d614110699b5642a4b726cbcb74bee77642ec7b4f17b06db88ee461848ead17cfcd9b0171f73154a0734c1cc95ae552d9f3180d7d64e8b50d3837b14b5afd222aafd3f8056d3462eda0083ac22241db692c4671249a14a04c2f0a2959aab4126dc96b44d66194bb8d466903d20f3f7b04217c3b5ec66111c325ff76450954665d669fa5f68e69276919abd026fad265d5062567425e3f2d364960dfbdbcfd3417afcd4713265cfd83dd24d3bfdba3d67384f32e4ce357fd88c4586d3abffbd33d2ebb6671ff854613aa3ad169250e037aadbf0ea14c87982d7382f09c7b8c967e24208a0bbbb7035130798abba24cab205d22443e8973817b685f13c9012b97c38a1fdd2dbd3f5ce02f08fd3858799ee6a994c48cc1db6d713d6eea3dfd4a93590f0a210318068c2a90f4dc4f2e114cb83367e561d811e18c30a6c2d7c8a7272128714ed41e3d13b8aad0d076b7ad34af4946866f552568eadd3d3582b4c4f50f286ac449dbc94282864e76dac48fb9bce48124189d2d45e2b2e16b8084c022b3405a94626a6d3cecc0492a268e974e9864826f8745403fbb98f55bf45c0b62002d1ae50abf4787916aa4d35e41d807f88e32460fb084187b4070c3a7331f92f6ad32f9b9aff185ae19ac28f3032c96ffd8fe3dd72cd0446f9e0098ed3a2fe2d56aee499b2dffa90a79b118a646aec6b79e6766dc25665db73a98e173fa6381a484d1bff4961f87c7ff6a6a68beac9264665f87ba1a5fab9802f1cd729391a711af7dc55da09babaf097d1304b4cde14562506f4db4897644895324b542d8f5778f186de80c5d2d0669404118ff1591ff141a606e05e2835889a5f42a32e9a1ff4e91b06cf4e6f6ecf77590356fa1773c014185bdf5a44972e03576c477fa731925f1d69f20b9d9cbdec900346fb9dfc869c696b3614062e5716ab0a579ca33fb429d0687fef75f26e5503379a61920777ef1f254af024922e382dd19e752e699e2c6f01ad57676c99bcf413211db6d82b36c39b441d65b0d7ed4c5aa0bf24050658f8f3a64ec6949a26916ae2cd976fe531947a9c9e93e6d587bac746cb08264eed0663b1d15bcbf9e99c372c041ef118de7d179c68899a645a0fa0983b473ef81c50a41863194537aa28f805d69280250c97b5c4f913d4030f8110085b200cc802ed675571cba95d42bfe5c3394fb7ad5778ddc436f407fcce0ea0eb427c0ada5bd7647f8d8388c2b4dbc138e36b8679284eadc49370ce0a16a4e0be28804b88c40cc8b84d75f043545a46bc8124a169ccaa40158b1f60915817f5f22ccb75f6c138e9e4061b3a799bf7987ef5c820c1e534df298f3328e1093c5d0758d434ea33c3da5b7189094e98315abff23fb4044c5d78633336658dd5e47e973ade4d8a7477bdafa88e49f5c8cd88fbcbc1724d8e227935eabce71ec303d832c4ab27106827b00917fd22c6b8e62eda5e130344c9214f2565b92ddcd6b6edfa18e95fd4d65053a5ef2ab1152c72f3b15d4f24d4bced3b7e277735eb49450dd867c115a4572a284f0f812d5fcedd8983f24df41875dac1ed854f1bd126b4d76c416e54b48268cf5d93c19d1969468b3fa94ba9f249b0c9464c6635728a2d3fac3d123472d3ac8b4dbb4b6a02692af692160b113da09d4ae9f0464c5522b7236a59b70d98b499a9c38970f6f3dbee7e6220ee0e12a582a76ae036347816baa6cd7c9a7bcc90ef1acebf194c7b9820968e554e2ec4d34346eedf80cacdafcdbf118a3f15a47238af22f221626e9a03a6005a06e53ea9554fed6ae199c0b84c769d4731709662caa1a29ff92ad66794001cfaaebbdf4071f4db6d74ee767ba59cca4cb36c0828f0bfffc49973cd14329675728a2d243102ab486601f1581b1e741bb5c775de464459b18deeea6f02d5882e80a8696b00c9f703da84bc5769921053ecc7494e8c22d93dbca83c05bc5222ae72b85617956f04eded477369ec95312c7c783564a615616a60f11f3faf3b83415d572e0c7db6bed9aa119aa6372f6eb7ecbc01cc3ceec15a5af2b64d5a43ae54fcccd31ddabe95461fdcb5be506267404ba432b0cfe1745dd408f6dfa0ceaa1780ad4ae1747a8912a589a754ed86373a08ff557a99adb8191a2eab2473283f387361100853b1eb98eb69959d8802d730bbde3d969ae5d9d6efa40c6255ec4b27b0a4752d7f4068163116e76cd0d4041c471431de365e70f8503654e384a4524c1c16900873792541ef023019a68f62250b7c21865b996d545865beeef3b84ab62610764825db06457340d99d3051903a759b4a68a25e2913e0d6e61521809ccd9dbead6b71744771c25d31cfec9c4ca5ac0c21765478a56c4b3708da965c36dac2e8caca9398d50bff836219540b179bae76671077a01e7352b7f4ea4faa4d7176fb75dd9c99844a76a8d042a48c5f76a34a2cc056df4318d12a052ab505db7d06dfe03767eb5f46cf0d271393db1db2516c52a0d9c323ea08a0551f96c28b05ac0c7b0e338cc5004bac22d06feea5a8f5c0011619ab90bff00f89ea8055f0d7d45f8c8aa9c04b7fc1d06468837c6c563a6529c414ad7aab917306d30209c502394c169a698d1461eb23ba81dcf998bafb3635aa091181db267cc8ff6c5201acaad6fc2c3a2cd18eb729ad0c1526c6c348e3308e650f7e08ac882d65fb09141fc5c7d252da9b1d8ca2ae311752ddce97713722aa0b27274712eaaf13c959cb84495856b51b71d066d3d4a346b37d3e2d587a0bee13fa85260215c5235169fea113546e7b4aa7a1c936c47a14e81d3df912601ab2a1fefc7a956231a446a575db2e31f7c084c2945094f3927519617d7b913712061f1060d5207533b44b4977f128acd44bfe1bfe235f2f4b2d042a87c7da4d1d82faebc67455d17caf2247f2b470db6bd8917913635bb8e41582ff0e06d22f092a27a84cd2398fd21f533281bc0d6ed0ea6c50fc7077add24dba8eb41b43670ca2fe2f72540e18669d0e534dc562fa03af53b90a8003e7e355849dc2c489082f4408b86991f7ff8f5676ee81ee9b44be90d067969cfdf6a95d4004396be34c5c80fc5fd10948cd231f68ec00397e22a19042578431aad63546679e72efa3cc61b40ef939e553ef7b366ae8d3b1da893ecef71a2bad32e39e7597b1a664d5393c34d4c6438f429028ba64818bedeff64b1db1ebdd89f2c2b2fe3336942a03036bb46bbbb430df46c7c792d3a23c29de2dd7189892b1a28742091213c56139b20a408b1d453ae31f699e53904605cfdbaa72639138cea3e544258e0484a5322163ba846878e4f157741703bb4c3ab4f3ff2e9b99916624a9965a4256d893c84e150ed18130a0ed0513b2a2bfa7ed6c9090cb350983746b1936c6a92f7304a70054a82cfd0a101c80974526db2868471fe3b84d802610a5effddb0a1d84f03f276afc2dfec5fc9e062cce0b84af38f1aa1e0aa8cdf197da7df8abd786a47a3c7861108b830844381b9efb92625d7333f62f5ed580f29c83cc232fbadf64439cdb32e2ca7cc3abf450897e2c320b9595850ce89fc41da36cac7c2ca9b135daeab148645771381f31a42a1e0bca62f752fb49e8d2a49f942cd48a03129a709e763d23547b4c766e40db6b1685c455de210347c5757ebb7d463d1910eb70fb290b5c7b8afa23b3c8f159391a3ffb6dda5ce3c9f6b40f25c1dc7a742186b7b693f30111c4b778017656b9a7d69d3e69159852f38adf971f5a25df65f9950e97411c1c3638c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e85297eeab48cb88c51118ced6c65368c5197ec7f014c443b47d898627cdb77813514782e505e29567f9cd04ef52e106d671e5591af83fa3a5475e6dc2ede9ef7f03f70d2ffd3b72525806a645e5abd09a51d257c30dcf016435c114d26d3d3be17085809bbd7c01492cb4105e4fbb173650c3586f94af7b6d9ad2835f62872e7ba4f5cac0ffa042ee550a3bf70d380dc032d11eabe311e0796c5143341600ef62664ce534070da425ee9c583103b7a1df8603d6dc9b08dc3692d6ca6a831c93b822cae73975ffedd91e81d8d6d9dd6c865356ae655ad1d55fa4a3e3641d2e2b3d12582942ab79f74656a8f51ab8c1b088f33ddfa20992eaaae491dc3dfff9742fe32263ad657e55682de826f6137dedd2d246971fd8c5d318034940160fc179efa6306b888519767218eed7b884fb221f597a2d4edb69c094961ace2e65a7e40913c5edbe8dcd591d30511a0fc08bc5172ff58ff98fa848387b25f99205361348105107c0623b54b469b13f24fb30d9556087096c900413e5f1229b844ef0fbd8846b0acf62c24bb58eeb0a71365ba5f890a594cc046a483d9b306a487ea4eb5e80518913d34cc4d0c2b0602803371bb33f5946fe6f4a44388a05bdfa02226be6f176c36aa9c0762a59eada83c70e1049d5d09f7f7304c465f2ff56dbe21687ece20e60838991dfc86f6a774c295cbde7fc208880cbe0a02c4434d31b7532976f66f2270467b0c03fcfd8bac09473161c6eba9c25369a853193b472eb2f113a3d333806eb5dcaff87a28d25de336e240731a375be04c4bbff6be6a5ba4f1042a06706432533fdbdd1a739c62733cb36ac48c821dcb0311978f1027bc1e39d4c8964e42c2279a99ce0b66cb06a5005dc6061a241edfd1860476cc03abf527f668971cfeba93ce0a747704cdb63a6affc76d6e6753469532256f29226d97566bc7de00903f1b40303c03067b48189de899eca5f2a7d8081ef4c3ebfc8aa305dac4637758c1f97d369f4290e38a09b7187c55dbc2c6c180d278cde597075ba0fbd0a1262c19794d20de22edc9c4c1514f4f4e29ac16e6b421d3620ec6545f737100f01372e1be0414087552630274f329a465cb85e625d3bd3121ba7df904a753cdc70b5215aab350a03f5371cefeca57c3685e2cae8845673073c0d89e3f654e206c1bce5d949162cbc728667ecce548da5efe0448823e928463418342d41883dc6e2030f93bce6916b6b78ce4f7d550c39c7947c6860502333717d541fdb6697ab4472078921751764a4d5caf9a2ed29c0bc7c5ede2cfc5460155d4818f3bd211e3389e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712160bb493e536e83addf98be8cb2a0158cf18c6d5ba06ab586a2cb56cf1ad4cd09c81fafe5d47c4ee373a54a64d267c497c59f4c15077374317b91566d44c82f74b8d2a3c1187b96dbac7ec6ee71a9c9ae3713acb168a8f0e325d22fa6be66e74e4c29c11128e193f06c866e165662d903d9f799508e617920d786ebf75acd26743c50b2fab9b87f1a6228df23e9507c90bec51b8e3be978b526c0e0c7704c7334181e6b71b981059fa265cd76422e52fe175db6983c6ebdd0fea1a3075166b92936da4573a6c20044052b270916290b13a30adf3a821b467c4038a14026badd09ae9fcd9ab8a7020a1f967780a1ef49b13b40fc3cfd208e29f4d5d5ee9bb63c5f7cbe0f373967eabbe8b5f5302ca7d7d9ecd763d3d2dd4c28896f14e730098c443ea7825552b7f76db8f2ba2fce0e546d7e7abab7d59e7afee2bfe438bad60919a6c2006ee64daae1fc0dc0cb5473b35b338c934cd957a64e7ee970385650c342c6eda549af9f0787a7331fdc24174026c49bbc00a20cd9d723f6e172988b462990932c5bbb2666927583b8a8aa64f7480ce8d8705c0b2ec53fb39584b660481d148f2b835556a0c8d3b51ae0e823655bd4aa20fdadc6b4189de9f32cf228870000b9032129790c24e593457de03f1950c427a6958487a0a8b3cad21f7581e43d26552839c17a5dbf3b2f90875abc9959553b320da9f07f1392fa3065315a8b17c2d3f9f9f499e04d2f27dbe47ffbce115afd1bac9fe116ce7fae719325e4082436da9dac450b4c23405b4f93953b74b11815f0f0cd45d2022d4ecf6a320eda1ae232d9f4c8884a9f53a999e8ce7a27f68e9108a4fde15bc51a350774c22b2a147a599c3e8a28ad44c5e3677254b2587f269e73d370d0c04d267092a52274844ae8c13e37a4d00135dbe7699d91507f5a53a7b8ed36a3be29cb2fddab9f7a286c78f2db2e0d3736589c38da969e8ccdd8e175040e25af8bcbea5a5c0568c9c624744c3b91b676828a5f884e79d9c02d6f23ec246c3a1a8adcfa9dc1e531a9a5317ce213846134673a8addd69befcd121e08a53cebe9fff3b872a7debfffc96611264105f794545152cfbff9151899b846773cd928403d11400e4d514e5f703d408c33a12a32c203715ebd7b2e9f574c733d0197fb36f2587028614be990caa70aa02f9a012221d644717e2f1361ddfd9e6b5d0043f3a47eeffab15e43d7d45e1ff8d720c75db2894a9a2746ccba83bbae55c0a99b821a41db37b0011d12a01a6018d3fcd225254bfac8ee7f94e5f505496773b69c49697eb79ef8523530c55511d816c065e65b3583c8309e3465db95b458d0b42619e1ea75ca546e966d761c5394cc6b2efa21cfcaf122e7524a35dcded808306c042e70bab6298ade3ad80d33b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411da504b6dbcce848e56c21d870a965f61bc53894462a6997e78f55f20ebf32f8f4de37ae23e707c1df21527ba79fb2c6cb074d51ed0b90e361b2cbda0637c074415c3e585eeb7d466f7e38b980536e62c00fd3dc5c703c3bbd721c9491e6eb85c32a44664e74f116e47c0991afa7bc43d0b4aaf085d205ced8ea01235b224e9e2a57569eb394a00dd88f01a451ade235d634484a9c56c595224495874fbdbdfdc1e9329e2e155aa2dd16ed173f806fb4531de44350ea0f1ce530bf0199d2a4e5912a042c88235eb7ebc41513cb9d42bfef2e56ab0a86eba53150cdf24f8ca5429b6c5590a786a922fad3ae1f8e6ef534f341aa4ca800700499532dd0d9436fb24c1b1b5ebb74bbc3f5ea7cc6eb966a566123ce03005a73c0294531cdb87e6f4e95a51514a49f30a2a2f680daeab96ba080e9436779e88da9f35f1df28aa84992e99a0b3a836e898f478234d26fc7d8bf866a6a308f8f7cdaab738bc98b879669911a26e05965e7b4c7ef5319c98707e231a82bafbbc639a8613ba2d4f22584de53740c421e7f92dcd88622e35e35994021fd95c368ce30d455831b8d7b5431f33a7327d87f69b187cd620e910289b9d5c2704d332359fce4040b4978eb1527e743dc1526b7a3b02d5edba566f82d3f949278d4d0660165857965f123b1ff5aa680a62c36d972bf0421adc4a00cd631414f1cbecb646e0008529253e9c0169822efb33cbea69d9e769a9b465041255b591fe2708f1193c6a0d7e83e929c167d0f672a6c8c62c3e73695bc27a72c21d264daa0d40c012083c581e4a0dfc7f168b722b23736d3b2112224e3432e605d698c7809f9599544725f3bbd89e076742a2e33631e1c33a7f530505af5bd7347c366ee21d089ea4ef1f48acfe1bb6d6c340aecd66660d3a60f115c98e714b9ca80bb1bfbe16704fb841cbfb0bedad90d8ee5106d21a44c8d3067a4034b5d6101af80d9a2970f3443536302525e41dceba23d8862004e1f947c0be485986af1fefb306419c6fc3cc203303517dedafea231dd90856d62fa40d6ad22c0bd13811d9555f4b2adb0f639cf7ace8468db36e557c1e1176e42f7de325ac001c0d50c4d27c15248ae2023cbc52e2ee969b16fbef249ee2542a27e810f57d102788527c3e274dddc99f094edf73a09544cf3f162573d6da479d65e0318bcca6caafcefeb3452d68d6197c8ea0b26b971962e201405c4c157651e202a49166a5e267724e5bbd0d9efe57d34d8cd7a2e536cc7aee14f127260657849008fc52de08473191d53f8cff9c54059406398e89683d41db5ca287bb379e421d77953121b3efeb10cd44d504b5cf47a9807dacce8eb24d53ce62e1458353e9052ee1ea8f6f1a8fd7b2262bfb86110b06210c25e7fac37b49198155c24719e961df7e2cd5aa3f816fe8950ecc0c2c9838fbf68bca5d4955de8719bb6cf7972c623880702eed40e35aadcfcf6b09f67040effbeddd2b22af32c2978da711f6ea75184c3c36dcddad7c1a570d4167525f3f53d8d39ebaf2d239bc1f9e7572c9c2de89a454439ff9ddadea199ac62ed47b9326a4a08c06859dc6aa56cf5af62a0fe07efe8476c462860a01a5e4180a4de0249f05648c23f8e6e3bc49809eb27cc08d547840066bb56916d9bb9761e05133fd18a68324492ad7b9f9caa166803782939a3e4f8394ef0f1c9a8f811a7f5ea333cadd30d3404352aedbd7a2a7430f46dacd30ba7bc9797085a143f0fcdd6b0c7ffdde124bace833b758ee4ddfe50f261ebad3748d4e586cf4bb52da7a9c3a306113046efec9210cdac01dd254b6f5e30cb812643fc1d2857c220dcb944c423397264da353d5131d0c70933d72b55360d771b7d982561ac136d24b714920430c4110bcd961e12bdee0f47545d9a50c20e2c4e3989890f61c5b1df09c72d8a70b5e5a161c0077f73c816b17f59d95372ccb9ad0332fc9b36d3a24c6173a23014f684d0f1666b8331d108ff33986354b6edef3369e8da5f707e530fcf611301be6bab8187386d130d1f8c94e5c3602e0ac63a273f4213225773647e8a739187223eaf5c9f0f2e3d1b12e229fa77e65b9880b245038d021948c6700d89443c09f207b9da66d2ec05e1c567a8ae5fe502d4d02ae9d39b49dafea09bc363a28395b90f0c0482be2642d693c65b1dabd51d38cdf73e322686f01341d26623c2491c6340204508a421b5978d8f7f698b473ad8db813d1070487f577a18b9e163ed125ed818c0d13dde40503a10ed6c8d3e6ab231b7a7a68d58e125aada1bdc72c94363a3d8c1e3ff72da6102d37790dbdd11064da00b79d78901da2b568d1dfd70c58eaab561cb0dce9ec88d17684a783d36067bba03c1df0cbc3cfea77b39ee77b49d8b425455e45a27a245c1963853bd3532ed1f9d70028c2001ede3fb28ac4db0b0215889cb331f8bc637d8cd27d44435e0e4451bfef8b6e07bc00ff6fe17cdd12d45db9f816cace50b0682291a8dc25726a39cb65fb8a0456f4f5380b87473b2c6d3ae6c36664af57171130202317f5686635f0474f0fe3f7138dbd0c961b000d0c14707c9c3037792e2b59632bef200ecea24e409eec05550dd35c62be25a1612ab90b268015b40eaed9fa0717aab7604a659bb00f067a95adcff05c08c3250b864efeb0c75aec01b50d32d909a2a0b8e0595ca52e08fe5b0d37ac52bda3dc4c8a0b7d3e9d1812d5530ebcf9df0ca53581d176f5b8f880047f3803efbbcd442b7f8b1fe158353183f03d3f6acf468659eb30a9abe2de835e3229d8c3cd6b00e936d5339b325684a5c483b15420e123ca6b7893cfcd6ddb8a9ff65313caf6456f2ad2188feb5ba8dc102539e94beba5882614bbdd5de594a31b66107f0476d8e0f3e2f9b858634451f0fc2222e24db6608ca6874a522c58bc897c403a860cd5d05b731add09f9e24a465d0da6417d000a4533e0224cd2cf5426a5cdcab8c30caba2a0a36831bce623b526cac663bf76f4816a0ad32ac3690b658c96cc6e09d9510a57c8e28f32220210108791a15aa0d3a2cdcb143ba3e7fa41dccf5534c6fd36ef91187d55e35dac9d3925ac08e2c22c246361396ba03e69055b5347faa6c1cb9929766e4f2a7b41911e25448678f4856d131b61a171c4554591d3c74fbc8fb899600114d3a61951d7af36bb8e6460b88c1cfeb3f21e0b94d5a12f2615ed49cf7d67abf18a93af7ba649cd0ac29680d4a2e1e42195049ba8878f1d05a2e30251a57f7f4662d4bbe42ecc98b7399c13a52690fc3626bb5c1a0757a19226c7db6e42ec243932a2503b9b257fa271f933e58407803a283c989035fccba4ccbe481464529a8697f4057982aca7f3e9f8f5f429a69d97e299e3570c43db128086a548346eddf38a8fd24e270d954e57a425ada9a7597e0b1d1e880416c0a36fd5d9a8a1a0e277025e81af122c541ead22d788cc9567892bccaa9f0d0d4410a411d42de63d1e2908e4ebbcafdb25c1a4ee002aa63a6245db826d277bf7bed80169db1bccdc7a3eb0ae7852317a5fb2628982a7067757484a42e2e39a2c58cf41f683c3646c0e993fdb61ba33306f7524ee273dcbcfb064b2f296cbed17603820bbd3a5e93ec52e82e67ab2760735d2fc91512a677170aa190a675a10256c484c6d7ec374539b6a4e2cf91347b6a7ce07f7e3d5804d109d88647def7d8362b09e103f65285c88ff5ac9329ca40a9c29dca4e07de3bfa39f84a9545268f1b04c23b04556d7648e368e30e4c593f9c74a4dee34eaa146708071810254fb2b5fd49243a64bc29a6cf8638150988ebd9756b917719cc9bb55d2b8d2766660c370803b4aa4e0b87e1b76ea667faa2a9c43e861729499eb19a6e461dc5fcce21ea03fdc88fe1a67bdd4b67671794d5348a1b481ad45e5810293b5345958abc5f84808fd97351d481e6809e00bee6538408aea7c6c0744ac7db719c3be3a8a8fb077e5aaa181f69f89547570b88ecaba644b0c8623f799c809855b617cec1498a8e2313908d070839a80574b129b24245eded44df2d130474feb95e86dd6e211cd2e6f65ced4fbfff3817ccb8c25dae508502d4df393b2e85eadf3fb86959768990ad2c8625a553c4d920338ebe25de23761c08510255447c7d787652ba7c318efbd758620236476ecd6df6abc2cadf3488c7e6416c12269e3d114a73a0229bbc06b4f53b1f5c0ca2198e418a49af03440d375ae7c76e860ff18be0bfcefdb413d281ebc034b8b5f8722b041e90ec772e1e9449f61650b8a2bb40ce3658b1d71c42e68495a5504986f38696e56ba0fc2df70182a5b11f247f876b27b3d89aa71714f55561cbdd0ebbc4b24d39b044ca3e3ef42bf8f63b2ef6d9024f2194253e89d0ed237b1903f89dc510bbdfd982b518c3576659cd397e37db2ce13f8b1b0cc42acf317bf5a8f948dd3977725de1590421117c9ffd00602470f3e49488451e5d7bce797a71126028547bbf44dddd6bba9f67d53b9c20e8afbc8632efb5aabfcaa6e749cd45043ecb13046ce3209fa85ef21441ec2d1a120b53fc4e51e100e83a51da1239f64947e10f158bc42d10a3b20a366b431137d004e87da3ee9342f44b433ff1b8535e3f1928f927eaf8bdf52e31c5894673178a3ae897ec528be2ca7c977eca6cfc08a00266e96fd43a723fc7226b66aaa86f2864f98b6fd26bbf80abe1a9ecef909810ecefd129f3a73bd3296a2999b9bb45f2574cb85143f66a0bc2ff2a9811e62cca6fe559c14e606a1c9ac2753af2050d3a8f81e4731205cf0af72285f08cdaf87f9cda4cd3c7c7d51bce592ea15d692ee694c399bc8bd5f07c0db8fab186d5ee762d33a5debc1902bed79a68d8420d068878e367fea06978192e6e69d4b8acadd42ac1133fb3a9e9e1dc50e281254144bacd43a231dadc4f4116e333fc9f88fbcb64abea30e650a11ac56a1988eca45902fcf424a1223968027d877793bf9f4636cdba3b47dfac921296a818d1b0882170641d3606bc050e0383940f0e25880e6b183b137ab86e3ddd52a0ea7024db4446b4988c5f282984edae2a11e1a4a4a1dcf28583c092c331aeb08799f8cff204fa2810bfcd09e53dad5f37258fa86f46560785713ec711c9f5ab98c631bb3e3b92f097884bc8751c88ee126bd1f3682449da8181bc9cc5b90f0bd9dce1cb0d1966bb15bdd7b78a1138b7927890dffd8b76a9385fabcc2a5fbf454fbeacc8e61f0c5b2ab0a4db4d0a259bc517898153957166f01726a25d2012da74a8fcfec1043c1d970403cebabf7a1af318743767411fda52e046b2fdbee1680978da2f6641dc5012547ee806376f3ffab1e2780f491f33a0cb355ea6b677c4ea1b54ab6e561ed96024055de5d02392688133abeee6aa2f4d3048df6efbb7e64a6aa902b811a674b0b9ebcc31efa34cdc88d6209367d7c9cb38d96a9ceb0b51e8e23643996556171e270fec0156069e8006f48956683abccd1427e3ec9df93abc4fbee9170eaad8190353d85860814a81887509424d72a79cef1534ea7655db318a424d6a03868b391a7c49dbde0913228107a7795db90a5e3e91e505d9922c2914d7755e0c56d25ea4e37f9ed5c7988835ca83818b75c344d06ea03e6dd7e582c6afdc5e0cc2dc395f40b62b11adfb0a552412447e35ac364bee1f8ce0ad23a72daad149442cf0be27858cf5b7eccaec2b6d06a107b676e9fd7e573066e9155fede55c357a90b980074580512dc2e7d3e2b87a063a5da17648602d66ed743cf227b0ef5a34fc4458e5fe418d5a7ed1c33878563e44403bf194507c93079ff9105b433e6078b2b9bb22f1c69337d131a4c91c2b70f1b45fa522eb556b7960f937e6fba63e1a50c687afb0416d584561da16f22ecb1d016076358d918b6d5ef2246424b5051872ddffd8c30b482d9c34b428ed5eaa2fe80cc4b5b4f603f714bc42e0efe338188a7dfb0be6f66f395cfd85bde8b957d8285328c303d001bf5a98fb9f26e6051a1e43dc9142274e0b70a75a903791928a1bfcec374626d3c6136c409de439066c5887221563f3ead0d53f19846cb8c3345403ba3f7209d78da91196896a687824e4e6047dd8e85212633fba991cea2364c746d0ec558d0fdfd64f2ca44bcc9763c26b68e2002ea0633e6c3d7484493771c50eeb727d6fcea84ed9c26bdaddaf73d676c3554c66ecb08ee954d3de09ddaa2e3d11f5fa4f9d4c89cbdce2c3accd6f38c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e8529eab3c9bc2858788c7077ea13728eed4debededfd07f1672798856c3a055a134014b924dfc217dbc5b9b44e89d25f35314db49b096287a77d1734d0f8f8d16846281439426e64348199839d84de5c3d2441a5dd9c75bd064c1385ca083cd1df6e72e42327ed298ddac2fc87c59442d545b0ff476caed9e785f2bed1bff26b033312dd6bdedd4ded92b9647ecd2ce31eda2a6f5a4ef9df833b9b4c70ec0924a92a3c6761b167ab56948265b496cb7529b01cc4e53c3cd9a39384643996beac7e7e841eb0fdbd766a1e860249639928c27ea49a3d1b2bc02bb95c9663eb07e0232ba0ede4e40a7b352f38ccd532d1a416ffb5207d68c2b7b3a6cfd957d7efa5b7143abe63296589646fa4fd48c7d15548b46fe4f60435bf69fb31260205482eab02b276cf5c2ddbf28d010e2a6976cf03488c0d1d11c5c1f9b23d7ac44ed221724bd0d505f36fdd6c1f2f87ae7f7b7d2a84caf41d8db3d926a728904ffc98ade11410e880b38007beeaff985e007a1460051bb827ffb24970b0fbf79cde0264cf02d08eca7f936f1a8a1fd902a4395ac8be7312d9eaf784c761cb1354dd40baf30138d361ef8d4cbc840dbcc9336d9348f3cbd51fcb6541da05bb0cf039edbb5e203845b97698e2511195a1fbb646bd896dad04547a95f1941a1df510c4f799006284dcacf83ad61a2b13644eba1c459299b7a92a42c735c24fe9a4b2e2e9fd6a0070c84f2e19c4aa5a2610030e19ea4093bd118f72e066ba44693db5cef94f390532d3fdefa1807e6bf9c14050d63d2c37bf357802a7d8e813baee24cefa76b229a035f7c6b0546f536c07cfd7a2d8e3be9ac2c7b7e854ebf59eaeda5edad7dc23eadaa7ee423a19ddf921117a558f52bc7238e74738f6b182f284404461dbbf5b9ac11dd9ca793e7d4ad05cfe205d6ba0969f8e965d571cfbf51f54a8e3317b795c76523eec774719d38f8ecbbb192bc298fdca9b0a9304386b0791c671fa441dee797d349e052a0edd93134d2a7c57ee3fdacad7f8e00de15fee3a091b2c8e51faba26ef3daab055a97199108ceea0d3b0dfee6ef4f8ad55f1eca9c15771251dce196dfdef45901abfd0236327e527b7b5a90085cadf18125f106358211b47259e193b2d7bd2a55e7e715c64e67d0be4b76086d9cc31c11ec35caeb68634eb556c5a293370fec522d61149c7bb09bd4256e55a71487db84f95cffaefd2c4a3054e528241405f8618bcc663a513318815f67de9a13e6786615542b715d6d2bb3dc44c310feaea7537b2040a1c0668b795fde4c9ef029aebc5a58ddf0dd100da729e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd93257121305908aceeb3388deb21c5ceaa4c1dae6b8ef3ef9ccfca9bc6523b609bcddd0bc210cfc2275da1aba94d5bd2b963fbd80dda7a9c8ff88271f152875d7cccd66404e095e1dcee94fdf133c53e148690e813cbf3a049c76d2e098135864a11fc370cf33eead0be3cea163831560bf46c98931a1dd530301d054fad074fb22e5d6a923ef8cdfac92e83ce444c9a2b61fe92d6043d108129649a3c6ea306c5d9db7ba6740f6b046ac8d7b77f5451a405975c2588b5b82cfb70843359010be8b7f328f8bf480b21d5fcfdf7c0ed21b4968982c3b4798fe04b9e9462fe2bd8fb6c511bc0d4fd794bc886625c783228e520fde1dbed723fc9779bef796e04307444ff32882e89471f99ad0b367c55273a7a4a3dfff10ea4c7816a44c1cad69137741b64d4c2addda665d13fc93f613f8de4ae6526a7ec8bcc418d9d190bff5fb2bf8a576c7aa614ce9faa7901f55f64b0b0bf1c084f52e7069e5bf1097a9889ff977307061399848cc96c7a631da2855f503865eb732fd4e5c3976571cde050a1777e67a4b8c95221524a3c23c6b5401c00b5030ac5fc9d0a0463ad9e34009a00ad426ac296fc0f38221dca15bbd3ad95092e6a4f38b8ef8e9f3b9992d57409c7833c0e3c2e6ab0c7a26dd2cad7646133b739b24e20159d38cb2e11faad8ea1743054178c642ebb1fcbeccda9a1e3aed8762eaf0d9ed97308e08e7489424c321f49af5f2caf02567c87ef2729ac221651de0efa7ccc8de802d0ced1036b68b51868bd36ac7ce8054384aa6a10b17928e57abda181dd6caed22f35fdc74e5fa8cbc8520b3a414b00e01850a90adb945205173ed44279aeb17ca7ebf9a239d5f6ecc9306a0074af6bb1098b22b21e3b9d12bfcf4ba0ee5e9c3cf8820ef6061d10c3648d73b8c0ff0094b6feeb0707b5cd61797ca034755fa42aab8c5c9e245157f5425f5d9c43b10c831d840579f3fb8ab975e36f52ddbb4fef464e8bc62f5bb730fbfe5332c4252393c6cb8e07655646eca309a1481552ecbd9569e94a0cbb6905c4571720adc754722bc8f182a697c43e34c44782ead62b2b4d01ed046ac0d7187fdf4e1ea75d41bd9ef4da3a7a5ee404600a4880f8915d2a0d4943210c8e5e71277e7fa6aea2e843cde25869445dce969fda78091938b3cfdd6f1ab376e62e9f94ff04a8336309a4f867baccec1e6369b73bdf4b757c1049448f4bb3999ee0d8ffcf00c6d22bb9a4502c3b263699d0ea24baa448b12d24f501412d09da75d99714c91406d47dbbbde1bdb9b1bfa8dab1989c600610422ddba5fabd57a54dc955ccfc7e00bc1f800f46d8c06a9861b5ebb82ee710a67a28a410942c343c5385210af2239444d4186539c1983075c1100c45b2a80ec93371fb04da55a70d7e4064542210b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d66f5b305293c5ce2538e4d8e773a6d51cb10adc0c50d9b9cba83e8429a2e2e1e628b901883b088d7b9dedc64dc86f636e337839c21edf802b526c26346ff314a86f8e7ead704ea80c6fabc0641fdb53599f2e2532b2733e93514058b042af10b86a8ecbd7b1a217342e937037c0bebc6a026371b85698d124c09998e5a531b6c98d2853047a428891a431d89979492f261809be176ccc6f09660d5cd4b624f33faa2a0487a29d08064960b2068be68c3c830254caee33d9436053af9fd02847472a558406365b77652cb2bd1ccf651da71b0b22bf789af3d24014217fea74522c87f228bd61350ac8ebe6922fbe3db9b1f1c95cc6fad66daca76115c222bee07689e5192515b7b99cfd14d624ea54dbe5eea6c8f22b59babc3c6a3ce22286f1a7e98797f7d5a383fdf3eba7a9d9f91ef76bca8a1f5e028013db30143acb3e550a812ae8f2fcfcbfd6b8ae693e1ea88c730469e018cc7c303389843f05d67ee133a524e56e2044349643bea61e7d9d3ae3dc19e660d754e6cac3fa4f24ae46d7990bb3badda6ebe181dbf2e7a2b6d1983b75388ed410c04105e5790c0ece24b0e2e85194adb91496335138d5815f82e01ebc93b757c1ff94620f3a87ef48ca064f0d2434a7152607d997781ffdbd8987c5b14b6f20449493fdab89717e43a141592305be0faf22877173da64f6bb647b3a636b831df365b7c3394915ca6209d756e01ef99a3542549cacdede905e8e8304ad6d95f6d04b85fceb7e28499ac16104eb13b75b149505ccf56ad08a10df211eba48ffd7a2d0d42a1bd943dcc12f86efe3fdf6285d91ddb739bc5c2481ed4d77589febde82e624d0af0ff9796e59932d858087e220893ac87e5b5203582ed469929c865ca6e35cafc0886f8e5a9f813d471496a02cc87ca65544c0ef979e7f4c1f0a7269e3eb21fea4e0d91ec4fe86be49b18cc3d5ecb36f4a8dfd602319507ba7dade07e22ca3a895e9ce0a2f59d7f441bd6bd7dd64756c6cb272ce5ea2a934c56dec8f3be010f8ea74cc61f20d130221c6faa48e432e6ad29d22301073d3dcd3dad319399258dae99d20eb634bd697482ad1abb0ef6ca6488989637ea1d44a918f062b169f1b802c9ee6d05a2fe348e76d655032dad5ed688567ea02cd741c0f1684f271e1e6f57e70339d949187fc02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c24169cc5ed830203c45863ffda2b704a0bfc77cd4cbaf3279e937c9415d47635c23544512e70a1dd7110e04b778646d4f7b399d36712e40bd06a6907f25046639e4fe0bac941c2e9591a1af974b9d7ed718ae8c2c5246458375efb92aa04a645b615ac131413580ad09206331a67387cdfbf12cee28aab9a8b0aefc03d6d1f2fde7000c82090e61c34b4675c01815b7e25a1fd09d2fc60f60ec1f3f435096790681ce4bc1869026d0ca9966cfa34a5506577dd7eaa826a1dbd86bf3e8ae5fe73cd59f45e5edff6c3c216a16d4b6539790325daae1a6400ee446c2b4fd1852c409d43c22a3f4b757aa0ea308743fdaa83feb2bba825098346ef0ec8a0a752833e2a5fbed2bab603e428eba5d241504949b6d4c4f02b543fd709a15be42ee92b6bd37baa61bc2904832a15e7077176451dbb49a688cf55649c5637bab364126c473c492c09b76fc9de21fd95de63f8e5b0276a7fe25efa62bedecf69ceb278c8309d1ca641fe2f9f61c57dd21ffc4ea32c8ac547bcbe01fa01634d739c86d75ff0681db6ba6b02f41eb730989a90ffe2f8948b98eda9bb5bdaddacaba1ac1877ea8c775ccae18338cd298c2ce4780f31255dd1321fbd0dbb6f8f64f321e0e0b665130b58ecfa2acaff06cdc5d550de264d6d61988290e84649f3faef516f21a36b40345c681a841ce65fe1848e33fe6c929cfdb09181ed6f10f9b5d42b079890c93f6c407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71d8885a58a341f31387950a999ec683cac9de2d53d8eced4cf1a4e76d753dcf20026074c387dc5714b8038735a05a39459797ad1f591aede76adbce55e99ed94a4ed5f55ec45727a57e2d8d6914f6d2acffb17b9515d347ba045067502a0b14022a269560e0d95cb168c7097ea8eccca5aecb328a24b1eda37bdb600fffb212178ec0923744a6402d58d7d738f233ce9b64b6a9f1dbfeec1505db36c5a06eab7366740f5785cf6b88326cc3136f3e677ee943c7f1c1ec6da6591f72d17c667479c47074d544333068438bbce32a53bc0117d123ddb9718eb62baa88f7a7bc78677686eed59f920597a10643f36f40b821f85fc2e6b62569c88b32189a52966c52f011fb08ba33475f7e9b64397ce8355542f0d31bebdb5238414fbc41ab88fe2a7e3af5596f09c8a333cc19880d51fcd11a73c7b8eb1b02485903f9c3b3d15b56ac304e37b46e43a844db9b7bcda351e09ad1efc57db99dc2a7c12e553ca9a604e463c7df481005fcaa51f86223229d9aa3f1dc10b0bc97f9814eedae2d1a0d4824b5eaccc793902c3f48b7529b6d116f4e7418406b6dfcabf008b65268d1b375fe932b8407f5434fc3b4165e5c0bdaac4887eddb7102cbe8be428b09c8d43979e83eb30dfa3dd91753614a811769d6a564e5e2b27c43c70d7497a0834ea96e50a61b0015878e7e28903dbcdb802b63c5e6c895e2619c6511dfa0723fc48f796982580e61b8d0dc0c1652fcb6ad0fe74186d4f30f931ded5712a16e9724b9993c5c832c850ec9d476fa68c807d36d09edf0c1eb9b2995a3812cec5092b90c4c72a842dc9eca0e5774a6374ed583ce8605795f084731e95e368d039b6ac539d614924eb791afc0aacb141b54f0d75fcde46e4682e806926114b2ec7ee5a1a5626a3a00a72c2f0fd68497472feb62d2481dfa1ae93b14895fd3773d48635738847ddeffde56148294271b50d17c8ecfec51791fde88bb15b07ef5a9f0f13b9ee20cee21322f3a6fd0783089d9dd32a9344cb0a89e9746bd35c0bc36f37afacb5e3590a7bfeb5fd893b53578b04160e3162b0aae5d6f67dfcb75abbcf01b2ebb10694cb91586856f0f35245f0b614af51a8ec9de0c16b4c52d4a722b1c44424e2837fa47643df9b11a50e4f6f2c820c284d4c147481412e5e4945115040df8151123dcbbcf3aa3616297725b2ea6ce68ade3be8d490a0839ff1ad65f6cdc9f3b410424c41b6ccc361bdd655dbd0f0a5b5e7c86fb1bf779a912921794e17746c37f40309c890258c6702ea0943d8a32748f67d8dfa4a29fd85282d949f1cff5faba2722a8f95b4c20b4a2545baa5879a817128101c28cc253f3a7a73cb74f0c43d60924cc7c0c46b93aa96c8e69afd833d5c5f4ee23346e35053b1fa6044421208a5fb0a75847a0e9f3e97824f457206271c9147e2862e8728b4d69cbe84e785d9260bc6104bd6770c69d9e19769899be4884707e9fe7a4cc7460577ac05769874d16a6a7bcef3064eafe8855f607996bf06eb728978f6535d6bf0b089bfc0be52105b8daa8790dd2fda2c3493f33b66804385212b1c3747f61ba6de535688b2ec24dd2c7ee29fd05b5cab4d8ea4b8868446d4562a8b2d6f182d818b448b165d8497a2849b441c4f0a26462ef0a1dc6f963cd36adbc02c0a0f040b662e314819eb236dc6adcb19ffaa9366908510f4e29ea59a98726597eb3f2bb8cad776a1f6b5065d440ada739faad77e82f68b346adcded75163d50f3a0a6ffac67559c3c72d87c96c35481c26a024016382c63d0c393e3fd7dccc91275dc3a610a95f0c63bb8553034a4c23a5fe2e1a82fe0b885d736e57a0883291961a087a2719664020a574c20e4764775b18b4c0668fa3ca1e9183ed8e57c30c211e97e7cfdc685e6c082449a1fcf68fc3da9660e86c1189f879b8c9cb6611d57d470765dec4c3514243009d8ac7ad5aa36f30863234f789eb1d0092f42deb6ca72061146b920d71b45770090680e74933520624041ba2cca522af3caf37c267991f7910e042e5800632d66d021a519c3d7a9c5614710da694bc1e1b7d5cfe40931ce3f0e1f35d253566b236c7b8a1064cbfd234f3e26fcd14b1eb52a0b46a47e8a8d38027bb3fa2cba9471b63489fe6ca5926a30f68d89fea2985c600a9114516a6c29aa1a9a390358ae1146ce84fba254aa25005dd08c988f4dbdcc3dc795d3487566e587f8f99fa6d222603fe0045e0a581002149e02f12f72a340fcd78d5723d10b6869cb54bc64940d6cbeabce345363e57dc45931c6bf8f278f704cf252234e0e580741af38024e153c2f2d4af59046fba73c6d72ca8cc525648416b9b2143dac665457204258b81bf0097f3dac95ce491ef6f07d89dd7a409b0f13475eeef708fbb0cac0f200cd312103944d2868c4978492fa514359fd3ca4231f9a3b7689833643ca183622e8cd963918c07625bf860ec2281a5fb55025fce0f79d2e3f09168907c20bc34dc2d4b34d5cd5b78bbbf06900f74bbcb83754b0860f97e0d40bfaa956dbad7103f938255f7a45f5b334202ec3bdf629961bee8974b2e756e4c7b638ddcb558e8b8fe0e8021c85fbe0c8b8739b8b1079d14900f8469f5ec613ec65576c6773608f36e062331a5e94b4f5c4a1b124898399f3db554636f854464f232ee1a6f169100dd180195a6eff150ba89382577e8770a15e32faf075697770f85fe1067c8f5841d37c6988ba4efdf07ae6c46e9c2d1e726de30e53229ba4428ffaf8aa05391454b4e41234534af2f0c4e38ba3617ddd1c70bbd23365639fa7cd5f191861c7fbed74a80914c06cdef71226f89708e71ef9c6ab3d95def2dd7f487e42efa411f4eb05a33b78f83a80e6764aa6f07eaa4e22d1741ed853c68c6ab19999edb739487eaaee49a422102fe32fed2c73c7d5490f536ba5a7e96691c8c0bc34dd1f6ae02690a438e419c40c9cd26869e6ce0e3e2e6e1db4a35037625efc1ee4aa2d6a26530c3417b05113ccb3c725993fb28e76ac53f00b9ed3ab5f6912e0786fc1138fdd9eb43bde42db08d3a2ae3363169cf1de0faac09b586e3da4527c94f3e773341a31864c76f31fc1f72c9a86eccbe29a1060e2a5b0d6abf7c452613018b69e8385b7ab50e468bd570a388c6eda0d4b98552d27b9aacca2bcdf7f90b75243f624e0181f20901a6c759e4cffd958b68736a9a1ee2ebdff616811e63d43b100947549aef12a1858ca58ee54562ddd8ce1604479185664a744017e539e3a7737b7eba00d767562c6ee73a704bbd52bd17331679914ef0e5a5888b9e2cb6448263a75c0585d56342263a48a5cd916d64a902dcca41efa763e77935265e3b2d8164fc8d819762a7ca74dd548b3c5d98e4f70c9a85d29ddd2296fa1cb8be37e5d8701af88c70c55d65c6b0300db4259152800ab8a88f85e276b32399f0746cdbfd93182863a850dd68496b94fdfed16540c30b13d0d7e65a4ff1bb1b73ae867b96e7c912b00ff6ae02a488e8df0f2c1a026bdcb1c9e5e273773626b603e9c7ff6b9bf0beb5a573cd8dbc6cb60997da70aa06d0db39d1dba72c0eb35a773994dfb1cc3447614540d0eecf2766560b1c77937fcec07555c995ffa2eb97e7bed217c46cc798a407a05a8e2b2f015072895fe33d26bdf621bc4357610234e563f1f6dbf1584d21aac7bdcf47bce5b008b72eb8b01e183285e635da5eaf069358ab0142d54b28f30bc599e460dbd802cd49164665229340e29a14dcadf345f493f00ebe1d829515c6528f61a6ff498c1bd104b004ad09211420e761faab5c193746843ffac77b8387414dc4b5aa9706a54c576dd1caad7fb29bdca6dbbce5cac2eb1e65d89633e3dfa6040b63fe6d05a67a51e96b309235a66e1114494d37a75e8a285828f0d6dc61161c47f0780f95ab40533a28771af010a3866c099cbe7de1b5ba926757ff2ebc73544e1b21418fc96c9b11246ec54148661fd7515be3636f5d3fb5e2723cfb1a725b43c10323e2df2841c9f221b061b01baf702df0c335e0932977ab4978260fb37c2a1f4c8869fd97e805ab0157b6325650d1e03909ae85ae3751e582cd823db5380ac9496d1d015ec2b28839d5daa888718cde30870f8fac9282e4471182b911196817ee864c2396b7b2a9f349d959b6fae1d66ec9104ff9c942f030e65a8aa549866470e32cbb4e38b8c0bc430bacb0ad6aa1c372776f812b941ab4297ee1468b2a296fc8053d12508a47fa99f2cbd5b7fcea38d04fb896e5421661613af2b533ec2bb28c57cf7d9a02708e13edbc55df986cc4b1711bcc75d1ce872b9d48e260ea1878a5d7f6f7f964340f6da824c0e74e6d6990cf0707ac8f1dc11924bfa5c1ca130af9ee39ddd16c4d9cdccc036856f84eda4ab17cc28106323024c8e72663a41b5a85c0e978d30601e32bfa02697f9eab6f756a1d83440c49028baa4607d6a339aaedb6cdac744b85af70456c65c9025b86a7426169cda4490dc7f20d022ea6edb9107df7695cf745e061c1c8b98f078d88f50881eda8dea89dc75b6633fa44303147839275ddbe891c2ce4f93b4e51ba2a2709de73de8b659f9ad0d8a6aaecf1e5de8f4724004d7a92a652474b63824c30f8027de4f9b98386208a27001b41fcd121741e20510209b0740cb89c118f190cae98339b07e65df9cc9dd126b2ae3538a4d0985c9e7b52c5de7e5787b3109845cc803314d2b6d9692ed5e2e0adebbc148a87ab25752ca0e8aaae7558ebeb7d98955066e38ec3fe38a00b7606128b4a3ba320237b20444e34f94f2c8f9d5e0173b28a2dea1a88f7e40403b11375e8fcf6841f2e94ebd740f848a2b4e72c31c7a21aea6ae8917400c81d43bb522a417c3a364675ca3cb6a8235ce24cfc39325150995dd367ebed4e2adba7efd67bef767d681dba2b2af833aada512c7f867dbe6e01b2a7eb49c7b6e50bb8d9e6c728d9a044cfc98d6435f5a73643ddfa896ed51671f0a76359ad302d329a7d64886437478cf402887d5021d87404431bbc0b7780e1746b73747f7c01d7f6f141012dca88d721016b8b21871289774455306da42ae89e9c762a2ec58a22a96eb5356336537e0ff56854b097b976be07974484f59b0626729a1f672e146de5ac57b4ae5233ea7370c02412b04da5cecbbb9154f804dc0c8e74e2ac9daca31a3b872ca80ef8c5a7f17dda7b9554e659d2b24c2373f3dcd7473bf12aefe152f200333c87b090fc60e3aed8773a753b992935e33d35c92f1055f2a5261bfecb98b27031686e69b2e843937643581a8b3a670e34bb0bf9850ccc4dd1b4be267775b18608af4d2400c18023b5de425d219f9efcafb72aa555fd994cf9f67ebeb5de47b6ab4577184b74582b4774b8ddc3f186fdab84f01e0f988b74bacfe932f46aa7023100538397589fa07b331c10ff03ffcf5cac1691840ba63344882cad3a161b13520417266880fc4c2de2e2d5c0529af712ef5570db2121f86419a0e63c1da3d2000d9eb5c85c76bb728eafd2dfdcf41599f816c32951d724e3b41f921317cd41c60ab0ec43fca15dc14d5312371e0b26d5cf58477961dbd96fcdf2b31d78c450fee02ee85779a0ee900ad2e02300ecc774f73ec419fdd15546141233308dd4e051c826ce665878ade3dace990e64ecfb1ba367f4c3c0a61d4aa1dad084d5c32793e97f57984a6c431796df3d153e6b310d25c37fd451bb16e2ed028aa7b09e42e20b4eb5a03fe8157f3d4be0998c98bc7320ba91b9729b9b466fb2595a1ab4000a4063793ddb24833d15dbabd24ec4e2bc0eb73436b0f08b9a562503729ab644180185bd09edd014de26223b5f1a82e054dfebb79336d891b767f8be214f88151c6e7cf8783284c7b1adbc75d8f414979d725fdc7c0dc5d013e0ee51879df8a5e3451595f904e1bcc1ecaffb327a9375f9f09251fd12a66f7cbd6faf86fe902439e0ea0f5bfff13843f2b4a2067c577278af1558bddd481e153602c11d5c81a42dcd5ccdb01ea371454f8fc228aeab0a651b71316bb9e4303f24b0faeda606521c4625ad1221843515f2b55467cd591a16e91a5a119431c0a40030412724be545aeec5145d93ca5215998b118cd43fe6f953be84cdf704bda68dec68fb14c3e642079b36172d8392420362d0ff639df122d90c48bfb4463a941f942309e768527e8b207b02674157f4b2fac359d2595191b18223ef8d7a62f203c30dfb407d3016e2942de95012f636a769b665370660d2906c68900072fc9e5cd13b24490f424e0bd98aef19726d7d2749d8f316b798b87ac700de86806c0586e96d5fa35d9085a6313b77aea6326c8a3ce609b67aa4b2de89a10da711cc35cf593e91f701a0f0ae752dca9264748a313dc53b63231d29e9fad3bf5e6ec9134177e105125ee61b888aab2d6eeaaac9b63e99b4554c617848d6d4addd41ff261a14972bbae7427f40cfc7286e8ef47f58ac239e46d974a0e0ac57679f6c0497e0f15419f8c0b3e563ee5edebece3368fcbf345b930c92fca7072eceb55222b960c5f7e0fd54d5842383c5e1385b87afd269b475a6fde0ffb7bd90e239d010036426a9102aab37b309f130f7d93dc434d02fa0318a7a63dcb6fc7a8cccb8eb8452ee3c1cb6540517e9f6bc9f832332e4fd732cd54f8e33896323ca2a6642d7bd30c4c8b9d4afd1c5e7822263c75b2709c939073244489a929410cd8eaf39549a7f7e39808fb4311a03477bcfddddd9319bcfa6de112cd37ab5040bc19e0b3a52f039a6ba60d20459884cef69623c717e7aade3c1f270584fa38cd0d9b6a56045e318ec49ba8a961ba754247a7319d29a2d250be22ad5e7494d649b11898276a964aafd01459781202fa7e77dcb212548e7028b56cec34b508d478e84034a501e5f67aae930c2a56aae7bb0cc818fc18b6ffff18592e8e8671eb94ceb0c2e15b33f9f54415cc9e625abed39d47633eeccd98be10042d5d03d852c5bd930a89f0ce256a9332521f282813a5a6c2f9facd2659c39efa1ea822a53b4dc428a9521c954e669dbb9bda2e94add842eb339426c7a1f44fe90370fb00c10664c8f2c9515800831c45fb524866c2be38a68a4f8d2cb06766b1cec3242cf191ff9ecec987893588a89b042c208cc9770c48d2480ca83a7762d7aa8eefc4ee180600d3620aed0414847a2198747821b006346ba2ff93226fdd08d92fe2e8c22014ee9c389db737f3d5d8201f0c8657bf91d13f2dd4f1bb6adc1d6da398e1d9b2a4884c63631d46aeeac4ca734882dbf7453254ccefe535131d857e9baf418f9a77afae84446c06762d62ad302db644f122be630c593c15b16fb21e9cab0fc7b0140c981652059d2310ea20e46356d8e06152648b0c9f937d26c08490a5752ece4b16ced9ed97d75143de35326baed933b6c623a04853e8e76cab3219c59d5ed56410b366482128627181b5aa4e3a3e9bfddd01b73c36c624ee4eb5eb445009a0fdc7dc15c08a48c83927500e0d887106b8f07b427790d1cf4a2713ad56af6e1e1629ef93edf14348535e50013dee7757f605a7b0d7d518a7751ffc17479ef2cdbec637e4bfb3dad4d8993a553d081a31120746c200d8748f031b9b010d21fe20a80c69f06959feee4de31337320a5ef93a98dbe72b55880c843da199106393fa4db8a6f659207f6f419b31a6784e2a1e946483bdda59d530949954fc0d7e42afce9454b6faa5b7575f6fa1d23712d8f0e3c51c77bd269f51b501bc3056358b894a4efd94d6f3ab31c60a2e6d42f843678d2baab7d571b1ee2a585968e65e63f91974d5da580edb472af08b1b03921ad08b16ec25a554a5a4c3a354078b7e7715d29df11eeaa50531e726323a7fb657d9c44d701faefea31ce086fb59618c914224c48d1b1d5820f67bc528d05e42f8781052403fc0abb1c201272cdef98963450211e46b0c280f8c83b25e371bd827a1b3dd1a3cd1ff4732a3826ac5a468c6464286aca145027df161442843524a009a4c3e5a8732003fe7a21d212e1e7743a8206fdec564f55b413d7376785610f820389a6e253f09f99692ffc4359b494a30096a3eb8a5b97c3aba02933a370e7d5bf068b765dd5f6fad73b66753452a03b21933d2625a570e8f1406fb81781c698336cca9cda4ce660b4873e19098521277c6167a5090ebc2df903b9e6827ceec7f1352a57bf84ff4eb62099a8875cc61b06d7c3dc6094fe96948c881c60e4e395013f2599efd1c800bb1a8d30d5f57f82ac1df5056e7ab4b9b21cf69a979c218ebff5e25bba8d563f5640c602a33208b632d59f14fe714bb407af7e74472209faffa3a3f224d1457e0b6f2a055f4d64621658f227698a5d5bc7734739677dadbceae2cfabe8d2263210ff6c07f3d44f26d82b51679c57bfe223732829a7b9e91280ec090176d08d5f9606dd24a835c71171595de9e3c0c54c6a0ce7a9a159c415bb13419d4c73469ba912eb7d346b91629642940f117e1aa50a09fd5dd482a69b1d98b990ab979c98b9a66995d1665017790168ae8b5dd1608ad0bf62c35a8e27969e0a4642d03481c477ea3219946b9e8b8b1271dd6fbc2da017b45d321bc46c0d63e2847067350555940f33ffa238dc7137ea04ecb81d9abc5b068794738c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e8529d833c6d57f623b8f0c8ed846045cf44fea32bcbe0bc04e118f3922c6a45c890eac97e3090de6829cacf681651f2a2c95582f40369321aa9e4b9b4e8a4c731f31cc38779f9c7b1a6ca93f2c4f6d04a6b0f3e699c8a40511a2e3b9fb7f897266172ad643c8a692b2345d538097d284c68b6a92f1e9843fc3a4ffba593dd95df36e7ee4eeeb4e3410a8326cab9ea1eb95213475d669589cc8b1331ccc7d65eed95506d4426e3ecd0cb1d069420ecad77d65acb51c0b03ed6634f1ec46f4caed7e1b1c7033c6986d616077de809dad1e4c7dcf3060175b19babe4609a5601f5a7a286caa34d62c1fee27f253562286a466c2b2f91a711cbfaebc527f705bc8bc73510a1f9b915d9b65deb6f9add45e7b03240fec592fd59851a1fced2bf84b59977c3ca84536e7b0ef7109b756252405947adb4dfeaf4712a116940f296667427b1c783daaa9274a0ebb267618be37418eb65bd822d1caac9f77229bb6c60962c5158659d275728fa84b319c357eb867b9d18aa4d4759a8665c3b8375644d168f97e7ef28d1fe4a0ee885dea9edf31e01e23e896796b8fcdecd44b4b180dc7e02617a269b553a28177388c3c4176ee50e6721a43aebf52959252f937914ea9352669c269f1e31a344f8884e5ae3450628689e6356669e7a94e43ea1ac65578a8a21d06171703bf6509b7691a28cbda6929bb1f6de818b314d73bc1fc97fa5cb16c34b64c2aaa0a1986e68954e4ca7b5784088392fda54f4dfbac75e454458e01583d22d254e33b7c35d78ed4f76db5578f07a6c1bcb7dc46199c567c4a61f84c574f3ebc10064373d6227daca15f68a54710eea722a4c7ac9d8cb34c289634b7a83122011136c8b42a837199b6425a68b53f9ea56033d30bd62b1cddd8482f91d74f6173676ee3296563205563eb39965933d33ea5a591c45af07f0eee2272ef67238e7a55035403dd1cc7efcbd204360f01748ddb5d64095b865b5e45633f14727c5eaaf6ca123d995b8841ebcc8faf301ab032da70d4684b15e2042a59b4c1a333ea50f1aa4ca2c2c57af4783c613dfe8392229ee5fdf145d7506ef3d9e559246590c4864aa19ea70edc3be719cf9bdb22bd454500833be9d6eb25db42bc9c9c2b3e15f10cbbbf8faac4a982da16a236850a2ef22deaf688924420288cc4d4a7164a33f70273ba18c23050e010109645dd600bbb52809754ddeaf668a72b443d636cde95375caf3e05b69ec9d53a3c3d46d2c269274d4c297ea4c1849854c73f6fccbd1da5cbc533bd0779c44f05aa802aac65e825ab3ca5f8cf80e76032355f2d9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd932571219c3cb77d7a563214f32cae5c3ab5a379198c36ac46ef0f151a21bb0db55720417e475ac343e5f8f85b776ea6276755f5d9069447d01bf34604c0389a5a80b7684ad20d2069c15633ca011354afd94f15a0c1d2ea3a3f77e17ce258d8febd0a7358463ea4005ea0f83e358d15a789493bea81664169d09e26df8e8e3a2361e622da442aa4ea276a4e1cad5e196a6945f4f9feb7e434a747a9244eab3dce1ed953f2218fc25708efa7679c23d318c33cdbfce6be7e9125002352d34948fa8b3a67683e701c397f4118ddc67c11ade82127f6d66ca2b4137aa4876cf62bc50a20398cf64b22197ab966b1a20a098fe08768b0f5e53e25c71864a657cb42ea209e75c2201fa9b4088faae5a11d0cf74aac72f94c6cb592c2c5d6846f380d5b80202232d554abf826a19340bd0f7c5984343cb49e89936f55f2256bfc32871448794e94549ff4abc33e994c97fcdab7b3f9b270389c498899a27ca0ad92d3bcf54640c0627cbe29ee4dba357fe561619ed221c9654cc767444663abcc31edb5c66f03eee45a13503e7009cbd62d9c747fe2e8a878b4160957eb1d7ee5994382077c2ba8704ed2503421465b1e68c51817ae25727b7b72f3817febe4ec7451fc241d77109b0b4e62ec3cdb59588eef72c1b430d0640b7298820ece3c60f289be7f6c0af834a3195e89e19ae67d96b45a0bee0beb3ec45595def5f6e8fc37ba73c0515e0ec72e68159e3a59b6311dca75e37ce70329997f97069f11df50dfcfd9f0527d5ef1b407254c56d5f6f501e2d9e85d7095d7ca960a0d2c59c6f00607d66b987e1c7fb016c01016f8225393bfbb03533db594d4e1f289484f7c5eaf4babc9ff199ebe55cea3a137ac99ed39ca64c7a264e417f9bc026e5ca91a6479d8789e4638387358534d37a9b2bc6b9ec84bbcda7f2f8fc16f848423e1dae978e729d4886fc68b21dc5c90176d0dcce1c75866cc21365d383ca485c8e2e8165a264849897efaf86a2d30c068ff63e9fd065e1f84362827c46ccb49a8ec04049d1e04db6f7b50c79104f025b46d5d86e159a01e0c67310a000fc9782d29768a5b4994d46148021da4d5bf1c36ad11120ff11768b55bace7b6ca92e943d0ebd040ec7580e86094a3d569b23ef56bb4f4fcbb7b488503e0c59b287b368ed13913e7ec7d6f296df0b6a53e8785a5b3392bb92c3a0e904b1c0e100735390c8676dd2da11747fd6086f667481a70f2f2bfb352943af0492be82236a48bfd7bf8107bc6adc3928d492016aa2a13c0e05dabd3e3754bbf0e87775ff06bdca2da1382448fbabfde077584256e12aea7e877a8b9b5cbcc01119aa6a8e732f551d99dfa4fc239739c0c1d2404ee5da87e1864c313fc86fe52b02e33ec1103f9f0b7d829ab967b443bbf46b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411dac140000000001000000020000000300000004000000140500000006000000070000000800000009000000140a0000000b0000000c0000000d0000000e000000140f0000001000000011000000120000001300000014140000001500000016000000170000001800000014190000001a0000001b0000001c0000001d000000141e0000001f0000002000000021000000220000001423000000240000002500000026000000270000001428000000290000002a0000002b0000002c000000142d0000002e0000002f0000003000000031000000143200000033000000340000003500000036000000143700000038000000390000003a0000003b000000143c0000003d0000003e0000003f0000004000000014410000004200000043000000440000004500000014460000004700000048000000490000004a000000144b0000004c0000004d0000004e0000004f000000145000000051000000520000005300000054000000145500000056000000570000005800000059000000145a0000005b0000005c0000005d0000005e000000145f0000006000000061000000620000006300000014640000006500000066000000670000006800000014690000006a0000006b0000006c0000006d000000146e0000006f0000007000000071000000720000001473000000740000007500000076000000770000001478000000790000007a0000007b0000007c000000147d0000007e0000007f0000008000000081000000148200000083000000840000008500000086000000148700000088000000890000008a0000008b000000108c0000008d0000008e0000008f000000109000000091000000920000009300000010940000009500000096000000970000001098000000990000009a0000009b000000109c0000009d0000009e0000009f00000010a0000000a1000000a2000000a300000010a4000000a5000000a6000000a700000010a8000000a9000000aa000000ab00000010ac000000ad000000ae000000af00000010b0000000b1000000b2000000b300000010b4000000b5000000b6000000b700000010b8000000b9000000ba000000bb00000010bc000000bd000000be000000bf00000010c0000000c1000000c2000000c300000010c4000000c5000000c6000000c70000002b000000000000002800000059000000020000001e000000" + result := "0x01210350000000fe0000008000000096000000d200000000000000b0000000bf00000021010000ab000000970000008500000051000000c40000000800000028010000a700000032000000e200000016010000bc000000f9000000780000000c00000088000000f2000000ad000000260000009400000046000000120100004d0000002300000009010000cb00000082000000750000000e0000008f0000002f000000f8000000100100003d000000a000000006000000c90000000f0000000501000065000000540000003f00000098000000d600000047000000b7000000df000000380000004400000007000000b9000000e70000008c000000900000000a0100000b0000001901000042000000af000000020000007c0000007a000000240100004c000000010000004f00000063000000f0000000c7000000e60000006100000025010000d70000009c0000008d000000e30000001800000019000000030000006a00000003010000ec000000fc00000008010000ff00000058000000b10000006c00000043000000290000005f000000fb000000a1000000c20000002a000000be000000c3000000600000003c0000001e0000004a0000005e000000200100003e000000c800000093000000ed00000073000000040100004500000009000000d50000009200000076000000110000003300000055000000a6000000fa000000d40000002000000086000000aa000000560000007b000000a500000015010000bd000000b30000000a0000006f0000005d00000005000000180100001c0100001300000069000000e500000028000000a3000000d30000000b0100001500000079000000b500000068000000350000000d00000031000000e80000005b000000260100001200000011010000db0000001b000000d100000059000000070100003000000016000000870000002c000000240000000001000070000000360000007d000000480000009e0000008a000000270100004000000057000000cf00000067000000fd000000f5000000060100001d0100009d000000cc000000130100002d0000007f0000001e010000b200000021000000e900000025000000ac000000ea24d73b1607c8fd7d6542870c2563c7891a9085b74ddd253d4322a9b3d3d1560600000021034a3487dc0c46f976d352e5e152e120d2d23774f921583d1f2c128f7cf9f66529d49f031c94d9c3b33494849eb9682c0311b3c283b17373f18b9ca02d94e2c05c969ae5d9d6efa40c6255ec4b27b0a4752d7f4068163116e76cd0d4041c471431e8c13e37a4d00135dbe7699d91507f5a53a7b8ed36a3be29cb2fddab9f7a286c347964127e9d8bcd119989a92646c80886c2eb8440c87dd7dd94437873a3ce286432533fdbdd1a739c62733cb36ac48c821dcb0311978f1027bc1e39d4c8964e6a6570b80ba0a90a857ef4ebdabfbf958898bdb12ea1edbb17eb903b00746a14e059357312bfd525317b4f93e5eee1de639872edfaec9d2a320a6fac04d6105188fe28737bdbfec193327886b5c4906675d2a49ed43fe8cfb4e079698de82d2d042cd5a9d8624860310a963ed20c4192a19a9d163bcf366e48122c00a1e9744c5cac0ffa042ee550a3bf70d380dc032d11eabe311e0796c5143341600ef626644eed0663b1d15bcbf9e99c372c041ef118de7d179c68899a645a0fa0983b473eb2a1fefc7a956231a446a575db2e31f7c084c2945094f3927519617d7b913712c60cc4d544536a7190ec68525a70fde1309723986ab984a1e97aca4092ad721c744c3b91b676828a5f884e79d9c02d6f23ec246c3a1a8adcfa9dc1e531a9a5310e2d777330aba66c9558434a592fa5e5aec49c3a70f49f66017f194d41240d66148f2b835556a0c8d3b51ae0e823655bd4aa20fdadc6b4189de9f32cf2288700d8eff37aca87eea6637118337fb1704bc33f1fc685aec019c8e9eec48b62a728a8cb454f4e75ed6d28c458cd8df1c2bdce6101e09b650fe22d139e360fb809200ed18130a0ed0513b2a2bfa7ed6c9090cb350983746b1936c6a92f7304a7005450b1f33df75af8dfeca1cd7e94fcce445c6d55651259fdca2972a4d62f6732561af7dc55da09babaf097d1304b4cde14562506f4db4897644895324b542d8f573c39b3f67c487c1df902d0397792b7cdf987b657b2d27920bc6846eca466c155c4b778017656b9a7d69d3e69159852f38adf971f5a25df65f9950e97411c1c36e8bb9f2665b217df30a15bcd22f231f66f4f21711363cb0b0da8b3594003ae014e8c22d93dbca83c05bc5222ae72b85617956f04eded477369ec95312c7c78353256f3f643ebc6300f32561a0a5583813bb3b42844d1ad3d3779a438771a295e306daa91a5a25590d2290fd262d40f239f87d37e1c03a2494035a42961db2f33407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71482cdc214f825dc7085e54a984230a753d66d08425f9763f52f8f68911120260d4d65053a5ef2ab1152c72f3b15d4f24d4bced3b7e277735eb49450dd867c115263ad657e55682de826f6137dedd2d246971fd8c5d318034940160fc179efa63701058e68510bdf68a3678d32145780e13c29b88fe77b27440bdf3ea9762a63964675cc62a59886ce5fc12d2f48694c7ac836a0157e0e6630d694d11faa605034c51def135330ddca851fcb670c865235dc1b405242cf9f7ccb728e449e09f4ad614110699b5642a4b726cbcb74bee77642ec7b4f17b06db88ee461848ead17c906f769166b3ff9b0fb13c1ccb36358d9dda3f25bfa18e2857fe01a92328eb70cacb5514b570b9338c8602cd4a49128006a902494029c2728056b02a900dcc7798b499a9c38970f6f3dbee7e6220ee0e12a582a76ae036347816baa6cd7c9a7b9662caa1a29ff92ad66794001cfaaebbdf4071f4db6d74ee767ba59cca4cb36cac6854840b7eb103ce5723aa0d6625709d4c4378c46903ff236d9d8d61f21f76b22d6245ef2ea126366dae7f9c072d2d6e0e71a54c9bbafaed36448a4a552b51f02a182d14b38906ce1f4693cd9b87d0369e6af514cf7ec91455b26cd4c0d71bc2d3f9f9f499e04d2f27dbe47ffbce115afd1bac9fe116ce7fae719325e4082460c09defe1f43c8591655101dd3dc806c7b07762c97ad21e4142705e46a1e17306b888519767218eed7b884fb221f597a2d4edb69c094961ace2e65a7e40913c0658f8f3a64ec6949a26916ae2cd976fe531947a9c9e93e6d587bac746cb0826e4b23b64b0eaea19cab0333369b93e11693d2b4334306ee579360814adfc1339524dad3d2adfad0b2db5fc2de781a22fc63dbc4e30a5fcba2c63c2fcbda238668e06587bec427bd5b5cc33da6f7cabaebcb7688de50b59125434493fadcaa94d1e0560d2b374b7d6e1380b6b88ee8ef92cdde7edbd9a48d66f5e219840a1155818b9272f50007b87be88422e3da9599286087f5e578c0d1c2a3db9a77110f9173a69e0e58185dd4e76aa52804b2de15ebff8c3f3237e29dc7157e61b30b9b00a30f93bce6916b6b78ce4f7d550c39c7947c6860502333717d541fdb6697ab447aadd01c0f366ff1c65d331da120ca3ac630ea6e8d7339e7317518920d710e3325edbe8dcd591d30511a0fc08bc5172ff58ff98fa848387b25f99205361348105f6c138e9e4061b3a799bf7987ef5c820c1e534df298f3328e1093c5d0758d434280f6162242be89d139d52f449e2bad667d7d974cb80d0edbce7237185b11475fcd9b0171f73154a0734c1cc95ae552d9f3180d7d64e8b50d3837b14b5afd2221808dfb6c44ce63a08d4567cef4b2a9aff1b408d2c99fa4adef25724cce85368b429d0687fef75f26e5503379a61920777ef1f254af024922e382dd19e752e69784ff2911acf10ffcf4b1d795df6d8b55f38eceeadffe577cf5bc0360f35005940c73278b76425a158be63207452b1a8018f53309f47486a273b9bf60cb51c48d67770af6f19ab75537f06388373ec17a3c88ff1714806c0c99ad44e6dbdfa713ea7825552b7f76db8f2ba2fce0e546d7e7abab7d59e7afee2bfe438bad6091934cc7903dcaaeddb2bd99fd6b36ab15fc32ee001bd1d95e87020019f7c88be2e74afd1a3a66e44e8b7845e7f63923b706dae49eb96cdc73b04c9e6cfd1459d06d6f02e6854e6df29f08f7e015d511ff48d7bbb13bacc9aab1b06ab73c1f3350ce6a864e68dc99758ce2920256f75bdbe8c918c556a5a2467a3aa13a306808740484d1bff4961f87c7ff6a6a68beac9264665f87ba1a5fab9802f1cd729391a718a7477bdafa88e49f5c8cd88fbcbc1724d8e227935eabce71ec303d832c4ab27aafd3f8056d3462eda0083ac22241db692c4671249a14a04c2f0a2959aab412660bb493e536e83addf98be8cb2a0158cf18c6d5ba06ab586a2cb56cf1ad4cd099ef1e3e727f41ebeb3aea2815f004002d27714db121fd6f92fac8bedbb97160976c4d221bfc6da82c7055e469a1405eca842b4b8efd101e984a2482e526ecb085229a5a3f09f444f6d39d71e0b936cfed125e87883db8876444288d0cbd17642ce97b61a3cb7d20f9048830a34520de889098b4435dfc79a73a0518ba9f61924de365e70f8503654e384a4524c1c16900873792541ef023019a68f62250b7c219a149b9b68af793ab31f83f500126e0fffa71469e78e22e754f3b49db1dbe631f286ac449dbc94282864e76dac48fb9bce48124189d2d45e2b2e16b8084c022bcc90ef1acebf194c7b9820968e554e2ec4d34346eedf80cacdafcdbf118a3f158e45e6a8766869e2e5418499d3cfbe215762a4a0cffe4315edea5ef47c60c163be4aa5196c5241f5c772f3f90c57a3580fa0735a7340e37372048c1f60a20531f830d60634a177f3974d5399fca046417a6e4327c4c569d8f4f5b47b263b0f07408b1d453ae31f699e53904605cfdbaa72639138cea3e544258e0484a532216372ca569751b32be145716eac8ee5e731a1db2b1dae4b9023b05876077cdd78084c79e58d16ecbaecee3965ad4685c1780154b678bbfcf725fb2e91be3cc0864ba0f682ce1460eff27c8518451b3a9ec811e18b8839808256e18a89219fda2772c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416da5bd7647f8d8388c2b4dbc138e36b8679284eadc49370ce0a16a4e0be28804b04f9b593ec5987c0608e3913acb29a322355a554e010d33acf155e6ab9bad337c4bc688653010a7720d44168b4552bf75974219788ac1cf3fb440c67ff692d499e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd93257121806eb5dcaff87a28d25de336e240731a375be04c4bbff6be6a5ba4f1042a067086008bd1c894c74e4ab0b16dd36effafc8f04a4617aefa7f68b40df033149c0a98bd89778f1276a0ee404b17d81b96c524a8aeda9f671be9e724f090c397977714f425d45bda5f3373c374e9b2710f477e2e923a0f0b2b259c941965f6e88c0334fe5947d75ed7ce18612988df5f227b149c66f371593a8c248206f1b59e10248e650f7e08ac882d65fb09141fc5c7d252da9b1d8ca2ae311752ddce977137229ab3993dc198b5cfee52c273f6145c25afaaa6de14670eccdc1b61fd53821513fa519134b630c1d53b78cbb67e8b8414c30247101be5de118662237b8388cc7d3c50b2fab9b87f1a6228df23e9507c90bec51b8e3be978b526c0e0c7704c7334dc8495596755b6b5a83796315f9e316bb871c0465cac91290b34812c5f0e34120ce455c4566893481e7afa89c0c425533fb4eecab574f0399ca29b162a4c78053405a94626a6d3cecc0492a268e974e9864826f8745403fbb98f55bf45c0b620da0f2b6e2eb2808b3e713d1a3f774966e3e00f81226887d5e1c165af998d6e57645c3b5a2e17df20f698507190332c6951d761c5f46e0dcf997c7337c0bb7e54e232d9f4c8884a9f53a999e8ce7a27f68e9108a4fde15bc51a350774c22b2a1480fc5fd10948cd231f68ec00397e22a19042578431aad63546679e72efa3cc619c9564390d54bd989ac1fb089a57964ee4313f857411373d34161939633c8f4230930357b8b54ce94dfac3276daca91ccbab9b944bdd9754fb27d2b786427b30b6d3a029d0c998a49c406fb0778936c3bbd0708774bbf21b400aa8a41e604401c8e5f3c9fe54712dfa93b8f223c4bf30e2d037a36a768f160cf0c6e6a8c42a45908fdba40941f018589894c721ae6eddb3ad080bfca4aae349a8e7ae261f0a0f18d3fcd225254bfac8ee7f94e5f505496773b69c49697eb79ef8523530c55511106827b00917fd22c6b8e62eda5e130344c9214f2565b92ddcd6b6edfa18e95f8afa23b3c8f159391a3ffb6dda5ce3c9f6b40f25c1dc7a742186b7b693f30111e4b9ad468b9d1e0cf4f79c5078c9cc4e409f8a0fb170d7c4f421ed5fcf597e3f061f1060d5207533b44b4977f128acd44bfe1bfe235f2f4b2d042a87c7da4d1d526a096e110f710d48d0a0bb58b06ceb1d6ba2189ac3dc984dc24e80fb6522431e282ef8862f121223f6aa19fc1f929106d7a916747f21e1973eec1e8c5b7f78cc3ceec15a5af2b64d5a43ae54fcccd31ddabe95461fdcb5be506267404ba432e41161e6df14443df6eadfb3c5ad5228291d1383cdaaef20c9cc8125f7952f249a0de7093e895f4c599aeb4b0310673b00785b33fb9cacd556acc9abdc3de57fc056df4318d12a052ab505db7d06dfe03767eb5f46cf0d271393db1db2516c52aca4be351c39cc0bd557e7afe547a479f8a7218cad2c784e197f3494dbb9436292833db878c0dab763cdeac36e752c7cda12c98686c05704a8b2a695a315bb1146b3d1cb07cfb8d2e13fa9158734dc2bd1ea554fd3032bdbf9e9871d2937060236da4573a6c20044052b270916290b13a30adf3a821b467c4038a14026badd09126d6621e31b47269829a47f9be24a0d63c4bd7ae112b395498ec2502c3b4f46547b4c766e40db6b1685c455de210347c5757ebb7d463d1910eb70fb290b5c7bc63163ac00341573dfc794b0d53e6bab40a84e60ffb1dc3f6642aa1a246ee579703579df75d2c2dd3d53003f55ebbefeb59446d476d0a722ef8ed1954fae9d6ddc2f1b5a31a3e46efe8097d83d7f80ec284bc72a48b7916a74a1cad145eed554722609bff1c0970e439f19fff06a080a67677712b09762b90a82fd9f97bbc50c12b2408a440f2c91824179203d689db4245fa3087e8b01a9316ba973c6ed1a7556aee499b2dffa90a79b118a646aec6b79e6766dc25665db73a98e173fa6381ae47c9de57628b53ed9958a889d278fe707b4284327bc582599019bfc4630616b78f186de80c5d2d0669404118ff1591ff141a606e05e2835889a5f42a32e9a1f34d4c6438f429028ba64818bedeff64b1db1ebdd89f2c2b2fe3336942a03036b9e86a336aeeee1b94c5d5a821e4ab4c136cbf2766a43dd37078e02927ca8a562d2ebb6671ff854613aa3ad169250e037aadbf0ea14c87982d7382f09c7b8c96770d2ffd3b72525806a645e5abd09a51d257c30dcf016435c114d26d3d3be170800af2466b5e4a434ad5ef602a77f311fa22300a5a6ebf03bdcc04f92fdf0da3c74f0c1461d8bef6e668a2cd0c95fdfc9ef30cf9133619aeb9c3d5187f23bd83c765478a56c4b3708da965c36dac2e8caca9398d50bff836219540b179bae7667aa091181db267cc8ff6c5201acaad6fc2c3a2cd18eb729ad0c1526c6c348e330ce5d949162cbc728667ecce548da5efe0448823e928463418342d41883dc6e20d8e45f1d6d02c43c3e38d6e7871f18ee80f60415adc76fdf4c8ad2c67ac7d11682942ab79f74656a8f51ab8c1b088f33ddfa20992eaaae491dc3dfff9742fe32c4428233d691dfb69a1713087e4fbfef8f7c96df760e85354069eef1ddbaa01d52f9664fbed82ddb5cd6ceec78143f1e27ee7a0fa73873d01e80e368825e3b05bef7cb0005833a9d0ae360c420a66a5353836acf1fa3c65578c9c5b3b9c7831e944ae887694e9fc6a8634f213d8d061cc2a34a00f214d9f67cd17effc527a07e060bea20b143a7bf515a130000f93cba10536a1204f0a14cdba7b627412d383c308672a7e2974b837e4a89d54e63c47966b36fcfa3efa5854046d3ce09d45f226c36aa9c0762a59eada83c70e1049d5d09f7f7304c465f2ff56dbe21687ece20ae9fcd9ab8a7020a1f967780a1ef49b13b40fc3cfd208e29f4d5d5ee9bb63c5fc81fafe5d47c4ee373a54a64d267c497c59f4c15077374317b91566d44c82f74167e6d847ad207f3a1221ce1f958946317e77ba146d16aa7bd82810c5e913c4da0bc5d3a5923a156f0990c79f01317a3140ef3aff708acfdcd30a838706db819dc3a5a9fa2b1bed2a4a48fb21792b44c5772f888132d414d13a98bb5bbbbd70ac42afa68950568131a449e70574ae0f45f28b87210c1ff7df1adee5576d03950b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d9a53c2f9f5f55bd687e359ef37196cd288fcd1a14adf6cad53c6704445a1f1212270467b0c03fcfd8bac09473161c6eba9c25369a853193b472eb2f113a3d333181e6b71b981059fa265cd76422e52fe175db6983c6ebdd0fea1a3075166b9291619ab90bff00f89ea8055f0d7d45f8c8aa9c04b7fc1d06468837c6c563a6529ba846878e4f157741703bb4c3ab4f3ff2e9b99916624a9965a4256d893c84e152c19794d20de22edc9c4c1514f4f4e29ac16e6b421d3620ec6545f737100f0134c29c11128e193f06c866e165662d903d9f799508e617920d786ebf75acd267462237ad2bb39f6a5a03a46c5a1dfdd3766a49e6c864ac5d45afa6400ce3a9809de464459b18deeea6f02d5882e80a8696b00c9f703da84bc5769921053ecc749b0cfe1745dd408f6dfa0ceaa1780ad4ae1747a8912a589a754ed86373a08ff5540a471d9a8272b09df08db1f998000cccef325d072ad79df6c1936cf0ccdeb77a0d9c323ea08a0551f96c28b05ac0c7b0e338cc5004bac22d06feea5a8f5c00104906813ee195100f82600e56bb5756831a260e4cf6e5ad275364130dbafba4ed4f9db6adcdce67708905276a01347cc1c800bf6ba246c3770a81c3c754fd65bee13fa85260215c5235169fea113546e7b4aa7a1c936c47a14e81d3df912601a2eb8ece17888100536bf7183c579eab3e6daa14e5e01602a2fc3a64b563f591f0828f0bfffc49973cd14329675728a2d243102ab486601f1581b1e741bb5c77526552839c17a5dbf3b2f90875abc9959553b320da9f07f1392fa3065315a8b1744a7e5b271f9394d6e23bdab9ae03491f51bbf21014364d919388b7fba4b5341bc4b759fa4234adb292ab984f7b69d3aac2e0afdc7dc075e18ad22f4456dfa48b0acf62c24bb58eeb0a71365ba5f890a594cc046a483d9b306a487ea4eb5e80572d3ac8b4dbb4b6a02692af692160b113da09d4ae9f0464c5522b7236a59b70d3667fd3b0c5fdf2c30cccdd640a7297da408b6aff82ee9651f889910fda9f24c706a617b082d626dfc74a657c5d17c5a763044f0230972fbe47c907a5a8fb75df4afa9726d496332a25823148258bf60b189ac898c92b9be15965a199a45ad563efc761392b915b58613f9fb99f45c9a78fdaa4358874f739cee7ebf2a5cbc2fbee73e2731e18f347de520f1878f0eab3a38f377a9263ad17333135c991d560da02f9a012221d644717e2f1361ddfd9e6b5d0043f3a47eeffab15e43d7d45e1f6e07945d95fb46ef5346bb3a502da9f005d1cdc956e1b96258fba48dc793f50b7eeab48cb88c51118ced6c65368c5197ec7f014c443b47d898627cdb7781351442c44398d0ea4ca4b697ffd505665531e7d4b4406431f2328943e8b72d030842128714ed41e3d13b8aad0d076b7ad34af4946866f552568eadd3d3582b4c4f50d816c065e65b3583c8309e3465db95b458d0b42619e1ea75ca546e966d761c53645771381f31a42a1e0bca62f752fb49e8d2a49f942cd48a03129a709e763d23aa4dc84c88423861d1ef31f5df99006156570aca69e571067899ddb156a2027e0acb8f278b4e156f96ecf0eb2658c6504fcd39e4e20bfb5905be7cfa05ed907aa5041e202a49166a5e267724e5bbd0d9efe57d34d8cd7a2e536cc7aee14f12726065cc08d547840066bb56916d9bb9761e05133fd18a68324492ad7b9f9caa1668038a3ae897ec528be2ca7c977eca6cfc08a00266e96fd43a723fc7226b66aaa86fb8c0ff0094b6feeb0707b5cd61797ca034755fa42aab8c5c9e245157f5425f5d9c2de89a454439ff9ddadea199ac62ed47b9326a4a08c06859dc6aa56cf5af62a035f7c6b0546f536c07cfd7a2d8e3be9ac2c7b7e854ebf59eaeda5edad7dc23e83eb30dfa3dd91753614a811769d6a564e5e2b27c43c70d7497a0834ea96e50b6edef3369e8da5f707e530fcf611301be6bab8187386d130d1f8c94e5c3602ec613f83c1ce2708d6fceff206d25c511772a85eec3fe2b4ee066681cc6c58313ac304e37b46e43a844db9b7bcda351e09ad1efc57db99dc2a7c12e553ca9a60412dd6bdedd4ded92b9647ecd2ce31eda2a6f5a4ef9df833b9b4c70ec0924a92a7067757484a42e2e39a2c58cf41f683c3646c0e993fdb61ba33306f7524ee2733c1d970403cebabf7a1af318743767411fda52e046b2fdbee1680978da2f66413a00a72c2f0fd68497472feb62d2481dfa1ae93b14895fd3773d48635738847d32c4252393c6cb8e07655646eca309a1481552ecbd9569e94a0cbb6905c45717f0097f3dac95ce491ef6f07d89dd7a409b0f13475eeef708fbb0cac0f200cd31c296fc0f38221dca15bbd3ad95092e6a4f38b8ef8e9f3b9992d57409c7833c0e2e85194adb91496335138d5815f82e01ebc93b757c1ff94620f3a87ef48ca064b8daa8790dd2fda2c3493f33b66804385212b1c3747f61ba6de535688b2ec24db2b9bb22f1c69337d131a4c91c2b70f1b45fa522eb556b7960f937e6fba63e1a5c832c850ec9d476fa68c807d36d09edf0c1eb9b2995a3812cec5092b90c4c724a2e1e42195049ba8878f1d05a2e30251a57f7f4662d4bbe42ecc98b7399c13a00c82090e61c34b4675c01815b7e25a1fd09d2fc60f60ec1f3f435096790681cd676c3554c66ecb08ee954d3de09ddaa2e3d11f5fa4f9d4c89cbdce2c3accd6f9495757f069ede7b956256595c7d083b47c610efce658762467518bdb11be9597e37db2ce13f8b1b0cc42acf317bf5a8f948dd3977725de1590421117c9ffd003a836e898f478234d26fc7d8bf866a6a308f8f7cdaab738bc98b879669911a26d87f69b187cd620e910289b9d5c2704d332359fce4040b4978eb1527e743dc15407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d7162fa40d6ad22c0bd13811d9555f4b2adb0f639cf7ace8468db36e557c1e1176e4ac7db719c3be3a8a8fb077e5aaa181f69f89547570b88ecaba644b0c8623f793abe63296589646fa4fd48c7d15548b46fe4f60435bf69fb31260205482eab0226b7a3b02d5edba566f82d3f949278d4d0660165857965f123b1ff5aa680a62c6c7b8a1064cbfd234f3e26fcd14b1eb52a0b46a47e8a8d38027bb3fa2cba947124c41b6ccc361bdd655dbd0f0a5b5e7c86fb1bf779a912921794e17746c37f40e0e4451bfef8b6e07bc00ff6fe17cdd12d45db9f816cace50b0682291a8dc257ac131413580ad09206331a67387cdfbf12cee28aab9a8b0aefc03d6d1f2fde70a8c597075eec72c0adb7c050db76ed8d86e7785f056db19e02775ea099672c7f447c7d787652ba7c318efbd758620236476ecd6df6abc2cadf3488c7e6416c12b8a2bb40ce3658b1d71c42e68495a5504986f38696e56ba0fc2df70182a5b11fea0d61d2472c21da757115c4aeb85f1ad06831b0b41779a118995340fe6c352e6cbeabce345363e57dc45931c6bf8f278f704cf252234e0e580741af38024e1536d3b2112224e3432e605d698c7809f9599544725f3bbd89e076742a2e33631e2caf02567c87ef2729ac221651de0efa7ccc8de802d0ced1036b68b51868bd3686a8ecbd7b1a217342e937037c0bebc6a026371b85698d124c09998e5a531b6cb276cf5c2ddbf28d010e2a6976cf03488c0d1d11c5c1f9b23d7ac44ed221724baa63a6245db826d277bf7bed80169db1bccdc7a3eb0ae7852317a5fb2628982aa0fff7c6916548204396e77dd2fc044e2a37c192789053627b2c81fa1c0f3d1f7482ad1abb0ef6ca6488989637ea1d44a918f062b169f1b802c9ee6d05a2fe34fe3fdf6285d91ddb739bc5c2481ed4d77589febde82e624d0af0ff9796e5993242f7de325ac001c0d50c4d27c15248ae2023cbc52e2ee969b16fbef249ee2542026074c387dc5714b8038735a05a39459797ad1f591aede76adbce55e99ed94a98b68d8ce62060e2c77262da54a918fe5942925597cad811f00d13599f0062784e528241405f8618bcc663a513318815f67de9a13e6786615542b715d6d2bb3d82580e61b8d0dc0c1652fcb6ad0fe74186d4f30f931ded5712a16e9724b9993cd0d505f36fdd6c1f2f87ae7f7b7d2a84caf41d8db3d926a728904ffc98ade114aa146708071810254fb2b5fd49243a64bc29a6cf8638150988ebd9756b917719664e74f116e47c0991afa7bc43d0b4aaf085d205ced8ea01235b224e9e2a575626a39cb65fb8a0456f4f5380b87473b2c6d3ae6c36664af57171130202317f567e7a89975b0683a31b08cabf966ecc62d48ac257c297ac4825c75e59c4271562da9a7597e0b1d1e880416c0a36fd5d9a8a1a0e277025e81af122c541ead22d78609154fd9334b34c1b724aafefb4de93d02e360bcd69f4d179b8f973f0a229525c681a841ce65fe1848e33fe6c929cfdb09181ed6f10f9b5d42b079890c93f6cb63489fe6ca5926a30f68d89fea2985c600a9114516a6c29aa1a9a390358ae11d4c2addda665d13fc93f613f8de4ae6526a7ec8bcc418d9d190bff5fb2bf8a57d4d02ae9d39b49dafea09bc363a28395b90f0c0482be2642d693c65b1dabd51d6456d129d5c987093349056b99398c6c59efe7949aa90e6480719aa04ad8816124b5eaccc793902c3f48b7529b6d116f4e7418406b6dfcabf008b65268d1b3757c713863c80e960241776adfb775052d810b59fbc83edabf4b607bd44c6a610788c1cfeb3f21e0b94d5a12f2615ed49cf7d67abf18a93af7ba649cd0ac29680d9eb19a6e461dc5fcce21ea03fdc88fe1a67bdd4b67671794d5348a1b481ad45e86635f0474f0fe3f7138dbd0c961b000d0c14707c9c3037792e2b59632bef200305908aceeb3388deb21c5ceaa4c1dae6b8ef3ef9ccfca9bc6523b609bcddd0b66f5b305293c5ce2538e4d8e773a6d51cb10adc0c50d9b9cba83e8429a2e2e1e4e1f947c0be485986af1fefb306419c6fc3cc203303517dedafea231dd90856df4af58129352adfbd4c714e33aa5cea74c6e39a097a1155bb8a0f59242addc542e1ce485f81eb5df11ba9bf4e0267aba89ad594b06066c4a7f52ca7947de90772864f98b6fd26bbf80abe1a9ecef909810ecefd129f3a73bd3296a2999b9bb455ebb74bbc3f5ea7cc6eb966a566123ce03005a73c0294531cdb87e6f4e95a515a4533e0224cd2cf5426a5cdcab8c30caba2a0a36831bce623b526cac663bf76f269e3d114a73a0229bbc06b4f53b1f5c0ca2198e418a49af03440d375ae7c76e24cc7c0c46b93aa96c8e69afd833d5c5f4ee23346e35053b1fa6044421208a5fc47074d544333068438bbce32a53bc0117d123ddb9718eb62baa88f7a7bc786758ecfa2acaff06cdc5d550de264d6d61988290e84649f3faef516f21a36b403490b980074580512dc2e7d3e2b87a063a5da17648602d66ed743cf227b0ef5a34067bba03c1df0cbc3cfea77b39ee77b49d8b425455e45a27a245c1963853bd35689e5192515b7b99cfd14d624ea54dbe5eea6c8f22b59babc3c6a3ce22286f1a628b901883b088d7b9dedc64dc86f636e337839c21edf802b526c26346ff314ac02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c24165804d109d88647def7d8362b09e103f65285c88ff5ac9329ca40a9c29dca4e073034a4c23a5fe2e1a82fe0b885d736e57a0883291961a087a2719664020a574cd8db813d1070487f577a18b9e163ed125ed818c0d13dde40503a10ed6c8d3e6a9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712132d3fdefa1807e6bf9c14050d63d2c37bf357802a7d8e813baee24cefa76b229d471496a02cc87ca65544c0ef979e7f4c1f0a7269e3eb21fea4e0d91ec4fe86ba67e4ee5cc212e44e3488e61c6c1ce07e25614b8c23cb4d0442b35e6b0d8ab3744512e70a1dd7110e04b778646d4f7b399d36712e40bd06a6907f25046639e4f9a632636d4945986ce97bc67ea13897025c220e7297598460ccd7cedb8a0c54792f097884bc8751c88ee126bd1f3682449da8181bc9cc5b90f0bd9dce1cb0d19441bd6bd7dd64756c6cb272ce5ea2a934c56dec8f3be010f8ea74cc61f20d1309a1fcf68fc3da9660e86c1189f879b8c9cb6611d57d470765dec4c3514243009923ef8cdfac92e83ce444c9a2b61fe92d6043d108129649a3c6ea306c5d9db7b924eb791afc0aacb141b54f0d75fcde46e4682e806926114b2ec7ee5a1a5626a3a524e56e2044349643bea61e7d9d3ae3dc19e660d754e6cac3fa4f24ae46d794816a0ad32ac3690b658c96cc6e09d9510a57c8e28f32220210108791a15aa0dea2e3482714178bee78fee64d0d61e6933d06f8e8dedbfa5ec5cde870dde2d7a9880b245038d021948c6700d89443c09f207b9da66d2ec05e1c567a8ae5fe5023a414b00e01850a90adb945205173ed44279aeb17ca7ebf9a239d5f6ecc9306a868b391a7c49dbde0913228107a7795db90a5e3e91e505d9922c2914d7755e0ca47af8f394eabf539adc4509e5958a7935179f1fe3f8c22b4cc2e2a345933f59d65e0318bcca6caafcefeb3452d68d6197c8ea0b26b971962e201405c4c157653c2f2d4af59046fba73c6d72ca8cc525648416b9b2143dac665457204258b81bbad3d109701bd807e75845178590a4c5b8d44421e0225d9fd994af2aa1d0c65590a7bfeb5fd893b53578b04160e3162b0aae5d6f67dfcb75abbcf01b2ebb106906d47dbbbde1bdb9b1bfa8dab1989c600610422ddba5fabd57a54dc955ccfc7e5810293b5345958abc5f84808fd97351d481e6809e00bee6538408aea7c6c074c26b68e2002ea0633e6c3d7484493771c50eeb727d6fcea84ed9c26bdaddaf73d8ac7ad5aa36f30863234f789eb1d0092f42deb6ca72061146b920d71b457700dc5012547ee806376f3ffab1e2780f491f33a0cb355ea6b677c4ea1b54ab6e5698d2853047a428891a431d89979492f261809be176ccc6f09660d5cd4b624f339e961df7e2cd5aa3f816fe8950ecc0c2c9838fbf68bca5d4955de8719bb6cf79e8afbc8632efb5aabfcaa6e749cd45043ecb13046ce3209fa85ef21441ec2d1a0ac63a273f4213225773647e8a739187223eaf5c9f0f2e3d1b12e229fa77e65bfaa2a0487a29d08064960b2068be68c3c830254caee33d9436053af9fd028474bacd43a231dadc4f4116e333fc9f88fbcb64abea30e650a11ac56a1988eca459d858087e220893ac87e5b5203582ed469929c865ca6e35cafc0886f8e5a9f813f011fb08ba33475f7e9b64397ce8355542f0d31bebdb5238414fbc41ab88fe2abea69d9e769a9b465041255b591fe2708f1193c6a0d7e83e929c167d0f672a6cf8bf480b21d5fcfdf7c0ed21b4968982c3b4798fe04b9e9462fe2bd8fb6c511b1c153d0637fd584e30e35b6a07aa739ca4f37d82d9c8e4369606257edbbb2f6ee4e6047dd8e85212633fba991cea2364c746d0ec558d0fdfd64f2ca44bcc97637e3af5596f09c8a333cc19880d51fcd11a73c7b8eb1b02485903f9c3b3d15b56b6dbcce848e56c21d870a965f61bc53894462a6997e78f55f20ebf32f8f4de37a05611860ed6704be9587f1a0c12bf329f83fadd02c191a288925cf1aa151d387686eed59f920597a10643f36f40b821f85fc2e6b62569c88b32189a52966c52301f029b0c231c81ba02285edfcf032a441c296500e2a2979e4b4b0caff11b6656d131b61a171c4554591d3c74fbc8fb899600114d3a61951d7af36bb8e6460ba61b0015878e7e28903dbcdb802b63c5e6c895e2619c6511dfa0723fc48f796952690fc3626bb5c1a0757a19226c7db6e42ec243932a2503b9b257fa271f933ec2dc395f40b62b11adfb0a552412447e35ac364bee1f8ce0ad23a72daad14944e49b18cc3d5ecb36f4a8dfd602319507ba7dade07e22ca3a895e9ce0a2f59d7f581d176f5b8f880047f3803efbbcd442b7f8b1fe158353183f03d3f6acf46865281439426e64348199839d84de5c3d2441a5dd9c75bd064c1385ca083cd1df6ef46dacd30ba7bc9797085a143f0fcdd6b0c7ffdde124bace833b758ee4ddfe5072a558406365b77652cb2bd1ccf651da71b0b22bf789af3d24014217fea74522e694c399bc8bd5f07c0db8fab186d5ee762d33a5debc1902bed79a68d8420d06fa2810bfcd09e53dad5f37258fa86f46560785713ec711c9f5ab98c631bb3e3b6c5a293370fec522d61149c7bb09bd4256e55a71487db84f95cffaefd2c4a3058c62c3e73695bc27a72c21d264daa0d40c012083c581e4a0dfc7f168b722b237a0ede4e40a7b352f38ccd532d1a416ffb5207d68c2b7b3a6cfd957d7efa5b71446ce84fba254aa25005dd08c988f4dbdcc3dc795d3487566e587f8f99fa6d222c406942f33c9a694d0a5b974d247fd6d4a37727a7eeb184f4139d300cb9d2264e4bc1869026d0ca9966cfa34a5506577dd7eaa826a1dbd86bf3e8ae5fe73cd591837a5d6075a386bea6701e431ace3f383154ebf64ff61e2e4b520bf3a723908aa855ffca926ec6b18bc48a7dc48b52b839507453def5fd2898cbce2c611ba2af0d2434a7152607d997781ffdbd8987c5b14b6f20449493fdab89717e43a14153845b97698e2511195a1fbb646bd896dad04547a95f1941a1df510c4f7990062c0d4fd794bc886625c783228e520fde1dbed723fc9779bef796e04307444ff32c210cfc2275da1aba94d5bd2b963fbd80dda7a9c8ff88271f152875d7cccd664a44c8d3067a4034b5d6101af80d9a2970f3443536302525e41dceba23d8862006a1893e47f69018c2ed81677b4c43016ddd24ba54311aa590562ce1ad6991a1736d972bf0421adc4a00cd631414f1cbecb646e0008529253e9c0169822efb33ce421d77953121b3efeb10cd44d504b5cf47a9807dacce8eb24d53ce62e145835b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d32ed1f9d70028c2001ede3fb28ac4db0b0215889cb331f8bc637d8cd27d4443570c84f2e19c4aa5a2610030e19ea4093bd118f72e066ba44693db5cef94f3905a6740f6b046ac8d7b77f5451a405975c2588b5b82cfb70843359010be8b7f32870641d3606bc050e0383940f0e25880e6b183b137ab86e3ddd52a0ea7024db44fc4458e5fe418d5a7ed1c33878563e44403bf194507c93079ff9105b433e6078faba26ef3daab055a97199108ceea0d3b0dfee6ef4f8ad55f1eca9c15771251d0cf33eead0be3cea163831560bf46c98931a1dd530301d054fad074fb22e5d6ad86e5f79ca0607a6108ef6030015ee05ed6229bafe13806894461b51199f5b3d2ef6d9024f2194253e89d0ed237b1903f89dc510bbdfd982b518c3576659cd39120b53fc4e51e100e83a51da1239f64947e10f158bc42d10a3b20a366b4311370e2e5c4b8c303383b3e579cd1196f3dd13db99c99a48397fe1df8987a58b942b02fcf424a1223968027d877793bf9f4636cdba3b47dfac921296a818d1b08821f45e5edff6c3c216a16d4b6539790325daae1a6400ee446c2b4fd1852c409d43d0bfb72b3c0946f9edc151873293bcf16d1360b340d7b98eda07f00b1333fa020c5b2ab0a4db4d0a259bc517898153957166f01726a25d2012da74a8fcfec104b6ba6b02f41eb730989a90ffe2f8948b98eda9bb5bdaddacaba1ac1877ea8c77247f876b27b3d89aa71714f55561cbdd0ebbc4b24d39b044ca3e3ef42bf8f63b8c642ebb1fcbeccda9a1e3aed8762eaf0d9ed97308e08e7489424c321f49af5ff24bc10f697dde29bb97031ff65fc6cea39036367972d5627a48c4f9cb8ec56d22a8f95b4c20b4a2545baa5879a817128101c28cc253f3a7a73cb74f0c43d609d08eca7f936f1a8a1fd902a4395ac8be7312d9eaf784c761cb1354dd40baf3012e85eadf3fb86959768990ad2c8625a553c4d920338ebe25de23761c085102555e30cb812643fc1d2857c220dcb944c423397264da353d5131d0c70933d72b55d021a519c3d7a9c5614710da694bc1e1b7d5cfe40931ce3f0e1f35d253566b238265670dbf08b30c63410be69245689bbfb89a17eca0f6c9542454b1e92ed9421ab1827a2f0013b37d7a0653c54a480e1adb20f4d6621955b8b41b7fc0dc7f66309c890258c6702ea0943d8a32748f67d8dfa4a29fd85282d949f1cff5faba27a8336309a4f867baccec1e6369b73bdf4b757c1049448f4bb3999ee0d8ffcf0014a49f30a2a2f680daeab96ba080e9436779e88da9f35f1df28aa84992e99a0beab3c9bc2858788c7077ea13728eed4debededfd07f1672798856c3a055a13408241a7531f1edd8411be59bcddf843f745850a77afe6ac8984ce9110aae0cd6008ca6874a522c58bc897c403a860cd5d05b731add09f9e24a465d0da6417d00000bc1f800f46d8c06a9861b5ebb82ee710a67a28a410942c343c5385210af2235887221563f3ead0d53f19846cb8c3345403ba3f7209d78da91196896a687824d8afb71dfa6f71d993f900470493108fe9db363bf82126d7af537072262fd8208ab0488b72ddc27a4f9dbb2c191e699746de264af70e8325a3a8040652d3cc3e86f8e7ead704ea80c6fabc0641fdb53599f2e2532b2733e93514058b042af10bd004e87da3ee9342f44b433ff1b8535e3f1928f927eaf8bdf52e31c589467317ee797d349e052a0edd93134d2a7c57ee3fdacad7f8e00de15fee3a091b2c8e51c87f228bd61350ac8ebe6922fbe3db9b1f1c95cc6fad66daca76115c222bee077e98797f7d5a383fdf3eba7a9d9f91ef76bca8a1f5e028013db30143acb3e55096b4d63a9ba75c34b652b711c471606219755a72fc7db90eca93c617bac3191bb231b7a7a68d58e125aada1bdc72c94363a3d8c1e3ff72da6102d37790dbdd1172e42327ed298ddac2fc87c59442d545b0ff476caed9e785f2bed1bff26b0333a6b7893cfcd6ddb8a9ff65313caf6456f2ad2188feb5ba8dc102539e94beba58707699d560bbcce83134bc3f92ffca813e62865f3d2d56680b0ddfaedcac5d5d84dcacf83ad61a2b13644eba1c459299b7a92a42c735c24fe9a4b2e2e9fd6a003c6761b167ab56948265b496cb7529b01cc4e53c3cd9a39384643996beac7e7e8c5b9548bb53ebf8bbca632e490bedf7f4c1de2fe41bcb746afd7380a6ba561610e880b38007beeaff985e007a1460051bb827ffb24970b0fbf79cde0264cf0292305be0faf22877173da64f6bb647b3a636b831df365b7c3394915ca6209d753a2cdcb143ba3e7fa41dccf5534c6fd36ef91187d55e35dac9d3925ac08e2c22c80dda4c60aa6e074cbad95a68215cc134e03ac7e516179bae944ce17cb54d086ea75184c3c36dcddad7c1a570d4167525f3f53d8d39ebaf2d239bc1f9e7572cbce85b1fa08568230c663866d47c3af0c12e609217ab0284f8b8694563933a48ae23e707c1df21527ba79fb2c6cb074d51ed0b90e361b2cbda0637c074415c3e4eb13b75b149505ccf56ad08a10df211eba48ffd7a2d0d42a1bd943dcc12f86e3e9052ee1ea8f6f1a8fd7b2262bfb86110b06210c25e7fac37b49198155c2471aad8190353d85860814a81887509424d72a79cef1534ea7655db318a424d6a036c7aa614ce9faa7901f55f64b0b0bf1c084f52e7069e5bf1097a9889ff9773079eb30a9abe2de835e3229d8c3cd6b00e936d5339b325684a5c483b15420e123c221c6faa48e432e6ad29d22301073d3dcd3dad319399258dae99d20eb634bd69867ef8695bedf1478abdea28e97985ba68b3810318e3cb12ef946594ef5447668e76d655032dad5ed688567ea02cd741c0f1684f271e1e6f57e70339d949187f9cc5ed830203c45863ffda2b704a0bfc77cd4cbaf3279e937c9415d47635c23582b2cc0e19d01abf7b442930cab1acb6b6d1c87fcbabb93d1ee778339fc75b0aa674b0b9ebcc31efa34cdc88d6209367d7c9cb38d96a9ceb0b51e8e2364399650074af6bb1098b22b21e3b9d12bfcf4ba0ee5e9c3cf8820ef6061d10c3648d73c6d22bb9a4502c3b263699d0ea24baa448b12d24f501412d09da75d99714c914e0bac941c2e9591a1af974b9d7ed718ae8c2c5246458375efb92aa04a645b615f261ebad3748d4e586cf4bb52da7a9c3a306113046efec9210cdac01dd254b6f9444d4186539c1983075c1100c45b2a80ec93371fb04da55a70d7e4064542210bed2bab603e428eba5d241504949b6d4c4f02b543fd709a15be42ee92b6bd37baa61bc2904832a15e7077176451dbb49a688cf55649c5637bab364126c473c49dcbcfb064b2f296cbed17603820bbd3a5e93ec52e82e67ab2760735d2fc915122c09b76fc9de21fd95de63f8e5b0276a7fe25efa62bedecf69ceb278c8309d1c5ccae18338cd298c2ce4780f31255dd1321fbd0dbb6f8f64f321e0e0b665130b8a0379aaf5aa6bdafe07af1312f637e3911b8d18fbcdee38fc22ca35094f912decea24e409eec05550dd35c62be25a1612ab90b268015b40eaed9fa0717aab769e193b2d7bd2a55e7e715c64e67d0be4b76086d9cc31c11ec35caeb68634eb554ed5f55ec45727a57e2d8d6914f6d2acffb17b9515d347ba045067502a0b14022a269560e0d95cb168c7097ea8eccca5aecb328a24b1eda37bdb600fffb212178ec0923744a6402d58d7d738f233ce9b64b6a9f1dbfeec1505db36c5a06eab73142a86b27dc175155cb30310da6295a7fb1a7fd6e4ef00c998b82ab8b3300133c6af14e5077c26aa202e6fc5e69a792012590d42ae2694b82fc1efc68ebf7b5df2574cb85143f66a0bc2ff2a9811e62cca6fe559c14e606a1c9ac2753af2050d14b924dfc217dbc5b9b44e89d25f35314db49b096287a77d1734d0f8f8d168467849008fc52de08473191d53f8cff9c54059406398e89683d41db5ca287bb379e463c7df481005fcaa51f86223229d9aa3f1dc10b0bc97f9814eedae2d1a0d48826da8fea991d14f1358e94badeb070719ef7e1ff2021c1cb5acd297695c34310474feb95e86dd6e211cd2e6f65ced4fbfff3817ccb8c25dae508502d4df393b421e7f92dcd88622e35e35994021fd95c368ce30d455831b8d7b5431f33a73278cc9567892bccaa9f0d0d4410a411d42de63d1e2908e4ebbcafdb25c1a4ee00238cdf73e322686f01341d26623c2491c6340204508a421b5978d8f7f698b473aa842dc9eca0e5774a6374ed583ce8605795f084731e95e368d039b6ac539d614882e89471f99ad0b367c55273a7a4a3dfff10ea4c7816a44c1cad69137741b64deffde56148294271b50d17c8ecfec51791fde88bb15b07ef5a9f0f13b9ee20cee21322f3a6fd0783089d9dd32a9344cb0a89e9746bd35c0bc36f37afacb5e35fa47643df9b11a50e4f6f2c820c284d4c147481412e5e4945115040df81511233a8f81e4731205cf0af72285f08cdaf87f9cda4cd3c7c7d51bce592ea15d692e2a1700f5467da9707838a1feff9c989cf84c7b2a3965f146be7fadff1b72aa0338c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e8529585eeb7d466f7e38b980536e62c00fd3dc5c703c3bbd721c9491e6eb85c32a44a4b8c95221524a3c23c6b5401c00b5030ac5fc9d0a0463ad9e34009a00ad426a782939a3e4f8394ef0f1c9a8f811a7f5ea333cadd30d3404352aedbd7a2a743020670a8d1c3fef7c3cee5b34ea05aee62597374b2d6143e51039b706bc660f371ea75d41bd9ef4da3a7a5ee404600a4880f8915d2a0d4943210c8e5e71277e7fb0a75847a0e9f3e97824f457206271c9147e2862e8728b4d69cbe84e785d92608878e367fea06978192e6e69d4b8acadd42ac1133fb3a9e9e1dc50e281254144a0fe07efe8476c462860a01a5e4180a4de0249f05648c23f8e6e3bc49809eb27d2c7ee29fd05b5cab4d8ea4b8868446d4562a8b2d6f182d818b448b165d8497a72c623880702eed40e35aadcfcf6b09f67040effbeddd2b22af32c2978da711f60d3a60f115c98e714b9ca80bb1bfbe16704fb841cbfb0bedad90d8ee5106d2178980cf59e6836eed32dc22ec231e5556dde151c0081a83bf4389916868f9a5c9eb394a00dd88f01a451ade235d634484a9c56c595224495874fbdbdfdc1e93220adc754722bc8f182a697c43e34c44782ead62b2b4d01ed046ac0d7187fdf4ec246361396ba03e69055b5347faa6c1cb9929766e4f2a7b41911e25448678f4820e4764775b18b4c0668fa3ca1e9183ed8e57c30c211e97e7cfdc685e6c082448e0595ca52e08fe5b0d37ac52bda3dc4c8a0b7d3e9d1812d5530ebcf9df0ca539c809855b617cec1498a8e2313908d070839a80574b129b24245eded44df2d131e43dc9142274e0b70a75a903791928a1bfcec374626d3c6136c409de439066c72ccb9ad0332fc9b36d3a24c6173a23014f684d0f1666b8331d108ff33986354061399848cc96c7a631da2855f503865eb732fd4e5c3976571cde050a1777e67603fe0045e0a581002149e02f12f72a340fcd78d5723d10b6869cb54bc64940dc20e2c4e3989890f61c5b1df09c72d8a70b5e5a161c0077f73c816b17f59d9533c2e6ab0c7a26dd2cad7646133b739b24e20159d38cb2e11faad8ea174305417860ff18be0bfcefdb413d281ebc034b8b5f8722b041e90ec772e1e9449f61650a27e810f57d102788527c3e274dddc99f094edf73a09544cf3f162573d6da4798895daec9986a41222047ae0d3ce9b6d84c6e91ff5abd4296b1e777b8e22b077a6aea2e843cde25869445dce969fda78091938b3cfdd6f1ab376e62e9f94ff0456171e270fec0156069e8006f48956683abccd1427e3ec9df93abc4fbee9170e9ac11dd9ca793e7d4ad05cfe205d6ba0969f8e965d571cfbf51f54a8e3317b795c76523eec774719d38f8ecbbb192bc298fdca9b0a9304386b0791c671fa441d2103a8e2b2f015072895fe33d26bdf621bc4357610234e563f1f6dbf1584d21aac7bc2a1f4c8869fd97e805ab0157b6325650d1e03909ae85ae3751e582cd823db5394add842eb339426c7a1f44fe90370fb00c10664c8f2c9515800831c45fb5248387358534d37a9b2bc6b9ec84bbcda7f2f8fc16f848423e1dae978e729d4886f44e1b21418fc96c9b11246ec54148661fd7515be3636f5d3fb5e2723cfb1a7253ebc10064373d6227daca15f68a54710eea722a4c7ac9d8cb34c289634b7a831c0d58ff0c5654f9edf692e49403f40a9b1b1bd4acaebd7c2ed9d02378c9a9b763a41b5a85c0e978d30601e32bfa02697f9eab6f756a1d83440c49028baa4607d4ec080ace306ea6094d615cc220736fadb0bddb33b4d7381d35d265c13e35b0d829219ad12e42d1b56bc54f1fea860b18d6440a9c44c56c41dbadd6085d0e3707ee4eeeb4e3410a8326cab9ea1eb95213475d669589cc8b1331ccc7d65eed9559e0ea0f5bfff13843f2b4a2067c577278af1558bddd481e153602c11d5c81a424e2a1e946483bdda59d530949954fc0d7e42afce9454b6faa5b7575f6fa1d2374efafe1363b36df330d958bfa12b5efdf7d274943cf6dd8c5448e3d30bd0d05afaf86a2d30c068ff63e9fd065e1f84362827c46ccb49a8ec04049d1e04db6f7b88c193400ee5818956472db1a5d3ab044e18f4e918b2547eb275d8910d103c13a8704ed2503421465b1e68c51817ae25727b7b72f3817febe4ec7451fc241d7794b8a63f1317707c329bed6bfb2a0023bef0917a4f8944b2023efbe2fe3d2131c41ab066ec2eacaf389834b55ec862fcbca7862a3addeb9a4fd147bd07f480464e395013f2599efd1c800bb1a8d30d5f57f82ac1df5056e7ab4b9b21cf69a97916c8a50072a9fa50439bf52d8ca7aaf50f5bd9591a5422b079114f0bfe4acf561c826ce665878ade3dace990e64ecfb1ba367f4c3c0a61d4aa1dad084d5c3279ceb5a4343f16894ba217fb7c1bb67c328dc7a5834ea59c48d0db9f4a5d9ad304bc46c0d63e2847067350555940f33ffa238dc7137ea04ecb81d9abc5b068794756c4f812d1c5af309231bfb4b27281eb33f8df6c7152ec14ed6fc9a8a644e174ba754247a7319d29a2d250be22ad5e7494d649b11898276a964aafd01459781278f83a80e6764aa6f07eaa4e22d1741ed853c68c6ab19999edb739487eaaee49b05113ccb3c725993fb28e76ac53f00b9ed3ab5f6912e0786fc1138fdd9eb43b407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71d68496b94fdfed16540c30b13d0d7e65a4ff1bb1b73ae867b96e7c912b00ff6a0ae752dca9264748a313dc53b63231d29e9fad3bf5e6ec9134177e105125ee610a1f9b915d9b65deb6f9add45e7b03240fec592fd59851a1fced2bf84b59977cde42db08d3a2ae3363169cf1de0faac09b586e3da4527c94f3e773341a31864c9cbe171e9d2dee147797d4242195bb40ac11e174db2328fe1eb75af660ac3467a41c20b10ebaf33b287cca0bd628c8e0776b9bf95584947c130993f4560f6f01a417c3a364675ca3cb6a8235ce24cfc39325150995dd367ebed4e2adba7efd67f631073311641d31a868698b9453e88b51df1f6dce9144da9ebea27285a1260bd849ef59e925c176159e087d784b4c571ff12c63386066a9565234ceabc1d14242383c5e1385b87afd269b475a6fde0ffb7bd90e239d010036426a9102aab37b5e7822263c75b2709c939073244489a929410cd8eaf39549a7f7e39808fb43114cccaaeacc16d611dd34b249acc4f8bc2276ac510bf3052b08e057425c87fd10a6c6f7979f5044137535fe3f4335ab4d53ff7a251b2d799539e0852b557861591858ca58ee54562ddd8ce1604479185664a744017e539e3a7737b7eba00d76750ec72e68159e3a59b6311dca75e37ce70329997f97069f11df50dfcfd9f0527d72a5f91327ba5470d80b2854a57596101f5dd528153c8e07bc10fd47d0ec9c6b3ca84536e7b0ef7109b756252405947adb4dfeaf4712a116940f296667427b1c3451595f904e1bcc1ecaffb327a9375f9f09251fd12a66f7cbd6faf86fe9024394f1eb3df27c88e651042254b623a6d4f21c9d4ff62f4819dbe9e6a4ef2e243a664589311423742fae46323f94994ab346ac1582f51747493b32611a563ad057baea8cd9643b8d548fe547146d615bee842aed92fc83470ae7116abdf4ab1944e02a488e8df0f2c1a026bdcb1c9e5e273773626b603e9c7ff6b9bf0beb5a573c6e918efa944501d59226cf102566661ea103bbe11febe431a1ff61e7c44a9852e25b13c8f1bb89f75aa4f297f36eff83fb89c7fd7627643fafbb62323508202f6cde95375caf3e05b69ec9d53a3c3d46d2c269274d4c297ea4c1849854c73f6f6841ca230369c180417f4a65f648b88e8a5dd04c309f31d09161a0207dee3469783daaa9274a0ebb267618be37418eb65bd822d1caac9f77229bb6c60962c515e8b207b02674157f4b2fac359d2595191b18223ef8d7a62f203c30dfb407d3017a45f5b334202ec3bdf629961bee8974b2e756e4c7b638ddcb558e8b8fe0e802bef767d681dba2b2af833aada512c7f867dbe6e01b2a7eb49c7b6e50bb8d9e6cfa8ed1321b415771d5535b817beb8831160ffb5f256a040d662f90742d2be25580185bd09edd014de26223b5f1a82e054dfebb79336d891b767f8be214f88151b8a8ed8bf99febaa10c51a9b07f80b130f73cfd4d1de282f6d7f5ccefcccb64a4ae407d0c8e29650b1c0c1c00c292d0afc5ebed5da7e7a9d0eced3c6894548043aa537407a69dfbfe0fd4dffdf896a363d75ac5707eda016347a63abfaa6435132d554abf826a19340bd0f7c5984343cb49e89936f55f2256bfc32871448794ea44303147839275ddbe891c2ce4f93b4e51ba2a2709de73de8b659f9ad0d8a6aa8e2f1c300418e07035b4a39936ac69772520c167ef33f576198a70bea1a3e6a4810868fffb8bf70abb870ece4fd40a2c286d65a1a768776bcdddba218f6854236270d550b0acdb1e87c0a647026b5982426dc8bfd02bbfbe5ecf33fdef0b048ee02ee85779a0ee900ad2e02300ecc774f73ec419fdd15546141233308dd4e05e0bd98aef19726d7d2749d8f316b798b87ac700de86806c0586e96d5fa35d908728d9a044cfc98d6435f5a73643ddfa896ed51671f0a76359ad302d329a7d6489c3cb77d7a563214f32cae5c3ab5a379198c36ac46ef0f151a21bb0db55720418ac16e2487ae411a37a41f7a086824b2efd39c94b3494efa7c1b708e360b380cd65c6b0300db4259152800ab8a88f85e276b32399f0746cdbfd93182863a850da4404584a8ed17f70aec3cb4412c17b854cbeb6e4ed1e94d97bf16f7b343ff7b1c0d02b11555ae20d30819e6ccccbb44b7538770c3aecbe7351ded9dff5a0a7c66c2be38a68a4f8d2cb06766b1cec3242cf191ff9ecec987893588a89b042c2034534af2f0c4e38ba3617ddd1c70bbd23365639fa7cd5f191861c7fbed74a809b4577184b74582b4774b8ddc3f186fdab84f01e0f988b74bacfe932f46aa7023309f130f7d93dc434d02fa0318a7a63dcb6fc7a8cccb8eb8452ee3c1cb6540512a78cc5ebbb671f9ad9a244567471923ff0a04fb615834380caaf01494ebc73ca0d5c640440be29f2206fae788ece44aca654e36a2ea1777e93e939111387068eae8a7ac652da78f63545288ebe0eeaa2eef9ec82ba6bacc11acc6e110d82f4a1c698336cca9cda4ce660b4873e19098521277c6167a5090ebc2df903b9e682728b4a3ba320237b20444e34f94f2c8f9d5e0173b28a2dea1a88f7e40403b113752a6f9aa0b49ca6a5c34a2b92b2d2bc5f480ee94faab28f01dc0d7ad19392060a4f0a8a95ad318982f081ab3c35895f83a6d4611d888a1a0d0a8ac62075ca703c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416aeec5145d93ca5215998b118cd43fe6f953be84cdf704bda68dec68fb14c3e6490399277cafd3b75630f0b826e2dd6d287a161cf892fbdd889e0c6b19cc0be4bb41fcd121741e20510209b0740cb89c118f190cae98339b07e65df9cc9dd126b9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712122d254e33b7c35d78ed4f76db5578f07a6c1bcb7dc46199c567c4a61f84c574fc4ed042b0f2c8397da95d7dfafa615f163ee77de3725afe64561d65a370b3430bc9746fc125c950f425b970da866f8944bf368a765eea617c7ae949c214c405a9250eaeb7dff21e3804b3656037370d9b2694a83536a4e924c9f3dedf1ba083962d04439175a2d98c3e54aba79db4b5fbc425c1ae4d759878086569d2afcba33ee7757f605a7b0d7d518a7751ffc17479ef2cdbec637e4bfb3dad4d8993a553d0ccbb191f4be4cff5ad204d9ef12e321d851b431a0487b9b00a71213f2c95a3e48a1025c18a4bb04dbe9c259e0ec5a57863699f0eb5efd7767175b02b9bebf4eda442aa4ea276a4e1cad5e196a6945f4f9feb7e434a747a9244eab3dce1ed9534262c8fbfdc245ad9dcf846980488cb4d18a79606fce942d48063f0455392e5d825f515af082f6906036c246bb7b1f3b75d1344466e45c96967f8cb73049970c100538397589fa07b331c10ff03ffcf5cac1691840ba63344882cad3a161b135fc74cd2834b4d7d555117ffd19bb23e6ce26d31a3c34bb5626688c2388f32937ea6edb9107df7695cf745e061c1c8b98f078d88f50881eda8dea89dc75b6633f1c7fb016c01016f8225393bfbb03533db594d4e1f289484f7c5eaf4babc9ff19d827a1b3dd1a3cd1ff4732a3826ac5a468c6464286aca145027df161442843522e2ea9f89b72832b1d5fe563cc115c44ce2ba0c383e5d6824f8260f9697397660eecf2766560b1c77937fcec07555c995ffa2eb97e7bed217c46cc798a407a054e3e8c342de20d821c684b2529a9260b8c75b32c9e0232f6870db100b286915baa9ddfef29ba03584ca140af25d0ae285191427484dfca3a722f8729a0c76d7fec1a9c987bfb111cc69796ebd1976ad4ebcf4b3560c1bf2662f77a10271993092016aa2a13c0e05dabd3e3754bbf0e87775ff06bdca2da1382448fbabfde07755a6313b77aea6326c8a3ce609b67aa4b2de89a10da711cc35cf593e91f701a0fa8e27969e0a4642d03481c477ea3219946b9e8b8b1271dd6fbc2da017b45d3210095667544b271eedf036d8b2ffe8d5f903ac79718d2bda2a14a9fb3cba6911012d8f0e3c51c77bd269f51b501bc3056358b894a4efd94d6f3ab31c60a2e6d42022e0b1f1daae90dcba1b96d681a018636a09bfbc8381cf40a502de14de2b67adc4b5aa9706a54c576dd1caad7fb29bdca6dbbce5cac2eb1e65d89633e3dfa60aae7bb0cc818fc18b6ffff18592e8e8671eb94ceb0c2e15b33f9f54415cc9e626a339aaedb6cdac744b85af70456c65c9025b86a7426169cda4490dc7f20d0220467f6af1ed61d0b39bd7cc4f9e94861a28fa6f27709921625b455c2a5981634b644f122be630c593c15b16fb21e9cab0fc7b0140c981652059d2310ea20e463dc56e7b203c1dbcce46929b2013bff2270b86d4951584ef7bc2472febdcca611282f3dd2a3026e65945ed13d52e629d6d6a120b1f6442b75e0b2660e0f05824ce468bd570a388c6eda0d4b98552d27b9aacca2bcdf7f90b75243f624e0181f20683e701c397f4118ddc67c11ade82127f6d66ca2b4137aa4876cf62bc50a203954cb3460a6f509b816726d7b0427c7552a24e1ad207087af15ff6e5619ec37622a69b1d98b990ab979c98b9a66995d1665017790168ae8b5dd1608ad0bf62c35c2ac54ee3c95f27faeedf474fcf1fa50ca27f2087b110a88585c255830f56048944d2868c4978492fa514359fd3ca4231f9a3b7689833643ca183622e8cd9639ead81d38d3c3ef6a38a08f0415e8f2569d4b698449bf2c5ca74346454838e92bf4ef4200963a061b35007b1a77d0b68fe244fc7a65c339aa06f8fc468150d649eee8dd05156213b4b376830067601b89c2f3ecac6db895a8078e65ff80e7d04e60ab0ec43fca15dc14d5312371e0b26d5cf58477961dbd96fcdf2b31d78c450fdaad5e9bb9248f6bb0cb58946f2e01dbe23224e6af11e5eaaa5b6d43d700a8083e97f57984a6c431796df3d153e6b310d25c37fd451bb16e2ed028aa7b09e42e10f820389a6e253f09f99692ffc4359b494a30096a3eb8a5b97c3aba02933a37cc732e055d41a2acf695dfa9d59dfd5627864efeed20c24ad2ecac463db3c12b4ae5233ea7370c02412b04da5cecbbb9154f804dc0c8e74e2ac9daca31a3b872cc38779f9c7b1a6ca93f2c4f6d04a6b0f3e699c8a40511a2e3b9fb7f8972661796817ee864c2396b7b2a9f349d959b6fae1d66ec9104ff9c942f030e65a8aa546173676eee3beca7af1636aca17582f30829782e2c9b1b9c72aaf8060563ab378657bf91d13f2dd4f1bb6adc1d6da398e1d9b2a4884c63631d46aeeac4ca7348887106b8f07b427790d1cf4a2713ad56af6e1e1629ef93edf14348535e50013d4a33f70273ba18c23050e010109645dd600bbb52809754ddeaf668a72b443d63901a6c759e4cffd958b68736a9a1ee2ebdff616811e63d43b100947549aef12a6caa34d62c1fee27f253562286a466c2b2f91a711cbfaebc527f705bc8bc7351cc7bd57d0af9f150e6466174f1da6ac71c79a2a4df82d44f585a3865f7364024c6f9a7ec7442cd32dc7566e2531fe4366ce5e22aa6931f8d2cd5f258b334011fba79242837b662646211a788b62ff54a6e9bf54761372954bc5b1503cc1b49403054b96be468c1f8b22ec177da74fc851f7562a10a49417b5b6a76168f52931be46aafc2211ceb98056a1bd1102545401d8698944771e079f3aa93974eaf9960d6bcbf23b14834f0d7034f8d5e6589e4a7f13f65e72705884ee8dcbf1360274ec269f1e31a344f8884e5ae3450628689e6356669e7a94e43ea1ac65578a8a21d8cf64b22197ab966b1a20a098fe08768b0f5e53e25c71864a657cb42ea209e757e475ac343e5f8f85b776ea6276755f5d9069447d01bf34604c0389a5a80b7687ca74dd548b3c5d98e4f70c9a85d29ddd2296fa1cb8be37e5d8701af88c70c55baf0ef059358fb8506ab8dabcb8642da7052e6493cc40a035dc86b8d5c88164976f31fc1f72c9a86eccbe29a1060e2a5b0d6abf7c452613018b69e8385b7ab509e460dbd802cd49164665229340e29a14dcadf345f493f00ebe1d829515c6528b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d5e8fcf6841f2e94ebd740f848a2b4e72c31c7a21aea6ae8917400c81d43bb522b64c2aaa0a1986e68954e4ca7b5784088392fda54f4dfbac75e454458e01583df2218fc25708efa7679c23d318c33cdbfce6be7e9125002352d34948fa8b3a67aed933b6c623a04853e8e76cab3219c59d5ed56410b366482128627181b5aa4eceec7f1352a57bf84ff4eb62099a8875cc61b06d7c3dc6094fe96948c881c60eea50f1aa4ca2c2c57af4783c613dfe8392229ee5fdf145d7506ef3d9e559246558463ea4005ea0f83e358d15a789493bea81664169d09e26df8e8e3a2361e6226a54c73b0bb645b846c9bf3c2883b4936fcd3f629f9d24086d9ce4c20cd226199884cef69623c717e7aade3c1f270584fa38cd0d9b6a56045e318ec49ba8a9615abed39d47633eeccd98be10042d5d03d852c5bd930a89f0ce256a9332521f287c5b3a221df63628851acb241908838bac9774b28721290f082f7b143e8d102756d8e06152648b0c9f937d26c08490a5752ece4b16ced9ed97d75143de35326b6e46ad517f13ce464516302d89289478f09e15905bf5d8326d95437860df2f72c0d2cc0f3c40972b07c54745de572f912a58b2bba9c42f105f09be83e69491690a5ef93a98dbe72b55880c843da199106393fa4db8a6f659207f6f419b31a678ceaadcc3330cf95892fe9ec136744640751b38026e009740867b10de8eb67f15a03477bcfddddd9319bcfa6de112cd37ab5040bc19e0b3a52f039a6ba60d2045f834a3195e89e19ae67d96b45a0bee0beb3ec45595def5f6e8fc37ba73c0515e6ade7566e5eda3fe184f22a89211634ed256471c1f3e0f3ad64717fb58cd0a44709a330f39d5e8cdb773ee71afdd2f9d57b44fa579937be3aeaa1adae3b57d047ef28d1fe4a0ee885dea9edf31e01e23e896796b8fcdecd44b4b180dc7e02617563ee5edebece3368fcbf345b930c92fca7072eceb55222b960c5f7e0fd54d58b2a296fc8053d12508a47fa99f2cbd5b7fcea38d04fb896e5421661613af2b53ae7f9cf9da7141efb199d0830298feeb364ff4ad75fad31d8e7285e6d63e4c3f149c65a859747611e99d8cb5d06bd5eb20c5121ccc64e431ffb0c6981f059d02a6924cd1ad196dfff80d76bf99383b20bee491a49cbe9a66f16ad93859533515ecaf1ce37791cdfdcdadec44734ab9a4e4d16a25f18d2e207f66037bed355c32f0b6a53e8785a5b3392bb92c3a0e904b1c0e100735390c8676dd2da11747fd6014c06cdef71226f89708e71ef9c6ab3d95def2dd7f487e42efa411f4eb05a33bd833c6d57f623b8f0c8ed846045cf44fea32bcbe0bc04e118f3922c6a45c890e469de71ef3008558f64ece794dff8660ca2d18a49e2e7b3beaf1e6c903da7e0e8af4d2400c18023b5de425d219f9efcafb72aa555fd994cf9f67ebeb5de47b6a84256e12aea7e877a8b9b5cbcc01119aa6a8e732f551d99dfa4fc239739c0c1d9c415bb13419d4c73469ba912eb7d346b91629642940f117e1aa50a09fd5dd48caa48fe936563f4a200c29d77a80f5657781f6849373684b82a029b1fa3d2c566173676ed7bb07c67c2bc80e7d5ba4623f8ef0d565d266723ec60497f0375b3bac140000000001000000020000000300000004000000140500000006000000070000000800000009000000140a0000000b0000000c0000000d0000000e000000140f0000001000000011000000120000001300000014140000001500000016000000170000001800000014190000001a0000001b0000001c0000001d000000141e0000001f0000002000000021000000220000001423000000240000002500000026000000270000001428000000290000002a0000002b0000002c000000142d0000002e0000002f0000003000000031000000143200000033000000340000003500000036000000143700000038000000390000003a0000003b000000143c0000003d0000003e0000003f0000004000000014410000004200000043000000440000004500000014460000004700000048000000490000004a000000144b0000004c0000004d0000004e0000004f000000145000000051000000520000005300000054000000145500000056000000570000005800000059000000145a0000005b0000005c0000005d0000005e000000145f0000006000000061000000620000006300000014640000006500000066000000670000006800000014690000006a0000006b0000006c0000006d000000146e0000006f0000007000000071000000720000001473000000740000007500000076000000770000001478000000790000007a0000007b0000007c000000147d0000007e0000007f0000008000000081000000148200000083000000840000008500000086000000148700000088000000890000008a0000008b000000108c0000008d0000008e0000008f000000109000000091000000920000009300000010940000009500000096000000970000001098000000990000009a0000009b000000109c0000009d0000009e0000009f00000010a0000000a1000000a2000000a300000010a4000000a5000000a6000000a700000010a8000000a9000000aa000000ab00000010ac000000ad000000ae000000af00000010b0000000b1000000b2000000b300000010b4000000b5000000b6000000b700000010b8000000b9000000ba000000bb00000010bc000000bd000000be000000bf00000010c0000000c1000000c2000000c300000010c4000000c5000000c6000000c70000002b000000000000002800000059000000020000001e000000" resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -248,3 +248,24 @@ func TestInboundHrmpMessage(t *testing.T) { require.NoError(t, err) require.Equal(t, result, common.BytesToHex(encoded)) } + +// TestCandidateEvent tests the scale encoding of a CandidateEvent +func TestCandidateEvent(t *testing.T) { + t.Parallel() + + result := "0x9001e80300002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f3282a8119a659fb3c94c3c951e5215daa35c741d13719d0be7368ca8e089537b5b3704113bf3c0d7fafa20033cad97002e9b9cad03fb998cb35cd71a9873d87a6af72afd5fa059b18e2e13eb3ac6158212b57ba060772886bf962b12034127908e54749e8014a7525ca4eb8815d1565185b31aecb38121e4347b54ccc8e49d13e2a732f9e332e0b425c741a07206c71d801011c2c0a278c87fefbf8064e0631875d1ed14e57816dde31202e999e6e24ad0f8ae2fc830bc1d325e73c3f3dcd186be8e59074c5553d8b65ed0a7034b310abd88b894263dd5869a8cf87e5ef4f0a79985e134020e8a1e2e211afcd5ac9ec6a2fd21dfb5e1c39b3b670f4415e904061adfacb103f25340b938dbfd331ba478351f9173a81134bff8a8fa1c0fe6be68e9025ea1f9f9f24e7fa5437238b01826b451001da46638f62b334300923068d1691f42d0e400b65ae90c283a08ee958a10a0e8c33eebbcb01d137f1612e39973a10489164135f64606c111f8d5d21ec2f8ae932676beda36b07e3577c7d8103c7cf2cf878ce90806617572612083635c0800000000056175726101016f5b6937ad29ad8721ba848694820840b25d91a631d2cf19f8c63ffcf1fcef260d25513fbaeb64c090d371bdba09663f2cd3bb4a8f8f7838b6620bde5c6e5905000000002000000001e90300002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f84b5c6e57a116cba4148aaad37fbfc3edc54e7728b5192a40391d9c8ef33bc405ecd07dedf12350fca80ea9faa4288186ef3dd0b40badbbc49f858a38cfde88c2bf80adf8f3282e527e242daa821b07b2972d9630b1eea6d2ffbaeb90446a8bc62a19241993b622e6321aa73a113c354958dd7266e7e2a28acde078ae276bcf7cad7aa37dace9d97c31549cc22292b650a04cfbcdc44e20c9225d499c8241735168858f1c5382ae1cbb9ece1165e63f01471338afe7714b8928ef3b2a15e6f86fb4ae217da22aa2880ae8d874d21f8852d76ce7d32554830cb82467a66658784dcc6cda49b51efbe0fd184b974074d1258ca9f15b9fccfedc35b7dee6e1ab9e9bc06de0d02e4b3871341b268751813d0fcfbdb0bbb2ec4fa9798959ab01a48dbe9029ccf0aff2230779960fcd86efb10ab9d36ee09ed20b3404b8da50f63a2f2aaeb6e43470084a5205b111c66b80cabbd010043085f5ba73c3a4e0f19105e32274bf19fab97145aca984aa0eaaa60c4528cdfb9aecfc2dba582729ad01ebf8d72ad39f1d70e0806617572612083635c080000000005617572610101ecd027c637c53ee91d7a0e98cea0e7e72f26f69415985ee9e28509aac917565522d428904e56757639946c30eb6228f11feae3bed1e1e60458922e892f89ba8c010000002100000001d00700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f605b88b35bbbc7463cd981713be480f1e7ea1d12b6c21eacf0c120126d24347f57dd8f8b64cdf03c5a171480ed3b0718ed0d2ba49ed0bc088b33c45e9f40c929db5ceb08943ef0f0cea09c1606e0822d9bf9f0a7297ac08335d13c87f28490ad2532a4846d8b951e37ed71582b2562027373adc871ec734cf1b77fd6de383cd5a2b09b240d86f318e67f5fe77e4b3714d5267699515c6696fbf7eb8d2150826f89faadb98f6b52ca914fb474ae9d10ee57c48669ebcf6568bc6c0a8833466f8174c4eaaceb528233d6b6ca4823171880f8853b0f02e6f829444f6eac27fbfaf477bb8d6c11c2ed5ee8a4e0933aa661d2e44e03dc8823cb180cb069463128a2c766b405ebd52f05687eb3288165c4808ab492750a0c0ad69f3d29134eb883cf5de9028ad5bd67ae9e27b97131608d072644251f45c38a49ed0ac3dcdfe3e6c6c9178e8620d600c955c50fe95eecec5125170c2ee7031c13b46c6c64d26278c805e74f5d98a89770c37ca072e8a11ec0adb6e178a689d285b066c93bf63444a1be78977081c6fa0806617572612083635c0800000000056175726101017a9dd3c3f5b3c34e7804b2a4e92c08a4aba153098f51229d81be212fd0345e2be37a41cbe3265e448b8afc03475e33b2b9cb762a9df3e04bcdae19af3aef0d8c020000002200000001d60700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fa23d6b412989d9b453ba20b524d14a4932218d5d20cb57529b5d8481fd9d1717c79dc1dd9fbc475efab87f98c901499443b467cb30fef5e85ffb9429b028fb69b7632d7583557ea812404498c4c544c574b43b952c0f642f208a47c837871974d324446e0b5362729c6f287ae6781da900bf67a02a0675327c8b0c4eb716d79c12dcfed6687a9e1cbf5a58b4d4c1428cddfc93b6031fe5a45441dc6a363f43676fa41104feb13bb292af09d5929eccb40b00b1ba9856a4a7727e3a82f9689c8d58eed3e4d8a61504356c2f5f230bd53ac9ad08605c6366a65ee919decea46ef17520623e2407d6c2a89b4c660b073fbbaf0418452b0959d1018293e923cc0c70ef48a7f0993dd843c38142939ccc1d8937f7600ec33f8e203529f3c0bb741bde0d1e56f9f2bbf7b0f5b44f5a8fd26c1641938379cb13bde0d422c3e5db5675964cd736a2d500e8c1d62f574c4a67bc94e0d38ce45fa94b7fd1af9dfd8c1902f34802a4f849af258f105cc555928f36e117e2efd519ee691784304be5a7c7fdfe5ba3128576150c06617572612083635c08000000000466726f6e091b01ccd9ece066c3e5c23701aef8a8d166534049e0866bc96618feb63b27516af2bfd4c90a72b83065ae02bc073d72ec49901539e3dc74b84025913b2599c392f6daf5109eae1cef4251a2652df775975fcbd3267c254655f0623cff8d48c24d3a0f935472c4b01eeb46871659e4085d8afbb3091dd6a9559d56a889ecdd239ce4cafa23ba44589f0ec8aab1726096d29ee0c9e2676cb1b26cf2da888205cbd2dfaf1d2e87536aa7ca2330a777b9a43a8523bcfd9d9f041d661c688a8c2791fa5927ffd02ac2ea36c1f3f8a3250b94398171098e4de128bcc6333d68e8de6176f3209f66cef788ef9cf9bcdfd1560c5081311c00fa0d4a4d952bfe6c879f3752f7a1015e5ecbfcf729e0713df598b79f1b7981acd0595d8bdd4cf33f3a3b4d44bfa16b0fe8275f58a908984a0cea1fa464abe66705577c82cb660ba42391739003a6ec0dfccf329c2b6d81fe7ea47987e94b00fab2444a1c34eb3e1be1a21a31b6bf0a2c01828ca4247cdff7b0769ecbe0d186ca9af743e0ab05a823ae65bfe7fe871f7d1e5e2fe06d88139bfdc57f9169ae6f869c155bf1dab7d97ddd8ed0b31e2d7b6a1097a9e0e1ebe09539865f3abdfb20d83f39cd9a9ddbe70f2264cc5cc34cdaa45942ce51e3af015302a9a25df2ddc220657322ad6b03e843c24779d4ca45cc4ee30a6830e3c82855458becde33a4481a1e0bb4a548c244b7ecb8be06c6cd182f5e7d3e39010b0cbaff53d43f3bb471e994e01e8e79fba4dee058c59c0eb2364ef45fc1371f62f14dce74c67cafe44cba43cce596b6a37b0044ca9613180029a14a77908f74613db7650b31a2176cfd2cf7ef35e680b45d72bbf45c56a4b8a6327926f708a899548f224faa0cc95e0b58066d7a526f92bf53524d25e5e25c39a9f7523576f0af291e0ae37c7cd5282b14737a46a01b52d5b0a46b7c4674fb28551d2db05d6b6bf9ca560b49911d8087a6898b672e75d9447edf4700e7935cc0899cece13496a9f53e3533ab2e2f32814e36d2162d1316497ed6112c2b8fdb36bad16f697098f1445ccc3ff6efd641cde1b90e8012eecf0c3c5a005eed41d5a312d6ddc76c78b2ddc7219bcc62dc3c2e0dd84ee7c161a2181bd844830d8a533fe8a73ccb7af3a290f1cfd0758182572b5a4b9da22f93854ae35d0b6e79f7b289253ae05ae173ade67ee65f312577e0a1623b4c14982f33db8e10ed43874de707843f49e7d186a0b3ce48f5efa449647f230eb490ce8ab38fb460ebc8b6a26b5331a0dc5224b1914fa1c9a0e98b2092769b3e46066aabe127f3866f55d56faa702b5ce9faf3fbe22ab352469f5f86719624375497b2e9142e12b3f18dbfa0d6545c7637eb25f6f0243e14a7de2a79f5a725e484bd484cf4e8af7b2ad7e781bf6d5cc72b0f14abc95a407cba0bd01c4d47e192d9eced14bc33d509313d37ac40d2abd213d3961547fec1df1ce3450f1271575684cfaaa6867d7ac9b9fa9e939267e11f1bcece14cad2c9956fb316b8e4063db5389738faa82e1cac2685c1bb14c35f2846b1fd44076df9851ff3f6043fc3824e44ec0fd70f684d2140525e37f1ca00190672cf0d3f496d917e4e63eb23cf89aec96c62e352bae3010a165807e51ee2d8e90178f9285da18ed954fde7c7614fe88015f06cd290455c05667c58cd8210dbfb528bfeb70878776e9ace349aafe5ff9340b4598bd70097f8faa9e37a9e3caa2a628e67d83117107e99257785a45c144d29e970c424a0eda79be84fb94287e56f9fb3e746da3847a56403e9618a5420e93832989fb58116d712ef4b1d2d23659682053b38d6410322a2f07444ada2aee3ef85d631e01cfaf5ed28bec9dcb2bae747f6c63e9e4a12a8814da4ec2ac713565574227d197851422b823db3f5eb669fe9ea324f0b939835b73eab6eaf8393221ce5540462b71770bbaa8b77682198e9830f75537221146d306ad07bf3f9de76cdd485a669607d9c5c8c517cbb87730b6e90a783b0f1bad7aac92ae0a0972a8424f6683c42d78400442e9271108953f1d40e0af58e8da33c1d9fc1aa77b572f0672a3020ef1465b1687381cd70e5b1ece01a7c08be69f55b1e0683c1f742dae07de6657e6e88f97b6d3314dc30e461ae492f8e3a180ba1eeecc64a856be520f8198a1c2a4e0bc6d295a2fc13d4bb81ada3553923ece3cb67047b7347ffcd13c6bae49885be17de3d478d3aa8dd2f964ec3ede11d84348f7a40015e588ef9c9a446a3699de1cbe1afa916d10356f412c32e085c3ec0115fd488d3785f9552f893bbe0b22c3773df967b7e36713177151c7c21b9b9b1b367953ab7199fb03947c31a57a94329c6edb9b6ca20d762423fefd38b1ef2ba3f179998a5a5bce656d8b5f14dff06715909d5b7a6343003bf33c0377003d680eeafe54a348cb7815e33c842eb658ffdf3151507e496343305617572610101744acd32f811aae5d80e20534e44195d03abd773156a54dc42204e7c33370702db76b09ff7448955b79a53f0ae958312e2bdaef5a6662350349ce955b8561286050000002500000001d70700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f7efb9393ca81fe0825670473a2d400ac00ad22c1f401a14bc154c5f92ad2443192f6141b3e3c8ff6efa5a85a4433a49aa88b225d64a40a6c500854222e4957243012e86d4a295ca3422a771ca745241b2ff615dc7a71758ca806b1f48525836b78e14daf47e1789603860a916feb342edb58a2b7acb095c4e93a52b987442ad39c854c794e49072f464fd7e0a418d9c7eaa790c89320f830a4919c109dd9795bd4c96ae86882d18ae5a8edbebc1be36c269313f50ee8e1ea30ad62770fe9f88ed5f6cf4e7fe30b0808f01d7b1e9571367979d1cbb8359088cf98ae22e8abab91ccfad85a4a6ce77f402b64b0f0524a831daf156f8af91f9d5d62ce4c687947c3fef1228b81636a938a7a242ad5f78aed0a218d582faa5176c28748621c0e24b9e902757eab60aabf67c35b6f64b7dfe695fa70c9213e15d0cf39dbc547924a5b2ef9f69d630014ff54af3384cb0391d00b06d7309bf0869519cba60f2bc41be171ed2f372f3e1b71a4f5d6958d3b1fd4e43f3173218aa9092f05bac9e7f4cdd4ec490f4d177a0806617572612083635c080000000005617572610101fab1ead14c7c2cff2e1f1ba2f2c0fad3d5a5d5b6c3cfde4e88dde08d978dfa1da06bcb5daedc8e960b11f9012473e7c237b5864609cacc9b4fe9832785864b83060000002600000001d80700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fe4bd11531d6789a4478dbf7a36a3c7d23b58c5a1debdc455e1fbaf1b5b2ab412ec6a464b90ff6ada8a89e3f8d180e74e293a8b2f01c8499ddb1e994293c4c0d0779b68a85a99a3e2d4e0a792e1537c07b3a56fc0a637f1db059d9c2755625b778096d82240cfa6f9fe0dd38b9e597504a42e58cbeb7919c789a917450ee00e73fc355482abce20f5b06ae119b1a9ee79866d5b4854a389550c9d9580a0c0332260e7a1a1b7d1ec159e23065c342070603750ab953543978b4c8f018b2565948ff775ceffb1e33fabccc1c2c6ed03cc463645aa63019a0e9a8aae015cc11c6c4d370085df65a76eb880baf100b4c7401d011a1fa1648876798a747f9aa372d114a81db419e0c739689abf0882f2dc771d2b3f247cad2cff8b1630840b4892b8d5e902dd6b8d78a9a6e1651c21c2928db2b305d78290e51cfbb807ffbf93ceb6b1696b1e0d4200471f7d3b2dbab4c04349ddd829a29c58d75f91bdf56534369705c46523b29229840f9bf10916cad670f0d3727bd747cd737bfcc525bf923632dc5957c032aa800806617572612083635c080000000005617572610101164bf5fff13882bf1a85e593295939d26115f85d9539faff0d76d7be8b7eaa59ea1f86566b58362a71c19076c5ed65d72cb79994091851bd8811193bda730b8d070000002700000001db0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0c743a94cd1707ad4117ab058e336425f029d591d3a0d48e895c732013c7085053dc502546f00302e84fc41e74a7a310c556481c76ff18fc1bbb97c457866b972dc5d56deb74248c917228b08ea5774022ad965420fb4130a53edd44dbe883c91beac7ff23003ff41339e09470ba672bd4b9de9d51aa32ea9c4ca080c6f1f9820e698a3c6c6ffa8523ffd01d125f46795c6cc3c4047c60b36f44d1e89ee037319344d5b89f31dc79f5db9e5aca9ad7925ee5b750c1a78ce34ce503d4fa4f0d8dc38992403757e8242f70fa6e3898ee68b82eedcf933db38e0adfd352a1b6671ec7691f79817eeba28caf545200d0e9df486d47af1c5ac79ddd05aac62546f6f8723aa1c622a8d4a7757a130d4c7a24e2928acd073b425bab04c5e960b4ce22f7e9028813af0548dbba39f8e667b2679069aadf411ad3a194a5ca50253221be0784058e668c006cb6f4c83ba533b775447a77060f2a2fc873d79045329954a814221b7b6d52b96a216e614a1e963366a98b3e4fcb728ef8c2265b2a6a0b9fcce0ecaa41f094a00806617572612083635c080000000005617572610101d8d56b387d8b2b434c1c4d2186a48765e9ee91a39b214c4808eeb9f3461351196740631854c04bcda5980e50b7cb759df2f64ceae11f6f321ed05f8e6323aa80080000002800000001dc0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f08fc371c2ce887eb3e132908c4dd533583177847b8434f5c7c0cfabd4852c24e6c7ae7aea674dd4bf6796cdc2d337782f885482bce24c9030e87b11bca54d7f5e50b6d38ff0fb29a9e76bdfe49f6f82140d112c80a357002c99a8941a08ec62190d3eda2b3ccfeed95db0ab62327db71f640621d80c753b4e69db9868dedfa7da60ce0b09e321b053d10dff1b04e435472170d760c41282be74154810f277b1360cc17225d667bf15fb35266c8cab27968b58813ea1ce41baede882d43bc1d83e973614a3dea1a30b67783af1e57f732e89eba9958b0fcb19fee08f9a3314eb9b44a574641d090ec0cf776b81af6ac92015443353b22a7db67f42bc7347a67aa8f846aa19dcdaf075ea1af3c7f1b0f66b33bf8505b7e94862bcc0c4f6e9eeabe890371dcb58c1c4fb0f5cad90c3ca6f598d596f8e47005536da04f424868b9963e9256e1d2002610491cd018b9dc0c88d6c9790b14b4b866b6e0600feffdc0c94c667a68c14f2264ecd4a757b0f14bf0b6d9ba93cb7e2e949191c86ee32c5402d158b85fadaf0c06617572612083635c08000000000466726f6e88016d1ffba7d4ede2a4c73b3740c4a775da3a0a1fb08e3b989ec5e49684d663be2700056175726101015adb821043ece09a08d82ae2cef89f37d7ca8f4f9350efeedc12db5884a0016763c60aa38c1abfccacd5f9ba16c4a8ab93f6b9177479100d0b6c975015a82280090000002900000001dd0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fca221b74c8d32fa6a45bdc2271371109a97cdbe2c82fcbe452c548874b7dc1665af5692ca9a27a9d2c2f55affabdaa466fd435945f091b45944e0f0596984b664b7f5bee6c782d18ae489b645be2afffac110bc7bd97840260a807550ee056ca22a4b9f9c32f4c502ebe462083ec11fa689a7f3fd948fad1e3cb5ebdeb4737c7ce6a2e873ae8e530de6065dda3890084d568507ca5d9a69df19683805bf5d24ddf938c7c9decbab422bd00c4757dfe18489bff7e017b40ad9552871b9a7be88a4e315ffb734e34f9c25170faa579eebc5b74caa8cac8b1b87827e84055b256d35c644799d29d2e6f4f2c065ca606744598719d85f8c3e7c4d39abc3ea59be4a35ba689f6c0af4bcf5988a4580840e313618deb3b835c4e4a78cc56434b2ed6e6e90231a890359de5d57ef9864cf19f3a48c1fd1a63812b0765661c598856f956177cb62e8900830038feac3e62aff1f1333ad0ee8696a4558f6cc42b876e0603d703ab0d7f0eea80b0973cfd2d3a59268bf68211e1bc014bd94fd917b6e9475c3a78508c03fc0806617572612083635c080000000005617572610101b86bda32f157f1e933143a934f6505a6690c0a31dc52bda5f49d40e5e26073545851c15949664b7f55b8cb2163a3caf7f487d8b4cc87752aa3b4f40638c2ed850a0000002a00000001e30700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fac991d1eb1203b3ac74ce441fa62e97c8d7b99628a85cdab3806bc68ec92131490b0d19498a2d0ec54c48572abadcde6a5a2aa9ed3ab74314fb4dabe30ba6408d4894734e270af31d21c80c4e9e3fd540899669aed2f9bc7fe28891bc0fa6ff9a58ebfa37a19b1e8479d3d41c7b78204d9719c8ad1212ef0bae7f2cb82746ddb6816850f2467e875176ce398d1607d13d2f458526126a222d47f10c13396eb069577928443d3ca93d4582e1291c0c7caa7bef8c1f39c9863385e472ff1e9b38d85bafb3d2fe2ca2354c2fd1fd197b36bcff57292ec4e7b8ffba280227b13aa0247ba47d4824fd30328f70f64b056d4e36e3b75594d6f590e1b85e90a65f9a63ad6d42232ebb0628b11aa6a5bc31c1b8ac45f683b0290b14ea725b2b53ec8017ee90265f1561c96e26a3ac239745a0746ae6fac255bbc9a19aca4765900819e7a532c12d1760059118acf89d6a62c0f724e283081c8bcfd74a1db5435983c6cb67272699024dcc1f7c4089088d1fd7a4ece328c3611ab9219a8e0f43240841673317a5d3932a90806617572612083635c080000000005617572610101eccee865e2c48f93bf2d1ef99bf22549e3994e74b2f91cd00e742be73173cc40e5518cd480b62778a627e15268c8439cde21a27eb24fe0386645a5b11430c1820b0000000000000001ea0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0cd0c3ce103900b501fc82da6f8999bfd42354f8fc4db6230a764b7926c75118d570816caa86a63f7fdf4d0e0cae604060a1ca4d53a6bc0aeda87d1f5c28918b5f8233fecb446796519206c3b97eddddf86237cadeded98b041ef6ff4e474e53287a1697c8caf461dd58930f749d53af8832c488780a012590b005c36eda0d6e16c775b8eb42663d5517b3e9cc198e9658421ae7af2a76706d64e3324ce39240a32fc27041caffa0ead9c0064ae0ace86242f8074273018316dca50bc96a978da3883c3993b1a32b26325ff85be0b63084960a8b50132433176fdfb5c6ffc07bad1936428467f481ac53e71165512663839cf61457fba5ff17ed63e71b8c717680a10e1f33cda8f8d81c50c91152776a54b50195d6ec7f0d4bda452f9ac73012e902dc413d61ee372b7bc1305b79f10d3644a42c88cca1c4c8539760bdcced3d8c2b16819f00b2faf4d0fcf22d03a7cd76920487eeffed5b599f6cd32ccc9a64801fea2aa079feff2af002f0a71bd1fac90e9fea3a0573a5bfa2765a3a931bb5b8d55c9717290806617572612083635c08000000000561757261010166e2910c9513e1dbd2a6d3f938cd6a6253fbb2cfcf6a1f6cd76a8b7941b07b36824ead10eb5d99188c749988b49b9bb673571fac8b9317235b89b8d443a5fa860d0000000200000001f00700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0e4c8eb3dc54e5c0d1b9402f44f89137c1c2d095bed90ecbb80e38c5cf245c4828efb3599bef57b84619255f76f0aa168ba42a0c7d3a7e519bcaa784bf0c66e38b0a4168467cc53f93902feb5d97440405d82d672f86e440c362301c6283263fe870ecde7baa2895003dec3d07836c095ae4f3e4a05347dbd7d7c4eee1f811e18628cc961b32b53e4cdd3a60be566fd3ab6a686041c07a8d4750133047a6907232365380453504c52c6b96438fdabd2d972e3dfe6bd1e9bf0f254bdc07583e80acfe461dc363714109b6e04784803614ee2b00967cb51eb899327193cf485260130b0b9ac802b3db074f304ddc428950e80ee3e2a14d9f009d8376fdff493b7da24d7edadba1d6f9a8bd642f426851bab186b7aae7eb8fe526b05e362b996704e9028625ec7da0150afcd6c1431ed2e8b56be1dfdbbbcc7e3eef1275b5bcdcf5f4091622a20013b839aa611349e4450391abb30a5e0bf166d201351ff2eeb43d5057714a5b6c959ed33b8bae5fa99ba5d0154e08ce851e94502c8cd069c78c0a0d748ba782160806617572612083635c08000000000561757261010112e21a778c7c5404d9cf20fb4ecfe2c06b14e3e5ce45c76619077a2d47920b5e2d605528db37f2d4724f811429bb3bd308c9a20ac0d05b91329bb6b49b3f5a80110000000600000001f20700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fa6703abcf0fc554a4cec1cb5677c287f06e3bfc3f74bbab462dcc1062c88ce353939f9e6aaad990f2c9837dafd9f5a22c17455389a73f05570a74aed86a63b1ca65a09155dcea6eb1d458cc292968124a0f9b2bf125cb797ab96086dd3ed40da478e5401533e30c628939b081e4e383a28a6890ff949d27913939b7bf5d9c4dc0419a23af2d8a14090a06412179f31a575a917c04973f1f645d777e5ec48c938ad24670905b57cb5e29d8e2b285fd25778a69930cb1e71a366be9594f58c1a80322a31962e767ce5d6aed172950bf0d2ace5df6050df675a4e6a58a4c308372d89fd8d101e7dc06f0ee9a515dd338f2d29098485ffa2c2eff98c6bcdb6805b483ebfb1a48db52c4f8bc5cd264c2746ab4034bad57e11be369e459fdda1bc9810e9025375b7d9d546b18adc6ed91373ba5ca0a1e0e2549458ed06d4a9ff337dc4b7f11a9e9700a5ac8cecafd414c670faa4c56cc84c1efdfbdd63620fb2afb77983d5bf004a11177c31f7cac28712d992f31156ff0627678961f8ac57d3a41afede86cb1e31d30806617572612083635c080000000005617572610101e8bc4a1acbda300bdc4da4c20caa87ec14e7d91c04718c20d677ba82a2adf422e72d52c66fdfa17eb1fa426428ea9f015f8ec3b4dafe3b59e9062f0e8a4e3580120000000700000001f30700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f12528c5a9d2d33f06fe0197fd72642634a924caa92f954c84d0b30a5af9f621282ef2d609cd65387717749105fc4e7266cc29d8fa13accb72282526ac1e28f285f18f4e449efb717850369313139477445e5f16e58c14d5fb079d1e95a4c15f9bb6baaef2e82cfb97712dcbcef475efdca635371ff35d5e300090491f05aab135cfff964324889a26d9a999c5644bfab36a5f2b900df8dd33260f70ff4685c212d423273981adabcb2d89ab22068042fda0beb26bffb730348f31d3d739eef8ec6b6f7e799362b07a29726bde1d02cd6fd231852f6d0df84695832f70b69df9f724160bbde1c8a99b1f8014f200f6752e90265361f4c1e55a576e58a0a1ada06c73c69f77b4076a93404329f96cc0d9fa7ff77bfd5e457f1caf71688c95cbef6e9022b8b83e8888c042d9e2f0fb1a9bbc456a8b07a9572f1e4fafdc8d699438a9bb296be96007d6837a96593348603378036a8638aa191f7164617e732af28d26929f83245736740228224f3d42f71eafba39c8f4faa94a01a589f51929cdee85a28b7895f760806617572612083635c080000000005617572610101a2f595ba846acda337e0a6891b3f517de907a15ae96920676e7aa300c603d903091eb30a8613fa54a684f1aa488272ebce844a5f9c44a0c56990c60f6149e882130000000800000001f50700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fba252d10741845a93492f9ad5fcb431e93c51be0f71ea6a8bd164093d4fc9f06df0b8c4567e4808dbbde228cad475e6060a923c214a5c4636f556eb42a7a4ba91f04569f398c5b44d0aa5cb46a0e95f958b5a3e8352da4092daab9cd8c4859bfcfd415dec6748a823e1141a8ea36b283cf6384420f9bfb21b22579a580402394ecccae790c40a892f3417def8c361ff5a86b33779c74316c77c548c4612fb838c362ebc4332cf2a926e56af72339da43cf00bfcf190ab013df11fc575919858136699ab86fbca58f8f5aed50b70c125329af294571a4e1172e3d25b8d1c0894079c48d94b4f1140f83e68d0517db11f4d29ed81a93ba725c0516ef4d81f2543579a1430ae725802df267fe527b925ac709ea5f238c6b87cfbe7ecaf751855e688903d303d17a8af293a6d14b5f06dd6ace4d5a465ebc84d372da88b1d00fba851237864c8b00f9c1ba4d0f26ecb08528e3c156de07ee51cdbf6fe50c332a727d46f303f688f8ef451f0175c1f5902c4200a374026f4e1b73706cf03f33dc1a1a2fc0877346cb0c06617572612083635c08000000000466726f6e88014968c2fd312c9100837a25718581fa2438136bfce75918d9974e85bab2d26a6300056175726101017a5c5bd08201a067464db34a431fdd575008542f500582eb799c010c99c28f325a1092ab8501da0a0e9dcb07dc7eb849c6ade998b512282ce5786fe3b84d168c140000000900000001f70700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fe0b5632409e78aba11d0d559c96acff0247194879afad0741ae3848f61e74a02397ee4075a31cdfdf00c080c5ae192e9a8921bf216eec48cd06a0ec54f3728e627e68a325aa980ab408e110b842221f262f65fb9c9ff3bf2526d7a454e1f5bb31c4957f9abac96eaee0b0e4592b60fc6abf498f2b216099590c593fd2d6956525001477ea73bc4f27bbf93246c8ed89995f7e69d9e003c4b80bafac51cba1b7a8669945a41c3693a006a1cb8a9000b443f45cc4db5b1ccdb50ea7c8d7330768b445c9a763b1e6309dbc77d14e1e27ddb362cce7ef9e4023660b6db4e520bde91088b3f2153fdc8dedb22d5984ca5773ab7e794d3a9a6f700d1fdac1e54ca83a9455b24f78b25d8dc601e67cb9c1a60ea2e7e907576b4579a091566ce062d7b9fe90294e33d043375a9630b8b43a8176a4b8620e3341e1e22e9ea344ca3bc8b6d989e86ea5900c0bac6b93a608c8ed70554e38d2a513b20072d9f2556008e9cd917066c54e371326902973308c86b18c426b4dfe19c571cd158847f719b5b23daead339f4889a0806617572612083635c0800000000056175726101018a4d75e4d4af8ea9dcd1ee5c8d18659be74f9e3dd4af5312f566705f7fe08f03b6453775880c2d6cc9552f0c99462de4845de92be70ec21d537143377fbf4e8b150000000a00000001f80700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f30cd84fed2904f8f55b7c41d0638af65a209ed81abf76645862f999e1900273d800e3bae3d3c043d319ff1b86f66954e336dfb77f4f62e2cba632ca321a19edf3f600c334e02e5f6ffb1b0a482e3d1ff6e8da744cb98ff90f4e32f87f038cc682462c29e53670de6368795f8e42b58b565b4b0edaee2dab8a1b9e7f2c5b485b4ece9de94fb93817787e0a41ec5703599be3d47882754fd9de578996f9c23f441060bc13cea84d987edb6859731738ee0046151a27ca5d150d89d09dfc33c7b8ba56677abec76be5329edd0100932d6ad28aa84ec94ee0f38fa28dcd7428370186c113fd2ca1d93c9c59e2047eea8b9d0c6d52e15c73398d58433ecaf2c85274ccdc35e3d74de2af6b8b3a2af12ca02f9f14c0a168519ed83cce058a4409204c5e9023d756ae602b1db65712f5c037388b6162cc31b73268aff4572f0b02f706d67145aa38d009ee4491a3c7e2d63f2f2bdc16c70244435ca7f4b86b282a82aec767fac5f02f7489304e192850975b4acfbd1825ee836b803947e5704b6dd1ff7c59c44adaf950806617572612083635c080000000005617572610101d8fd11466fd2a4ea198104ce9c2d273b49e32dcac2900be2313085c941ef415464e0f1fbd3431900521af212814b266900a8a95d2ba9fd74db69092891ef1681160000000b00000001fe0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f007a3643f15ab58061fe650dddb783e26ac918157f6414ceafa7027500721f43b043862b71d1dd71242ecaaeccbfb79a5d742557eb7ea49c6f6c9f8a4d0f3057c7b4ea49c745843988fc3e575d3afe2433ae789f87be82d6aaca8f8eca674e4c2c7d5e2ea06f6b1768ca7fd09ae4f4b40866331a4da0cde2d5092394f50c7f58500047700c9e0db25489c6f932e40c357e945914ee47ca84666410e7d5f4320731aa082085acca46517147f2925244a62cf6cdc12e0d1dba722ac51ebc034988c2d2ba2d6a33d8c373a69d92f154d8b404c16f73fa872a864488126f84d3168b3f0f212826e2b9c0c9e49fcdd3d099bf3ef8d93b11c71abd2601da09acf1f8fb139a332d9a5601f727c537d8edba21117d7be408a87d6b9279dad0d31da1dea289033d2444574e1a1ea77abf1d1183b53dd83993c39fe1c82e21a2c331e84673c2d10e7e0400e6bc71df504d3496437a3c4851298d686579cdcd6a0eb507d3bb3807b10b483abda468fe3b2e3f5c42ee4223b991b3a15f0f52c7e847691a692c36791391980d0c06617572612083635c08000000000466726f6e880127856dcce783370e0f2f8d245e6962e65da80ac30e97fb2fbe2fed1b290f77910005617572610101e6ee0eb043a6b5ef5dd2060a1280d0c51cb63c1cdd386c77f1b03fbfea95741e8e4f7f250c9e031120c116a69f5091690ac472b19bc082d2b8955711c28d508d180000000d00000001000800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f4c31488e9125c86f7c78b1174f11bc54e10e24d63b075bf9edb77d7a521b8a7c72aa802d70982fe9261673dfbde97a4e0085892f7e826784a62e974449168d280cc6780f3f88b07267c5bd28035c1ea8d3c7d57bd46c7aea9f3686d5dcbf0e5cd67ae5a926a93a34221dfa7965bb1bf5bdfe550eb4302b952a19747373223929defaaaac2a4312b976551770dd90b277a0fea279f4e133172053e186276ea502a4c071f88e10a9fea38468083ada172cf4c4b71fb676cc911d061b1182557483e9bf72a5cb0332c44eb9f1c9e7621ad6edb850cea38d14550d91a326c4501a9201ed82c8a883f444d0300947104879b646d005468d5cf853725170f9b358bd5ad59c197ab76485206c59f36a6036994dc543aa252b11a3c056814311d27f1404e9024f2df319184d0dfbb1db4f4259dd717a98a856adc2a8c8912efcc98fdf4abdfa2e002d00399fa53f7c1f185d8427c874a8f23b13afc475e5cee1f760d46974e71a54ccb2d353e4aa9bb6d3b4a641c9472a2faefe5adac9bd04b36beefb4168050b77a7f70806617572612083635c08000000000561757261010132730fe531d29230b22a9a0935ef83d80e40aff7efd8db34ce12604e23492d3ca79135c8bd2a4df2849c018629b7aa544222db8ad821d0f04720ee11e255a48c190000000e00000001030800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f48c1b5e26d4c749374e8f69ead4a5b953951cafcbc541903b9ff0496ce82796005d8114aa42d92f25e4aab90e7c0e5bcaf8e0b27364123b0a0442634aa351e0df5c0abdb50c18e3c20d85c1c0d85ffe9fc4b3d2fa6334a888f89fda67fd34125075303600635530959cfa99e3dab3e4e48746930e6c4b416c857d7974b5dfd703c0ad6dcc383bf87f8204dd9c4204e7586a5048bf43854682d5e6753e824c0358e2e245bd9ffa05c64f572f7ff97753222ace44ed6d7599503a4d5b0bb4674819ade986462caf64eb706b9dc9cac0f23d5a9ac8784f067d43663b936525e949c99823eaf56a8d5abc4a8efb4cdcf6f72330a94b423b765fb0267f6be2fd343d2e68724dfd57dc416a9e429bfea4c4265c30f8f3420f1dc6e7ee002b7d73edf0de9027005ab65c401c5eaafe10bac663bad41901d29b6303401251affd054103b251c22b24400e801ed65820b0cd6e8deebbac787b371c89060775a0decfc2a7112b01c51ef7c1e616da83f89c8305d421b535e08d1b33570743958df7c712c4adf9c96cddd330806617572612083635c08000000000561757261010146354b89f12715e609b5e0a272b1e790070fae3c06593211bcb1fc0c40d9806fa21be4cec44a86a847982f6598f92ea1895acbebe39ee857012ef88fc80eb9891a0000000f000000010a0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fc00ba151fa23caf3a11590fe480f8713e26df35213521f26010a50d2da4d7c7356448cf00a57c405a2759052775a9ab72ef3975fbbfaa8c972b777958774db6c053837856a44c2ba69cb62bb627f28404b1de1f564f254f1a9b3d34d5b698f697ca16b1f5bb61e5b6cbbc9414a5bf0621ed419b43cc72ec90edd901a648d92f0b65504c69ee4a2793b9566effe4685816cc9e9b5afbeb574617a44181f56f84e9485fd594e5a541005820e3fbdaed7713dcedd4ba1c39ee31e386cdab27ea68b95d5c4474278dcea31832321ab93eb6b9d8f2cb5fb75a8e03cbcfba0dc6d495a900f07dfc7cfa4567f2f8ee94fb18793c79d46f233331913516c82a8ea379095c06172eb64373f8e6e622f61cc963278de4558aebbfcef14e1146d85964197e89501ef226b220d0a9f3ce159cd9fe3ce808391b3b90055c3960918277984e45f4c249e9a01006070e574c692886332a9cdfdd2bdbd972889c16e16354f1e470e52bf36db81d2bc7851c7622decd220c83b3668e028145434255ec44cd50cef9c25e5b868e92c001f0000001400000001260800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fead4b15c40389b68b80da252f1c64ccdff8b7deda378cad3bc2040df93bc0b5e7252eaa94a54db1b10710b81df91791d58a801e17ac7e6c5be9558f6ddbd3c555b19f587cb3e1436049a1e54564e1539f558a5641e3822542ef04a8029f6c03c7cb08847b3ec399f336d9532afb4a312db3b0226c3e740d12b274eb378aec9f87c169bc67da0715fb92c783b5b8fa646489179f8bf7e4a4271fa7d6edee05e74605c69aee2333339e8a08abafeb357a0281a206a64d184dceec971d6d55f248b741ed705f509eb20a558dd1772cd34ff1359d80a4c176982169f7a7f44e8250f9027b2b9d48451380121cdfc5a041491c3fb5eefc07009d1aee921df7a0599bc01034b5e0124a5042e25c42f67aa1303afd59571d83ea865eb1a3aee512467d6e9025befd6bf43197109f64511896b4ab95b2bd221e6810459242b4053c8284686e822d3e200a8f49a3d18ac36932f3608c00c7e004147b3868fdb6d9fa0d431f2ac5c180bbff6f0a28f55b64489087c1e2e91989c0b886fa55e5ca22989fec8626754b531320806617572612083635c0800000000056175726101016c40c4eb4eba5a7917edb38b4813bd5160442f44c16f743b1ab83fbca0aab837686b92638dc57ff1280973721c79102295a43260c4dcd93a6b6dea614077ff812000000015000000012b0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f7ec2f69737ac6304d9b45fc7bdad23a6e8b6b8c35c77226a9270a105205d5816f8f871b0e0903970117dac29c057cd2d5090f7381019703f20ef82e38de9484d4487ceaa35c2b85da43887dd27238c4a77a28d76326c0bb44244f2fd51fa8ec2298c0bd4ee975e581149da8c6b891bb511a5ae7f5b1794b58a133adba5beb7a75ec607a812b0ef58815e341279396158ae4d5234e03f750c7039bbf2b8b31c2ec4e675c6f7dd170b2fb31de633e340a39fba599e45cc13275825f7c505bc8088f059c6fb23e2e6148346053ee02154cfb8f1eae02f04419e59d9e23ec672d96610883519517ecee74ee2ca4c3a7d47ce8dea260ccfa1542ec8255ba9eca949a06f1c283dba5bef677dbbbe5b25fe5171ac3f48bebf64747f70bb7f689c57ecade90254ea986a37d66353e404a2f75415fe3470a1b41fd447a220d33953b9284c16d83ea543000d8737c8c55fcd4c37ab87b7558e052dfaeacdd7cb168de9064e583276e1a7046e68b68199397af29e1c83f02e4083890c222e4da2b762463e62a870cb327adb0806617572612083635c080000000005617572610101e6ab5f369c205dfda284a6744f7a74a83d94369526a4126c20161c5d273c81053f65482be2ac6e762d95a8a5f0e0474385b10e52bcff0b4e2116d9128108c6892200000017000000012c0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f8eabe2f87cf524db949c7ce4a300c9943d5ce7cb61eaf056407256614567cf6808599ad0612f70b2011e286f46bb6499e08a50a483fd8f6dd0af19e1596945f877d87e4f34c7c2a362ad3ab7860336ef91c50037eb839a57418f6989b347c701e0b8c7d6d75a732aaa50c303c7c411e87bbb8479f3afc1e31fd7713002d275bb7a0ca5e2cb228b6e38d1806487741429d1dc70ee946a51c3ba3285432ccd0b3dd07663c15018b3931889fc09646632be942a7ec9e4764e9aaeb031663f6fc380401dfb396fe48d83b1d0d25eab92e1dcbc61365db4fc2178436ef2b7b9ab29b50cf12be580eb72539ac227b4fe392c8868b2feb21de9067224d77fae5f6769e46c526f8430531d3b87d1abd12f8df54b0fe7d2e5c6c68c7d45c88eb6a8266ad24903339562159a30ba82f5e54db05cfcf1b517c911492234e3698b3a25410f07a55beee0af0018bc9c144df2b89cf89269120ac2db451dca153e63509b970e86778f340bab743fa69abcba4b75ffe19442f27b7522589c8dca513b1bbfa2ceb2dea2358fefb908066e6d62738088197ec695687b3c54268b18d071a0ebb4323e84179ba664894124beefc56f52056e6d627301016609447513272ebcb0271154883e924a6165a990dbe10ac8f63c33dd71124432c2bb3550926a2c1edf8d3f392c22046af6f1e86347864de3465660969b55a3832300000018000000012d0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f66064f3465604d64246bf810b9fe8e49a1cf470be7263b11a699edc83a9f352d4c87742fc24e8aeb858e82d633c5d21aaf645efce69123d14a5bf10cf2e87b829b622d5143362571270ca3f4f451bda43be9f870145afb34e3c3a25c97960a255c35ea9c5f11d8b5b87d7eca9b38db17bba211193fcb4df872dc755078e4bdf096a0b786e3efadc128eba8062eb163b018b1763689f1765872b64a88a4c3103c4796565257c6f24d0ee68e26627947ae8d033d2dbabd19d2f6796fab2a3488814af90dc6120f52e8b176ec45828b93ab9ed570537cb311f3006eb17a4b04add9aaf8b111859be1b3d33934ee9bc8a6fdc2bd674f5236099d42bf469cae8e9dde924db656504ab1637673c75be1d51e171906c6e8c12c51a06f6f89e712f7fa19e902f00e5727bb4eb555d4a4f5140b82f4d72ded6eff3506cef9f2eb8b57e36d13f732d41c00310b800ce61efabc623f074c2f728d6c7c2cfbd7c2be565b5bc4943a7a3bb2794ce3e5a2cae2afbc804926c92b104ba1e8eebb2fae209f6b244ced22de968a4e0806617572612083635c080000000005617572610101e81f196b8d3114ddeaf9eaf15d34be8e9ff43db5e25d1aad1774d6a819da913919f6f0b6a16dd668e2880547df0716338b7d0a8bf27203dd8b8d03c90adea88f2400000019000000012e0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f723e5619fa775cfa0b85ed1f73557d87bfaf34c269c00141e20a8e4fede6c76c8148b38f39593ea9b1d336460e35f225c624104259c9e8338b6f7f74322dd1b8e18091df02039f421e89714802f6be2f2652d714893299798f6f059c5a37dda0fba4bcfd13dbee90229d0771f973af9995468146472ac6aeb912116b4d8bb5ea147bfe6f234a1d1f7bc9d4f10656648269075b7268ae6a243a1a745c7c85f077f2a0fc35b52911a0984a7d2d8641e25952ec16186995a251213ce8c932d3008a05530d6923ca084b8837f15cc4d4dc0bb3c63a1921fa15ec9556ae3ff9d359b1647a0094fc9493f16cf2deb282b73f53985acb3177cfcec28a6f455ef0b43a6eddd7bbebc1214a12baf9cc2bd7a46fbc1e5204d6c192fab5db3fb53c0304c3a6e902acc812718e754faa8f3b4979311ce24e7a9510bbc1160e124e881180d6f678c2debb20001d57ebbdc54d39ebc6c72bda6004b766154578ed841d357151fe9f7b7d80c42d43197f6f6983c8e53d10ce0384d8830a6f1b2121958dab34edff2a7849253d620806617572612083635c0800000000056175726101017e927e09f71f3a2af25d161aff972a98f588d4f42f84a28d295488cc2ebbe024223147f58a7afc121215ee03e9300d5e11058ae1e7f0e80f675967c1367e8e8b250000001a00000001350800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f1c3964b2c71a0c5fb5c51687909a83cbaa4e94b907d2518bad392fc9a5a7ab7fe35190789786820fddab97684b50b4e8ce0f3595106ab256593fb1cae9ec8c9656a2f0d8e332d511e9b80f31f01eb57248a1a68fc87f8745b71b7d3c8f81982981df3189ee192b2a32bbd331fe28d70851d1d41462957f232206c470fe7c8e0be6133da394c2bb60467b7764e7648794626315f4f2ca7028fe235b0e9b47c33a974fd23cace0213c08cb20565b61ca4bcb3c0e5cdd4a20cf290b0e58d814688d0f34ff3fc478732698c85d8ddf6d0b5bd428df77b267a77999f6ab24b9728458cffa7727cd0ea5c03a212dabe51c377dbd53f0e7f0a1ddb79033fb3d7b73c1db5558455d3b6442a3da1f7827a645952460ccc5c3dd691bcae64a2d2668fe0097e9020425014b3839b51b99be80baa9dbf1a3ef01662a7ea51d6cb2da23814ae835357270a9006870fd9e022c9ac5b4de06bc198a481ae60f3909b8affe519a6c04ffed18438f3c163fa7c3cc25faf40c18eae7c40dbd5a27625fdc6646dce86a5773b6ab6d6b0806617572612083635c0800000000056175726101018c3417489b99706c04255a8b8648f2d6b6c701576dfd25ecd1de9d3b1e0cce4970616567b06ab1190b95a95572d61a4ae637ddbf7bf13bf648af9be585166785270000001c00000001050d00002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f54de495b57c7c3505c62633f1ac3a2f22be74ed497a5884379e0821607d9173beb5dd269e10d71dc754ce3fac591364afce61b007925730544bf530068087c7d38e3e2cd8bdf7fef72ad23b076e0620ab5d97d3c0a98207dd8b6af8c3becff696cd2c59aefd1a3bd654df00febe502e9f6ba788b8584c7278c47a2983fd8e87bcea2f2c3fdf7cfe328e695f1a111ef699739c5054adcfd40969c673b39080e4dfa869839757fab6bf946cf5695e1a0d9335ad95e445cd5fe9988a1c82fb53c83fedc8cf6b2555199ecc95e7092742c5959f96bce04becaebfd9266f7642c23d76e25771c2505f549b5af7734c84213bd1fd39278fa8f07298ba69da55a5c70899ece96d300d33d733840cfd4035249b50618e4e81f1cd425bd304b0cffc13b8ee902e66008704ade0c28fa58a8abc788e7b1c3ef78710408947dd4fb2f400effb2344a581900c5c07c6729c92d2b6d2dd7b5e6a05c26adc79e138d57c1b74a2d42ff7c021eb3f127490b8eef8e2c1cff1b685fc398f2dfeef4554328f288259cd9de2280e3200806617572612083635c0800000000056175726101017e7b7d496aef40f4e44a8819b2652fe2d64d286288f21f25a08b31f937d82c7ad7a48673092c23d7a2aa5cb2ca8dead00a2ace14361537ef7f338dc51f34bb842a0000001f00000000d207000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43216af2664480544590bc51a68be4ab955ba1e9d66544fb5ddd87455187539e427c0f0596d61ef285c22dc8d3e2f29bcfa542b00f0474045735c327e32b81a1e7fb4856020ebb9fb922899fe872508d3105d22f9749a0ed5cd6a2ee894140e1bc46ea832c2ab3e85936053ce6b203eb5396a696dc8d4977092004738ed02c4f5504a932e236c018a5ffcb5f0bed02fc84ee8a1d18fc7e02bd2550ea4606e043e4e6018a6818a0dc0acfb0e5ea67880a8e20dc6ef1f7399658c2fd4a7603eac9085a5574ce91797bfb2df82d4939ddd9f8aff952e1ce48b1d261c97088dcd5c86e532283647ac87830d1b136bce5fe3bad5acba67add2a89f005497d93fac9e5d2088e825d7969dad2cc6c04f8c4a6e65b5002877aaf6b7c32d0943efe5e127824089032a6b0cfbd22318888f75e0f1d6fd92d22de5cd8fb974579b68a848ee1a394979c675d0000e427f6dd8407605cc5ecb040ad322f127d040c84616ed6f41af284720d7c4e289ca21a7e551c98bed636f70900a463ebd20ae087491f8cab4b90668e7b3bc3c0c06617572612007c7b810000000000466726f6e8801b1adac139bde159ecba683741d3ecc31221e98eab5a429f3bb3f38c553018ecf00056175726101013c7952f659e18808ab2c763a25fb0c7532634085cec8d495f3030c6c3cb5b05722c5143a5dd1fad4f7d84eee22196d845e2e1309a48eba4859aba690c2e6a083030000002300000000d407000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43228919c055a0f2137f13690e949df8f7d97d322fd990946b698f985989116ba7725269c36d48994939f136e4118d4344b4ec13a8c468ea71c52848177ee200ebab55f213795cf2769a0bc7d5ece59be01b8afc921529684f158ec31c4bc58eca35e4f74b2e3c8decba237f50ffbfe45753135891432ca98e1ce2cd1aafc02e67a80d7bd3ff76b4162eb32a149d0673960080c609ace1755ec2f60d6edcdd79309b9bcefd1b379e2291be3ec29e5429c11bb5269d085ef32e86996bb6086f9528541ab122ce2a5db613f84f3b2f96a7dc6bc53ceaa18f6985f08391a449a440c6332e9b1f9c0b02e36ec11b5167c7e7a00d24222061b4769e03517ab2e2ee6170c55a25e183e83a80c3d4968040681b1d15366669926dbf45ab4d7a84e553e426389065fd3dc2ad1fe4f17b0d3bb1bc2bbb7090363c52706ca6509f14a6a128d85ef337e52d5008cc9bdf131d19272e7143953afec22aa607608e1399048c920388988e7834c68139f2af193d65a5517524c47908fc3a6a6275d581dc9661a5594a853b0aacbe810066e6d6273801ec11d2d43768a4d5d45b5611db0b3298b77621d26742547fe41ce91c0d661260672616e648101ceaf24ecf730d7e039d2de8aa45733921ffba8cb0e7c6f75bd06d2591b901c77b1e807742745efcbd5a57bf08935eb21cc1fbeb85d80ed7c615ca7d35e249a07bf6d39c123ba9ba0bd7e75318040bc489985b106d6c98c5aa5a0811ede08f9060466726f6e890101ff0a22a78c0683078446688ddeebbc95a99b1884cd22a8201bf911cabb18059908309e9c2c6a18f7387da2ee66bf312501f6b7d5c7e5f0b9a17df6a084a87d334c3022239463cef94bfd88bf8317dd9b6cab00f087cb8df769cb6bb2c0d0f1d312056e6d62730101d6fa19a093846a11dbd3b9f26dca8a0dcdba8493d6b346b86486f3c54dd7ec72b46a8f8d7d17f1192788c741d069e068c08eb0c5cc6f6aae09d7548b6faabf82040000002400000000e507000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432cc8a84b06644b0fd1e790c2de73d66c562f0cd3f6239d81b25cd278e5111266388a9171ad58bcbd15396dde9b68b6aeb9a7a6a5b5c7a47d77603f1889cfde56f1ac40ba6eb288239b7dd9c8af7f2b9fb0795cd5b28820c87180e3d735e7bcc0b51df051cf8f33419ca0f07f31f4e8dd2ad6f62bafdc1f0c47f9b727603cda6ae34a3726a20df66d660d77f1c01195a112535db1e046a4beaef91de906901911dc374d89fe1f805734c6f6144db3152748f9b0541cd6583e6c3d2894e04970082b98df5d914b951c9183bf25117b1a9072768e4df487f8e6ed918e5d6754319322d991a6158947113ff320990f38f5e37f0ece574395edfae743439824efbabd2d04f9ebc499a3c2040abe8fddc43943b8f123b71bb490e5f93c5f6093dad9f58e90231d5d69ba54e8052c9c50daa412c580711b273461ec198a7d5399fbfe614faa5ae8d9f004508b43b4a234f1cb724cce8e3e6b00c81f94bc0f321502794f4616392849994f67c842d1b63e4a18df453da38b88267d8389934b1f86bbb988e29162c71dd480806617572612083635c0800000000056175726101011c43c9dc41050f47d24f799941efe385c0b41380cb1b19fb9910ce4f2c55222a6e836b3aeb5c1c931f9c3e95dc9cd27e1d1585d69e18813f5cb889ecea1da3830c0000000100000000ee07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432021071f1207ce1d22e80903c737f4c89f2113bd1c7753de41092a70552dd6c17cffb003d8b5359ae9c274650df76ffdd14c52814ce9b5c17900bc52834e30a83ce59e7d5f163371f5d99dd3784d693dfac0e4eec4fa8accf45a881150ceebab3f42382ac9fa47baae525b7af81f2ba3125302b795ec05b0a3d9b4bca133d3a63e2c5da2612da3f1b3c8f42cd1522f6a7a48d2693d58088e5288694b90307074ef116265b6660b03112547414f40025cc4154c6eb7a6de2ad52e51a55af54b38aa1c54fa1bd03bcbd527584aa648fdd075dc0f8e79c247f5ffb1e6ac9c2be225ea60db84bb8d7ab17120d682d16696c329e958433a449faeb88b1c50464e2e4e2eaa75a54e13a8d890399906e24d00454ec4e709e4f7b939691771a23dab762bbe9023a3389663194f4d084a27298adb033bfd6a263f4d3c4c20a3e6f0e00863cb85196408b005a0aee92f8c6b9858c667067f971772855a47e11daf73a2aab1ae29e5db1dc095e8b6f463c0264370e99ac799f7b717e685218b437e4f6181e4abd56e1a0c0d60806617572612083635c08000000000561757261010122106da90907f90dfa17d639b60ab9d3aabdd7ea95daaeeccf3b4dee072fce038e61f86d7189ee821aec9a11d6ecc5c484d12229183553ca27a9d20f668af9860f0000000400000000ef07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc4327ef0f295b0fdc0c650ffebced6be72c4dd0e1176da30930364fdb01a6713d036f0831c577230924e9326d19f346e64c95e84193c52352eda105704b09d804268b5a6b9e2d162fdb73841ea9372584d9699f321a111fe6f470b89b99b07d8431bafca0227eea00a532e1484c02ec006fa6495eba21abc438584d76f48802d0a910a508a2ee6c3f905a242e92b41e1bb438c7a083504fda57a1849ddd35896c47d78a5956fe6c7531a3c8ddefd9d17c1284ba60dac9040aca954dec18f365c9b8fbe455b67d90249d0096cd35843e3d71badc12c49381bce7312852dec8a1eb64498bbf023fc9e033deee0b54e1b2e1ca8e747d2dd9cb658cc07344df196fbd222e9520eab0f4b1fa37fc4afcb93a1c0ace0cde92aa0689ebcb0c5d1245bcd2c10e9028a0cc2de076fcc8655cd5cc9ae23351591616aded6d8ecab7f2a44e5d624a8fe422bb00056c4bf23b31c58b9773346f043fb8bf5373ded1962c0fec66853e9d754bb642036900eb42f10c8e6021345c5ca5bd1ab4e22e5b8022bf38b06f66425eebf4c5c0806617572612083635c0800000000056175726101011a3c100d29a795c4fbb068012b0291991aa5db384bc0d8c775ffadb60c9a955b4e259391b7f5c22a32ed066345b09aca2fb0b06fb2254ea3723b462ee7ce478a100000000500000000fb07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432740beb55375d7c8b84577fbe1c0743965ea389fe7585d6f68975111716c1ce24eb2dadcc3c91fcb5f23b9008ea9c6f934dc261a84b3d1b5b43ae437c6aa992452aea0a684700ff36d0a8b8ebd07fecc353bda87aad24b37c8944de3ce45efcb42fd6220dd68bba2bbc6a3756154fa5cf878797dacda5fe063c16fd8436a46bc160c9820134984676bc4e14204671db0b5494513b5a7fe4df5d0ea250e554a2080e31802525806814554d3a5677af77a3673b500d3539f04afdcfd720573b608ab0b09939c11cbff67c66f806f5221a61fdcfab5c4fa11c0d7ca12988135efa54ed1d69cd74ceee75480f46a7b15b926904d12cdea281aa28e908ec00a9d07cf8a82bcf585ae95386cc747fdf003d5802d9fe7484687bbbad0448af45553ff3b58903174881b8182392f9757efb143ba61d046a0208302a7a7b3df8041059ca538fef169b8d0012fd33199e57825afe600bbfff192f2b9e0f6b72f5da7e8f1f3147e859987cc129b23e32b2278bada2bc2795d7cd6034e3afa8e9a333d01b36b4e2250e583fe20c06617572612083635c08000000000466726f6e88014920420a08c71a4b56953bf3efbae9a45e737f4cea978bdbc470de907d64e1550005617572610101b491cb7862f8d14fb0e2f6cb8d1287b83a55ee7feb468577ca78d9c120fabe5f6b909448827d93de5eb8bd7afe6c9aea63fef46254208969cdab95fe6d02f18b170000000c000000000808000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432c663d22aea82481985ee77a58f1e54bb8c64fe22c48df15aa43f69aad1c7276b53c400f7fb9008e65a12443807e49224efa495a9cfa03e6ce5298a88fc744478f3820cb625cff327e14fe2006713cce73555c4336a7d861715aa2429a7d349102f0b4f9017440cf5a06a286856c5795b974f5006aa07357854c3eb4c3892b7f5125cb08a3e444ff92b8868bb8d6d64947c84862353870b0e5121b002929c136db31e000378c0f3241a5408a49bc458bd75af5c0d16b35661e212a981ecf5be8d61707c8adc571e83812efa6aa3673e4423c1b56780c437c500583abf6839a68d096600b21370ef6b990d6922acbfc71de68d751ee2d62fbfc49125bd9709ffe33bbce32c9e23b266d24cc175dcc0d99e7c1182b6ce8824d724e9c34ad852a611e9021145925a3f018c9aaba6b3981aaa8e1e24f0c7d9b38f65643a16d3f55d77ff6ca60a4800e3f4f2125d650231ba3ecaa0a51aeda71beada9dad70479d4571b5f2ebfa480c16116166d9e35a66dcadb999da853bfcd1872563f5d0a785507bf67796e568ec0806617572612083635c080000000005617572610101de7241c718f67134d32b6b5656f8e8f3f31e8d29af28043a37c2b49429a082633c8c7abbe502084c28c4a548ac75f97732521c7e66ea9917e704e5469572558c1e00000013000000003808000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43278b266c6c3ba60a6e648093bcd62419d4ea68eec772f22b7dfc78c6b255dac57bd149cd2b1b166d73be2ed9409a0bebe842c1901d65b1fd3c5f8d98d82ea2a5c3ae10acc8770276d737e6334c59e468be878e6264c050f48ac3e4a6524b76b37c399c4a820e1a50b2bcbc805192c2609e8372e8ddd8432127f6200427dcb2d72386429023e01fcf193d96cc55f1d4d85db5b2f0a9e3a5fb6855c0e07b891d6581ea371a39cb30eaa0ea2d0b9bbe5734e8793d4db7c366277619bdff9611dfb8d4bba89ec371746a5e689ece6f2a117d2b4e7894776b7a96209e7177446c076874bde474bbe3f7bb78669eb48648bf238110f690c144c097988314989bf9b3d4ef410cd043b32cf71a25a00655ab6a0558e383e546c3728412be664273b51908f4903de6835c05f9da3c6ca7fc65846438da7947f93a152f77bb75a85e3d05385feb47e071300b797adcbfd7d3a94ba4b2e0ab454bfded856f759d2b674839d4adcacb72d2c1361edc442862859f46d384db20db351390b2d261be35211db5232e585f985291a08066e6d6273804852f3c0a603d7da194fbff174c24700f3f89d86b462760033bdcb1663c76c60056e6d62730101e2f5f706646cbfc613a98564ff9b4a958acead02fa488e1f3bbcee114d13594d75e9b79d5f5be257e9da81d3ab97cefe36a620a2384f6f1f8719ec2b23532684280000001d000000" + resultBytes, err := common.HexToBytes(result) + require.NoError(t, err) + + candidateEvent, err := NewCandidateEventVDT() + require.NoError(t, err) + candidateEvents := scale.NewVaryingDataTypeSlice(candidateEvent) + err = scale.Unmarshal(resultBytes, &candidateEvents) + require.NoError(t, err) + + // TODO: assert candidateEvents + + encoded, err := scale.Marshal(candidateEvents) + require.NoError(t, err) + require.Equal(t, result, common.BytesToHex(encoded)) +} From fad1dfa413690c0e3419dd084b7d4fa10a90ec77 Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 5 May 2023 15:26:01 +0530 Subject: [PATCH 38/65] use types in inherents --- lib/babe/inherents/parachain_inherents.go | 82 +---------------------- 1 file changed, 1 insertion(+), 81 deletions(-) diff --git a/lib/babe/inherents/parachain_inherents.go b/lib/babe/inherents/parachain_inherents.go index b1731abc91..685b69c8c3 100644 --- a/lib/babe/inherents/parachain_inherents.go +++ b/lib/babe/inherents/parachain_inherents.go @@ -239,86 +239,6 @@ func newDisputeStatement() disputeStatement { //skipcq return disputeStatement(vdt) } -// collatorID is the collator's relay-chain account ID -type collatorID []byte - -// collatorSignature is the signature on a candidate's block data signed by a collator. -type collatorSignature signature - -// validationCodeHash is the blake2-256 hash of the validation code bytes. -type validationCodeHash common.Hash - -// candidateDescriptor is a unique descriptor of the candidate receipt. -type candidateDescriptor struct { - // The ID of the para this is a candidate for. - ParaID uint32 `scale:"1"` - - // RelayParent is the hash of the relay-chain block this should be executed in - // the context of. - // NOTE: the fact that the hash includes this value means that code depends - // on this for deduplication. Removing this field is likely to break things. - RelayParent common.Hash `scale:"2"` - - // Collator is the collator's relay-chain account ID - Collator collatorID `scale:"3"` - - // PersistedValidationDataHash is the blake2-256 hash of the persisted validation data. This is extra data derived from - // relay-chain state which may vary based on bitfields included before the candidate. - // Thus it cannot be derived entirely from the relay-parent. - PersistedValidationDataHash common.Hash `scale:"4"` - - // PovHash is the hash of the `pov-block`. - PovHash common.Hash `scale:"5"` - // ErasureRoot is the root of a block's erasure encoding Merkle tree. - ErasureRoot common.Hash `scale:"6"` - - // Signature on blake2-256 of components of this receipt: - // The parachain index, the relay parent, the validation data hash, and the `pov_hash`. - Signature collatorSignature `scale:"7"` - - // ParaHead is the hash of the para header that is being generated by this candidate. - ParaHead common.Hash `scale:"8"` - // ValidationCodeHash is the blake2-256 hash of the validation code bytes. - ValidationCodeHash validationCodeHash `scale:"9"` -} - -// upwardMessage is a message from a parachain to its Relay Chain. -type upwardMessage []byte - -// outboundHrmpMessage is an HRMP message seen from the perspective of a sender. -type outboundHrmpMessage struct { - Recipient uint32 `scale:"1"` - Data []byte `scale:"2"` -} - -// validationCode is Parachain validation code. -type validationCode []byte - -// headData is Parachain head data included in the chain. -type headData []byte - -// candidateCommitments are Commitments made in a `CandidateReceipt`. Many of these are outputs of validation. -type candidateCommitments struct { - // Messages destined to be interpreted by the Relay chain itself. - UpwardMessages []upwardMessage `scale:"1"` - // Horizontal messages sent by the parachain. - HorizontalMessages []outboundHrmpMessage `scale:"2"` - // New validation code. - NewValidationCode *validationCode `scale:"3"` - // The head-data produced as a result of execution. - HeadData headData `scale:"4"` - // The number of messages processed from the DMQ. - ProcessedDownwardMessages uint32 `scale:"5"` - // The mark which specifies the block number up to which all inbound HRMP messages are processed. - HrmpWatermark uint32 `scale:"6"` -} - -// committedCandidateReceipt is a candidate-receipt with commitments directly included. -type committedCandidateReceipt struct { - Descriptor candidateDescriptor `scale:"1"` - Commitments candidateCommitments `scale:"2"` -} - // uncheckedSignedAvailabilityBitfield is a set of unchecked signed availability bitfields. // Should be sorted by validator index, ascending. type uncheckedSignedAvailabilityBitfield struct { @@ -334,7 +254,7 @@ type uncheckedSignedAvailabilityBitfield struct { // backedCandidate is a backed (or backable, depending on context) candidate. type backedCandidate struct { // The candidate referred to. - Candidate committedCandidateReceipt `scale:"1"` + Candidate types.CommittedCandidateReceipt `scale:"1"` // The validity votes themselves, expressed as signatures. ValidityVotes []validityAttestation `scale:"2"` // The indices of the validators within the group, expressed as a bitfield. From 09661befddacad493fac7dff21536f1bb57bf1f4 Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 5 May 2023 17:50:53 +0530 Subject: [PATCH 39/65] cleanup --- dot/interfaces.go | 1 - dot/state/interfaces.go | 1 - dot/types/parachain.go | 6 ++++++ dot/types/parachain_test.go | 34 +++++++++++++++++----------------- lib/blocktree/interfaces.go | 1 - lib/runtime/wasmer/exports.go | 16 +++++++++------- 6 files changed, 32 insertions(+), 27 deletions(-) diff --git a/dot/interfaces.go b/dot/interfaces.go index 1649087d6f..abf7622b7b 100644 --- a/dot/interfaces.go +++ b/dot/interfaces.go @@ -74,5 +74,4 @@ type runtimeInterface interface { GrandpaSubmitReportEquivocationUnsignedExtrinsic( equivocationProof types.GrandpaEquivocationProof, keyOwnershipProof types.GrandpaOpaqueKeyOwnershipProof, ) error - ParachainHostValidators() ([]types.Validator, error) } diff --git a/dot/state/interfaces.go b/dot/state/interfaces.go index 5716f3d069..64e9d358b1 100644 --- a/dot/state/interfaces.go +++ b/dot/state/interfaces.go @@ -99,7 +99,6 @@ type Runtime interface { GrandpaSubmitReportEquivocationUnsignedExtrinsic( equivocationProof types.GrandpaEquivocationProof, keyOwnershipProof types.GrandpaOpaqueKeyOwnershipProof, ) error - ParachainHostValidators() ([]types.Validator, error) } // BabeConfigurer returns the babe configuration of the runtime. diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 5fdcdd8496..07a27c0f5b 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -177,6 +177,9 @@ func (Free) Index() uint { // CoreState represents the state of a particular availability core. type CoreState scale.VaryingDataType +// AvailabilityCores represents a slice of CoreState +type AvailabilityCores scale.VaryingDataTypeSlice + // Set will set a VaryingDataTypeValue using the underlying VaryingDataType func (va *CoreState) Set(val scale.VaryingDataTypeValue) (err error) { // cast to VaryingDataType to use VaryingDataType.Set method @@ -406,6 +409,9 @@ func (va *CandidateEvent) Value() (scale.VaryingDataTypeValue, error) { return vdt.Value() } +// CandidateEvents is a slice of CandidateEvent +type CandidateEvents scale.VaryingDataTypeSlice + // NewCandidateEventVDT returns a new CandidateEvent VaryingDataType func NewCandidateEventVDT() (scale.VaryingDataType, error) { vdt, err := scale.NewVaryingDataType(CandidateBacked{}, CandidateIncluded{}, CandidateTimedOut{}) diff --git a/dot/types/parachain_test.go b/dot/types/parachain_test.go index 134056c42a..e786b2123f 100644 --- a/dot/types/parachain_test.go +++ b/dot/types/parachain_test.go @@ -170,23 +170,23 @@ func TestCommittedCandidateReceipt(t *testing.T) { // TestSessionInfo tests the SessionInfo encoding and decoding. // TODO: fix the test -func TestSessionInfo(t *testing.T) { - t.Parallel() - - result := "0x01210350000000fe0000008000000096000000d200000000000000b0000000bf00000021010000ab000000970000008500000051000000c40000000800000028010000a700000032000000e200000016010000bc000000f9000000780000000c00000088000000f2000000ad000000260000009400000046000000120100004d0000002300000009010000cb00000082000000750000000e0000008f0000002f000000f8000000100100003d000000a000000006000000c90000000f0000000501000065000000540000003f00000098000000d600000047000000b7000000df000000380000004400000007000000b9000000e70000008c000000900000000a0100000b0000001901000042000000af000000020000007c0000007a000000240100004c000000010000004f00000063000000f0000000c7000000e60000006100000025010000d70000009c0000008d000000e30000001800000019000000030000006a00000003010000ec000000fc00000008010000ff00000058000000b10000006c00000043000000290000005f000000fb000000a1000000c20000002a000000be000000c3000000600000003c0000001e0000004a0000005e000000200100003e000000c800000093000000ed00000073000000040100004500000009000000d50000009200000076000000110000003300000055000000a6000000fa000000d40000002000000086000000aa000000560000007b000000a500000015010000bd000000b30000000a0000006f0000005d00000005000000180100001c0100001300000069000000e500000028000000a3000000d30000000b0100001500000079000000b500000068000000350000000d00000031000000e80000005b000000260100001200000011010000db0000001b000000d100000059000000070100003000000016000000870000002c000000240000000001000070000000360000007d000000480000009e0000008a000000270100004000000057000000cf00000067000000fd000000f5000000060100001d0100009d000000cc000000130100002d0000007f0000001e010000b200000021000000e900000025000000ac000000ea24d73b1607c8fd7d6542870c2563c7891a9085b74ddd253d4322a9b3d3d1560600000021034a3487dc0c46f976d352e5e152e120d2d23774f921583d1f2c128f7cf9f66529d49f031c94d9c3b33494849eb9682c0311b3c283b17373f18b9ca02d94e2c05c969ae5d9d6efa40c6255ec4b27b0a4752d7f4068163116e76cd0d4041c471431e8c13e37a4d00135dbe7699d91507f5a53a7b8ed36a3be29cb2fddab9f7a286c347964127e9d8bcd119989a92646c80886c2eb8440c87dd7dd94437873a3ce286432533fdbdd1a739c62733cb36ac48c821dcb0311978f1027bc1e39d4c8964e6a6570b80ba0a90a857ef4ebdabfbf958898bdb12ea1edbb17eb903b00746a14e059357312bfd525317b4f93e5eee1de639872edfaec9d2a320a6fac04d6105188fe28737bdbfec193327886b5c4906675d2a49ed43fe8cfb4e079698de82d2d042cd5a9d8624860310a963ed20c4192a19a9d163bcf366e48122c00a1e9744c5cac0ffa042ee550a3bf70d380dc032d11eabe311e0796c5143341600ef626644eed0663b1d15bcbf9e99c372c041ef118de7d179c68899a645a0fa0983b473eb2a1fefc7a956231a446a575db2e31f7c084c2945094f3927519617d7b913712c60cc4d544536a7190ec68525a70fde1309723986ab984a1e97aca4092ad721c744c3b91b676828a5f884e79d9c02d6f23ec246c3a1a8adcfa9dc1e531a9a5310e2d777330aba66c9558434a592fa5e5aec49c3a70f49f66017f194d41240d66148f2b835556a0c8d3b51ae0e823655bd4aa20fdadc6b4189de9f32cf2288700d8eff37aca87eea6637118337fb1704bc33f1fc685aec019c8e9eec48b62a728a8cb454f4e75ed6d28c458cd8df1c2bdce6101e09b650fe22d139e360fb809200ed18130a0ed0513b2a2bfa7ed6c9090cb350983746b1936c6a92f7304a7005450b1f33df75af8dfeca1cd7e94fcce445c6d55651259fdca2972a4d62f6732561af7dc55da09babaf097d1304b4cde14562506f4db4897644895324b542d8f573c39b3f67c487c1df902d0397792b7cdf987b657b2d27920bc6846eca466c155c4b778017656b9a7d69d3e69159852f38adf971f5a25df65f9950e97411c1c36e8bb9f2665b217df30a15bcd22f231f66f4f21711363cb0b0da8b3594003ae014e8c22d93dbca83c05bc5222ae72b85617956f04eded477369ec95312c7c78353256f3f643ebc6300f32561a0a5583813bb3b42844d1ad3d3779a438771a295e306daa91a5a25590d2290fd262d40f239f87d37e1c03a2494035a42961db2f33407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71482cdc214f825dc7085e54a984230a753d66d08425f9763f52f8f68911120260d4d65053a5ef2ab1152c72f3b15d4f24d4bced3b7e277735eb49450dd867c115263ad657e55682de826f6137dedd2d246971fd8c5d318034940160fc179efa63701058e68510bdf68a3678d32145780e13c29b88fe77b27440bdf3ea9762a63964675cc62a59886ce5fc12d2f48694c7ac836a0157e0e6630d694d11faa605034c51def135330ddca851fcb670c865235dc1b405242cf9f7ccb728e449e09f4ad614110699b5642a4b726cbcb74bee77642ec7b4f17b06db88ee461848ead17c906f769166b3ff9b0fb13c1ccb36358d9dda3f25bfa18e2857fe01a92328eb70cacb5514b570b9338c8602cd4a49128006a902494029c2728056b02a900dcc7798b499a9c38970f6f3dbee7e6220ee0e12a582a76ae036347816baa6cd7c9a7b9662caa1a29ff92ad66794001cfaaebbdf4071f4db6d74ee767ba59cca4cb36cac6854840b7eb103ce5723aa0d6625709d4c4378c46903ff236d9d8d61f21f76b22d6245ef2ea126366dae7f9c072d2d6e0e71a54c9bbafaed36448a4a552b51f02a182d14b38906ce1f4693cd9b87d0369e6af514cf7ec91455b26cd4c0d71bc2d3f9f9f499e04d2f27dbe47ffbce115afd1bac9fe116ce7fae719325e4082460c09defe1f43c8591655101dd3dc806c7b07762c97ad21e4142705e46a1e17306b888519767218eed7b884fb221f597a2d4edb69c094961ace2e65a7e40913c0658f8f3a64ec6949a26916ae2cd976fe531947a9c9e93e6d587bac746cb0826e4b23b64b0eaea19cab0333369b93e11693d2b4334306ee579360814adfc1339524dad3d2adfad0b2db5fc2de781a22fc63dbc4e30a5fcba2c63c2fcbda238668e06587bec427bd5b5cc33da6f7cabaebcb7688de50b59125434493fadcaa94d1e0560d2b374b7d6e1380b6b88ee8ef92cdde7edbd9a48d66f5e219840a1155818b9272f50007b87be88422e3da9599286087f5e578c0d1c2a3db9a77110f9173a69e0e58185dd4e76aa52804b2de15ebff8c3f3237e29dc7157e61b30b9b00a30f93bce6916b6b78ce4f7d550c39c7947c6860502333717d541fdb6697ab447aadd01c0f366ff1c65d331da120ca3ac630ea6e8d7339e7317518920d710e3325edbe8dcd591d30511a0fc08bc5172ff58ff98fa848387b25f99205361348105f6c138e9e4061b3a799bf7987ef5c820c1e534df298f3328e1093c5d0758d434280f6162242be89d139d52f449e2bad667d7d974cb80d0edbce7237185b11475fcd9b0171f73154a0734c1cc95ae552d9f3180d7d64e8b50d3837b14b5afd2221808dfb6c44ce63a08d4567cef4b2a9aff1b408d2c99fa4adef25724cce85368b429d0687fef75f26e5503379a61920777ef1f254af024922e382dd19e752e69784ff2911acf10ffcf4b1d795df6d8b55f38eceeadffe577cf5bc0360f35005940c73278b76425a158be63207452b1a8018f53309f47486a273b9bf60cb51c48d67770af6f19ab75537f06388373ec17a3c88ff1714806c0c99ad44e6dbdfa713ea7825552b7f76db8f2ba2fce0e546d7e7abab7d59e7afee2bfe438bad6091934cc7903dcaaeddb2bd99fd6b36ab15fc32ee001bd1d95e87020019f7c88be2e74afd1a3a66e44e8b7845e7f63923b706dae49eb96cdc73b04c9e6cfd1459d06d6f02e6854e6df29f08f7e015d511ff48d7bbb13bacc9aab1b06ab73c1f3350ce6a864e68dc99758ce2920256f75bdbe8c918c556a5a2467a3aa13a306808740484d1bff4961f87c7ff6a6a68beac9264665f87ba1a5fab9802f1cd729391a718a7477bdafa88e49f5c8cd88fbcbc1724d8e227935eabce71ec303d832c4ab27aafd3f8056d3462eda0083ac22241db692c4671249a14a04c2f0a2959aab412660bb493e536e83addf98be8cb2a0158cf18c6d5ba06ab586a2cb56cf1ad4cd099ef1e3e727f41ebeb3aea2815f004002d27714db121fd6f92fac8bedbb97160976c4d221bfc6da82c7055e469a1405eca842b4b8efd101e984a2482e526ecb085229a5a3f09f444f6d39d71e0b936cfed125e87883db8876444288d0cbd17642ce97b61a3cb7d20f9048830a34520de889098b4435dfc79a73a0518ba9f61924de365e70f8503654e384a4524c1c16900873792541ef023019a68f62250b7c219a149b9b68af793ab31f83f500126e0fffa71469e78e22e754f3b49db1dbe631f286ac449dbc94282864e76dac48fb9bce48124189d2d45e2b2e16b8084c022bcc90ef1acebf194c7b9820968e554e2ec4d34346eedf80cacdafcdbf118a3f158e45e6a8766869e2e5418499d3cfbe215762a4a0cffe4315edea5ef47c60c163be4aa5196c5241f5c772f3f90c57a3580fa0735a7340e37372048c1f60a20531f830d60634a177f3974d5399fca046417a6e4327c4c569d8f4f5b47b263b0f07408b1d453ae31f699e53904605cfdbaa72639138cea3e544258e0484a532216372ca569751b32be145716eac8ee5e731a1db2b1dae4b9023b05876077cdd78084c79e58d16ecbaecee3965ad4685c1780154b678bbfcf725fb2e91be3cc0864ba0f682ce1460eff27c8518451b3a9ec811e18b8839808256e18a89219fda2772c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416da5bd7647f8d8388c2b4dbc138e36b8679284eadc49370ce0a16a4e0be28804b04f9b593ec5987c0608e3913acb29a322355a554e010d33acf155e6ab9bad337c4bc688653010a7720d44168b4552bf75974219788ac1cf3fb440c67ff692d499e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd93257121806eb5dcaff87a28d25de336e240731a375be04c4bbff6be6a5ba4f1042a067086008bd1c894c74e4ab0b16dd36effafc8f04a4617aefa7f68b40df033149c0a98bd89778f1276a0ee404b17d81b96c524a8aeda9f671be9e724f090c397977714f425d45bda5f3373c374e9b2710f477e2e923a0f0b2b259c941965f6e88c0334fe5947d75ed7ce18612988df5f227b149c66f371593a8c248206f1b59e10248e650f7e08ac882d65fb09141fc5c7d252da9b1d8ca2ae311752ddce977137229ab3993dc198b5cfee52c273f6145c25afaaa6de14670eccdc1b61fd53821513fa519134b630c1d53b78cbb67e8b8414c30247101be5de118662237b8388cc7d3c50b2fab9b87f1a6228df23e9507c90bec51b8e3be978b526c0e0c7704c7334dc8495596755b6b5a83796315f9e316bb871c0465cac91290b34812c5f0e34120ce455c4566893481e7afa89c0c425533fb4eecab574f0399ca29b162a4c78053405a94626a6d3cecc0492a268e974e9864826f8745403fbb98f55bf45c0b620da0f2b6e2eb2808b3e713d1a3f774966e3e00f81226887d5e1c165af998d6e57645c3b5a2e17df20f698507190332c6951d761c5f46e0dcf997c7337c0bb7e54e232d9f4c8884a9f53a999e8ce7a27f68e9108a4fde15bc51a350774c22b2a1480fc5fd10948cd231f68ec00397e22a19042578431aad63546679e72efa3cc619c9564390d54bd989ac1fb089a57964ee4313f857411373d34161939633c8f4230930357b8b54ce94dfac3276daca91ccbab9b944bdd9754fb27d2b786427b30b6d3a029d0c998a49c406fb0778936c3bbd0708774bbf21b400aa8a41e604401c8e5f3c9fe54712dfa93b8f223c4bf30e2d037a36a768f160cf0c6e6a8c42a45908fdba40941f018589894c721ae6eddb3ad080bfca4aae349a8e7ae261f0a0f18d3fcd225254bfac8ee7f94e5f505496773b69c49697eb79ef8523530c55511106827b00917fd22c6b8e62eda5e130344c9214f2565b92ddcd6b6edfa18e95f8afa23b3c8f159391a3ffb6dda5ce3c9f6b40f25c1dc7a742186b7b693f30111e4b9ad468b9d1e0cf4f79c5078c9cc4e409f8a0fb170d7c4f421ed5fcf597e3f061f1060d5207533b44b4977f128acd44bfe1bfe235f2f4b2d042a87c7da4d1d526a096e110f710d48d0a0bb58b06ceb1d6ba2189ac3dc984dc24e80fb6522431e282ef8862f121223f6aa19fc1f929106d7a916747f21e1973eec1e8c5b7f78cc3ceec15a5af2b64d5a43ae54fcccd31ddabe95461fdcb5be506267404ba432e41161e6df14443df6eadfb3c5ad5228291d1383cdaaef20c9cc8125f7952f249a0de7093e895f4c599aeb4b0310673b00785b33fb9cacd556acc9abdc3de57fc056df4318d12a052ab505db7d06dfe03767eb5f46cf0d271393db1db2516c52aca4be351c39cc0bd557e7afe547a479f8a7218cad2c784e197f3494dbb9436292833db878c0dab763cdeac36e752c7cda12c98686c05704a8b2a695a315bb1146b3d1cb07cfb8d2e13fa9158734dc2bd1ea554fd3032bdbf9e9871d2937060236da4573a6c20044052b270916290b13a30adf3a821b467c4038a14026badd09126d6621e31b47269829a47f9be24a0d63c4bd7ae112b395498ec2502c3b4f46547b4c766e40db6b1685c455de210347c5757ebb7d463d1910eb70fb290b5c7bc63163ac00341573dfc794b0d53e6bab40a84e60ffb1dc3f6642aa1a246ee579703579df75d2c2dd3d53003f55ebbefeb59446d476d0a722ef8ed1954fae9d6ddc2f1b5a31a3e46efe8097d83d7f80ec284bc72a48b7916a74a1cad145eed554722609bff1c0970e439f19fff06a080a67677712b09762b90a82fd9f97bbc50c12b2408a440f2c91824179203d689db4245fa3087e8b01a9316ba973c6ed1a7556aee499b2dffa90a79b118a646aec6b79e6766dc25665db73a98e173fa6381ae47c9de57628b53ed9958a889d278fe707b4284327bc582599019bfc4630616b78f186de80c5d2d0669404118ff1591ff141a606e05e2835889a5f42a32e9a1f34d4c6438f429028ba64818bedeff64b1db1ebdd89f2c2b2fe3336942a03036b9e86a336aeeee1b94c5d5a821e4ab4c136cbf2766a43dd37078e02927ca8a562d2ebb6671ff854613aa3ad169250e037aadbf0ea14c87982d7382f09c7b8c96770d2ffd3b72525806a645e5abd09a51d257c30dcf016435c114d26d3d3be170800af2466b5e4a434ad5ef602a77f311fa22300a5a6ebf03bdcc04f92fdf0da3c74f0c1461d8bef6e668a2cd0c95fdfc9ef30cf9133619aeb9c3d5187f23bd83c765478a56c4b3708da965c36dac2e8caca9398d50bff836219540b179bae7667aa091181db267cc8ff6c5201acaad6fc2c3a2cd18eb729ad0c1526c6c348e330ce5d949162cbc728667ecce548da5efe0448823e928463418342d41883dc6e20d8e45f1d6d02c43c3e38d6e7871f18ee80f60415adc76fdf4c8ad2c67ac7d11682942ab79f74656a8f51ab8c1b088f33ddfa20992eaaae491dc3dfff9742fe32c4428233d691dfb69a1713087e4fbfef8f7c96df760e85354069eef1ddbaa01d52f9664fbed82ddb5cd6ceec78143f1e27ee7a0fa73873d01e80e368825e3b05bef7cb0005833a9d0ae360c420a66a5353836acf1fa3c65578c9c5b3b9c7831e944ae887694e9fc6a8634f213d8d061cc2a34a00f214d9f67cd17effc527a07e060bea20b143a7bf515a130000f93cba10536a1204f0a14cdba7b627412d383c308672a7e2974b837e4a89d54e63c47966b36fcfa3efa5854046d3ce09d45f226c36aa9c0762a59eada83c70e1049d5d09f7f7304c465f2ff56dbe21687ece20ae9fcd9ab8a7020a1f967780a1ef49b13b40fc3cfd208e29f4d5d5ee9bb63c5fc81fafe5d47c4ee373a54a64d267c497c59f4c15077374317b91566d44c82f74167e6d847ad207f3a1221ce1f958946317e77ba146d16aa7bd82810c5e913c4da0bc5d3a5923a156f0990c79f01317a3140ef3aff708acfdcd30a838706db819dc3a5a9fa2b1bed2a4a48fb21792b44c5772f888132d414d13a98bb5bbbbd70ac42afa68950568131a449e70574ae0f45f28b87210c1ff7df1adee5576d03950b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d9a53c2f9f5f55bd687e359ef37196cd288fcd1a14adf6cad53c6704445a1f1212270467b0c03fcfd8bac09473161c6eba9c25369a853193b472eb2f113a3d333181e6b71b981059fa265cd76422e52fe175db6983c6ebdd0fea1a3075166b9291619ab90bff00f89ea8055f0d7d45f8c8aa9c04b7fc1d06468837c6c563a6529ba846878e4f157741703bb4c3ab4f3ff2e9b99916624a9965a4256d893c84e152c19794d20de22edc9c4c1514f4f4e29ac16e6b421d3620ec6545f737100f0134c29c11128e193f06c866e165662d903d9f799508e617920d786ebf75acd267462237ad2bb39f6a5a03a46c5a1dfdd3766a49e6c864ac5d45afa6400ce3a9809de464459b18deeea6f02d5882e80a8696b00c9f703da84bc5769921053ecc749b0cfe1745dd408f6dfa0ceaa1780ad4ae1747a8912a589a754ed86373a08ff5540a471d9a8272b09df08db1f998000cccef325d072ad79df6c1936cf0ccdeb77a0d9c323ea08a0551f96c28b05ac0c7b0e338cc5004bac22d06feea5a8f5c00104906813ee195100f82600e56bb5756831a260e4cf6e5ad275364130dbafba4ed4f9db6adcdce67708905276a01347cc1c800bf6ba246c3770a81c3c754fd65bee13fa85260215c5235169fea113546e7b4aa7a1c936c47a14e81d3df912601a2eb8ece17888100536bf7183c579eab3e6daa14e5e01602a2fc3a64b563f591f0828f0bfffc49973cd14329675728a2d243102ab486601f1581b1e741bb5c77526552839c17a5dbf3b2f90875abc9959553b320da9f07f1392fa3065315a8b1744a7e5b271f9394d6e23bdab9ae03491f51bbf21014364d919388b7fba4b5341bc4b759fa4234adb292ab984f7b69d3aac2e0afdc7dc075e18ad22f4456dfa48b0acf62c24bb58eeb0a71365ba5f890a594cc046a483d9b306a487ea4eb5e80572d3ac8b4dbb4b6a02692af692160b113da09d4ae9f0464c5522b7236a59b70d3667fd3b0c5fdf2c30cccdd640a7297da408b6aff82ee9651f889910fda9f24c706a617b082d626dfc74a657c5d17c5a763044f0230972fbe47c907a5a8fb75df4afa9726d496332a25823148258bf60b189ac898c92b9be15965a199a45ad563efc761392b915b58613f9fb99f45c9a78fdaa4358874f739cee7ebf2a5cbc2fbee73e2731e18f347de520f1878f0eab3a38f377a9263ad17333135c991d560da02f9a012221d644717e2f1361ddfd9e6b5d0043f3a47eeffab15e43d7d45e1f6e07945d95fb46ef5346bb3a502da9f005d1cdc956e1b96258fba48dc793f50b7eeab48cb88c51118ced6c65368c5197ec7f014c443b47d898627cdb7781351442c44398d0ea4ca4b697ffd505665531e7d4b4406431f2328943e8b72d030842128714ed41e3d13b8aad0d076b7ad34af4946866f552568eadd3d3582b4c4f50d816c065e65b3583c8309e3465db95b458d0b42619e1ea75ca546e966d761c53645771381f31a42a1e0bca62f752fb49e8d2a49f942cd48a03129a709e763d23aa4dc84c88423861d1ef31f5df99006156570aca69e571067899ddb156a2027e0acb8f278b4e156f96ecf0eb2658c6504fcd39e4e20bfb5905be7cfa05ed907aa5041e202a49166a5e267724e5bbd0d9efe57d34d8cd7a2e536cc7aee14f12726065cc08d547840066bb56916d9bb9761e05133fd18a68324492ad7b9f9caa1668038a3ae897ec528be2ca7c977eca6cfc08a00266e96fd43a723fc7226b66aaa86fb8c0ff0094b6feeb0707b5cd61797ca034755fa42aab8c5c9e245157f5425f5d9c2de89a454439ff9ddadea199ac62ed47b9326a4a08c06859dc6aa56cf5af62a035f7c6b0546f536c07cfd7a2d8e3be9ac2c7b7e854ebf59eaeda5edad7dc23e83eb30dfa3dd91753614a811769d6a564e5e2b27c43c70d7497a0834ea96e50b6edef3369e8da5f707e530fcf611301be6bab8187386d130d1f8c94e5c3602ec613f83c1ce2708d6fceff206d25c511772a85eec3fe2b4ee066681cc6c58313ac304e37b46e43a844db9b7bcda351e09ad1efc57db99dc2a7c12e553ca9a60412dd6bdedd4ded92b9647ecd2ce31eda2a6f5a4ef9df833b9b4c70ec0924a92a7067757484a42e2e39a2c58cf41f683c3646c0e993fdb61ba33306f7524ee2733c1d970403cebabf7a1af318743767411fda52e046b2fdbee1680978da2f66413a00a72c2f0fd68497472feb62d2481dfa1ae93b14895fd3773d48635738847d32c4252393c6cb8e07655646eca309a1481552ecbd9569e94a0cbb6905c45717f0097f3dac95ce491ef6f07d89dd7a409b0f13475eeef708fbb0cac0f200cd31c296fc0f38221dca15bbd3ad95092e6a4f38b8ef8e9f3b9992d57409c7833c0e2e85194adb91496335138d5815f82e01ebc93b757c1ff94620f3a87ef48ca064b8daa8790dd2fda2c3493f33b66804385212b1c3747f61ba6de535688b2ec24db2b9bb22f1c69337d131a4c91c2b70f1b45fa522eb556b7960f937e6fba63e1a5c832c850ec9d476fa68c807d36d09edf0c1eb9b2995a3812cec5092b90c4c724a2e1e42195049ba8878f1d05a2e30251a57f7f4662d4bbe42ecc98b7399c13a00c82090e61c34b4675c01815b7e25a1fd09d2fc60f60ec1f3f435096790681cd676c3554c66ecb08ee954d3de09ddaa2e3d11f5fa4f9d4c89cbdce2c3accd6f9495757f069ede7b956256595c7d083b47c610efce658762467518bdb11be9597e37db2ce13f8b1b0cc42acf317bf5a8f948dd3977725de1590421117c9ffd003a836e898f478234d26fc7d8bf866a6a308f8f7cdaab738bc98b879669911a26d87f69b187cd620e910289b9d5c2704d332359fce4040b4978eb1527e743dc15407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d7162fa40d6ad22c0bd13811d9555f4b2adb0f639cf7ace8468db36e557c1e1176e4ac7db719c3be3a8a8fb077e5aaa181f69f89547570b88ecaba644b0c8623f793abe63296589646fa4fd48c7d15548b46fe4f60435bf69fb31260205482eab0226b7a3b02d5edba566f82d3f949278d4d0660165857965f123b1ff5aa680a62c6c7b8a1064cbfd234f3e26fcd14b1eb52a0b46a47e8a8d38027bb3fa2cba947124c41b6ccc361bdd655dbd0f0a5b5e7c86fb1bf779a912921794e17746c37f40e0e4451bfef8b6e07bc00ff6fe17cdd12d45db9f816cace50b0682291a8dc257ac131413580ad09206331a67387cdfbf12cee28aab9a8b0aefc03d6d1f2fde70a8c597075eec72c0adb7c050db76ed8d86e7785f056db19e02775ea099672c7f447c7d787652ba7c318efbd758620236476ecd6df6abc2cadf3488c7e6416c12b8a2bb40ce3658b1d71c42e68495a5504986f38696e56ba0fc2df70182a5b11fea0d61d2472c21da757115c4aeb85f1ad06831b0b41779a118995340fe6c352e6cbeabce345363e57dc45931c6bf8f278f704cf252234e0e580741af38024e1536d3b2112224e3432e605d698c7809f9599544725f3bbd89e076742a2e33631e2caf02567c87ef2729ac221651de0efa7ccc8de802d0ced1036b68b51868bd3686a8ecbd7b1a217342e937037c0bebc6a026371b85698d124c09998e5a531b6cb276cf5c2ddbf28d010e2a6976cf03488c0d1d11c5c1f9b23d7ac44ed221724baa63a6245db826d277bf7bed80169db1bccdc7a3eb0ae7852317a5fb2628982aa0fff7c6916548204396e77dd2fc044e2a37c192789053627b2c81fa1c0f3d1f7482ad1abb0ef6ca6488989637ea1d44a918f062b169f1b802c9ee6d05a2fe34fe3fdf6285d91ddb739bc5c2481ed4d77589febde82e624d0af0ff9796e5993242f7de325ac001c0d50c4d27c15248ae2023cbc52e2ee969b16fbef249ee2542026074c387dc5714b8038735a05a39459797ad1f591aede76adbce55e99ed94a98b68d8ce62060e2c77262da54a918fe5942925597cad811f00d13599f0062784e528241405f8618bcc663a513318815f67de9a13e6786615542b715d6d2bb3d82580e61b8d0dc0c1652fcb6ad0fe74186d4f30f931ded5712a16e9724b9993cd0d505f36fdd6c1f2f87ae7f7b7d2a84caf41d8db3d926a728904ffc98ade114aa146708071810254fb2b5fd49243a64bc29a6cf8638150988ebd9756b917719664e74f116e47c0991afa7bc43d0b4aaf085d205ced8ea01235b224e9e2a575626a39cb65fb8a0456f4f5380b87473b2c6d3ae6c36664af57171130202317f567e7a89975b0683a31b08cabf966ecc62d48ac257c297ac4825c75e59c4271562da9a7597e0b1d1e880416c0a36fd5d9a8a1a0e277025e81af122c541ead22d78609154fd9334b34c1b724aafefb4de93d02e360bcd69f4d179b8f973f0a229525c681a841ce65fe1848e33fe6c929cfdb09181ed6f10f9b5d42b079890c93f6cb63489fe6ca5926a30f68d89fea2985c600a9114516a6c29aa1a9a390358ae11d4c2addda665d13fc93f613f8de4ae6526a7ec8bcc418d9d190bff5fb2bf8a57d4d02ae9d39b49dafea09bc363a28395b90f0c0482be2642d693c65b1dabd51d6456d129d5c987093349056b99398c6c59efe7949aa90e6480719aa04ad8816124b5eaccc793902c3f48b7529b6d116f4e7418406b6dfcabf008b65268d1b3757c713863c80e960241776adfb775052d810b59fbc83edabf4b607bd44c6a610788c1cfeb3f21e0b94d5a12f2615ed49cf7d67abf18a93af7ba649cd0ac29680d9eb19a6e461dc5fcce21ea03fdc88fe1a67bdd4b67671794d5348a1b481ad45e86635f0474f0fe3f7138dbd0c961b000d0c14707c9c3037792e2b59632bef200305908aceeb3388deb21c5ceaa4c1dae6b8ef3ef9ccfca9bc6523b609bcddd0b66f5b305293c5ce2538e4d8e773a6d51cb10adc0c50d9b9cba83e8429a2e2e1e4e1f947c0be485986af1fefb306419c6fc3cc203303517dedafea231dd90856df4af58129352adfbd4c714e33aa5cea74c6e39a097a1155bb8a0f59242addc542e1ce485f81eb5df11ba9bf4e0267aba89ad594b06066c4a7f52ca7947de90772864f98b6fd26bbf80abe1a9ecef909810ecefd129f3a73bd3296a2999b9bb455ebb74bbc3f5ea7cc6eb966a566123ce03005a73c0294531cdb87e6f4e95a515a4533e0224cd2cf5426a5cdcab8c30caba2a0a36831bce623b526cac663bf76f269e3d114a73a0229bbc06b4f53b1f5c0ca2198e418a49af03440d375ae7c76e24cc7c0c46b93aa96c8e69afd833d5c5f4ee23346e35053b1fa6044421208a5fc47074d544333068438bbce32a53bc0117d123ddb9718eb62baa88f7a7bc786758ecfa2acaff06cdc5d550de264d6d61988290e84649f3faef516f21a36b403490b980074580512dc2e7d3e2b87a063a5da17648602d66ed743cf227b0ef5a34067bba03c1df0cbc3cfea77b39ee77b49d8b425455e45a27a245c1963853bd35689e5192515b7b99cfd14d624ea54dbe5eea6c8f22b59babc3c6a3ce22286f1a628b901883b088d7b9dedc64dc86f636e337839c21edf802b526c26346ff314ac02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c24165804d109d88647def7d8362b09e103f65285c88ff5ac9329ca40a9c29dca4e073034a4c23a5fe2e1a82fe0b885d736e57a0883291961a087a2719664020a574cd8db813d1070487f577a18b9e163ed125ed818c0d13dde40503a10ed6c8d3e6a9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712132d3fdefa1807e6bf9c14050d63d2c37bf357802a7d8e813baee24cefa76b229d471496a02cc87ca65544c0ef979e7f4c1f0a7269e3eb21fea4e0d91ec4fe86ba67e4ee5cc212e44e3488e61c6c1ce07e25614b8c23cb4d0442b35e6b0d8ab3744512e70a1dd7110e04b778646d4f7b399d36712e40bd06a6907f25046639e4f9a632636d4945986ce97bc67ea13897025c220e7297598460ccd7cedb8a0c54792f097884bc8751c88ee126bd1f3682449da8181bc9cc5b90f0bd9dce1cb0d19441bd6bd7dd64756c6cb272ce5ea2a934c56dec8f3be010f8ea74cc61f20d1309a1fcf68fc3da9660e86c1189f879b8c9cb6611d57d470765dec4c3514243009923ef8cdfac92e83ce444c9a2b61fe92d6043d108129649a3c6ea306c5d9db7b924eb791afc0aacb141b54f0d75fcde46e4682e806926114b2ec7ee5a1a5626a3a524e56e2044349643bea61e7d9d3ae3dc19e660d754e6cac3fa4f24ae46d794816a0ad32ac3690b658c96cc6e09d9510a57c8e28f32220210108791a15aa0dea2e3482714178bee78fee64d0d61e6933d06f8e8dedbfa5ec5cde870dde2d7a9880b245038d021948c6700d89443c09f207b9da66d2ec05e1c567a8ae5fe5023a414b00e01850a90adb945205173ed44279aeb17ca7ebf9a239d5f6ecc9306a868b391a7c49dbde0913228107a7795db90a5e3e91e505d9922c2914d7755e0ca47af8f394eabf539adc4509e5958a7935179f1fe3f8c22b4cc2e2a345933f59d65e0318bcca6caafcefeb3452d68d6197c8ea0b26b971962e201405c4c157653c2f2d4af59046fba73c6d72ca8cc525648416b9b2143dac665457204258b81bbad3d109701bd807e75845178590a4c5b8d44421e0225d9fd994af2aa1d0c65590a7bfeb5fd893b53578b04160e3162b0aae5d6f67dfcb75abbcf01b2ebb106906d47dbbbde1bdb9b1bfa8dab1989c600610422ddba5fabd57a54dc955ccfc7e5810293b5345958abc5f84808fd97351d481e6809e00bee6538408aea7c6c074c26b68e2002ea0633e6c3d7484493771c50eeb727d6fcea84ed9c26bdaddaf73d8ac7ad5aa36f30863234f789eb1d0092f42deb6ca72061146b920d71b457700dc5012547ee806376f3ffab1e2780f491f33a0cb355ea6b677c4ea1b54ab6e5698d2853047a428891a431d89979492f261809be176ccc6f09660d5cd4b624f339e961df7e2cd5aa3f816fe8950ecc0c2c9838fbf68bca5d4955de8719bb6cf79e8afbc8632efb5aabfcaa6e749cd45043ecb13046ce3209fa85ef21441ec2d1a0ac63a273f4213225773647e8a739187223eaf5c9f0f2e3d1b12e229fa77e65bfaa2a0487a29d08064960b2068be68c3c830254caee33d9436053af9fd028474bacd43a231dadc4f4116e333fc9f88fbcb64abea30e650a11ac56a1988eca459d858087e220893ac87e5b5203582ed469929c865ca6e35cafc0886f8e5a9f813f011fb08ba33475f7e9b64397ce8355542f0d31bebdb5238414fbc41ab88fe2abea69d9e769a9b465041255b591fe2708f1193c6a0d7e83e929c167d0f672a6cf8bf480b21d5fcfdf7c0ed21b4968982c3b4798fe04b9e9462fe2bd8fb6c511b1c153d0637fd584e30e35b6a07aa739ca4f37d82d9c8e4369606257edbbb2f6ee4e6047dd8e85212633fba991cea2364c746d0ec558d0fdfd64f2ca44bcc97637e3af5596f09c8a333cc19880d51fcd11a73c7b8eb1b02485903f9c3b3d15b56b6dbcce848e56c21d870a965f61bc53894462a6997e78f55f20ebf32f8f4de37a05611860ed6704be9587f1a0c12bf329f83fadd02c191a288925cf1aa151d387686eed59f920597a10643f36f40b821f85fc2e6b62569c88b32189a52966c52301f029b0c231c81ba02285edfcf032a441c296500e2a2979e4b4b0caff11b6656d131b61a171c4554591d3c74fbc8fb899600114d3a61951d7af36bb8e6460ba61b0015878e7e28903dbcdb802b63c5e6c895e2619c6511dfa0723fc48f796952690fc3626bb5c1a0757a19226c7db6e42ec243932a2503b9b257fa271f933ec2dc395f40b62b11adfb0a552412447e35ac364bee1f8ce0ad23a72daad14944e49b18cc3d5ecb36f4a8dfd602319507ba7dade07e22ca3a895e9ce0a2f59d7f581d176f5b8f880047f3803efbbcd442b7f8b1fe158353183f03d3f6acf46865281439426e64348199839d84de5c3d2441a5dd9c75bd064c1385ca083cd1df6ef46dacd30ba7bc9797085a143f0fcdd6b0c7ffdde124bace833b758ee4ddfe5072a558406365b77652cb2bd1ccf651da71b0b22bf789af3d24014217fea74522e694c399bc8bd5f07c0db8fab186d5ee762d33a5debc1902bed79a68d8420d06fa2810bfcd09e53dad5f37258fa86f46560785713ec711c9f5ab98c631bb3e3b6c5a293370fec522d61149c7bb09bd4256e55a71487db84f95cffaefd2c4a3058c62c3e73695bc27a72c21d264daa0d40c012083c581e4a0dfc7f168b722b237a0ede4e40a7b352f38ccd532d1a416ffb5207d68c2b7b3a6cfd957d7efa5b71446ce84fba254aa25005dd08c988f4dbdcc3dc795d3487566e587f8f99fa6d222c406942f33c9a694d0a5b974d247fd6d4a37727a7eeb184f4139d300cb9d2264e4bc1869026d0ca9966cfa34a5506577dd7eaa826a1dbd86bf3e8ae5fe73cd591837a5d6075a386bea6701e431ace3f383154ebf64ff61e2e4b520bf3a723908aa855ffca926ec6b18bc48a7dc48b52b839507453def5fd2898cbce2c611ba2af0d2434a7152607d997781ffdbd8987c5b14b6f20449493fdab89717e43a14153845b97698e2511195a1fbb646bd896dad04547a95f1941a1df510c4f7990062c0d4fd794bc886625c783228e520fde1dbed723fc9779bef796e04307444ff32c210cfc2275da1aba94d5bd2b963fbd80dda7a9c8ff88271f152875d7cccd664a44c8d3067a4034b5d6101af80d9a2970f3443536302525e41dceba23d8862006a1893e47f69018c2ed81677b4c43016ddd24ba54311aa590562ce1ad6991a1736d972bf0421adc4a00cd631414f1cbecb646e0008529253e9c0169822efb33ce421d77953121b3efeb10cd44d504b5cf47a9807dacce8eb24d53ce62e145835b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d32ed1f9d70028c2001ede3fb28ac4db0b0215889cb331f8bc637d8cd27d4443570c84f2e19c4aa5a2610030e19ea4093bd118f72e066ba44693db5cef94f3905a6740f6b046ac8d7b77f5451a405975c2588b5b82cfb70843359010be8b7f32870641d3606bc050e0383940f0e25880e6b183b137ab86e3ddd52a0ea7024db44fc4458e5fe418d5a7ed1c33878563e44403bf194507c93079ff9105b433e6078faba26ef3daab055a97199108ceea0d3b0dfee6ef4f8ad55f1eca9c15771251d0cf33eead0be3cea163831560bf46c98931a1dd530301d054fad074fb22e5d6ad86e5f79ca0607a6108ef6030015ee05ed6229bafe13806894461b51199f5b3d2ef6d9024f2194253e89d0ed237b1903f89dc510bbdfd982b518c3576659cd39120b53fc4e51e100e83a51da1239f64947e10f158bc42d10a3b20a366b4311370e2e5c4b8c303383b3e579cd1196f3dd13db99c99a48397fe1df8987a58b942b02fcf424a1223968027d877793bf9f4636cdba3b47dfac921296a818d1b08821f45e5edff6c3c216a16d4b6539790325daae1a6400ee446c2b4fd1852c409d43d0bfb72b3c0946f9edc151873293bcf16d1360b340d7b98eda07f00b1333fa020c5b2ab0a4db4d0a259bc517898153957166f01726a25d2012da74a8fcfec104b6ba6b02f41eb730989a90ffe2f8948b98eda9bb5bdaddacaba1ac1877ea8c77247f876b27b3d89aa71714f55561cbdd0ebbc4b24d39b044ca3e3ef42bf8f63b8c642ebb1fcbeccda9a1e3aed8762eaf0d9ed97308e08e7489424c321f49af5ff24bc10f697dde29bb97031ff65fc6cea39036367972d5627a48c4f9cb8ec56d22a8f95b4c20b4a2545baa5879a817128101c28cc253f3a7a73cb74f0c43d609d08eca7f936f1a8a1fd902a4395ac8be7312d9eaf784c761cb1354dd40baf3012e85eadf3fb86959768990ad2c8625a553c4d920338ebe25de23761c085102555e30cb812643fc1d2857c220dcb944c423397264da353d5131d0c70933d72b55d021a519c3d7a9c5614710da694bc1e1b7d5cfe40931ce3f0e1f35d253566b238265670dbf08b30c63410be69245689bbfb89a17eca0f6c9542454b1e92ed9421ab1827a2f0013b37d7a0653c54a480e1adb20f4d6621955b8b41b7fc0dc7f66309c890258c6702ea0943d8a32748f67d8dfa4a29fd85282d949f1cff5faba27a8336309a4f867baccec1e6369b73bdf4b757c1049448f4bb3999ee0d8ffcf0014a49f30a2a2f680daeab96ba080e9436779e88da9f35f1df28aa84992e99a0beab3c9bc2858788c7077ea13728eed4debededfd07f1672798856c3a055a13408241a7531f1edd8411be59bcddf843f745850a77afe6ac8984ce9110aae0cd6008ca6874a522c58bc897c403a860cd5d05b731add09f9e24a465d0da6417d00000bc1f800f46d8c06a9861b5ebb82ee710a67a28a410942c343c5385210af2235887221563f3ead0d53f19846cb8c3345403ba3f7209d78da91196896a687824d8afb71dfa6f71d993f900470493108fe9db363bf82126d7af537072262fd8208ab0488b72ddc27a4f9dbb2c191e699746de264af70e8325a3a8040652d3cc3e86f8e7ead704ea80c6fabc0641fdb53599f2e2532b2733e93514058b042af10bd004e87da3ee9342f44b433ff1b8535e3f1928f927eaf8bdf52e31c589467317ee797d349e052a0edd93134d2a7c57ee3fdacad7f8e00de15fee3a091b2c8e51c87f228bd61350ac8ebe6922fbe3db9b1f1c95cc6fad66daca76115c222bee077e98797f7d5a383fdf3eba7a9d9f91ef76bca8a1f5e028013db30143acb3e55096b4d63a9ba75c34b652b711c471606219755a72fc7db90eca93c617bac3191bb231b7a7a68d58e125aada1bdc72c94363a3d8c1e3ff72da6102d37790dbdd1172e42327ed298ddac2fc87c59442d545b0ff476caed9e785f2bed1bff26b0333a6b7893cfcd6ddb8a9ff65313caf6456f2ad2188feb5ba8dc102539e94beba58707699d560bbcce83134bc3f92ffca813e62865f3d2d56680b0ddfaedcac5d5d84dcacf83ad61a2b13644eba1c459299b7a92a42c735c24fe9a4b2e2e9fd6a003c6761b167ab56948265b496cb7529b01cc4e53c3cd9a39384643996beac7e7e8c5b9548bb53ebf8bbca632e490bedf7f4c1de2fe41bcb746afd7380a6ba561610e880b38007beeaff985e007a1460051bb827ffb24970b0fbf79cde0264cf0292305be0faf22877173da64f6bb647b3a636b831df365b7c3394915ca6209d753a2cdcb143ba3e7fa41dccf5534c6fd36ef91187d55e35dac9d3925ac08e2c22c80dda4c60aa6e074cbad95a68215cc134e03ac7e516179bae944ce17cb54d086ea75184c3c36dcddad7c1a570d4167525f3f53d8d39ebaf2d239bc1f9e7572cbce85b1fa08568230c663866d47c3af0c12e609217ab0284f8b8694563933a48ae23e707c1df21527ba79fb2c6cb074d51ed0b90e361b2cbda0637c074415c3e4eb13b75b149505ccf56ad08a10df211eba48ffd7a2d0d42a1bd943dcc12f86e3e9052ee1ea8f6f1a8fd7b2262bfb86110b06210c25e7fac37b49198155c2471aad8190353d85860814a81887509424d72a79cef1534ea7655db318a424d6a036c7aa614ce9faa7901f55f64b0b0bf1c084f52e7069e5bf1097a9889ff9773079eb30a9abe2de835e3229d8c3cd6b00e936d5339b325684a5c483b15420e123c221c6faa48e432e6ad29d22301073d3dcd3dad319399258dae99d20eb634bd69867ef8695bedf1478abdea28e97985ba68b3810318e3cb12ef946594ef5447668e76d655032dad5ed688567ea02cd741c0f1684f271e1e6f57e70339d949187f9cc5ed830203c45863ffda2b704a0bfc77cd4cbaf3279e937c9415d47635c23582b2cc0e19d01abf7b442930cab1acb6b6d1c87fcbabb93d1ee778339fc75b0aa674b0b9ebcc31efa34cdc88d6209367d7c9cb38d96a9ceb0b51e8e2364399650074af6bb1098b22b21e3b9d12bfcf4ba0ee5e9c3cf8820ef6061d10c3648d73c6d22bb9a4502c3b263699d0ea24baa448b12d24f501412d09da75d99714c914e0bac941c2e9591a1af974b9d7ed718ae8c2c5246458375efb92aa04a645b615f261ebad3748d4e586cf4bb52da7a9c3a306113046efec9210cdac01dd254b6f9444d4186539c1983075c1100c45b2a80ec93371fb04da55a70d7e4064542210bed2bab603e428eba5d241504949b6d4c4f02b543fd709a15be42ee92b6bd37baa61bc2904832a15e7077176451dbb49a688cf55649c5637bab364126c473c49dcbcfb064b2f296cbed17603820bbd3a5e93ec52e82e67ab2760735d2fc915122c09b76fc9de21fd95de63f8e5b0276a7fe25efa62bedecf69ceb278c8309d1c5ccae18338cd298c2ce4780f31255dd1321fbd0dbb6f8f64f321e0e0b665130b8a0379aaf5aa6bdafe07af1312f637e3911b8d18fbcdee38fc22ca35094f912decea24e409eec05550dd35c62be25a1612ab90b268015b40eaed9fa0717aab769e193b2d7bd2a55e7e715c64e67d0be4b76086d9cc31c11ec35caeb68634eb554ed5f55ec45727a57e2d8d6914f6d2acffb17b9515d347ba045067502a0b14022a269560e0d95cb168c7097ea8eccca5aecb328a24b1eda37bdb600fffb212178ec0923744a6402d58d7d738f233ce9b64b6a9f1dbfeec1505db36c5a06eab73142a86b27dc175155cb30310da6295a7fb1a7fd6e4ef00c998b82ab8b3300133c6af14e5077c26aa202e6fc5e69a792012590d42ae2694b82fc1efc68ebf7b5df2574cb85143f66a0bc2ff2a9811e62cca6fe559c14e606a1c9ac2753af2050d14b924dfc217dbc5b9b44e89d25f35314db49b096287a77d1734d0f8f8d168467849008fc52de08473191d53f8cff9c54059406398e89683d41db5ca287bb379e463c7df481005fcaa51f86223229d9aa3f1dc10b0bc97f9814eedae2d1a0d48826da8fea991d14f1358e94badeb070719ef7e1ff2021c1cb5acd297695c34310474feb95e86dd6e211cd2e6f65ced4fbfff3817ccb8c25dae508502d4df393b421e7f92dcd88622e35e35994021fd95c368ce30d455831b8d7b5431f33a73278cc9567892bccaa9f0d0d4410a411d42de63d1e2908e4ebbcafdb25c1a4ee00238cdf73e322686f01341d26623c2491c6340204508a421b5978d8f7f698b473aa842dc9eca0e5774a6374ed583ce8605795f084731e95e368d039b6ac539d614882e89471f99ad0b367c55273a7a4a3dfff10ea4c7816a44c1cad69137741b64deffde56148294271b50d17c8ecfec51791fde88bb15b07ef5a9f0f13b9ee20cee21322f3a6fd0783089d9dd32a9344cb0a89e9746bd35c0bc36f37afacb5e35fa47643df9b11a50e4f6f2c820c284d4c147481412e5e4945115040df81511233a8f81e4731205cf0af72285f08cdaf87f9cda4cd3c7c7d51bce592ea15d692e2a1700f5467da9707838a1feff9c989cf84c7b2a3965f146be7fadff1b72aa0338c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e8529585eeb7d466f7e38b980536e62c00fd3dc5c703c3bbd721c9491e6eb85c32a44a4b8c95221524a3c23c6b5401c00b5030ac5fc9d0a0463ad9e34009a00ad426a782939a3e4f8394ef0f1c9a8f811a7f5ea333cadd30d3404352aedbd7a2a743020670a8d1c3fef7c3cee5b34ea05aee62597374b2d6143e51039b706bc660f371ea75d41bd9ef4da3a7a5ee404600a4880f8915d2a0d4943210c8e5e71277e7fb0a75847a0e9f3e97824f457206271c9147e2862e8728b4d69cbe84e785d92608878e367fea06978192e6e69d4b8acadd42ac1133fb3a9e9e1dc50e281254144a0fe07efe8476c462860a01a5e4180a4de0249f05648c23f8e6e3bc49809eb27d2c7ee29fd05b5cab4d8ea4b8868446d4562a8b2d6f182d818b448b165d8497a72c623880702eed40e35aadcfcf6b09f67040effbeddd2b22af32c2978da711f60d3a60f115c98e714b9ca80bb1bfbe16704fb841cbfb0bedad90d8ee5106d2178980cf59e6836eed32dc22ec231e5556dde151c0081a83bf4389916868f9a5c9eb394a00dd88f01a451ade235d634484a9c56c595224495874fbdbdfdc1e93220adc754722bc8f182a697c43e34c44782ead62b2b4d01ed046ac0d7187fdf4ec246361396ba03e69055b5347faa6c1cb9929766e4f2a7b41911e25448678f4820e4764775b18b4c0668fa3ca1e9183ed8e57c30c211e97e7cfdc685e6c082448e0595ca52e08fe5b0d37ac52bda3dc4c8a0b7d3e9d1812d5530ebcf9df0ca539c809855b617cec1498a8e2313908d070839a80574b129b24245eded44df2d131e43dc9142274e0b70a75a903791928a1bfcec374626d3c6136c409de439066c72ccb9ad0332fc9b36d3a24c6173a23014f684d0f1666b8331d108ff33986354061399848cc96c7a631da2855f503865eb732fd4e5c3976571cde050a1777e67603fe0045e0a581002149e02f12f72a340fcd78d5723d10b6869cb54bc64940dc20e2c4e3989890f61c5b1df09c72d8a70b5e5a161c0077f73c816b17f59d9533c2e6ab0c7a26dd2cad7646133b739b24e20159d38cb2e11faad8ea174305417860ff18be0bfcefdb413d281ebc034b8b5f8722b041e90ec772e1e9449f61650a27e810f57d102788527c3e274dddc99f094edf73a09544cf3f162573d6da4798895daec9986a41222047ae0d3ce9b6d84c6e91ff5abd4296b1e777b8e22b077a6aea2e843cde25869445dce969fda78091938b3cfdd6f1ab376e62e9f94ff0456171e270fec0156069e8006f48956683abccd1427e3ec9df93abc4fbee9170e9ac11dd9ca793e7d4ad05cfe205d6ba0969f8e965d571cfbf51f54a8e3317b795c76523eec774719d38f8ecbbb192bc298fdca9b0a9304386b0791c671fa441d2103a8e2b2f015072895fe33d26bdf621bc4357610234e563f1f6dbf1584d21aac7bc2a1f4c8869fd97e805ab0157b6325650d1e03909ae85ae3751e582cd823db5394add842eb339426c7a1f44fe90370fb00c10664c8f2c9515800831c45fb5248387358534d37a9b2bc6b9ec84bbcda7f2f8fc16f848423e1dae978e729d4886f44e1b21418fc96c9b11246ec54148661fd7515be3636f5d3fb5e2723cfb1a7253ebc10064373d6227daca15f68a54710eea722a4c7ac9d8cb34c289634b7a831c0d58ff0c5654f9edf692e49403f40a9b1b1bd4acaebd7c2ed9d02378c9a9b763a41b5a85c0e978d30601e32bfa02697f9eab6f756a1d83440c49028baa4607d4ec080ace306ea6094d615cc220736fadb0bddb33b4d7381d35d265c13e35b0d829219ad12e42d1b56bc54f1fea860b18d6440a9c44c56c41dbadd6085d0e3707ee4eeeb4e3410a8326cab9ea1eb95213475d669589cc8b1331ccc7d65eed9559e0ea0f5bfff13843f2b4a2067c577278af1558bddd481e153602c11d5c81a424e2a1e946483bdda59d530949954fc0d7e42afce9454b6faa5b7575f6fa1d2374efafe1363b36df330d958bfa12b5efdf7d274943cf6dd8c5448e3d30bd0d05afaf86a2d30c068ff63e9fd065e1f84362827c46ccb49a8ec04049d1e04db6f7b88c193400ee5818956472db1a5d3ab044e18f4e918b2547eb275d8910d103c13a8704ed2503421465b1e68c51817ae25727b7b72f3817febe4ec7451fc241d7794b8a63f1317707c329bed6bfb2a0023bef0917a4f8944b2023efbe2fe3d2131c41ab066ec2eacaf389834b55ec862fcbca7862a3addeb9a4fd147bd07f480464e395013f2599efd1c800bb1a8d30d5f57f82ac1df5056e7ab4b9b21cf69a97916c8a50072a9fa50439bf52d8ca7aaf50f5bd9591a5422b079114f0bfe4acf561c826ce665878ade3dace990e64ecfb1ba367f4c3c0a61d4aa1dad084d5c3279ceb5a4343f16894ba217fb7c1bb67c328dc7a5834ea59c48d0db9f4a5d9ad304bc46c0d63e2847067350555940f33ffa238dc7137ea04ecb81d9abc5b068794756c4f812d1c5af309231bfb4b27281eb33f8df6c7152ec14ed6fc9a8a644e174ba754247a7319d29a2d250be22ad5e7494d649b11898276a964aafd01459781278f83a80e6764aa6f07eaa4e22d1741ed853c68c6ab19999edb739487eaaee49b05113ccb3c725993fb28e76ac53f00b9ed3ab5f6912e0786fc1138fdd9eb43b407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71d68496b94fdfed16540c30b13d0d7e65a4ff1bb1b73ae867b96e7c912b00ff6a0ae752dca9264748a313dc53b63231d29e9fad3bf5e6ec9134177e105125ee610a1f9b915d9b65deb6f9add45e7b03240fec592fd59851a1fced2bf84b59977cde42db08d3a2ae3363169cf1de0faac09b586e3da4527c94f3e773341a31864c9cbe171e9d2dee147797d4242195bb40ac11e174db2328fe1eb75af660ac3467a41c20b10ebaf33b287cca0bd628c8e0776b9bf95584947c130993f4560f6f01a417c3a364675ca3cb6a8235ce24cfc39325150995dd367ebed4e2adba7efd67f631073311641d31a868698b9453e88b51df1f6dce9144da9ebea27285a1260bd849ef59e925c176159e087d784b4c571ff12c63386066a9565234ceabc1d14242383c5e1385b87afd269b475a6fde0ffb7bd90e239d010036426a9102aab37b5e7822263c75b2709c939073244489a929410cd8eaf39549a7f7e39808fb43114cccaaeacc16d611dd34b249acc4f8bc2276ac510bf3052b08e057425c87fd10a6c6f7979f5044137535fe3f4335ab4d53ff7a251b2d799539e0852b557861591858ca58ee54562ddd8ce1604479185664a744017e539e3a7737b7eba00d76750ec72e68159e3a59b6311dca75e37ce70329997f97069f11df50dfcfd9f0527d72a5f91327ba5470d80b2854a57596101f5dd528153c8e07bc10fd47d0ec9c6b3ca84536e7b0ef7109b756252405947adb4dfeaf4712a116940f296667427b1c3451595f904e1bcc1ecaffb327a9375f9f09251fd12a66f7cbd6faf86fe9024394f1eb3df27c88e651042254b623a6d4f21c9d4ff62f4819dbe9e6a4ef2e243a664589311423742fae46323f94994ab346ac1582f51747493b32611a563ad057baea8cd9643b8d548fe547146d615bee842aed92fc83470ae7116abdf4ab1944e02a488e8df0f2c1a026bdcb1c9e5e273773626b603e9c7ff6b9bf0beb5a573c6e918efa944501d59226cf102566661ea103bbe11febe431a1ff61e7c44a9852e25b13c8f1bb89f75aa4f297f36eff83fb89c7fd7627643fafbb62323508202f6cde95375caf3e05b69ec9d53a3c3d46d2c269274d4c297ea4c1849854c73f6f6841ca230369c180417f4a65f648b88e8a5dd04c309f31d09161a0207dee3469783daaa9274a0ebb267618be37418eb65bd822d1caac9f77229bb6c60962c515e8b207b02674157f4b2fac359d2595191b18223ef8d7a62f203c30dfb407d3017a45f5b334202ec3bdf629961bee8974b2e756e4c7b638ddcb558e8b8fe0e802bef767d681dba2b2af833aada512c7f867dbe6e01b2a7eb49c7b6e50bb8d9e6cfa8ed1321b415771d5535b817beb8831160ffb5f256a040d662f90742d2be25580185bd09edd014de26223b5f1a82e054dfebb79336d891b767f8be214f88151b8a8ed8bf99febaa10c51a9b07f80b130f73cfd4d1de282f6d7f5ccefcccb64a4ae407d0c8e29650b1c0c1c00c292d0afc5ebed5da7e7a9d0eced3c6894548043aa537407a69dfbfe0fd4dffdf896a363d75ac5707eda016347a63abfaa6435132d554abf826a19340bd0f7c5984343cb49e89936f55f2256bfc32871448794ea44303147839275ddbe891c2ce4f93b4e51ba2a2709de73de8b659f9ad0d8a6aa8e2f1c300418e07035b4a39936ac69772520c167ef33f576198a70bea1a3e6a4810868fffb8bf70abb870ece4fd40a2c286d65a1a768776bcdddba218f6854236270d550b0acdb1e87c0a647026b5982426dc8bfd02bbfbe5ecf33fdef0b048ee02ee85779a0ee900ad2e02300ecc774f73ec419fdd15546141233308dd4e05e0bd98aef19726d7d2749d8f316b798b87ac700de86806c0586e96d5fa35d908728d9a044cfc98d6435f5a73643ddfa896ed51671f0a76359ad302d329a7d6489c3cb77d7a563214f32cae5c3ab5a379198c36ac46ef0f151a21bb0db55720418ac16e2487ae411a37a41f7a086824b2efd39c94b3494efa7c1b708e360b380cd65c6b0300db4259152800ab8a88f85e276b32399f0746cdbfd93182863a850da4404584a8ed17f70aec3cb4412c17b854cbeb6e4ed1e94d97bf16f7b343ff7b1c0d02b11555ae20d30819e6ccccbb44b7538770c3aecbe7351ded9dff5a0a7c66c2be38a68a4f8d2cb06766b1cec3242cf191ff9ecec987893588a89b042c2034534af2f0c4e38ba3617ddd1c70bbd23365639fa7cd5f191861c7fbed74a809b4577184b74582b4774b8ddc3f186fdab84f01e0f988b74bacfe932f46aa7023309f130f7d93dc434d02fa0318a7a63dcb6fc7a8cccb8eb8452ee3c1cb6540512a78cc5ebbb671f9ad9a244567471923ff0a04fb615834380caaf01494ebc73ca0d5c640440be29f2206fae788ece44aca654e36a2ea1777e93e939111387068eae8a7ac652da78f63545288ebe0eeaa2eef9ec82ba6bacc11acc6e110d82f4a1c698336cca9cda4ce660b4873e19098521277c6167a5090ebc2df903b9e682728b4a3ba320237b20444e34f94f2c8f9d5e0173b28a2dea1a88f7e40403b113752a6f9aa0b49ca6a5c34a2b92b2d2bc5f480ee94faab28f01dc0d7ad19392060a4f0a8a95ad318982f081ab3c35895f83a6d4611d888a1a0d0a8ac62075ca703c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416aeec5145d93ca5215998b118cd43fe6f953be84cdf704bda68dec68fb14c3e6490399277cafd3b75630f0b826e2dd6d287a161cf892fbdd889e0c6b19cc0be4bb41fcd121741e20510209b0740cb89c118f190cae98339b07e65df9cc9dd126b9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712122d254e33b7c35d78ed4f76db5578f07a6c1bcb7dc46199c567c4a61f84c574fc4ed042b0f2c8397da95d7dfafa615f163ee77de3725afe64561d65a370b3430bc9746fc125c950f425b970da866f8944bf368a765eea617c7ae949c214c405a9250eaeb7dff21e3804b3656037370d9b2694a83536a4e924c9f3dedf1ba083962d04439175a2d98c3e54aba79db4b5fbc425c1ae4d759878086569d2afcba33ee7757f605a7b0d7d518a7751ffc17479ef2cdbec637e4bfb3dad4d8993a553d0ccbb191f4be4cff5ad204d9ef12e321d851b431a0487b9b00a71213f2c95a3e48a1025c18a4bb04dbe9c259e0ec5a57863699f0eb5efd7767175b02b9bebf4eda442aa4ea276a4e1cad5e196a6945f4f9feb7e434a747a9244eab3dce1ed9534262c8fbfdc245ad9dcf846980488cb4d18a79606fce942d48063f0455392e5d825f515af082f6906036c246bb7b1f3b75d1344466e45c96967f8cb73049970c100538397589fa07b331c10ff03ffcf5cac1691840ba63344882cad3a161b135fc74cd2834b4d7d555117ffd19bb23e6ce26d31a3c34bb5626688c2388f32937ea6edb9107df7695cf745e061c1c8b98f078d88f50881eda8dea89dc75b6633f1c7fb016c01016f8225393bfbb03533db594d4e1f289484f7c5eaf4babc9ff19d827a1b3dd1a3cd1ff4732a3826ac5a468c6464286aca145027df161442843522e2ea9f89b72832b1d5fe563cc115c44ce2ba0c383e5d6824f8260f9697397660eecf2766560b1c77937fcec07555c995ffa2eb97e7bed217c46cc798a407a054e3e8c342de20d821c684b2529a9260b8c75b32c9e0232f6870db100b286915baa9ddfef29ba03584ca140af25d0ae285191427484dfca3a722f8729a0c76d7fec1a9c987bfb111cc69796ebd1976ad4ebcf4b3560c1bf2662f77a10271993092016aa2a13c0e05dabd3e3754bbf0e87775ff06bdca2da1382448fbabfde07755a6313b77aea6326c8a3ce609b67aa4b2de89a10da711cc35cf593e91f701a0fa8e27969e0a4642d03481c477ea3219946b9e8b8b1271dd6fbc2da017b45d3210095667544b271eedf036d8b2ffe8d5f903ac79718d2bda2a14a9fb3cba6911012d8f0e3c51c77bd269f51b501bc3056358b894a4efd94d6f3ab31c60a2e6d42022e0b1f1daae90dcba1b96d681a018636a09bfbc8381cf40a502de14de2b67adc4b5aa9706a54c576dd1caad7fb29bdca6dbbce5cac2eb1e65d89633e3dfa60aae7bb0cc818fc18b6ffff18592e8e8671eb94ceb0c2e15b33f9f54415cc9e626a339aaedb6cdac744b85af70456c65c9025b86a7426169cda4490dc7f20d0220467f6af1ed61d0b39bd7cc4f9e94861a28fa6f27709921625b455c2a5981634b644f122be630c593c15b16fb21e9cab0fc7b0140c981652059d2310ea20e463dc56e7b203c1dbcce46929b2013bff2270b86d4951584ef7bc2472febdcca611282f3dd2a3026e65945ed13d52e629d6d6a120b1f6442b75e0b2660e0f05824ce468bd570a388c6eda0d4b98552d27b9aacca2bcdf7f90b75243f624e0181f20683e701c397f4118ddc67c11ade82127f6d66ca2b4137aa4876cf62bc50a203954cb3460a6f509b816726d7b0427c7552a24e1ad207087af15ff6e5619ec37622a69b1d98b990ab979c98b9a66995d1665017790168ae8b5dd1608ad0bf62c35c2ac54ee3c95f27faeedf474fcf1fa50ca27f2087b110a88585c255830f56048944d2868c4978492fa514359fd3ca4231f9a3b7689833643ca183622e8cd9639ead81d38d3c3ef6a38a08f0415e8f2569d4b698449bf2c5ca74346454838e92bf4ef4200963a061b35007b1a77d0b68fe244fc7a65c339aa06f8fc468150d649eee8dd05156213b4b376830067601b89c2f3ecac6db895a8078e65ff80e7d04e60ab0ec43fca15dc14d5312371e0b26d5cf58477961dbd96fcdf2b31d78c450fdaad5e9bb9248f6bb0cb58946f2e01dbe23224e6af11e5eaaa5b6d43d700a8083e97f57984a6c431796df3d153e6b310d25c37fd451bb16e2ed028aa7b09e42e10f820389a6e253f09f99692ffc4359b494a30096a3eb8a5b97c3aba02933a37cc732e055d41a2acf695dfa9d59dfd5627864efeed20c24ad2ecac463db3c12b4ae5233ea7370c02412b04da5cecbbb9154f804dc0c8e74e2ac9daca31a3b872cc38779f9c7b1a6ca93f2c4f6d04a6b0f3e699c8a40511a2e3b9fb7f8972661796817ee864c2396b7b2a9f349d959b6fae1d66ec9104ff9c942f030e65a8aa546173676eee3beca7af1636aca17582f30829782e2c9b1b9c72aaf8060563ab378657bf91d13f2dd4f1bb6adc1d6da398e1d9b2a4884c63631d46aeeac4ca7348887106b8f07b427790d1cf4a2713ad56af6e1e1629ef93edf14348535e50013d4a33f70273ba18c23050e010109645dd600bbb52809754ddeaf668a72b443d63901a6c759e4cffd958b68736a9a1ee2ebdff616811e63d43b100947549aef12a6caa34d62c1fee27f253562286a466c2b2f91a711cbfaebc527f705bc8bc7351cc7bd57d0af9f150e6466174f1da6ac71c79a2a4df82d44f585a3865f7364024c6f9a7ec7442cd32dc7566e2531fe4366ce5e22aa6931f8d2cd5f258b334011fba79242837b662646211a788b62ff54a6e9bf54761372954bc5b1503cc1b49403054b96be468c1f8b22ec177da74fc851f7562a10a49417b5b6a76168f52931be46aafc2211ceb98056a1bd1102545401d8698944771e079f3aa93974eaf9960d6bcbf23b14834f0d7034f8d5e6589e4a7f13f65e72705884ee8dcbf1360274ec269f1e31a344f8884e5ae3450628689e6356669e7a94e43ea1ac65578a8a21d8cf64b22197ab966b1a20a098fe08768b0f5e53e25c71864a657cb42ea209e757e475ac343e5f8f85b776ea6276755f5d9069447d01bf34604c0389a5a80b7687ca74dd548b3c5d98e4f70c9a85d29ddd2296fa1cb8be37e5d8701af88c70c55baf0ef059358fb8506ab8dabcb8642da7052e6493cc40a035dc86b8d5c88164976f31fc1f72c9a86eccbe29a1060e2a5b0d6abf7c452613018b69e8385b7ab509e460dbd802cd49164665229340e29a14dcadf345f493f00ebe1d829515c6528b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d5e8fcf6841f2e94ebd740f848a2b4e72c31c7a21aea6ae8917400c81d43bb522b64c2aaa0a1986e68954e4ca7b5784088392fda54f4dfbac75e454458e01583df2218fc25708efa7679c23d318c33cdbfce6be7e9125002352d34948fa8b3a67aed933b6c623a04853e8e76cab3219c59d5ed56410b366482128627181b5aa4eceec7f1352a57bf84ff4eb62099a8875cc61b06d7c3dc6094fe96948c881c60eea50f1aa4ca2c2c57af4783c613dfe8392229ee5fdf145d7506ef3d9e559246558463ea4005ea0f83e358d15a789493bea81664169d09e26df8e8e3a2361e6226a54c73b0bb645b846c9bf3c2883b4936fcd3f629f9d24086d9ce4c20cd226199884cef69623c717e7aade3c1f270584fa38cd0d9b6a56045e318ec49ba8a9615abed39d47633eeccd98be10042d5d03d852c5bd930a89f0ce256a9332521f287c5b3a221df63628851acb241908838bac9774b28721290f082f7b143e8d102756d8e06152648b0c9f937d26c08490a5752ece4b16ced9ed97d75143de35326b6e46ad517f13ce464516302d89289478f09e15905bf5d8326d95437860df2f72c0d2cc0f3c40972b07c54745de572f912a58b2bba9c42f105f09be83e69491690a5ef93a98dbe72b55880c843da199106393fa4db8a6f659207f6f419b31a678ceaadcc3330cf95892fe9ec136744640751b38026e009740867b10de8eb67f15a03477bcfddddd9319bcfa6de112cd37ab5040bc19e0b3a52f039a6ba60d2045f834a3195e89e19ae67d96b45a0bee0beb3ec45595def5f6e8fc37ba73c0515e6ade7566e5eda3fe184f22a89211634ed256471c1f3e0f3ad64717fb58cd0a44709a330f39d5e8cdb773ee71afdd2f9d57b44fa579937be3aeaa1adae3b57d047ef28d1fe4a0ee885dea9edf31e01e23e896796b8fcdecd44b4b180dc7e02617563ee5edebece3368fcbf345b930c92fca7072eceb55222b960c5f7e0fd54d58b2a296fc8053d12508a47fa99f2cbd5b7fcea38d04fb896e5421661613af2b53ae7f9cf9da7141efb199d0830298feeb364ff4ad75fad31d8e7285e6d63e4c3f149c65a859747611e99d8cb5d06bd5eb20c5121ccc64e431ffb0c6981f059d02a6924cd1ad196dfff80d76bf99383b20bee491a49cbe9a66f16ad93859533515ecaf1ce37791cdfdcdadec44734ab9a4e4d16a25f18d2e207f66037bed355c32f0b6a53e8785a5b3392bb92c3a0e904b1c0e100735390c8676dd2da11747fd6014c06cdef71226f89708e71ef9c6ab3d95def2dd7f487e42efa411f4eb05a33bd833c6d57f623b8f0c8ed846045cf44fea32bcbe0bc04e118f3922c6a45c890e469de71ef3008558f64ece794dff8660ca2d18a49e2e7b3beaf1e6c903da7e0e8af4d2400c18023b5de425d219f9efcafb72aa555fd994cf9f67ebeb5de47b6a84256e12aea7e877a8b9b5cbcc01119aa6a8e732f551d99dfa4fc239739c0c1d9c415bb13419d4c73469ba912eb7d346b91629642940f117e1aa50a09fd5dd48caa48fe936563f4a200c29d77a80f5657781f6849373684b82a029b1fa3d2c566173676ed7bb07c67c2bc80e7d5ba4623f8ef0d565d266723ec60497f0375b3bac140000000001000000020000000300000004000000140500000006000000070000000800000009000000140a0000000b0000000c0000000d0000000e000000140f0000001000000011000000120000001300000014140000001500000016000000170000001800000014190000001a0000001b0000001c0000001d000000141e0000001f0000002000000021000000220000001423000000240000002500000026000000270000001428000000290000002a0000002b0000002c000000142d0000002e0000002f0000003000000031000000143200000033000000340000003500000036000000143700000038000000390000003a0000003b000000143c0000003d0000003e0000003f0000004000000014410000004200000043000000440000004500000014460000004700000048000000490000004a000000144b0000004c0000004d0000004e0000004f000000145000000051000000520000005300000054000000145500000056000000570000005800000059000000145a0000005b0000005c0000005d0000005e000000145f0000006000000061000000620000006300000014640000006500000066000000670000006800000014690000006a0000006b0000006c0000006d000000146e0000006f0000007000000071000000720000001473000000740000007500000076000000770000001478000000790000007a0000007b0000007c000000147d0000007e0000007f0000008000000081000000148200000083000000840000008500000086000000148700000088000000890000008a0000008b000000108c0000008d0000008e0000008f000000109000000091000000920000009300000010940000009500000096000000970000001098000000990000009a0000009b000000109c0000009d0000009e0000009f00000010a0000000a1000000a2000000a300000010a4000000a5000000a6000000a700000010a8000000a9000000aa000000ab00000010ac000000ad000000ae000000af00000010b0000000b1000000b2000000b300000010b4000000b5000000b6000000b700000010b8000000b9000000ba000000bb00000010bc000000bd000000be000000bf00000010c0000000c1000000c2000000c300000010c4000000c5000000c6000000c70000002b000000000000002800000059000000020000001e000000" - resultBytes, err := common.HexToBytes(result) - require.NoError(t, err) - - var sessionInfo *SessionInfo - err = scale.Unmarshal(resultBytes, &sessionInfo) - require.NoError(t, err) - - //require.Equal(t, SessionInfo{}, sessionInfo) - - encoded, err := scale.Marshal(sessionInfo) - require.NoError(t, err) - require.Equal(t, result, common.BytesToHex(encoded)) -} +//func TestSessionInfo(t *testing.T) { +// t.Parallel() +// +// result := "0x01210350000000fe0000008000000096000000d200000000000000b0000000bf00000021010000ab000000970000008500000051000000c40000000800000028010000a700000032000000e200000016010000bc000000f9000000780000000c00000088000000f2000000ad000000260000009400000046000000120100004d0000002300000009010000cb00000082000000750000000e0000008f0000002f000000f8000000100100003d000000a000000006000000c90000000f0000000501000065000000540000003f00000098000000d600000047000000b7000000df000000380000004400000007000000b9000000e70000008c000000900000000a0100000b0000001901000042000000af000000020000007c0000007a000000240100004c000000010000004f00000063000000f0000000c7000000e60000006100000025010000d70000009c0000008d000000e30000001800000019000000030000006a00000003010000ec000000fc00000008010000ff00000058000000b10000006c00000043000000290000005f000000fb000000a1000000c20000002a000000be000000c3000000600000003c0000001e0000004a0000005e000000200100003e000000c800000093000000ed00000073000000040100004500000009000000d50000009200000076000000110000003300000055000000a6000000fa000000d40000002000000086000000aa000000560000007b000000a500000015010000bd000000b30000000a0000006f0000005d00000005000000180100001c0100001300000069000000e500000028000000a3000000d30000000b0100001500000079000000b500000068000000350000000d00000031000000e80000005b000000260100001200000011010000db0000001b000000d100000059000000070100003000000016000000870000002c000000240000000001000070000000360000007d000000480000009e0000008a000000270100004000000057000000cf00000067000000fd000000f5000000060100001d0100009d000000cc000000130100002d0000007f0000001e010000b200000021000000e900000025000000ac000000ea24d73b1607c8fd7d6542870c2563c7891a9085b74ddd253d4322a9b3d3d1560600000021034a3487dc0c46f976d352e5e152e120d2d23774f921583d1f2c128f7cf9f66529d49f031c94d9c3b33494849eb9682c0311b3c283b17373f18b9ca02d94e2c05c969ae5d9d6efa40c6255ec4b27b0a4752d7f4068163116e76cd0d4041c471431e8c13e37a4d00135dbe7699d91507f5a53a7b8ed36a3be29cb2fddab9f7a286c347964127e9d8bcd119989a92646c80886c2eb8440c87dd7dd94437873a3ce286432533fdbdd1a739c62733cb36ac48c821dcb0311978f1027bc1e39d4c8964e6a6570b80ba0a90a857ef4ebdabfbf958898bdb12ea1edbb17eb903b00746a14e059357312bfd525317b4f93e5eee1de639872edfaec9d2a320a6fac04d6105188fe28737bdbfec193327886b5c4906675d2a49ed43fe8cfb4e079698de82d2d042cd5a9d8624860310a963ed20c4192a19a9d163bcf366e48122c00a1e9744c5cac0ffa042ee550a3bf70d380dc032d11eabe311e0796c5143341600ef626644eed0663b1d15bcbf9e99c372c041ef118de7d179c68899a645a0fa0983b473eb2a1fefc7a956231a446a575db2e31f7c084c2945094f3927519617d7b913712c60cc4d544536a7190ec68525a70fde1309723986ab984a1e97aca4092ad721c744c3b91b676828a5f884e79d9c02d6f23ec246c3a1a8adcfa9dc1e531a9a5310e2d777330aba66c9558434a592fa5e5aec49c3a70f49f66017f194d41240d66148f2b835556a0c8d3b51ae0e823655bd4aa20fdadc6b4189de9f32cf2288700d8eff37aca87eea6637118337fb1704bc33f1fc685aec019c8e9eec48b62a728a8cb454f4e75ed6d28c458cd8df1c2bdce6101e09b650fe22d139e360fb809200ed18130a0ed0513b2a2bfa7ed6c9090cb350983746b1936c6a92f7304a7005450b1f33df75af8dfeca1cd7e94fcce445c6d55651259fdca2972a4d62f6732561af7dc55da09babaf097d1304b4cde14562506f4db4897644895324b542d8f573c39b3f67c487c1df902d0397792b7cdf987b657b2d27920bc6846eca466c155c4b778017656b9a7d69d3e69159852f38adf971f5a25df65f9950e97411c1c36e8bb9f2665b217df30a15bcd22f231f66f4f21711363cb0b0da8b3594003ae014e8c22d93dbca83c05bc5222ae72b85617956f04eded477369ec95312c7c78353256f3f643ebc6300f32561a0a5583813bb3b42844d1ad3d3779a438771a295e306daa91a5a25590d2290fd262d40f239f87d37e1c03a2494035a42961db2f33407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71482cdc214f825dc7085e54a984230a753d66d08425f9763f52f8f68911120260d4d65053a5ef2ab1152c72f3b15d4f24d4bced3b7e277735eb49450dd867c115263ad657e55682de826f6137dedd2d246971fd8c5d318034940160fc179efa63701058e68510bdf68a3678d32145780e13c29b88fe77b27440bdf3ea9762a63964675cc62a59886ce5fc12d2f48694c7ac836a0157e0e6630d694d11faa605034c51def135330ddca851fcb670c865235dc1b405242cf9f7ccb728e449e09f4ad614110699b5642a4b726cbcb74bee77642ec7b4f17b06db88ee461848ead17c906f769166b3ff9b0fb13c1ccb36358d9dda3f25bfa18e2857fe01a92328eb70cacb5514b570b9338c8602cd4a49128006a902494029c2728056b02a900dcc7798b499a9c38970f6f3dbee7e6220ee0e12a582a76ae036347816baa6cd7c9a7b9662caa1a29ff92ad66794001cfaaebbdf4071f4db6d74ee767ba59cca4cb36cac6854840b7eb103ce5723aa0d6625709d4c4378c46903ff236d9d8d61f21f76b22d6245ef2ea126366dae7f9c072d2d6e0e71a54c9bbafaed36448a4a552b51f02a182d14b38906ce1f4693cd9b87d0369e6af514cf7ec91455b26cd4c0d71bc2d3f9f9f499e04d2f27dbe47ffbce115afd1bac9fe116ce7fae719325e4082460c09defe1f43c8591655101dd3dc806c7b07762c97ad21e4142705e46a1e17306b888519767218eed7b884fb221f597a2d4edb69c094961ace2e65a7e40913c0658f8f3a64ec6949a26916ae2cd976fe531947a9c9e93e6d587bac746cb0826e4b23b64b0eaea19cab0333369b93e11693d2b4334306ee579360814adfc1339524dad3d2adfad0b2db5fc2de781a22fc63dbc4e30a5fcba2c63c2fcbda238668e06587bec427bd5b5cc33da6f7cabaebcb7688de50b59125434493fadcaa94d1e0560d2b374b7d6e1380b6b88ee8ef92cdde7edbd9a48d66f5e219840a1155818b9272f50007b87be88422e3da9599286087f5e578c0d1c2a3db9a77110f9173a69e0e58185dd4e76aa52804b2de15ebff8c3f3237e29dc7157e61b30b9b00a30f93bce6916b6b78ce4f7d550c39c7947c6860502333717d541fdb6697ab447aadd01c0f366ff1c65d331da120ca3ac630ea6e8d7339e7317518920d710e3325edbe8dcd591d30511a0fc08bc5172ff58ff98fa848387b25f99205361348105f6c138e9e4061b3a799bf7987ef5c820c1e534df298f3328e1093c5d0758d434280f6162242be89d139d52f449e2bad667d7d974cb80d0edbce7237185b11475fcd9b0171f73154a0734c1cc95ae552d9f3180d7d64e8b50d3837b14b5afd2221808dfb6c44ce63a08d4567cef4b2a9aff1b408d2c99fa4adef25724cce85368b429d0687fef75f26e5503379a61920777ef1f254af024922e382dd19e752e69784ff2911acf10ffcf4b1d795df6d8b55f38eceeadffe577cf5bc0360f35005940c73278b76425a158be63207452b1a8018f53309f47486a273b9bf60cb51c48d67770af6f19ab75537f06388373ec17a3c88ff1714806c0c99ad44e6dbdfa713ea7825552b7f76db8f2ba2fce0e546d7e7abab7d59e7afee2bfe438bad6091934cc7903dcaaeddb2bd99fd6b36ab15fc32ee001bd1d95e87020019f7c88be2e74afd1a3a66e44e8b7845e7f63923b706dae49eb96cdc73b04c9e6cfd1459d06d6f02e6854e6df29f08f7e015d511ff48d7bbb13bacc9aab1b06ab73c1f3350ce6a864e68dc99758ce2920256f75bdbe8c918c556a5a2467a3aa13a306808740484d1bff4961f87c7ff6a6a68beac9264665f87ba1a5fab9802f1cd729391a718a7477bdafa88e49f5c8cd88fbcbc1724d8e227935eabce71ec303d832c4ab27aafd3f8056d3462eda0083ac22241db692c4671249a14a04c2f0a2959aab412660bb493e536e83addf98be8cb2a0158cf18c6d5ba06ab586a2cb56cf1ad4cd099ef1e3e727f41ebeb3aea2815f004002d27714db121fd6f92fac8bedbb97160976c4d221bfc6da82c7055e469a1405eca842b4b8efd101e984a2482e526ecb085229a5a3f09f444f6d39d71e0b936cfed125e87883db8876444288d0cbd17642ce97b61a3cb7d20f9048830a34520de889098b4435dfc79a73a0518ba9f61924de365e70f8503654e384a4524c1c16900873792541ef023019a68f62250b7c219a149b9b68af793ab31f83f500126e0fffa71469e78e22e754f3b49db1dbe631f286ac449dbc94282864e76dac48fb9bce48124189d2d45e2b2e16b8084c022bcc90ef1acebf194c7b9820968e554e2ec4d34346eedf80cacdafcdbf118a3f158e45e6a8766869e2e5418499d3cfbe215762a4a0cffe4315edea5ef47c60c163be4aa5196c5241f5c772f3f90c57a3580fa0735a7340e37372048c1f60a20531f830d60634a177f3974d5399fca046417a6e4327c4c569d8f4f5b47b263b0f07408b1d453ae31f699e53904605cfdbaa72639138cea3e544258e0484a532216372ca569751b32be145716eac8ee5e731a1db2b1dae4b9023b05876077cdd78084c79e58d16ecbaecee3965ad4685c1780154b678bbfcf725fb2e91be3cc0864ba0f682ce1460eff27c8518451b3a9ec811e18b8839808256e18a89219fda2772c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416da5bd7647f8d8388c2b4dbc138e36b8679284eadc49370ce0a16a4e0be28804b04f9b593ec5987c0608e3913acb29a322355a554e010d33acf155e6ab9bad337c4bc688653010a7720d44168b4552bf75974219788ac1cf3fb440c67ff692d499e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd93257121806eb5dcaff87a28d25de336e240731a375be04c4bbff6be6a5ba4f1042a067086008bd1c894c74e4ab0b16dd36effafc8f04a4617aefa7f68b40df033149c0a98bd89778f1276a0ee404b17d81b96c524a8aeda9f671be9e724f090c397977714f425d45bda5f3373c374e9b2710f477e2e923a0f0b2b259c941965f6e88c0334fe5947d75ed7ce18612988df5f227b149c66f371593a8c248206f1b59e10248e650f7e08ac882d65fb09141fc5c7d252da9b1d8ca2ae311752ddce977137229ab3993dc198b5cfee52c273f6145c25afaaa6de14670eccdc1b61fd53821513fa519134b630c1d53b78cbb67e8b8414c30247101be5de118662237b8388cc7d3c50b2fab9b87f1a6228df23e9507c90bec51b8e3be978b526c0e0c7704c7334dc8495596755b6b5a83796315f9e316bb871c0465cac91290b34812c5f0e34120ce455c4566893481e7afa89c0c425533fb4eecab574f0399ca29b162a4c78053405a94626a6d3cecc0492a268e974e9864826f8745403fbb98f55bf45c0b620da0f2b6e2eb2808b3e713d1a3f774966e3e00f81226887d5e1c165af998d6e57645c3b5a2e17df20f698507190332c6951d761c5f46e0dcf997c7337c0bb7e54e232d9f4c8884a9f53a999e8ce7a27f68e9108a4fde15bc51a350774c22b2a1480fc5fd10948cd231f68ec00397e22a19042578431aad63546679e72efa3cc619c9564390d54bd989ac1fb089a57964ee4313f857411373d34161939633c8f4230930357b8b54ce94dfac3276daca91ccbab9b944bdd9754fb27d2b786427b30b6d3a029d0c998a49c406fb0778936c3bbd0708774bbf21b400aa8a41e604401c8e5f3c9fe54712dfa93b8f223c4bf30e2d037a36a768f160cf0c6e6a8c42a45908fdba40941f018589894c721ae6eddb3ad080bfca4aae349a8e7ae261f0a0f18d3fcd225254bfac8ee7f94e5f505496773b69c49697eb79ef8523530c55511106827b00917fd22c6b8e62eda5e130344c9214f2565b92ddcd6b6edfa18e95f8afa23b3c8f159391a3ffb6dda5ce3c9f6b40f25c1dc7a742186b7b693f30111e4b9ad468b9d1e0cf4f79c5078c9cc4e409f8a0fb170d7c4f421ed5fcf597e3f061f1060d5207533b44b4977f128acd44bfe1bfe235f2f4b2d042a87c7da4d1d526a096e110f710d48d0a0bb58b06ceb1d6ba2189ac3dc984dc24e80fb6522431e282ef8862f121223f6aa19fc1f929106d7a916747f21e1973eec1e8c5b7f78cc3ceec15a5af2b64d5a43ae54fcccd31ddabe95461fdcb5be506267404ba432e41161e6df14443df6eadfb3c5ad5228291d1383cdaaef20c9cc8125f7952f249a0de7093e895f4c599aeb4b0310673b00785b33fb9cacd556acc9abdc3de57fc056df4318d12a052ab505db7d06dfe03767eb5f46cf0d271393db1db2516c52aca4be351c39cc0bd557e7afe547a479f8a7218cad2c784e197f3494dbb9436292833db878c0dab763cdeac36e752c7cda12c98686c05704a8b2a695a315bb1146b3d1cb07cfb8d2e13fa9158734dc2bd1ea554fd3032bdbf9e9871d2937060236da4573a6c20044052b270916290b13a30adf3a821b467c4038a14026badd09126d6621e31b47269829a47f9be24a0d63c4bd7ae112b395498ec2502c3b4f46547b4c766e40db6b1685c455de210347c5757ebb7d463d1910eb70fb290b5c7bc63163ac00341573dfc794b0d53e6bab40a84e60ffb1dc3f6642aa1a246ee579703579df75d2c2dd3d53003f55ebbefeb59446d476d0a722ef8ed1954fae9d6ddc2f1b5a31a3e46efe8097d83d7f80ec284bc72a48b7916a74a1cad145eed554722609bff1c0970e439f19fff06a080a67677712b09762b90a82fd9f97bbc50c12b2408a440f2c91824179203d689db4245fa3087e8b01a9316ba973c6ed1a7556aee499b2dffa90a79b118a646aec6b79e6766dc25665db73a98e173fa6381ae47c9de57628b53ed9958a889d278fe707b4284327bc582599019bfc4630616b78f186de80c5d2d0669404118ff1591ff141a606e05e2835889a5f42a32e9a1f34d4c6438f429028ba64818bedeff64b1db1ebdd89f2c2b2fe3336942a03036b9e86a336aeeee1b94c5d5a821e4ab4c136cbf2766a43dd37078e02927ca8a562d2ebb6671ff854613aa3ad169250e037aadbf0ea14c87982d7382f09c7b8c96770d2ffd3b72525806a645e5abd09a51d257c30dcf016435c114d26d3d3be170800af2466b5e4a434ad5ef602a77f311fa22300a5a6ebf03bdcc04f92fdf0da3c74f0c1461d8bef6e668a2cd0c95fdfc9ef30cf9133619aeb9c3d5187f23bd83c765478a56c4b3708da965c36dac2e8caca9398d50bff836219540b179bae7667aa091181db267cc8ff6c5201acaad6fc2c3a2cd18eb729ad0c1526c6c348e330ce5d949162cbc728667ecce548da5efe0448823e928463418342d41883dc6e20d8e45f1d6d02c43c3e38d6e7871f18ee80f60415adc76fdf4c8ad2c67ac7d11682942ab79f74656a8f51ab8c1b088f33ddfa20992eaaae491dc3dfff9742fe32c4428233d691dfb69a1713087e4fbfef8f7c96df760e85354069eef1ddbaa01d52f9664fbed82ddb5cd6ceec78143f1e27ee7a0fa73873d01e80e368825e3b05bef7cb0005833a9d0ae360c420a66a5353836acf1fa3c65578c9c5b3b9c7831e944ae887694e9fc6a8634f213d8d061cc2a34a00f214d9f67cd17effc527a07e060bea20b143a7bf515a130000f93cba10536a1204f0a14cdba7b627412d383c308672a7e2974b837e4a89d54e63c47966b36fcfa3efa5854046d3ce09d45f226c36aa9c0762a59eada83c70e1049d5d09f7f7304c465f2ff56dbe21687ece20ae9fcd9ab8a7020a1f967780a1ef49b13b40fc3cfd208e29f4d5d5ee9bb63c5fc81fafe5d47c4ee373a54a64d267c497c59f4c15077374317b91566d44c82f74167e6d847ad207f3a1221ce1f958946317e77ba146d16aa7bd82810c5e913c4da0bc5d3a5923a156f0990c79f01317a3140ef3aff708acfdcd30a838706db819dc3a5a9fa2b1bed2a4a48fb21792b44c5772f888132d414d13a98bb5bbbbd70ac42afa68950568131a449e70574ae0f45f28b87210c1ff7df1adee5576d03950b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d9a53c2f9f5f55bd687e359ef37196cd288fcd1a14adf6cad53c6704445a1f1212270467b0c03fcfd8bac09473161c6eba9c25369a853193b472eb2f113a3d333181e6b71b981059fa265cd76422e52fe175db6983c6ebdd0fea1a3075166b9291619ab90bff00f89ea8055f0d7d45f8c8aa9c04b7fc1d06468837c6c563a6529ba846878e4f157741703bb4c3ab4f3ff2e9b99916624a9965a4256d893c84e152c19794d20de22edc9c4c1514f4f4e29ac16e6b421d3620ec6545f737100f0134c29c11128e193f06c866e165662d903d9f799508e617920d786ebf75acd267462237ad2bb39f6a5a03a46c5a1dfdd3766a49e6c864ac5d45afa6400ce3a9809de464459b18deeea6f02d5882e80a8696b00c9f703da84bc5769921053ecc749b0cfe1745dd408f6dfa0ceaa1780ad4ae1747a8912a589a754ed86373a08ff5540a471d9a8272b09df08db1f998000cccef325d072ad79df6c1936cf0ccdeb77a0d9c323ea08a0551f96c28b05ac0c7b0e338cc5004bac22d06feea5a8f5c00104906813ee195100f82600e56bb5756831a260e4cf6e5ad275364130dbafba4ed4f9db6adcdce67708905276a01347cc1c800bf6ba246c3770a81c3c754fd65bee13fa85260215c5235169fea113546e7b4aa7a1c936c47a14e81d3df912601a2eb8ece17888100536bf7183c579eab3e6daa14e5e01602a2fc3a64b563f591f0828f0bfffc49973cd14329675728a2d243102ab486601f1581b1e741bb5c77526552839c17a5dbf3b2f90875abc9959553b320da9f07f1392fa3065315a8b1744a7e5b271f9394d6e23bdab9ae03491f51bbf21014364d919388b7fba4b5341bc4b759fa4234adb292ab984f7b69d3aac2e0afdc7dc075e18ad22f4456dfa48b0acf62c24bb58eeb0a71365ba5f890a594cc046a483d9b306a487ea4eb5e80572d3ac8b4dbb4b6a02692af692160b113da09d4ae9f0464c5522b7236a59b70d3667fd3b0c5fdf2c30cccdd640a7297da408b6aff82ee9651f889910fda9f24c706a617b082d626dfc74a657c5d17c5a763044f0230972fbe47c907a5a8fb75df4afa9726d496332a25823148258bf60b189ac898c92b9be15965a199a45ad563efc761392b915b58613f9fb99f45c9a78fdaa4358874f739cee7ebf2a5cbc2fbee73e2731e18f347de520f1878f0eab3a38f377a9263ad17333135c991d560da02f9a012221d644717e2f1361ddfd9e6b5d0043f3a47eeffab15e43d7d45e1f6e07945d95fb46ef5346bb3a502da9f005d1cdc956e1b96258fba48dc793f50b7eeab48cb88c51118ced6c65368c5197ec7f014c443b47d898627cdb7781351442c44398d0ea4ca4b697ffd505665531e7d4b4406431f2328943e8b72d030842128714ed41e3d13b8aad0d076b7ad34af4946866f552568eadd3d3582b4c4f50d816c065e65b3583c8309e3465db95b458d0b42619e1ea75ca546e966d761c53645771381f31a42a1e0bca62f752fb49e8d2a49f942cd48a03129a709e763d23aa4dc84c88423861d1ef31f5df99006156570aca69e571067899ddb156a2027e0acb8f278b4e156f96ecf0eb2658c6504fcd39e4e20bfb5905be7cfa05ed907aa5041e202a49166a5e267724e5bbd0d9efe57d34d8cd7a2e536cc7aee14f12726065cc08d547840066bb56916d9bb9761e05133fd18a68324492ad7b9f9caa1668038a3ae897ec528be2ca7c977eca6cfc08a00266e96fd43a723fc7226b66aaa86fb8c0ff0094b6feeb0707b5cd61797ca034755fa42aab8c5c9e245157f5425f5d9c2de89a454439ff9ddadea199ac62ed47b9326a4a08c06859dc6aa56cf5af62a035f7c6b0546f536c07cfd7a2d8e3be9ac2c7b7e854ebf59eaeda5edad7dc23e83eb30dfa3dd91753614a811769d6a564e5e2b27c43c70d7497a0834ea96e50b6edef3369e8da5f707e530fcf611301be6bab8187386d130d1f8c94e5c3602ec613f83c1ce2708d6fceff206d25c511772a85eec3fe2b4ee066681cc6c58313ac304e37b46e43a844db9b7bcda351e09ad1efc57db99dc2a7c12e553ca9a60412dd6bdedd4ded92b9647ecd2ce31eda2a6f5a4ef9df833b9b4c70ec0924a92a7067757484a42e2e39a2c58cf41f683c3646c0e993fdb61ba33306f7524ee2733c1d970403cebabf7a1af318743767411fda52e046b2fdbee1680978da2f66413a00a72c2f0fd68497472feb62d2481dfa1ae93b14895fd3773d48635738847d32c4252393c6cb8e07655646eca309a1481552ecbd9569e94a0cbb6905c45717f0097f3dac95ce491ef6f07d89dd7a409b0f13475eeef708fbb0cac0f200cd31c296fc0f38221dca15bbd3ad95092e6a4f38b8ef8e9f3b9992d57409c7833c0e2e85194adb91496335138d5815f82e01ebc93b757c1ff94620f3a87ef48ca064b8daa8790dd2fda2c3493f33b66804385212b1c3747f61ba6de535688b2ec24db2b9bb22f1c69337d131a4c91c2b70f1b45fa522eb556b7960f937e6fba63e1a5c832c850ec9d476fa68c807d36d09edf0c1eb9b2995a3812cec5092b90c4c724a2e1e42195049ba8878f1d05a2e30251a57f7f4662d4bbe42ecc98b7399c13a00c82090e61c34b4675c01815b7e25a1fd09d2fc60f60ec1f3f435096790681cd676c3554c66ecb08ee954d3de09ddaa2e3d11f5fa4f9d4c89cbdce2c3accd6f9495757f069ede7b956256595c7d083b47c610efce658762467518bdb11be9597e37db2ce13f8b1b0cc42acf317bf5a8f948dd3977725de1590421117c9ffd003a836e898f478234d26fc7d8bf866a6a308f8f7cdaab738bc98b879669911a26d87f69b187cd620e910289b9d5c2704d332359fce4040b4978eb1527e743dc15407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d7162fa40d6ad22c0bd13811d9555f4b2adb0f639cf7ace8468db36e557c1e1176e4ac7db719c3be3a8a8fb077e5aaa181f69f89547570b88ecaba644b0c8623f793abe63296589646fa4fd48c7d15548b46fe4f60435bf69fb31260205482eab0226b7a3b02d5edba566f82d3f949278d4d0660165857965f123b1ff5aa680a62c6c7b8a1064cbfd234f3e26fcd14b1eb52a0b46a47e8a8d38027bb3fa2cba947124c41b6ccc361bdd655dbd0f0a5b5e7c86fb1bf779a912921794e17746c37f40e0e4451bfef8b6e07bc00ff6fe17cdd12d45db9f816cace50b0682291a8dc257ac131413580ad09206331a67387cdfbf12cee28aab9a8b0aefc03d6d1f2fde70a8c597075eec72c0adb7c050db76ed8d86e7785f056db19e02775ea099672c7f447c7d787652ba7c318efbd758620236476ecd6df6abc2cadf3488c7e6416c12b8a2bb40ce3658b1d71c42e68495a5504986f38696e56ba0fc2df70182a5b11fea0d61d2472c21da757115c4aeb85f1ad06831b0b41779a118995340fe6c352e6cbeabce345363e57dc45931c6bf8f278f704cf252234e0e580741af38024e1536d3b2112224e3432e605d698c7809f9599544725f3bbd89e076742a2e33631e2caf02567c87ef2729ac221651de0efa7ccc8de802d0ced1036b68b51868bd3686a8ecbd7b1a217342e937037c0bebc6a026371b85698d124c09998e5a531b6cb276cf5c2ddbf28d010e2a6976cf03488c0d1d11c5c1f9b23d7ac44ed221724baa63a6245db826d277bf7bed80169db1bccdc7a3eb0ae7852317a5fb2628982aa0fff7c6916548204396e77dd2fc044e2a37c192789053627b2c81fa1c0f3d1f7482ad1abb0ef6ca6488989637ea1d44a918f062b169f1b802c9ee6d05a2fe34fe3fdf6285d91ddb739bc5c2481ed4d77589febde82e624d0af0ff9796e5993242f7de325ac001c0d50c4d27c15248ae2023cbc52e2ee969b16fbef249ee2542026074c387dc5714b8038735a05a39459797ad1f591aede76adbce55e99ed94a98b68d8ce62060e2c77262da54a918fe5942925597cad811f00d13599f0062784e528241405f8618bcc663a513318815f67de9a13e6786615542b715d6d2bb3d82580e61b8d0dc0c1652fcb6ad0fe74186d4f30f931ded5712a16e9724b9993cd0d505f36fdd6c1f2f87ae7f7b7d2a84caf41d8db3d926a728904ffc98ade114aa146708071810254fb2b5fd49243a64bc29a6cf8638150988ebd9756b917719664e74f116e47c0991afa7bc43d0b4aaf085d205ced8ea01235b224e9e2a575626a39cb65fb8a0456f4f5380b87473b2c6d3ae6c36664af57171130202317f567e7a89975b0683a31b08cabf966ecc62d48ac257c297ac4825c75e59c4271562da9a7597e0b1d1e880416c0a36fd5d9a8a1a0e277025e81af122c541ead22d78609154fd9334b34c1b724aafefb4de93d02e360bcd69f4d179b8f973f0a229525c681a841ce65fe1848e33fe6c929cfdb09181ed6f10f9b5d42b079890c93f6cb63489fe6ca5926a30f68d89fea2985c600a9114516a6c29aa1a9a390358ae11d4c2addda665d13fc93f613f8de4ae6526a7ec8bcc418d9d190bff5fb2bf8a57d4d02ae9d39b49dafea09bc363a28395b90f0c0482be2642d693c65b1dabd51d6456d129d5c987093349056b99398c6c59efe7949aa90e6480719aa04ad8816124b5eaccc793902c3f48b7529b6d116f4e7418406b6dfcabf008b65268d1b3757c713863c80e960241776adfb775052d810b59fbc83edabf4b607bd44c6a610788c1cfeb3f21e0b94d5a12f2615ed49cf7d67abf18a93af7ba649cd0ac29680d9eb19a6e461dc5fcce21ea03fdc88fe1a67bdd4b67671794d5348a1b481ad45e86635f0474f0fe3f7138dbd0c961b000d0c14707c9c3037792e2b59632bef200305908aceeb3388deb21c5ceaa4c1dae6b8ef3ef9ccfca9bc6523b609bcddd0b66f5b305293c5ce2538e4d8e773a6d51cb10adc0c50d9b9cba83e8429a2e2e1e4e1f947c0be485986af1fefb306419c6fc3cc203303517dedafea231dd90856df4af58129352adfbd4c714e33aa5cea74c6e39a097a1155bb8a0f59242addc542e1ce485f81eb5df11ba9bf4e0267aba89ad594b06066c4a7f52ca7947de90772864f98b6fd26bbf80abe1a9ecef909810ecefd129f3a73bd3296a2999b9bb455ebb74bbc3f5ea7cc6eb966a566123ce03005a73c0294531cdb87e6f4e95a515a4533e0224cd2cf5426a5cdcab8c30caba2a0a36831bce623b526cac663bf76f269e3d114a73a0229bbc06b4f53b1f5c0ca2198e418a49af03440d375ae7c76e24cc7c0c46b93aa96c8e69afd833d5c5f4ee23346e35053b1fa6044421208a5fc47074d544333068438bbce32a53bc0117d123ddb9718eb62baa88f7a7bc786758ecfa2acaff06cdc5d550de264d6d61988290e84649f3faef516f21a36b403490b980074580512dc2e7d3e2b87a063a5da17648602d66ed743cf227b0ef5a34067bba03c1df0cbc3cfea77b39ee77b49d8b425455e45a27a245c1963853bd35689e5192515b7b99cfd14d624ea54dbe5eea6c8f22b59babc3c6a3ce22286f1a628b901883b088d7b9dedc64dc86f636e337839c21edf802b526c26346ff314ac02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c24165804d109d88647def7d8362b09e103f65285c88ff5ac9329ca40a9c29dca4e073034a4c23a5fe2e1a82fe0b885d736e57a0883291961a087a2719664020a574cd8db813d1070487f577a18b9e163ed125ed818c0d13dde40503a10ed6c8d3e6a9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712132d3fdefa1807e6bf9c14050d63d2c37bf357802a7d8e813baee24cefa76b229d471496a02cc87ca65544c0ef979e7f4c1f0a7269e3eb21fea4e0d91ec4fe86ba67e4ee5cc212e44e3488e61c6c1ce07e25614b8c23cb4d0442b35e6b0d8ab3744512e70a1dd7110e04b778646d4f7b399d36712e40bd06a6907f25046639e4f9a632636d4945986ce97bc67ea13897025c220e7297598460ccd7cedb8a0c54792f097884bc8751c88ee126bd1f3682449da8181bc9cc5b90f0bd9dce1cb0d19441bd6bd7dd64756c6cb272ce5ea2a934c56dec8f3be010f8ea74cc61f20d1309a1fcf68fc3da9660e86c1189f879b8c9cb6611d57d470765dec4c3514243009923ef8cdfac92e83ce444c9a2b61fe92d6043d108129649a3c6ea306c5d9db7b924eb791afc0aacb141b54f0d75fcde46e4682e806926114b2ec7ee5a1a5626a3a524e56e2044349643bea61e7d9d3ae3dc19e660d754e6cac3fa4f24ae46d794816a0ad32ac3690b658c96cc6e09d9510a57c8e28f32220210108791a15aa0dea2e3482714178bee78fee64d0d61e6933d06f8e8dedbfa5ec5cde870dde2d7a9880b245038d021948c6700d89443c09f207b9da66d2ec05e1c567a8ae5fe5023a414b00e01850a90adb945205173ed44279aeb17ca7ebf9a239d5f6ecc9306a868b391a7c49dbde0913228107a7795db90a5e3e91e505d9922c2914d7755e0ca47af8f394eabf539adc4509e5958a7935179f1fe3f8c22b4cc2e2a345933f59d65e0318bcca6caafcefeb3452d68d6197c8ea0b26b971962e201405c4c157653c2f2d4af59046fba73c6d72ca8cc525648416b9b2143dac665457204258b81bbad3d109701bd807e75845178590a4c5b8d44421e0225d9fd994af2aa1d0c65590a7bfeb5fd893b53578b04160e3162b0aae5d6f67dfcb75abbcf01b2ebb106906d47dbbbde1bdb9b1bfa8dab1989c600610422ddba5fabd57a54dc955ccfc7e5810293b5345958abc5f84808fd97351d481e6809e00bee6538408aea7c6c074c26b68e2002ea0633e6c3d7484493771c50eeb727d6fcea84ed9c26bdaddaf73d8ac7ad5aa36f30863234f789eb1d0092f42deb6ca72061146b920d71b457700dc5012547ee806376f3ffab1e2780f491f33a0cb355ea6b677c4ea1b54ab6e5698d2853047a428891a431d89979492f261809be176ccc6f09660d5cd4b624f339e961df7e2cd5aa3f816fe8950ecc0c2c9838fbf68bca5d4955de8719bb6cf79e8afbc8632efb5aabfcaa6e749cd45043ecb13046ce3209fa85ef21441ec2d1a0ac63a273f4213225773647e8a739187223eaf5c9f0f2e3d1b12e229fa77e65bfaa2a0487a29d08064960b2068be68c3c830254caee33d9436053af9fd028474bacd43a231dadc4f4116e333fc9f88fbcb64abea30e650a11ac56a1988eca459d858087e220893ac87e5b5203582ed469929c865ca6e35cafc0886f8e5a9f813f011fb08ba33475f7e9b64397ce8355542f0d31bebdb5238414fbc41ab88fe2abea69d9e769a9b465041255b591fe2708f1193c6a0d7e83e929c167d0f672a6cf8bf480b21d5fcfdf7c0ed21b4968982c3b4798fe04b9e9462fe2bd8fb6c511b1c153d0637fd584e30e35b6a07aa739ca4f37d82d9c8e4369606257edbbb2f6ee4e6047dd8e85212633fba991cea2364c746d0ec558d0fdfd64f2ca44bcc97637e3af5596f09c8a333cc19880d51fcd11a73c7b8eb1b02485903f9c3b3d15b56b6dbcce848e56c21d870a965f61bc53894462a6997e78f55f20ebf32f8f4de37a05611860ed6704be9587f1a0c12bf329f83fadd02c191a288925cf1aa151d387686eed59f920597a10643f36f40b821f85fc2e6b62569c88b32189a52966c52301f029b0c231c81ba02285edfcf032a441c296500e2a2979e4b4b0caff11b6656d131b61a171c4554591d3c74fbc8fb899600114d3a61951d7af36bb8e6460ba61b0015878e7e28903dbcdb802b63c5e6c895e2619c6511dfa0723fc48f796952690fc3626bb5c1a0757a19226c7db6e42ec243932a2503b9b257fa271f933ec2dc395f40b62b11adfb0a552412447e35ac364bee1f8ce0ad23a72daad14944e49b18cc3d5ecb36f4a8dfd602319507ba7dade07e22ca3a895e9ce0a2f59d7f581d176f5b8f880047f3803efbbcd442b7f8b1fe158353183f03d3f6acf46865281439426e64348199839d84de5c3d2441a5dd9c75bd064c1385ca083cd1df6ef46dacd30ba7bc9797085a143f0fcdd6b0c7ffdde124bace833b758ee4ddfe5072a558406365b77652cb2bd1ccf651da71b0b22bf789af3d24014217fea74522e694c399bc8bd5f07c0db8fab186d5ee762d33a5debc1902bed79a68d8420d06fa2810bfcd09e53dad5f37258fa86f46560785713ec711c9f5ab98c631bb3e3b6c5a293370fec522d61149c7bb09bd4256e55a71487db84f95cffaefd2c4a3058c62c3e73695bc27a72c21d264daa0d40c012083c581e4a0dfc7f168b722b237a0ede4e40a7b352f38ccd532d1a416ffb5207d68c2b7b3a6cfd957d7efa5b71446ce84fba254aa25005dd08c988f4dbdcc3dc795d3487566e587f8f99fa6d222c406942f33c9a694d0a5b974d247fd6d4a37727a7eeb184f4139d300cb9d2264e4bc1869026d0ca9966cfa34a5506577dd7eaa826a1dbd86bf3e8ae5fe73cd591837a5d6075a386bea6701e431ace3f383154ebf64ff61e2e4b520bf3a723908aa855ffca926ec6b18bc48a7dc48b52b839507453def5fd2898cbce2c611ba2af0d2434a7152607d997781ffdbd8987c5b14b6f20449493fdab89717e43a14153845b97698e2511195a1fbb646bd896dad04547a95f1941a1df510c4f7990062c0d4fd794bc886625c783228e520fde1dbed723fc9779bef796e04307444ff32c210cfc2275da1aba94d5bd2b963fbd80dda7a9c8ff88271f152875d7cccd664a44c8d3067a4034b5d6101af80d9a2970f3443536302525e41dceba23d8862006a1893e47f69018c2ed81677b4c43016ddd24ba54311aa590562ce1ad6991a1736d972bf0421adc4a00cd631414f1cbecb646e0008529253e9c0169822efb33ce421d77953121b3efeb10cd44d504b5cf47a9807dacce8eb24d53ce62e145835b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d32ed1f9d70028c2001ede3fb28ac4db0b0215889cb331f8bc637d8cd27d4443570c84f2e19c4aa5a2610030e19ea4093bd118f72e066ba44693db5cef94f3905a6740f6b046ac8d7b77f5451a405975c2588b5b82cfb70843359010be8b7f32870641d3606bc050e0383940f0e25880e6b183b137ab86e3ddd52a0ea7024db44fc4458e5fe418d5a7ed1c33878563e44403bf194507c93079ff9105b433e6078faba26ef3daab055a97199108ceea0d3b0dfee6ef4f8ad55f1eca9c15771251d0cf33eead0be3cea163831560bf46c98931a1dd530301d054fad074fb22e5d6ad86e5f79ca0607a6108ef6030015ee05ed6229bafe13806894461b51199f5b3d2ef6d9024f2194253e89d0ed237b1903f89dc510bbdfd982b518c3576659cd39120b53fc4e51e100e83a51da1239f64947e10f158bc42d10a3b20a366b4311370e2e5c4b8c303383b3e579cd1196f3dd13db99c99a48397fe1df8987a58b942b02fcf424a1223968027d877793bf9f4636cdba3b47dfac921296a818d1b08821f45e5edff6c3c216a16d4b6539790325daae1a6400ee446c2b4fd1852c409d43d0bfb72b3c0946f9edc151873293bcf16d1360b340d7b98eda07f00b1333fa020c5b2ab0a4db4d0a259bc517898153957166f01726a25d2012da74a8fcfec104b6ba6b02f41eb730989a90ffe2f8948b98eda9bb5bdaddacaba1ac1877ea8c77247f876b27b3d89aa71714f55561cbdd0ebbc4b24d39b044ca3e3ef42bf8f63b8c642ebb1fcbeccda9a1e3aed8762eaf0d9ed97308e08e7489424c321f49af5ff24bc10f697dde29bb97031ff65fc6cea39036367972d5627a48c4f9cb8ec56d22a8f95b4c20b4a2545baa5879a817128101c28cc253f3a7a73cb74f0c43d609d08eca7f936f1a8a1fd902a4395ac8be7312d9eaf784c761cb1354dd40baf3012e85eadf3fb86959768990ad2c8625a553c4d920338ebe25de23761c085102555e30cb812643fc1d2857c220dcb944c423397264da353d5131d0c70933d72b55d021a519c3d7a9c5614710da694bc1e1b7d5cfe40931ce3f0e1f35d253566b238265670dbf08b30c63410be69245689bbfb89a17eca0f6c9542454b1e92ed9421ab1827a2f0013b37d7a0653c54a480e1adb20f4d6621955b8b41b7fc0dc7f66309c890258c6702ea0943d8a32748f67d8dfa4a29fd85282d949f1cff5faba27a8336309a4f867baccec1e6369b73bdf4b757c1049448f4bb3999ee0d8ffcf0014a49f30a2a2f680daeab96ba080e9436779e88da9f35f1df28aa84992e99a0beab3c9bc2858788c7077ea13728eed4debededfd07f1672798856c3a055a13408241a7531f1edd8411be59bcddf843f745850a77afe6ac8984ce9110aae0cd6008ca6874a522c58bc897c403a860cd5d05b731add09f9e24a465d0da6417d00000bc1f800f46d8c06a9861b5ebb82ee710a67a28a410942c343c5385210af2235887221563f3ead0d53f19846cb8c3345403ba3f7209d78da91196896a687824d8afb71dfa6f71d993f900470493108fe9db363bf82126d7af537072262fd8208ab0488b72ddc27a4f9dbb2c191e699746de264af70e8325a3a8040652d3cc3e86f8e7ead704ea80c6fabc0641fdb53599f2e2532b2733e93514058b042af10bd004e87da3ee9342f44b433ff1b8535e3f1928f927eaf8bdf52e31c589467317ee797d349e052a0edd93134d2a7c57ee3fdacad7f8e00de15fee3a091b2c8e51c87f228bd61350ac8ebe6922fbe3db9b1f1c95cc6fad66daca76115c222bee077e98797f7d5a383fdf3eba7a9d9f91ef76bca8a1f5e028013db30143acb3e55096b4d63a9ba75c34b652b711c471606219755a72fc7db90eca93c617bac3191bb231b7a7a68d58e125aada1bdc72c94363a3d8c1e3ff72da6102d37790dbdd1172e42327ed298ddac2fc87c59442d545b0ff476caed9e785f2bed1bff26b0333a6b7893cfcd6ddb8a9ff65313caf6456f2ad2188feb5ba8dc102539e94beba58707699d560bbcce83134bc3f92ffca813e62865f3d2d56680b0ddfaedcac5d5d84dcacf83ad61a2b13644eba1c459299b7a92a42c735c24fe9a4b2e2e9fd6a003c6761b167ab56948265b496cb7529b01cc4e53c3cd9a39384643996beac7e7e8c5b9548bb53ebf8bbca632e490bedf7f4c1de2fe41bcb746afd7380a6ba561610e880b38007beeaff985e007a1460051bb827ffb24970b0fbf79cde0264cf0292305be0faf22877173da64f6bb647b3a636b831df365b7c3394915ca6209d753a2cdcb143ba3e7fa41dccf5534c6fd36ef91187d55e35dac9d3925ac08e2c22c80dda4c60aa6e074cbad95a68215cc134e03ac7e516179bae944ce17cb54d086ea75184c3c36dcddad7c1a570d4167525f3f53d8d39ebaf2d239bc1f9e7572cbce85b1fa08568230c663866d47c3af0c12e609217ab0284f8b8694563933a48ae23e707c1df21527ba79fb2c6cb074d51ed0b90e361b2cbda0637c074415c3e4eb13b75b149505ccf56ad08a10df211eba48ffd7a2d0d42a1bd943dcc12f86e3e9052ee1ea8f6f1a8fd7b2262bfb86110b06210c25e7fac37b49198155c2471aad8190353d85860814a81887509424d72a79cef1534ea7655db318a424d6a036c7aa614ce9faa7901f55f64b0b0bf1c084f52e7069e5bf1097a9889ff9773079eb30a9abe2de835e3229d8c3cd6b00e936d5339b325684a5c483b15420e123c221c6faa48e432e6ad29d22301073d3dcd3dad319399258dae99d20eb634bd69867ef8695bedf1478abdea28e97985ba68b3810318e3cb12ef946594ef5447668e76d655032dad5ed688567ea02cd741c0f1684f271e1e6f57e70339d949187f9cc5ed830203c45863ffda2b704a0bfc77cd4cbaf3279e937c9415d47635c23582b2cc0e19d01abf7b442930cab1acb6b6d1c87fcbabb93d1ee778339fc75b0aa674b0b9ebcc31efa34cdc88d6209367d7c9cb38d96a9ceb0b51e8e2364399650074af6bb1098b22b21e3b9d12bfcf4ba0ee5e9c3cf8820ef6061d10c3648d73c6d22bb9a4502c3b263699d0ea24baa448b12d24f501412d09da75d99714c914e0bac941c2e9591a1af974b9d7ed718ae8c2c5246458375efb92aa04a645b615f261ebad3748d4e586cf4bb52da7a9c3a306113046efec9210cdac01dd254b6f9444d4186539c1983075c1100c45b2a80ec93371fb04da55a70d7e4064542210bed2bab603e428eba5d241504949b6d4c4f02b543fd709a15be42ee92b6bd37baa61bc2904832a15e7077176451dbb49a688cf55649c5637bab364126c473c49dcbcfb064b2f296cbed17603820bbd3a5e93ec52e82e67ab2760735d2fc915122c09b76fc9de21fd95de63f8e5b0276a7fe25efa62bedecf69ceb278c8309d1c5ccae18338cd298c2ce4780f31255dd1321fbd0dbb6f8f64f321e0e0b665130b8a0379aaf5aa6bdafe07af1312f637e3911b8d18fbcdee38fc22ca35094f912decea24e409eec05550dd35c62be25a1612ab90b268015b40eaed9fa0717aab769e193b2d7bd2a55e7e715c64e67d0be4b76086d9cc31c11ec35caeb68634eb554ed5f55ec45727a57e2d8d6914f6d2acffb17b9515d347ba045067502a0b14022a269560e0d95cb168c7097ea8eccca5aecb328a24b1eda37bdb600fffb212178ec0923744a6402d58d7d738f233ce9b64b6a9f1dbfeec1505db36c5a06eab73142a86b27dc175155cb30310da6295a7fb1a7fd6e4ef00c998b82ab8b3300133c6af14e5077c26aa202e6fc5e69a792012590d42ae2694b82fc1efc68ebf7b5df2574cb85143f66a0bc2ff2a9811e62cca6fe559c14e606a1c9ac2753af2050d14b924dfc217dbc5b9b44e89d25f35314db49b096287a77d1734d0f8f8d168467849008fc52de08473191d53f8cff9c54059406398e89683d41db5ca287bb379e463c7df481005fcaa51f86223229d9aa3f1dc10b0bc97f9814eedae2d1a0d48826da8fea991d14f1358e94badeb070719ef7e1ff2021c1cb5acd297695c34310474feb95e86dd6e211cd2e6f65ced4fbfff3817ccb8c25dae508502d4df393b421e7f92dcd88622e35e35994021fd95c368ce30d455831b8d7b5431f33a73278cc9567892bccaa9f0d0d4410a411d42de63d1e2908e4ebbcafdb25c1a4ee00238cdf73e322686f01341d26623c2491c6340204508a421b5978d8f7f698b473aa842dc9eca0e5774a6374ed583ce8605795f084731e95e368d039b6ac539d614882e89471f99ad0b367c55273a7a4a3dfff10ea4c7816a44c1cad69137741b64deffde56148294271b50d17c8ecfec51791fde88bb15b07ef5a9f0f13b9ee20cee21322f3a6fd0783089d9dd32a9344cb0a89e9746bd35c0bc36f37afacb5e35fa47643df9b11a50e4f6f2c820c284d4c147481412e5e4945115040df81511233a8f81e4731205cf0af72285f08cdaf87f9cda4cd3c7c7d51bce592ea15d692e2a1700f5467da9707838a1feff9c989cf84c7b2a3965f146be7fadff1b72aa0338c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e8529585eeb7d466f7e38b980536e62c00fd3dc5c703c3bbd721c9491e6eb85c32a44a4b8c95221524a3c23c6b5401c00b5030ac5fc9d0a0463ad9e34009a00ad426a782939a3e4f8394ef0f1c9a8f811a7f5ea333cadd30d3404352aedbd7a2a743020670a8d1c3fef7c3cee5b34ea05aee62597374b2d6143e51039b706bc660f371ea75d41bd9ef4da3a7a5ee404600a4880f8915d2a0d4943210c8e5e71277e7fb0a75847a0e9f3e97824f457206271c9147e2862e8728b4d69cbe84e785d92608878e367fea06978192e6e69d4b8acadd42ac1133fb3a9e9e1dc50e281254144a0fe07efe8476c462860a01a5e4180a4de0249f05648c23f8e6e3bc49809eb27d2c7ee29fd05b5cab4d8ea4b8868446d4562a8b2d6f182d818b448b165d8497a72c623880702eed40e35aadcfcf6b09f67040effbeddd2b22af32c2978da711f60d3a60f115c98e714b9ca80bb1bfbe16704fb841cbfb0bedad90d8ee5106d2178980cf59e6836eed32dc22ec231e5556dde151c0081a83bf4389916868f9a5c9eb394a00dd88f01a451ade235d634484a9c56c595224495874fbdbdfdc1e93220adc754722bc8f182a697c43e34c44782ead62b2b4d01ed046ac0d7187fdf4ec246361396ba03e69055b5347faa6c1cb9929766e4f2a7b41911e25448678f4820e4764775b18b4c0668fa3ca1e9183ed8e57c30c211e97e7cfdc685e6c082448e0595ca52e08fe5b0d37ac52bda3dc4c8a0b7d3e9d1812d5530ebcf9df0ca539c809855b617cec1498a8e2313908d070839a80574b129b24245eded44df2d131e43dc9142274e0b70a75a903791928a1bfcec374626d3c6136c409de439066c72ccb9ad0332fc9b36d3a24c6173a23014f684d0f1666b8331d108ff33986354061399848cc96c7a631da2855f503865eb732fd4e5c3976571cde050a1777e67603fe0045e0a581002149e02f12f72a340fcd78d5723d10b6869cb54bc64940dc20e2c4e3989890f61c5b1df09c72d8a70b5e5a161c0077f73c816b17f59d9533c2e6ab0c7a26dd2cad7646133b739b24e20159d38cb2e11faad8ea174305417860ff18be0bfcefdb413d281ebc034b8b5f8722b041e90ec772e1e9449f61650a27e810f57d102788527c3e274dddc99f094edf73a09544cf3f162573d6da4798895daec9986a41222047ae0d3ce9b6d84c6e91ff5abd4296b1e777b8e22b077a6aea2e843cde25869445dce969fda78091938b3cfdd6f1ab376e62e9f94ff0456171e270fec0156069e8006f48956683abccd1427e3ec9df93abc4fbee9170e9ac11dd9ca793e7d4ad05cfe205d6ba0969f8e965d571cfbf51f54a8e3317b795c76523eec774719d38f8ecbbb192bc298fdca9b0a9304386b0791c671fa441d2103a8e2b2f015072895fe33d26bdf621bc4357610234e563f1f6dbf1584d21aac7bc2a1f4c8869fd97e805ab0157b6325650d1e03909ae85ae3751e582cd823db5394add842eb339426c7a1f44fe90370fb00c10664c8f2c9515800831c45fb5248387358534d37a9b2bc6b9ec84bbcda7f2f8fc16f848423e1dae978e729d4886f44e1b21418fc96c9b11246ec54148661fd7515be3636f5d3fb5e2723cfb1a7253ebc10064373d6227daca15f68a54710eea722a4c7ac9d8cb34c289634b7a831c0d58ff0c5654f9edf692e49403f40a9b1b1bd4acaebd7c2ed9d02378c9a9b763a41b5a85c0e978d30601e32bfa02697f9eab6f756a1d83440c49028baa4607d4ec080ace306ea6094d615cc220736fadb0bddb33b4d7381d35d265c13e35b0d829219ad12e42d1b56bc54f1fea860b18d6440a9c44c56c41dbadd6085d0e3707ee4eeeb4e3410a8326cab9ea1eb95213475d669589cc8b1331ccc7d65eed9559e0ea0f5bfff13843f2b4a2067c577278af1558bddd481e153602c11d5c81a424e2a1e946483bdda59d530949954fc0d7e42afce9454b6faa5b7575f6fa1d2374efafe1363b36df330d958bfa12b5efdf7d274943cf6dd8c5448e3d30bd0d05afaf86a2d30c068ff63e9fd065e1f84362827c46ccb49a8ec04049d1e04db6f7b88c193400ee5818956472db1a5d3ab044e18f4e918b2547eb275d8910d103c13a8704ed2503421465b1e68c51817ae25727b7b72f3817febe4ec7451fc241d7794b8a63f1317707c329bed6bfb2a0023bef0917a4f8944b2023efbe2fe3d2131c41ab066ec2eacaf389834b55ec862fcbca7862a3addeb9a4fd147bd07f480464e395013f2599efd1c800bb1a8d30d5f57f82ac1df5056e7ab4b9b21cf69a97916c8a50072a9fa50439bf52d8ca7aaf50f5bd9591a5422b079114f0bfe4acf561c826ce665878ade3dace990e64ecfb1ba367f4c3c0a61d4aa1dad084d5c3279ceb5a4343f16894ba217fb7c1bb67c328dc7a5834ea59c48d0db9f4a5d9ad304bc46c0d63e2847067350555940f33ffa238dc7137ea04ecb81d9abc5b068794756c4f812d1c5af309231bfb4b27281eb33f8df6c7152ec14ed6fc9a8a644e174ba754247a7319d29a2d250be22ad5e7494d649b11898276a964aafd01459781278f83a80e6764aa6f07eaa4e22d1741ed853c68c6ab19999edb739487eaaee49b05113ccb3c725993fb28e76ac53f00b9ed3ab5f6912e0786fc1138fdd9eb43b407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71d68496b94fdfed16540c30b13d0d7e65a4ff1bb1b73ae867b96e7c912b00ff6a0ae752dca9264748a313dc53b63231d29e9fad3bf5e6ec9134177e105125ee610a1f9b915d9b65deb6f9add45e7b03240fec592fd59851a1fced2bf84b59977cde42db08d3a2ae3363169cf1de0faac09b586e3da4527c94f3e773341a31864c9cbe171e9d2dee147797d4242195bb40ac11e174db2328fe1eb75af660ac3467a41c20b10ebaf33b287cca0bd628c8e0776b9bf95584947c130993f4560f6f01a417c3a364675ca3cb6a8235ce24cfc39325150995dd367ebed4e2adba7efd67f631073311641d31a868698b9453e88b51df1f6dce9144da9ebea27285a1260bd849ef59e925c176159e087d784b4c571ff12c63386066a9565234ceabc1d14242383c5e1385b87afd269b475a6fde0ffb7bd90e239d010036426a9102aab37b5e7822263c75b2709c939073244489a929410cd8eaf39549a7f7e39808fb43114cccaaeacc16d611dd34b249acc4f8bc2276ac510bf3052b08e057425c87fd10a6c6f7979f5044137535fe3f4335ab4d53ff7a251b2d799539e0852b557861591858ca58ee54562ddd8ce1604479185664a744017e539e3a7737b7eba00d76750ec72e68159e3a59b6311dca75e37ce70329997f97069f11df50dfcfd9f0527d72a5f91327ba5470d80b2854a57596101f5dd528153c8e07bc10fd47d0ec9c6b3ca84536e7b0ef7109b756252405947adb4dfeaf4712a116940f296667427b1c3451595f904e1bcc1ecaffb327a9375f9f09251fd12a66f7cbd6faf86fe9024394f1eb3df27c88e651042254b623a6d4f21c9d4ff62f4819dbe9e6a4ef2e243a664589311423742fae46323f94994ab346ac1582f51747493b32611a563ad057baea8cd9643b8d548fe547146d615bee842aed92fc83470ae7116abdf4ab1944e02a488e8df0f2c1a026bdcb1c9e5e273773626b603e9c7ff6b9bf0beb5a573c6e918efa944501d59226cf102566661ea103bbe11febe431a1ff61e7c44a9852e25b13c8f1bb89f75aa4f297f36eff83fb89c7fd7627643fafbb62323508202f6cde95375caf3e05b69ec9d53a3c3d46d2c269274d4c297ea4c1849854c73f6f6841ca230369c180417f4a65f648b88e8a5dd04c309f31d09161a0207dee3469783daaa9274a0ebb267618be37418eb65bd822d1caac9f77229bb6c60962c515e8b207b02674157f4b2fac359d2595191b18223ef8d7a62f203c30dfb407d3017a45f5b334202ec3bdf629961bee8974b2e756e4c7b638ddcb558e8b8fe0e802bef767d681dba2b2af833aada512c7f867dbe6e01b2a7eb49c7b6e50bb8d9e6cfa8ed1321b415771d5535b817beb8831160ffb5f256a040d662f90742d2be25580185bd09edd014de26223b5f1a82e054dfebb79336d891b767f8be214f88151b8a8ed8bf99febaa10c51a9b07f80b130f73cfd4d1de282f6d7f5ccefcccb64a4ae407d0c8e29650b1c0c1c00c292d0afc5ebed5da7e7a9d0eced3c6894548043aa537407a69dfbfe0fd4dffdf896a363d75ac5707eda016347a63abfaa6435132d554abf826a19340bd0f7c5984343cb49e89936f55f2256bfc32871448794ea44303147839275ddbe891c2ce4f93b4e51ba2a2709de73de8b659f9ad0d8a6aa8e2f1c300418e07035b4a39936ac69772520c167ef33f576198a70bea1a3e6a4810868fffb8bf70abb870ece4fd40a2c286d65a1a768776bcdddba218f6854236270d550b0acdb1e87c0a647026b5982426dc8bfd02bbfbe5ecf33fdef0b048ee02ee85779a0ee900ad2e02300ecc774f73ec419fdd15546141233308dd4e05e0bd98aef19726d7d2749d8f316b798b87ac700de86806c0586e96d5fa35d908728d9a044cfc98d6435f5a73643ddfa896ed51671f0a76359ad302d329a7d6489c3cb77d7a563214f32cae5c3ab5a379198c36ac46ef0f151a21bb0db55720418ac16e2487ae411a37a41f7a086824b2efd39c94b3494efa7c1b708e360b380cd65c6b0300db4259152800ab8a88f85e276b32399f0746cdbfd93182863a850da4404584a8ed17f70aec3cb4412c17b854cbeb6e4ed1e94d97bf16f7b343ff7b1c0d02b11555ae20d30819e6ccccbb44b7538770c3aecbe7351ded9dff5a0a7c66c2be38a68a4f8d2cb06766b1cec3242cf191ff9ecec987893588a89b042c2034534af2f0c4e38ba3617ddd1c70bbd23365639fa7cd5f191861c7fbed74a809b4577184b74582b4774b8ddc3f186fdab84f01e0f988b74bacfe932f46aa7023309f130f7d93dc434d02fa0318a7a63dcb6fc7a8cccb8eb8452ee3c1cb6540512a78cc5ebbb671f9ad9a244567471923ff0a04fb615834380caaf01494ebc73ca0d5c640440be29f2206fae788ece44aca654e36a2ea1777e93e939111387068eae8a7ac652da78f63545288ebe0eeaa2eef9ec82ba6bacc11acc6e110d82f4a1c698336cca9cda4ce660b4873e19098521277c6167a5090ebc2df903b9e682728b4a3ba320237b20444e34f94f2c8f9d5e0173b28a2dea1a88f7e40403b113752a6f9aa0b49ca6a5c34a2b92b2d2bc5f480ee94faab28f01dc0d7ad19392060a4f0a8a95ad318982f081ab3c35895f83a6d4611d888a1a0d0a8ac62075ca703c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416aeec5145d93ca5215998b118cd43fe6f953be84cdf704bda68dec68fb14c3e6490399277cafd3b75630f0b826e2dd6d287a161cf892fbdd889e0c6b19cc0be4bb41fcd121741e20510209b0740cb89c118f190cae98339b07e65df9cc9dd126b9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712122d254e33b7c35d78ed4f76db5578f07a6c1bcb7dc46199c567c4a61f84c574fc4ed042b0f2c8397da95d7dfafa615f163ee77de3725afe64561d65a370b3430bc9746fc125c950f425b970da866f8944bf368a765eea617c7ae949c214c405a9250eaeb7dff21e3804b3656037370d9b2694a83536a4e924c9f3dedf1ba083962d04439175a2d98c3e54aba79db4b5fbc425c1ae4d759878086569d2afcba33ee7757f605a7b0d7d518a7751ffc17479ef2cdbec637e4bfb3dad4d8993a553d0ccbb191f4be4cff5ad204d9ef12e321d851b431a0487b9b00a71213f2c95a3e48a1025c18a4bb04dbe9c259e0ec5a57863699f0eb5efd7767175b02b9bebf4eda442aa4ea276a4e1cad5e196a6945f4f9feb7e434a747a9244eab3dce1ed9534262c8fbfdc245ad9dcf846980488cb4d18a79606fce942d48063f0455392e5d825f515af082f6906036c246bb7b1f3b75d1344466e45c96967f8cb73049970c100538397589fa07b331c10ff03ffcf5cac1691840ba63344882cad3a161b135fc74cd2834b4d7d555117ffd19bb23e6ce26d31a3c34bb5626688c2388f32937ea6edb9107df7695cf745e061c1c8b98f078d88f50881eda8dea89dc75b6633f1c7fb016c01016f8225393bfbb03533db594d4e1f289484f7c5eaf4babc9ff19d827a1b3dd1a3cd1ff4732a3826ac5a468c6464286aca145027df161442843522e2ea9f89b72832b1d5fe563cc115c44ce2ba0c383e5d6824f8260f9697397660eecf2766560b1c77937fcec07555c995ffa2eb97e7bed217c46cc798a407a054e3e8c342de20d821c684b2529a9260b8c75b32c9e0232f6870db100b286915baa9ddfef29ba03584ca140af25d0ae285191427484dfca3a722f8729a0c76d7fec1a9c987bfb111cc69796ebd1976ad4ebcf4b3560c1bf2662f77a10271993092016aa2a13c0e05dabd3e3754bbf0e87775ff06bdca2da1382448fbabfde07755a6313b77aea6326c8a3ce609b67aa4b2de89a10da711cc35cf593e91f701a0fa8e27969e0a4642d03481c477ea3219946b9e8b8b1271dd6fbc2da017b45d3210095667544b271eedf036d8b2ffe8d5f903ac79718d2bda2a14a9fb3cba6911012d8f0e3c51c77bd269f51b501bc3056358b894a4efd94d6f3ab31c60a2e6d42022e0b1f1daae90dcba1b96d681a018636a09bfbc8381cf40a502de14de2b67adc4b5aa9706a54c576dd1caad7fb29bdca6dbbce5cac2eb1e65d89633e3dfa60aae7bb0cc818fc18b6ffff18592e8e8671eb94ceb0c2e15b33f9f54415cc9e626a339aaedb6cdac744b85af70456c65c9025b86a7426169cda4490dc7f20d0220467f6af1ed61d0b39bd7cc4f9e94861a28fa6f27709921625b455c2a5981634b644f122be630c593c15b16fb21e9cab0fc7b0140c981652059d2310ea20e463dc56e7b203c1dbcce46929b2013bff2270b86d4951584ef7bc2472febdcca611282f3dd2a3026e65945ed13d52e629d6d6a120b1f6442b75e0b2660e0f05824ce468bd570a388c6eda0d4b98552d27b9aacca2bcdf7f90b75243f624e0181f20683e701c397f4118ddc67c11ade82127f6d66ca2b4137aa4876cf62bc50a203954cb3460a6f509b816726d7b0427c7552a24e1ad207087af15ff6e5619ec37622a69b1d98b990ab979c98b9a66995d1665017790168ae8b5dd1608ad0bf62c35c2ac54ee3c95f27faeedf474fcf1fa50ca27f2087b110a88585c255830f56048944d2868c4978492fa514359fd3ca4231f9a3b7689833643ca183622e8cd9639ead81d38d3c3ef6a38a08f0415e8f2569d4b698449bf2c5ca74346454838e92bf4ef4200963a061b35007b1a77d0b68fe244fc7a65c339aa06f8fc468150d649eee8dd05156213b4b376830067601b89c2f3ecac6db895a8078e65ff80e7d04e60ab0ec43fca15dc14d5312371e0b26d5cf58477961dbd96fcdf2b31d78c450fdaad5e9bb9248f6bb0cb58946f2e01dbe23224e6af11e5eaaa5b6d43d700a8083e97f57984a6c431796df3d153e6b310d25c37fd451bb16e2ed028aa7b09e42e10f820389a6e253f09f99692ffc4359b494a30096a3eb8a5b97c3aba02933a37cc732e055d41a2acf695dfa9d59dfd5627864efeed20c24ad2ecac463db3c12b4ae5233ea7370c02412b04da5cecbbb9154f804dc0c8e74e2ac9daca31a3b872cc38779f9c7b1a6ca93f2c4f6d04a6b0f3e699c8a40511a2e3b9fb7f8972661796817ee864c2396b7b2a9f349d959b6fae1d66ec9104ff9c942f030e65a8aa546173676eee3beca7af1636aca17582f30829782e2c9b1b9c72aaf8060563ab378657bf91d13f2dd4f1bb6adc1d6da398e1d9b2a4884c63631d46aeeac4ca7348887106b8f07b427790d1cf4a2713ad56af6e1e1629ef93edf14348535e50013d4a33f70273ba18c23050e010109645dd600bbb52809754ddeaf668a72b443d63901a6c759e4cffd958b68736a9a1ee2ebdff616811e63d43b100947549aef12a6caa34d62c1fee27f253562286a466c2b2f91a711cbfaebc527f705bc8bc7351cc7bd57d0af9f150e6466174f1da6ac71c79a2a4df82d44f585a3865f7364024c6f9a7ec7442cd32dc7566e2531fe4366ce5e22aa6931f8d2cd5f258b334011fba79242837b662646211a788b62ff54a6e9bf54761372954bc5b1503cc1b49403054b96be468c1f8b22ec177da74fc851f7562a10a49417b5b6a76168f52931be46aafc2211ceb98056a1bd1102545401d8698944771e079f3aa93974eaf9960d6bcbf23b14834f0d7034f8d5e6589e4a7f13f65e72705884ee8dcbf1360274ec269f1e31a344f8884e5ae3450628689e6356669e7a94e43ea1ac65578a8a21d8cf64b22197ab966b1a20a098fe08768b0f5e53e25c71864a657cb42ea209e757e475ac343e5f8f85b776ea6276755f5d9069447d01bf34604c0389a5a80b7687ca74dd548b3c5d98e4f70c9a85d29ddd2296fa1cb8be37e5d8701af88c70c55baf0ef059358fb8506ab8dabcb8642da7052e6493cc40a035dc86b8d5c88164976f31fc1f72c9a86eccbe29a1060e2a5b0d6abf7c452613018b69e8385b7ab509e460dbd802cd49164665229340e29a14dcadf345f493f00ebe1d829515c6528b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d5e8fcf6841f2e94ebd740f848a2b4e72c31c7a21aea6ae8917400c81d43bb522b64c2aaa0a1986e68954e4ca7b5784088392fda54f4dfbac75e454458e01583df2218fc25708efa7679c23d318c33cdbfce6be7e9125002352d34948fa8b3a67aed933b6c623a04853e8e76cab3219c59d5ed56410b366482128627181b5aa4eceec7f1352a57bf84ff4eb62099a8875cc61b06d7c3dc6094fe96948c881c60eea50f1aa4ca2c2c57af4783c613dfe8392229ee5fdf145d7506ef3d9e559246558463ea4005ea0f83e358d15a789493bea81664169d09e26df8e8e3a2361e6226a54c73b0bb645b846c9bf3c2883b4936fcd3f629f9d24086d9ce4c20cd226199884cef69623c717e7aade3c1f270584fa38cd0d9b6a56045e318ec49ba8a9615abed39d47633eeccd98be10042d5d03d852c5bd930a89f0ce256a9332521f287c5b3a221df63628851acb241908838bac9774b28721290f082f7b143e8d102756d8e06152648b0c9f937d26c08490a5752ece4b16ced9ed97d75143de35326b6e46ad517f13ce464516302d89289478f09e15905bf5d8326d95437860df2f72c0d2cc0f3c40972b07c54745de572f912a58b2bba9c42f105f09be83e69491690a5ef93a98dbe72b55880c843da199106393fa4db8a6f659207f6f419b31a678ceaadcc3330cf95892fe9ec136744640751b38026e009740867b10de8eb67f15a03477bcfddddd9319bcfa6de112cd37ab5040bc19e0b3a52f039a6ba60d2045f834a3195e89e19ae67d96b45a0bee0beb3ec45595def5f6e8fc37ba73c0515e6ade7566e5eda3fe184f22a89211634ed256471c1f3e0f3ad64717fb58cd0a44709a330f39d5e8cdb773ee71afdd2f9d57b44fa579937be3aeaa1adae3b57d047ef28d1fe4a0ee885dea9edf31e01e23e896796b8fcdecd44b4b180dc7e02617563ee5edebece3368fcbf345b930c92fca7072eceb55222b960c5f7e0fd54d58b2a296fc8053d12508a47fa99f2cbd5b7fcea38d04fb896e5421661613af2b53ae7f9cf9da7141efb199d0830298feeb364ff4ad75fad31d8e7285e6d63e4c3f149c65a859747611e99d8cb5d06bd5eb20c5121ccc64e431ffb0c6981f059d02a6924cd1ad196dfff80d76bf99383b20bee491a49cbe9a66f16ad93859533515ecaf1ce37791cdfdcdadec44734ab9a4e4d16a25f18d2e207f66037bed355c32f0b6a53e8785a5b3392bb92c3a0e904b1c0e100735390c8676dd2da11747fd6014c06cdef71226f89708e71ef9c6ab3d95def2dd7f487e42efa411f4eb05a33bd833c6d57f623b8f0c8ed846045cf44fea32bcbe0bc04e118f3922c6a45c890e469de71ef3008558f64ece794dff8660ca2d18a49e2e7b3beaf1e6c903da7e0e8af4d2400c18023b5de425d219f9efcafb72aa555fd994cf9f67ebeb5de47b6a84256e12aea7e877a8b9b5cbcc01119aa6a8e732f551d99dfa4fc239739c0c1d9c415bb13419d4c73469ba912eb7d346b91629642940f117e1aa50a09fd5dd48caa48fe936563f4a200c29d77a80f5657781f6849373684b82a029b1fa3d2c566173676ed7bb07c67c2bc80e7d5ba4623f8ef0d565d266723ec60497f0375b3bac140000000001000000020000000300000004000000140500000006000000070000000800000009000000140a0000000b0000000c0000000d0000000e000000140f0000001000000011000000120000001300000014140000001500000016000000170000001800000014190000001a0000001b0000001c0000001d000000141e0000001f0000002000000021000000220000001423000000240000002500000026000000270000001428000000290000002a0000002b0000002c000000142d0000002e0000002f0000003000000031000000143200000033000000340000003500000036000000143700000038000000390000003a0000003b000000143c0000003d0000003e0000003f0000004000000014410000004200000043000000440000004500000014460000004700000048000000490000004a000000144b0000004c0000004d0000004e0000004f000000145000000051000000520000005300000054000000145500000056000000570000005800000059000000145a0000005b0000005c0000005d0000005e000000145f0000006000000061000000620000006300000014640000006500000066000000670000006800000014690000006a0000006b0000006c0000006d000000146e0000006f0000007000000071000000720000001473000000740000007500000076000000770000001478000000790000007a0000007b0000007c000000147d0000007e0000007f0000008000000081000000148200000083000000840000008500000086000000148700000088000000890000008a0000008b000000108c0000008d0000008e0000008f000000109000000091000000920000009300000010940000009500000096000000970000001098000000990000009a0000009b000000109c0000009d0000009e0000009f00000010a0000000a1000000a2000000a300000010a4000000a5000000a6000000a700000010a8000000a9000000aa000000ab00000010ac000000ad000000ae000000af00000010b0000000b1000000b2000000b300000010b4000000b5000000b6000000b700000010b8000000b9000000ba000000bb00000010bc000000bd000000be000000bf00000010c0000000c1000000c2000000c300000010c4000000c5000000c6000000c70000002b000000000000002800000059000000020000001e000000" +// resultBytes, err := common.HexToBytes(result) +// require.NoError(t, err) +// +// var sessionInfo *SessionInfo +// err = scale.Unmarshal(resultBytes, &sessionInfo) +// require.NoError(t, err) +// +// //require.Equal(t, SessionInfo{}, sessionInfo) +// +// encoded, err := scale.Marshal(sessionInfo) +// require.NoError(t, err) +// require.Equal(t, result, common.BytesToHex(encoded)) +//} // TestInboundHrmpMessage tests the scale encoding of an InboundHrmpMessage func TestInboundHrmpMessage(t *testing.T) { diff --git a/lib/blocktree/interfaces.go b/lib/blocktree/interfaces.go index 43196e2296..5dfde8d567 100644 --- a/lib/blocktree/interfaces.go +++ b/lib/blocktree/interfaces.go @@ -45,5 +45,4 @@ type Runtime interface { GrandpaSubmitReportEquivocationUnsignedExtrinsic( equivocationProof types.GrandpaEquivocationProof, keyOwnershipProof types.GrandpaOpaqueKeyOwnershipProof, ) error - ParachainHostValidators() ([]types.Validator, error) } diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index c7ac26aba7..841ff72742 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -380,8 +380,8 @@ func (in *Instance) ParachainHostValidatorGroups() (*types.ValidatorGroups, erro return &validatorGroups, nil } -// ParachainHostAvailabilityCores Returns information on all availability cores -func (in *Instance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { +// ParachainHostAvailabilityCores Returns the availability cores for the current state. +func (in *Instance) ParachainHostAvailabilityCores() (*types.AvailabilityCores, error) { ret, err := in.Exec(runtime.ParachainHostAvailabilityCores, []byte{}) if err != nil { return nil, err @@ -391,13 +391,14 @@ func (in *Instance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlic if err != nil { return nil, err } - availabilityCores := scale.NewVaryingDataTypeSlice(coreStateVDT) - err = scale.Unmarshal(ret, &availabilityCores) + vdtSlice := scale.NewVaryingDataTypeSlice(coreStateVDT) + err = scale.Unmarshal(ret, &vdtSlice) if err != nil { return nil, err } + availabilityCores := types.AvailabilityCores(vdtSlice) return &availabilityCores, nil } @@ -469,7 +470,7 @@ func (in *Instance) ParachainHostCandidatePendingAvailability(parachainID types. } // ParachainHostCandidateEvents Returns an array of candidate events that occurred within the latest state. -func (in *Instance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { +func (in *Instance) ParachainHostCandidateEvents() (*types.CandidateEvents, error) { ret, err := in.Exec(runtime.ParachainHostCandidateEvents, []byte{}) if err != nil { return nil, err @@ -480,12 +481,13 @@ func (in *Instance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, return nil, err } - candidateEvents := scale.NewVaryingDataTypeSlice(candidateEvent) - err = scale.Unmarshal(ret, &candidateEvents) + vdts := scale.NewVaryingDataTypeSlice(candidateEvent) + err = scale.Unmarshal(ret, &vdts) if err != nil { return nil, err } + candidateEvents := types.CandidateEvents(vdts) return &candidateEvents, nil } From 30a724f45b46b1122781880512eb11cf83bac8a3 Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 5 May 2023 18:18:11 +0530 Subject: [PATCH 40/65] fix lint --- dot/types/parachain.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index 07a27c0f5b..c9a3e1968c 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -1,3 +1,6 @@ +// Copyright 2023 ChainSafe Systems (ON) +// SPDX-License-Identifier: LGPL-3.0-only + package types import ( @@ -10,6 +13,7 @@ import ( "github.com/centrifuge/go-substrate-rpc-client/v4/types" ) +// BlockNumber represents a block number type BlockNumber uint32 // ValidatorID represents a validator ID @@ -59,6 +63,7 @@ type GroupRotationInfo struct { Now uint32 `scale:"3"` } +// ValidatorGroups represents the validator groups type ValidatorGroups struct { // Validators is an array of validator set Ids Validators [][]ValidatorIndex `scale:"1"` From 738a123246ef54d6f4844edbd7700b6c4bd5e84a Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 5 May 2023 18:41:04 +0530 Subject: [PATCH 41/65] fix lint --- dot/types/parachain_test.go | 10 +++++----- lib/runtime/wasmer/exports.go | 19 ++++++++++++++----- lib/runtime/wasmer/exports_test.go | 1 - 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/dot/types/parachain_test.go b/dot/types/parachain_test.go index e786b2123f..2fc0eae0bf 100644 --- a/dot/types/parachain_test.go +++ b/dot/types/parachain_test.go @@ -17,7 +17,7 @@ import ( func Test_Validators(t *testing.T) { t.Parallel() - resultHex := "0x444c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e368589360e101de266b8f5f05431dcaf63ecd936988cc348a271f42519bef19df1e9af7f4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57ecee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237ac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a" + resultHex := "0x444c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e368589360e101de266b8f5f05431dcaf63ecd936988cc348a271f42519bef19df1e9af7f4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57ecee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237ac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a" //nolint:all resultBytes, err := common.HexToBytes(resultHex) require.NoError(t, err) @@ -63,7 +63,7 @@ func Test_Validators(t *testing.T) { func Test_ValidatorGroup(t *testing.T) { t.Parallel() - result := "0x0c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f0000001000000062e9ee000a00000054eaee00" + result := "0x0c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f0000001000000062e9ee000a00000054eaee00" //nolint:all resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -153,7 +153,7 @@ func TestSessionIndex(t *testing.T) { func TestCommittedCandidateReceipt(t *testing.T) { t.Parallel() - result := "0x01e9030000328b2b271db466af1870b5918aa43aec671de9803aeadf75013d3c78de35ceea84b5c6e57a116cba4148aaad37fbfc3edc54e7728b5192a40391d9c8ef33bc40e0a84b429996989d65526edda87a56b79f51b98cbeb347ce22a356cc7da02e38ab0e77029716d6a3e8b45e3ac27c623c347f28d433926a7f762cf0018484f58e505b19ef3223929a5ac8e2f17e5add18665a164f002b806899329b25c8da3be76c5664eb273bc0dbc3016d1304e53fc86b20d4d3583c4b72599ffe4386aa7060c9e6f1ad9699ddcc8f2bbe324c882cba6307b47e991cff013ffc307cc7d3e4831efb8e925358db3e93e466f6238871a8a29a6028279db855f0eed3fe4d7705f2dcc6cda49b51efbe0fd184b974074d1258ca9f15b9fccfedc35b7dee6e1ab9e9000000e902bc8e637ddab3bc69db43a62181e9a5807647ae518b205161b1beb25cc72bb441a6dc4600cd7190aaa808a47ac7c2cce73922a0cdde3fc639969c76d5ab44566e25e5fee50cc06625cdc46c76bd0bf8c046308022fe7b2cfd31859fcab2c7d84a2b208b1b080661757261206f495c0800000000056175726101012cd5b2805efcf8f0d7a35e05a9b3582df5af3cab0c912af9a56e83a10a42ef56b4feea6347c7c862c71ad66e0a6296cb6e46cdf10baf65dc89315f2768fd4f8100000000a18fea00" + result := "0x01e9030000328b2b271db466af1870b5918aa43aec671de9803aeadf75013d3c78de35ceea84b5c6e57a116cba4148aaad37fbfc3edc54e7728b5192a40391d9c8ef33bc40e0a84b429996989d65526edda87a56b79f51b98cbeb347ce22a356cc7da02e38ab0e77029716d6a3e8b45e3ac27c623c347f28d433926a7f762cf0018484f58e505b19ef3223929a5ac8e2f17e5add18665a164f002b806899329b25c8da3be76c5664eb273bc0dbc3016d1304e53fc86b20d4d3583c4b72599ffe4386aa7060c9e6f1ad9699ddcc8f2bbe324c882cba6307b47e991cff013ffc307cc7d3e4831efb8e925358db3e93e466f6238871a8a29a6028279db855f0eed3fe4d7705f2dcc6cda49b51efbe0fd184b974074d1258ca9f15b9fccfedc35b7dee6e1ab9e9000000e902bc8e637ddab3bc69db43a62181e9a5807647ae518b205161b1beb25cc72bb441a6dc4600cd7190aaa808a47ac7c2cce73922a0cdde3fc639969c76d5ab44566e25e5fee50cc06625cdc46c76bd0bf8c046308022fe7b2cfd31859fcab2c7d84a2b208b1b080661757261206f495c0800000000056175726101012cd5b2805efcf8f0d7a35e05a9b3582df5af3cab0c912af9a56e83a10a42ef56b4feea6347c7c862c71ad66e0a6296cb6e46cdf10baf65dc89315f2768fd4f8100000000a18fea00" //nolint:all resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -192,7 +192,7 @@ func TestCommittedCandidateReceipt(t *testing.T) { func TestInboundHrmpMessage(t *testing.T) { t.Parallel() - result := "0x28e803000000d007000000d207000000d407000000db07000000ee07000000f007000000f207000000f307000000fe07000000" + result := "0x28e803000000d007000000d207000000d407000000db07000000ee07000000f007000000f207000000f307000000fe07000000" //nolint:all resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -253,7 +253,7 @@ func TestInboundHrmpMessage(t *testing.T) { func TestCandidateEvent(t *testing.T) { t.Parallel() - result := "0x9001e80300002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f3282a8119a659fb3c94c3c951e5215daa35c741d13719d0be7368ca8e089537b5b3704113bf3c0d7fafa20033cad97002e9b9cad03fb998cb35cd71a9873d87a6af72afd5fa059b18e2e13eb3ac6158212b57ba060772886bf962b12034127908e54749e8014a7525ca4eb8815d1565185b31aecb38121e4347b54ccc8e49d13e2a732f9e332e0b425c741a07206c71d801011c2c0a278c87fefbf8064e0631875d1ed14e57816dde31202e999e6e24ad0f8ae2fc830bc1d325e73c3f3dcd186be8e59074c5553d8b65ed0a7034b310abd88b894263dd5869a8cf87e5ef4f0a79985e134020e8a1e2e211afcd5ac9ec6a2fd21dfb5e1c39b3b670f4415e904061adfacb103f25340b938dbfd331ba478351f9173a81134bff8a8fa1c0fe6be68e9025ea1f9f9f24e7fa5437238b01826b451001da46638f62b334300923068d1691f42d0e400b65ae90c283a08ee958a10a0e8c33eebbcb01d137f1612e39973a10489164135f64606c111f8d5d21ec2f8ae932676beda36b07e3577c7d8103c7cf2cf878ce90806617572612083635c0800000000056175726101016f5b6937ad29ad8721ba848694820840b25d91a631d2cf19f8c63ffcf1fcef260d25513fbaeb64c090d371bdba09663f2cd3bb4a8f8f7838b6620bde5c6e5905000000002000000001e90300002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f84b5c6e57a116cba4148aaad37fbfc3edc54e7728b5192a40391d9c8ef33bc405ecd07dedf12350fca80ea9faa4288186ef3dd0b40badbbc49f858a38cfde88c2bf80adf8f3282e527e242daa821b07b2972d9630b1eea6d2ffbaeb90446a8bc62a19241993b622e6321aa73a113c354958dd7266e7e2a28acde078ae276bcf7cad7aa37dace9d97c31549cc22292b650a04cfbcdc44e20c9225d499c8241735168858f1c5382ae1cbb9ece1165e63f01471338afe7714b8928ef3b2a15e6f86fb4ae217da22aa2880ae8d874d21f8852d76ce7d32554830cb82467a66658784dcc6cda49b51efbe0fd184b974074d1258ca9f15b9fccfedc35b7dee6e1ab9e9bc06de0d02e4b3871341b268751813d0fcfbdb0bbb2ec4fa9798959ab01a48dbe9029ccf0aff2230779960fcd86efb10ab9d36ee09ed20b3404b8da50f63a2f2aaeb6e43470084a5205b111c66b80cabbd010043085f5ba73c3a4e0f19105e32274bf19fab97145aca984aa0eaaa60c4528cdfb9aecfc2dba582729ad01ebf8d72ad39f1d70e0806617572612083635c080000000005617572610101ecd027c637c53ee91d7a0e98cea0e7e72f26f69415985ee9e28509aac917565522d428904e56757639946c30eb6228f11feae3bed1e1e60458922e892f89ba8c010000002100000001d00700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f605b88b35bbbc7463cd981713be480f1e7ea1d12b6c21eacf0c120126d24347f57dd8f8b64cdf03c5a171480ed3b0718ed0d2ba49ed0bc088b33c45e9f40c929db5ceb08943ef0f0cea09c1606e0822d9bf9f0a7297ac08335d13c87f28490ad2532a4846d8b951e37ed71582b2562027373adc871ec734cf1b77fd6de383cd5a2b09b240d86f318e67f5fe77e4b3714d5267699515c6696fbf7eb8d2150826f89faadb98f6b52ca914fb474ae9d10ee57c48669ebcf6568bc6c0a8833466f8174c4eaaceb528233d6b6ca4823171880f8853b0f02e6f829444f6eac27fbfaf477bb8d6c11c2ed5ee8a4e0933aa661d2e44e03dc8823cb180cb069463128a2c766b405ebd52f05687eb3288165c4808ab492750a0c0ad69f3d29134eb883cf5de9028ad5bd67ae9e27b97131608d072644251f45c38a49ed0ac3dcdfe3e6c6c9178e8620d600c955c50fe95eecec5125170c2ee7031c13b46c6c64d26278c805e74f5d98a89770c37ca072e8a11ec0adb6e178a689d285b066c93bf63444a1be78977081c6fa0806617572612083635c0800000000056175726101017a9dd3c3f5b3c34e7804b2a4e92c08a4aba153098f51229d81be212fd0345e2be37a41cbe3265e448b8afc03475e33b2b9cb762a9df3e04bcdae19af3aef0d8c020000002200000001d60700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fa23d6b412989d9b453ba20b524d14a4932218d5d20cb57529b5d8481fd9d1717c79dc1dd9fbc475efab87f98c901499443b467cb30fef5e85ffb9429b028fb69b7632d7583557ea812404498c4c544c574b43b952c0f642f208a47c837871974d324446e0b5362729c6f287ae6781da900bf67a02a0675327c8b0c4eb716d79c12dcfed6687a9e1cbf5a58b4d4c1428cddfc93b6031fe5a45441dc6a363f43676fa41104feb13bb292af09d5929eccb40b00b1ba9856a4a7727e3a82f9689c8d58eed3e4d8a61504356c2f5f230bd53ac9ad08605c6366a65ee919decea46ef17520623e2407d6c2a89b4c660b073fbbaf0418452b0959d1018293e923cc0c70ef48a7f0993dd843c38142939ccc1d8937f7600ec33f8e203529f3c0bb741bde0d1e56f9f2bbf7b0f5b44f5a8fd26c1641938379cb13bde0d422c3e5db5675964cd736a2d500e8c1d62f574c4a67bc94e0d38ce45fa94b7fd1af9dfd8c1902f34802a4f849af258f105cc555928f36e117e2efd519ee691784304be5a7c7fdfe5ba3128576150c06617572612083635c08000000000466726f6e091b01ccd9ece066c3e5c23701aef8a8d166534049e0866bc96618feb63b27516af2bfd4c90a72b83065ae02bc073d72ec49901539e3dc74b84025913b2599c392f6daf5109eae1cef4251a2652df775975fcbd3267c254655f0623cff8d48c24d3a0f935472c4b01eeb46871659e4085d8afbb3091dd6a9559d56a889ecdd239ce4cafa23ba44589f0ec8aab1726096d29ee0c9e2676cb1b26cf2da888205cbd2dfaf1d2e87536aa7ca2330a777b9a43a8523bcfd9d9f041d661c688a8c2791fa5927ffd02ac2ea36c1f3f8a3250b94398171098e4de128bcc6333d68e8de6176f3209f66cef788ef9cf9bcdfd1560c5081311c00fa0d4a4d952bfe6c879f3752f7a1015e5ecbfcf729e0713df598b79f1b7981acd0595d8bdd4cf33f3a3b4d44bfa16b0fe8275f58a908984a0cea1fa464abe66705577c82cb660ba42391739003a6ec0dfccf329c2b6d81fe7ea47987e94b00fab2444a1c34eb3e1be1a21a31b6bf0a2c01828ca4247cdff7b0769ecbe0d186ca9af743e0ab05a823ae65bfe7fe871f7d1e5e2fe06d88139bfdc57f9169ae6f869c155bf1dab7d97ddd8ed0b31e2d7b6a1097a9e0e1ebe09539865f3abdfb20d83f39cd9a9ddbe70f2264cc5cc34cdaa45942ce51e3af015302a9a25df2ddc220657322ad6b03e843c24779d4ca45cc4ee30a6830e3c82855458becde33a4481a1e0bb4a548c244b7ecb8be06c6cd182f5e7d3e39010b0cbaff53d43f3bb471e994e01e8e79fba4dee058c59c0eb2364ef45fc1371f62f14dce74c67cafe44cba43cce596b6a37b0044ca9613180029a14a77908f74613db7650b31a2176cfd2cf7ef35e680b45d72bbf45c56a4b8a6327926f708a899548f224faa0cc95e0b58066d7a526f92bf53524d25e5e25c39a9f7523576f0af291e0ae37c7cd5282b14737a46a01b52d5b0a46b7c4674fb28551d2db05d6b6bf9ca560b49911d8087a6898b672e75d9447edf4700e7935cc0899cece13496a9f53e3533ab2e2f32814e36d2162d1316497ed6112c2b8fdb36bad16f697098f1445ccc3ff6efd641cde1b90e8012eecf0c3c5a005eed41d5a312d6ddc76c78b2ddc7219bcc62dc3c2e0dd84ee7c161a2181bd844830d8a533fe8a73ccb7af3a290f1cfd0758182572b5a4b9da22f93854ae35d0b6e79f7b289253ae05ae173ade67ee65f312577e0a1623b4c14982f33db8e10ed43874de707843f49e7d186a0b3ce48f5efa449647f230eb490ce8ab38fb460ebc8b6a26b5331a0dc5224b1914fa1c9a0e98b2092769b3e46066aabe127f3866f55d56faa702b5ce9faf3fbe22ab352469f5f86719624375497b2e9142e12b3f18dbfa0d6545c7637eb25f6f0243e14a7de2a79f5a725e484bd484cf4e8af7b2ad7e781bf6d5cc72b0f14abc95a407cba0bd01c4d47e192d9eced14bc33d509313d37ac40d2abd213d3961547fec1df1ce3450f1271575684cfaaa6867d7ac9b9fa9e939267e11f1bcece14cad2c9956fb316b8e4063db5389738faa82e1cac2685c1bb14c35f2846b1fd44076df9851ff3f6043fc3824e44ec0fd70f684d2140525e37f1ca00190672cf0d3f496d917e4e63eb23cf89aec96c62e352bae3010a165807e51ee2d8e90178f9285da18ed954fde7c7614fe88015f06cd290455c05667c58cd8210dbfb528bfeb70878776e9ace349aafe5ff9340b4598bd70097f8faa9e37a9e3caa2a628e67d83117107e99257785a45c144d29e970c424a0eda79be84fb94287e56f9fb3e746da3847a56403e9618a5420e93832989fb58116d712ef4b1d2d23659682053b38d6410322a2f07444ada2aee3ef85d631e01cfaf5ed28bec9dcb2bae747f6c63e9e4a12a8814da4ec2ac713565574227d197851422b823db3f5eb669fe9ea324f0b939835b73eab6eaf8393221ce5540462b71770bbaa8b77682198e9830f75537221146d306ad07bf3f9de76cdd485a669607d9c5c8c517cbb87730b6e90a783b0f1bad7aac92ae0a0972a8424f6683c42d78400442e9271108953f1d40e0af58e8da33c1d9fc1aa77b572f0672a3020ef1465b1687381cd70e5b1ece01a7c08be69f55b1e0683c1f742dae07de6657e6e88f97b6d3314dc30e461ae492f8e3a180ba1eeecc64a856be520f8198a1c2a4e0bc6d295a2fc13d4bb81ada3553923ece3cb67047b7347ffcd13c6bae49885be17de3d478d3aa8dd2f964ec3ede11d84348f7a40015e588ef9c9a446a3699de1cbe1afa916d10356f412c32e085c3ec0115fd488d3785f9552f893bbe0b22c3773df967b7e36713177151c7c21b9b9b1b367953ab7199fb03947c31a57a94329c6edb9b6ca20d762423fefd38b1ef2ba3f179998a5a5bce656d8b5f14dff06715909d5b7a6343003bf33c0377003d680eeafe54a348cb7815e33c842eb658ffdf3151507e496343305617572610101744acd32f811aae5d80e20534e44195d03abd773156a54dc42204e7c33370702db76b09ff7448955b79a53f0ae958312e2bdaef5a6662350349ce955b8561286050000002500000001d70700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f7efb9393ca81fe0825670473a2d400ac00ad22c1f401a14bc154c5f92ad2443192f6141b3e3c8ff6efa5a85a4433a49aa88b225d64a40a6c500854222e4957243012e86d4a295ca3422a771ca745241b2ff615dc7a71758ca806b1f48525836b78e14daf47e1789603860a916feb342edb58a2b7acb095c4e93a52b987442ad39c854c794e49072f464fd7e0a418d9c7eaa790c89320f830a4919c109dd9795bd4c96ae86882d18ae5a8edbebc1be36c269313f50ee8e1ea30ad62770fe9f88ed5f6cf4e7fe30b0808f01d7b1e9571367979d1cbb8359088cf98ae22e8abab91ccfad85a4a6ce77f402b64b0f0524a831daf156f8af91f9d5d62ce4c687947c3fef1228b81636a938a7a242ad5f78aed0a218d582faa5176c28748621c0e24b9e902757eab60aabf67c35b6f64b7dfe695fa70c9213e15d0cf39dbc547924a5b2ef9f69d630014ff54af3384cb0391d00b06d7309bf0869519cba60f2bc41be171ed2f372f3e1b71a4f5d6958d3b1fd4e43f3173218aa9092f05bac9e7f4cdd4ec490f4d177a0806617572612083635c080000000005617572610101fab1ead14c7c2cff2e1f1ba2f2c0fad3d5a5d5b6c3cfde4e88dde08d978dfa1da06bcb5daedc8e960b11f9012473e7c237b5864609cacc9b4fe9832785864b83060000002600000001d80700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fe4bd11531d6789a4478dbf7a36a3c7d23b58c5a1debdc455e1fbaf1b5b2ab412ec6a464b90ff6ada8a89e3f8d180e74e293a8b2f01c8499ddb1e994293c4c0d0779b68a85a99a3e2d4e0a792e1537c07b3a56fc0a637f1db059d9c2755625b778096d82240cfa6f9fe0dd38b9e597504a42e58cbeb7919c789a917450ee00e73fc355482abce20f5b06ae119b1a9ee79866d5b4854a389550c9d9580a0c0332260e7a1a1b7d1ec159e23065c342070603750ab953543978b4c8f018b2565948ff775ceffb1e33fabccc1c2c6ed03cc463645aa63019a0e9a8aae015cc11c6c4d370085df65a76eb880baf100b4c7401d011a1fa1648876798a747f9aa372d114a81db419e0c739689abf0882f2dc771d2b3f247cad2cff8b1630840b4892b8d5e902dd6b8d78a9a6e1651c21c2928db2b305d78290e51cfbb807ffbf93ceb6b1696b1e0d4200471f7d3b2dbab4c04349ddd829a29c58d75f91bdf56534369705c46523b29229840f9bf10916cad670f0d3727bd747cd737bfcc525bf923632dc5957c032aa800806617572612083635c080000000005617572610101164bf5fff13882bf1a85e593295939d26115f85d9539faff0d76d7be8b7eaa59ea1f86566b58362a71c19076c5ed65d72cb79994091851bd8811193bda730b8d070000002700000001db0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0c743a94cd1707ad4117ab058e336425f029d591d3a0d48e895c732013c7085053dc502546f00302e84fc41e74a7a310c556481c76ff18fc1bbb97c457866b972dc5d56deb74248c917228b08ea5774022ad965420fb4130a53edd44dbe883c91beac7ff23003ff41339e09470ba672bd4b9de9d51aa32ea9c4ca080c6f1f9820e698a3c6c6ffa8523ffd01d125f46795c6cc3c4047c60b36f44d1e89ee037319344d5b89f31dc79f5db9e5aca9ad7925ee5b750c1a78ce34ce503d4fa4f0d8dc38992403757e8242f70fa6e3898ee68b82eedcf933db38e0adfd352a1b6671ec7691f79817eeba28caf545200d0e9df486d47af1c5ac79ddd05aac62546f6f8723aa1c622a8d4a7757a130d4c7a24e2928acd073b425bab04c5e960b4ce22f7e9028813af0548dbba39f8e667b2679069aadf411ad3a194a5ca50253221be0784058e668c006cb6f4c83ba533b775447a77060f2a2fc873d79045329954a814221b7b6d52b96a216e614a1e963366a98b3e4fcb728ef8c2265b2a6a0b9fcce0ecaa41f094a00806617572612083635c080000000005617572610101d8d56b387d8b2b434c1c4d2186a48765e9ee91a39b214c4808eeb9f3461351196740631854c04bcda5980e50b7cb759df2f64ceae11f6f321ed05f8e6323aa80080000002800000001dc0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f08fc371c2ce887eb3e132908c4dd533583177847b8434f5c7c0cfabd4852c24e6c7ae7aea674dd4bf6796cdc2d337782f885482bce24c9030e87b11bca54d7f5e50b6d38ff0fb29a9e76bdfe49f6f82140d112c80a357002c99a8941a08ec62190d3eda2b3ccfeed95db0ab62327db71f640621d80c753b4e69db9868dedfa7da60ce0b09e321b053d10dff1b04e435472170d760c41282be74154810f277b1360cc17225d667bf15fb35266c8cab27968b58813ea1ce41baede882d43bc1d83e973614a3dea1a30b67783af1e57f732e89eba9958b0fcb19fee08f9a3314eb9b44a574641d090ec0cf776b81af6ac92015443353b22a7db67f42bc7347a67aa8f846aa19dcdaf075ea1af3c7f1b0f66b33bf8505b7e94862bcc0c4f6e9eeabe890371dcb58c1c4fb0f5cad90c3ca6f598d596f8e47005536da04f424868b9963e9256e1d2002610491cd018b9dc0c88d6c9790b14b4b866b6e0600feffdc0c94c667a68c14f2264ecd4a757b0f14bf0b6d9ba93cb7e2e949191c86ee32c5402d158b85fadaf0c06617572612083635c08000000000466726f6e88016d1ffba7d4ede2a4c73b3740c4a775da3a0a1fb08e3b989ec5e49684d663be2700056175726101015adb821043ece09a08d82ae2cef89f37d7ca8f4f9350efeedc12db5884a0016763c60aa38c1abfccacd5f9ba16c4a8ab93f6b9177479100d0b6c975015a82280090000002900000001dd0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fca221b74c8d32fa6a45bdc2271371109a97cdbe2c82fcbe452c548874b7dc1665af5692ca9a27a9d2c2f55affabdaa466fd435945f091b45944e0f0596984b664b7f5bee6c782d18ae489b645be2afffac110bc7bd97840260a807550ee056ca22a4b9f9c32f4c502ebe462083ec11fa689a7f3fd948fad1e3cb5ebdeb4737c7ce6a2e873ae8e530de6065dda3890084d568507ca5d9a69df19683805bf5d24ddf938c7c9decbab422bd00c4757dfe18489bff7e017b40ad9552871b9a7be88a4e315ffb734e34f9c25170faa579eebc5b74caa8cac8b1b87827e84055b256d35c644799d29d2e6f4f2c065ca606744598719d85f8c3e7c4d39abc3ea59be4a35ba689f6c0af4bcf5988a4580840e313618deb3b835c4e4a78cc56434b2ed6e6e90231a890359de5d57ef9864cf19f3a48c1fd1a63812b0765661c598856f956177cb62e8900830038feac3e62aff1f1333ad0ee8696a4558f6cc42b876e0603d703ab0d7f0eea80b0973cfd2d3a59268bf68211e1bc014bd94fd917b6e9475c3a78508c03fc0806617572612083635c080000000005617572610101b86bda32f157f1e933143a934f6505a6690c0a31dc52bda5f49d40e5e26073545851c15949664b7f55b8cb2163a3caf7f487d8b4cc87752aa3b4f40638c2ed850a0000002a00000001e30700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fac991d1eb1203b3ac74ce441fa62e97c8d7b99628a85cdab3806bc68ec92131490b0d19498a2d0ec54c48572abadcde6a5a2aa9ed3ab74314fb4dabe30ba6408d4894734e270af31d21c80c4e9e3fd540899669aed2f9bc7fe28891bc0fa6ff9a58ebfa37a19b1e8479d3d41c7b78204d9719c8ad1212ef0bae7f2cb82746ddb6816850f2467e875176ce398d1607d13d2f458526126a222d47f10c13396eb069577928443d3ca93d4582e1291c0c7caa7bef8c1f39c9863385e472ff1e9b38d85bafb3d2fe2ca2354c2fd1fd197b36bcff57292ec4e7b8ffba280227b13aa0247ba47d4824fd30328f70f64b056d4e36e3b75594d6f590e1b85e90a65f9a63ad6d42232ebb0628b11aa6a5bc31c1b8ac45f683b0290b14ea725b2b53ec8017ee90265f1561c96e26a3ac239745a0746ae6fac255bbc9a19aca4765900819e7a532c12d1760059118acf89d6a62c0f724e283081c8bcfd74a1db5435983c6cb67272699024dcc1f7c4089088d1fd7a4ece328c3611ab9219a8e0f43240841673317a5d3932a90806617572612083635c080000000005617572610101eccee865e2c48f93bf2d1ef99bf22549e3994e74b2f91cd00e742be73173cc40e5518cd480b62778a627e15268c8439cde21a27eb24fe0386645a5b11430c1820b0000000000000001ea0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0cd0c3ce103900b501fc82da6f8999bfd42354f8fc4db6230a764b7926c75118d570816caa86a63f7fdf4d0e0cae604060a1ca4d53a6bc0aeda87d1f5c28918b5f8233fecb446796519206c3b97eddddf86237cadeded98b041ef6ff4e474e53287a1697c8caf461dd58930f749d53af8832c488780a012590b005c36eda0d6e16c775b8eb42663d5517b3e9cc198e9658421ae7af2a76706d64e3324ce39240a32fc27041caffa0ead9c0064ae0ace86242f8074273018316dca50bc96a978da3883c3993b1a32b26325ff85be0b63084960a8b50132433176fdfb5c6ffc07bad1936428467f481ac53e71165512663839cf61457fba5ff17ed63e71b8c717680a10e1f33cda8f8d81c50c91152776a54b50195d6ec7f0d4bda452f9ac73012e902dc413d61ee372b7bc1305b79f10d3644a42c88cca1c4c8539760bdcced3d8c2b16819f00b2faf4d0fcf22d03a7cd76920487eeffed5b599f6cd32ccc9a64801fea2aa079feff2af002f0a71bd1fac90e9fea3a0573a5bfa2765a3a931bb5b8d55c9717290806617572612083635c08000000000561757261010166e2910c9513e1dbd2a6d3f938cd6a6253fbb2cfcf6a1f6cd76a8b7941b07b36824ead10eb5d99188c749988b49b9bb673571fac8b9317235b89b8d443a5fa860d0000000200000001f00700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0e4c8eb3dc54e5c0d1b9402f44f89137c1c2d095bed90ecbb80e38c5cf245c4828efb3599bef57b84619255f76f0aa168ba42a0c7d3a7e519bcaa784bf0c66e38b0a4168467cc53f93902feb5d97440405d82d672f86e440c362301c6283263fe870ecde7baa2895003dec3d07836c095ae4f3e4a05347dbd7d7c4eee1f811e18628cc961b32b53e4cdd3a60be566fd3ab6a686041c07a8d4750133047a6907232365380453504c52c6b96438fdabd2d972e3dfe6bd1e9bf0f254bdc07583e80acfe461dc363714109b6e04784803614ee2b00967cb51eb899327193cf485260130b0b9ac802b3db074f304ddc428950e80ee3e2a14d9f009d8376fdff493b7da24d7edadba1d6f9a8bd642f426851bab186b7aae7eb8fe526b05e362b996704e9028625ec7da0150afcd6c1431ed2e8b56be1dfdbbbcc7e3eef1275b5bcdcf5f4091622a20013b839aa611349e4450391abb30a5e0bf166d201351ff2eeb43d5057714a5b6c959ed33b8bae5fa99ba5d0154e08ce851e94502c8cd069c78c0a0d748ba782160806617572612083635c08000000000561757261010112e21a778c7c5404d9cf20fb4ecfe2c06b14e3e5ce45c76619077a2d47920b5e2d605528db37f2d4724f811429bb3bd308c9a20ac0d05b91329bb6b49b3f5a80110000000600000001f20700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fa6703abcf0fc554a4cec1cb5677c287f06e3bfc3f74bbab462dcc1062c88ce353939f9e6aaad990f2c9837dafd9f5a22c17455389a73f05570a74aed86a63b1ca65a09155dcea6eb1d458cc292968124a0f9b2bf125cb797ab96086dd3ed40da478e5401533e30c628939b081e4e383a28a6890ff949d27913939b7bf5d9c4dc0419a23af2d8a14090a06412179f31a575a917c04973f1f645d777e5ec48c938ad24670905b57cb5e29d8e2b285fd25778a69930cb1e71a366be9594f58c1a80322a31962e767ce5d6aed172950bf0d2ace5df6050df675a4e6a58a4c308372d89fd8d101e7dc06f0ee9a515dd338f2d29098485ffa2c2eff98c6bcdb6805b483ebfb1a48db52c4f8bc5cd264c2746ab4034bad57e11be369e459fdda1bc9810e9025375b7d9d546b18adc6ed91373ba5ca0a1e0e2549458ed06d4a9ff337dc4b7f11a9e9700a5ac8cecafd414c670faa4c56cc84c1efdfbdd63620fb2afb77983d5bf004a11177c31f7cac28712d992f31156ff0627678961f8ac57d3a41afede86cb1e31d30806617572612083635c080000000005617572610101e8bc4a1acbda300bdc4da4c20caa87ec14e7d91c04718c20d677ba82a2adf422e72d52c66fdfa17eb1fa426428ea9f015f8ec3b4dafe3b59e9062f0e8a4e3580120000000700000001f30700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f12528c5a9d2d33f06fe0197fd72642634a924caa92f954c84d0b30a5af9f621282ef2d609cd65387717749105fc4e7266cc29d8fa13accb72282526ac1e28f285f18f4e449efb717850369313139477445e5f16e58c14d5fb079d1e95a4c15f9bb6baaef2e82cfb97712dcbcef475efdca635371ff35d5e300090491f05aab135cfff964324889a26d9a999c5644bfab36a5f2b900df8dd33260f70ff4685c212d423273981adabcb2d89ab22068042fda0beb26bffb730348f31d3d739eef8ec6b6f7e799362b07a29726bde1d02cd6fd231852f6d0df84695832f70b69df9f724160bbde1c8a99b1f8014f200f6752e90265361f4c1e55a576e58a0a1ada06c73c69f77b4076a93404329f96cc0d9fa7ff77bfd5e457f1caf71688c95cbef6e9022b8b83e8888c042d9e2f0fb1a9bbc456a8b07a9572f1e4fafdc8d699438a9bb296be96007d6837a96593348603378036a8638aa191f7164617e732af28d26929f83245736740228224f3d42f71eafba39c8f4faa94a01a589f51929cdee85a28b7895f760806617572612083635c080000000005617572610101a2f595ba846acda337e0a6891b3f517de907a15ae96920676e7aa300c603d903091eb30a8613fa54a684f1aa488272ebce844a5f9c44a0c56990c60f6149e882130000000800000001f50700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fba252d10741845a93492f9ad5fcb431e93c51be0f71ea6a8bd164093d4fc9f06df0b8c4567e4808dbbde228cad475e6060a923c214a5c4636f556eb42a7a4ba91f04569f398c5b44d0aa5cb46a0e95f958b5a3e8352da4092daab9cd8c4859bfcfd415dec6748a823e1141a8ea36b283cf6384420f9bfb21b22579a580402394ecccae790c40a892f3417def8c361ff5a86b33779c74316c77c548c4612fb838c362ebc4332cf2a926e56af72339da43cf00bfcf190ab013df11fc575919858136699ab86fbca58f8f5aed50b70c125329af294571a4e1172e3d25b8d1c0894079c48d94b4f1140f83e68d0517db11f4d29ed81a93ba725c0516ef4d81f2543579a1430ae725802df267fe527b925ac709ea5f238c6b87cfbe7ecaf751855e688903d303d17a8af293a6d14b5f06dd6ace4d5a465ebc84d372da88b1d00fba851237864c8b00f9c1ba4d0f26ecb08528e3c156de07ee51cdbf6fe50c332a727d46f303f688f8ef451f0175c1f5902c4200a374026f4e1b73706cf03f33dc1a1a2fc0877346cb0c06617572612083635c08000000000466726f6e88014968c2fd312c9100837a25718581fa2438136bfce75918d9974e85bab2d26a6300056175726101017a5c5bd08201a067464db34a431fdd575008542f500582eb799c010c99c28f325a1092ab8501da0a0e9dcb07dc7eb849c6ade998b512282ce5786fe3b84d168c140000000900000001f70700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fe0b5632409e78aba11d0d559c96acff0247194879afad0741ae3848f61e74a02397ee4075a31cdfdf00c080c5ae192e9a8921bf216eec48cd06a0ec54f3728e627e68a325aa980ab408e110b842221f262f65fb9c9ff3bf2526d7a454e1f5bb31c4957f9abac96eaee0b0e4592b60fc6abf498f2b216099590c593fd2d6956525001477ea73bc4f27bbf93246c8ed89995f7e69d9e003c4b80bafac51cba1b7a8669945a41c3693a006a1cb8a9000b443f45cc4db5b1ccdb50ea7c8d7330768b445c9a763b1e6309dbc77d14e1e27ddb362cce7ef9e4023660b6db4e520bde91088b3f2153fdc8dedb22d5984ca5773ab7e794d3a9a6f700d1fdac1e54ca83a9455b24f78b25d8dc601e67cb9c1a60ea2e7e907576b4579a091566ce062d7b9fe90294e33d043375a9630b8b43a8176a4b8620e3341e1e22e9ea344ca3bc8b6d989e86ea5900c0bac6b93a608c8ed70554e38d2a513b20072d9f2556008e9cd917066c54e371326902973308c86b18c426b4dfe19c571cd158847f719b5b23daead339f4889a0806617572612083635c0800000000056175726101018a4d75e4d4af8ea9dcd1ee5c8d18659be74f9e3dd4af5312f566705f7fe08f03b6453775880c2d6cc9552f0c99462de4845de92be70ec21d537143377fbf4e8b150000000a00000001f80700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f30cd84fed2904f8f55b7c41d0638af65a209ed81abf76645862f999e1900273d800e3bae3d3c043d319ff1b86f66954e336dfb77f4f62e2cba632ca321a19edf3f600c334e02e5f6ffb1b0a482e3d1ff6e8da744cb98ff90f4e32f87f038cc682462c29e53670de6368795f8e42b58b565b4b0edaee2dab8a1b9e7f2c5b485b4ece9de94fb93817787e0a41ec5703599be3d47882754fd9de578996f9c23f441060bc13cea84d987edb6859731738ee0046151a27ca5d150d89d09dfc33c7b8ba56677abec76be5329edd0100932d6ad28aa84ec94ee0f38fa28dcd7428370186c113fd2ca1d93c9c59e2047eea8b9d0c6d52e15c73398d58433ecaf2c85274ccdc35e3d74de2af6b8b3a2af12ca02f9f14c0a168519ed83cce058a4409204c5e9023d756ae602b1db65712f5c037388b6162cc31b73268aff4572f0b02f706d67145aa38d009ee4491a3c7e2d63f2f2bdc16c70244435ca7f4b86b282a82aec767fac5f02f7489304e192850975b4acfbd1825ee836b803947e5704b6dd1ff7c59c44adaf950806617572612083635c080000000005617572610101d8fd11466fd2a4ea198104ce9c2d273b49e32dcac2900be2313085c941ef415464e0f1fbd3431900521af212814b266900a8a95d2ba9fd74db69092891ef1681160000000b00000001fe0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f007a3643f15ab58061fe650dddb783e26ac918157f6414ceafa7027500721f43b043862b71d1dd71242ecaaeccbfb79a5d742557eb7ea49c6f6c9f8a4d0f3057c7b4ea49c745843988fc3e575d3afe2433ae789f87be82d6aaca8f8eca674e4c2c7d5e2ea06f6b1768ca7fd09ae4f4b40866331a4da0cde2d5092394f50c7f58500047700c9e0db25489c6f932e40c357e945914ee47ca84666410e7d5f4320731aa082085acca46517147f2925244a62cf6cdc12e0d1dba722ac51ebc034988c2d2ba2d6a33d8c373a69d92f154d8b404c16f73fa872a864488126f84d3168b3f0f212826e2b9c0c9e49fcdd3d099bf3ef8d93b11c71abd2601da09acf1f8fb139a332d9a5601f727c537d8edba21117d7be408a87d6b9279dad0d31da1dea289033d2444574e1a1ea77abf1d1183b53dd83993c39fe1c82e21a2c331e84673c2d10e7e0400e6bc71df504d3496437a3c4851298d686579cdcd6a0eb507d3bb3807b10b483abda468fe3b2e3f5c42ee4223b991b3a15f0f52c7e847691a692c36791391980d0c06617572612083635c08000000000466726f6e880127856dcce783370e0f2f8d245e6962e65da80ac30e97fb2fbe2fed1b290f77910005617572610101e6ee0eb043a6b5ef5dd2060a1280d0c51cb63c1cdd386c77f1b03fbfea95741e8e4f7f250c9e031120c116a69f5091690ac472b19bc082d2b8955711c28d508d180000000d00000001000800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f4c31488e9125c86f7c78b1174f11bc54e10e24d63b075bf9edb77d7a521b8a7c72aa802d70982fe9261673dfbde97a4e0085892f7e826784a62e974449168d280cc6780f3f88b07267c5bd28035c1ea8d3c7d57bd46c7aea9f3686d5dcbf0e5cd67ae5a926a93a34221dfa7965bb1bf5bdfe550eb4302b952a19747373223929defaaaac2a4312b976551770dd90b277a0fea279f4e133172053e186276ea502a4c071f88e10a9fea38468083ada172cf4c4b71fb676cc911d061b1182557483e9bf72a5cb0332c44eb9f1c9e7621ad6edb850cea38d14550d91a326c4501a9201ed82c8a883f444d0300947104879b646d005468d5cf853725170f9b358bd5ad59c197ab76485206c59f36a6036994dc543aa252b11a3c056814311d27f1404e9024f2df319184d0dfbb1db4f4259dd717a98a856adc2a8c8912efcc98fdf4abdfa2e002d00399fa53f7c1f185d8427c874a8f23b13afc475e5cee1f760d46974e71a54ccb2d353e4aa9bb6d3b4a641c9472a2faefe5adac9bd04b36beefb4168050b77a7f70806617572612083635c08000000000561757261010132730fe531d29230b22a9a0935ef83d80e40aff7efd8db34ce12604e23492d3ca79135c8bd2a4df2849c018629b7aa544222db8ad821d0f04720ee11e255a48c190000000e00000001030800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f48c1b5e26d4c749374e8f69ead4a5b953951cafcbc541903b9ff0496ce82796005d8114aa42d92f25e4aab90e7c0e5bcaf8e0b27364123b0a0442634aa351e0df5c0abdb50c18e3c20d85c1c0d85ffe9fc4b3d2fa6334a888f89fda67fd34125075303600635530959cfa99e3dab3e4e48746930e6c4b416c857d7974b5dfd703c0ad6dcc383bf87f8204dd9c4204e7586a5048bf43854682d5e6753e824c0358e2e245bd9ffa05c64f572f7ff97753222ace44ed6d7599503a4d5b0bb4674819ade986462caf64eb706b9dc9cac0f23d5a9ac8784f067d43663b936525e949c99823eaf56a8d5abc4a8efb4cdcf6f72330a94b423b765fb0267f6be2fd343d2e68724dfd57dc416a9e429bfea4c4265c30f8f3420f1dc6e7ee002b7d73edf0de9027005ab65c401c5eaafe10bac663bad41901d29b6303401251affd054103b251c22b24400e801ed65820b0cd6e8deebbac787b371c89060775a0decfc2a7112b01c51ef7c1e616da83f89c8305d421b535e08d1b33570743958df7c712c4adf9c96cddd330806617572612083635c08000000000561757261010146354b89f12715e609b5e0a272b1e790070fae3c06593211bcb1fc0c40d9806fa21be4cec44a86a847982f6598f92ea1895acbebe39ee857012ef88fc80eb9891a0000000f000000010a0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fc00ba151fa23caf3a11590fe480f8713e26df35213521f26010a50d2da4d7c7356448cf00a57c405a2759052775a9ab72ef3975fbbfaa8c972b777958774db6c053837856a44c2ba69cb62bb627f28404b1de1f564f254f1a9b3d34d5b698f697ca16b1f5bb61e5b6cbbc9414a5bf0621ed419b43cc72ec90edd901a648d92f0b65504c69ee4a2793b9566effe4685816cc9e9b5afbeb574617a44181f56f84e9485fd594e5a541005820e3fbdaed7713dcedd4ba1c39ee31e386cdab27ea68b95d5c4474278dcea31832321ab93eb6b9d8f2cb5fb75a8e03cbcfba0dc6d495a900f07dfc7cfa4567f2f8ee94fb18793c79d46f233331913516c82a8ea379095c06172eb64373f8e6e622f61cc963278de4558aebbfcef14e1146d85964197e89501ef226b220d0a9f3ce159cd9fe3ce808391b3b90055c3960918277984e45f4c249e9a01006070e574c692886332a9cdfdd2bdbd972889c16e16354f1e470e52bf36db81d2bc7851c7622decd220c83b3668e028145434255ec44cd50cef9c25e5b868e92c001f0000001400000001260800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fead4b15c40389b68b80da252f1c64ccdff8b7deda378cad3bc2040df93bc0b5e7252eaa94a54db1b10710b81df91791d58a801e17ac7e6c5be9558f6ddbd3c555b19f587cb3e1436049a1e54564e1539f558a5641e3822542ef04a8029f6c03c7cb08847b3ec399f336d9532afb4a312db3b0226c3e740d12b274eb378aec9f87c169bc67da0715fb92c783b5b8fa646489179f8bf7e4a4271fa7d6edee05e74605c69aee2333339e8a08abafeb357a0281a206a64d184dceec971d6d55f248b741ed705f509eb20a558dd1772cd34ff1359d80a4c176982169f7a7f44e8250f9027b2b9d48451380121cdfc5a041491c3fb5eefc07009d1aee921df7a0599bc01034b5e0124a5042e25c42f67aa1303afd59571d83ea865eb1a3aee512467d6e9025befd6bf43197109f64511896b4ab95b2bd221e6810459242b4053c8284686e822d3e200a8f49a3d18ac36932f3608c00c7e004147b3868fdb6d9fa0d431f2ac5c180bbff6f0a28f55b64489087c1e2e91989c0b886fa55e5ca22989fec8626754b531320806617572612083635c0800000000056175726101016c40c4eb4eba5a7917edb38b4813bd5160442f44c16f743b1ab83fbca0aab837686b92638dc57ff1280973721c79102295a43260c4dcd93a6b6dea614077ff812000000015000000012b0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f7ec2f69737ac6304d9b45fc7bdad23a6e8b6b8c35c77226a9270a105205d5816f8f871b0e0903970117dac29c057cd2d5090f7381019703f20ef82e38de9484d4487ceaa35c2b85da43887dd27238c4a77a28d76326c0bb44244f2fd51fa8ec2298c0bd4ee975e581149da8c6b891bb511a5ae7f5b1794b58a133adba5beb7a75ec607a812b0ef58815e341279396158ae4d5234e03f750c7039bbf2b8b31c2ec4e675c6f7dd170b2fb31de633e340a39fba599e45cc13275825f7c505bc8088f059c6fb23e2e6148346053ee02154cfb8f1eae02f04419e59d9e23ec672d96610883519517ecee74ee2ca4c3a7d47ce8dea260ccfa1542ec8255ba9eca949a06f1c283dba5bef677dbbbe5b25fe5171ac3f48bebf64747f70bb7f689c57ecade90254ea986a37d66353e404a2f75415fe3470a1b41fd447a220d33953b9284c16d83ea543000d8737c8c55fcd4c37ab87b7558e052dfaeacdd7cb168de9064e583276e1a7046e68b68199397af29e1c83f02e4083890c222e4da2b762463e62a870cb327adb0806617572612083635c080000000005617572610101e6ab5f369c205dfda284a6744f7a74a83d94369526a4126c20161c5d273c81053f65482be2ac6e762d95a8a5f0e0474385b10e52bcff0b4e2116d9128108c6892200000017000000012c0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f8eabe2f87cf524db949c7ce4a300c9943d5ce7cb61eaf056407256614567cf6808599ad0612f70b2011e286f46bb6499e08a50a483fd8f6dd0af19e1596945f877d87e4f34c7c2a362ad3ab7860336ef91c50037eb839a57418f6989b347c701e0b8c7d6d75a732aaa50c303c7c411e87bbb8479f3afc1e31fd7713002d275bb7a0ca5e2cb228b6e38d1806487741429d1dc70ee946a51c3ba3285432ccd0b3dd07663c15018b3931889fc09646632be942a7ec9e4764e9aaeb031663f6fc380401dfb396fe48d83b1d0d25eab92e1dcbc61365db4fc2178436ef2b7b9ab29b50cf12be580eb72539ac227b4fe392c8868b2feb21de9067224d77fae5f6769e46c526f8430531d3b87d1abd12f8df54b0fe7d2e5c6c68c7d45c88eb6a8266ad24903339562159a30ba82f5e54db05cfcf1b517c911492234e3698b3a25410f07a55beee0af0018bc9c144df2b89cf89269120ac2db451dca153e63509b970e86778f340bab743fa69abcba4b75ffe19442f27b7522589c8dca513b1bbfa2ceb2dea2358fefb908066e6d62738088197ec695687b3c54268b18d071a0ebb4323e84179ba664894124beefc56f52056e6d627301016609447513272ebcb0271154883e924a6165a990dbe10ac8f63c33dd71124432c2bb3550926a2c1edf8d3f392c22046af6f1e86347864de3465660969b55a3832300000018000000012d0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f66064f3465604d64246bf810b9fe8e49a1cf470be7263b11a699edc83a9f352d4c87742fc24e8aeb858e82d633c5d21aaf645efce69123d14a5bf10cf2e87b829b622d5143362571270ca3f4f451bda43be9f870145afb34e3c3a25c97960a255c35ea9c5f11d8b5b87d7eca9b38db17bba211193fcb4df872dc755078e4bdf096a0b786e3efadc128eba8062eb163b018b1763689f1765872b64a88a4c3103c4796565257c6f24d0ee68e26627947ae8d033d2dbabd19d2f6796fab2a3488814af90dc6120f52e8b176ec45828b93ab9ed570537cb311f3006eb17a4b04add9aaf8b111859be1b3d33934ee9bc8a6fdc2bd674f5236099d42bf469cae8e9dde924db656504ab1637673c75be1d51e171906c6e8c12c51a06f6f89e712f7fa19e902f00e5727bb4eb555d4a4f5140b82f4d72ded6eff3506cef9f2eb8b57e36d13f732d41c00310b800ce61efabc623f074c2f728d6c7c2cfbd7c2be565b5bc4943a7a3bb2794ce3e5a2cae2afbc804926c92b104ba1e8eebb2fae209f6b244ced22de968a4e0806617572612083635c080000000005617572610101e81f196b8d3114ddeaf9eaf15d34be8e9ff43db5e25d1aad1774d6a819da913919f6f0b6a16dd668e2880547df0716338b7d0a8bf27203dd8b8d03c90adea88f2400000019000000012e0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f723e5619fa775cfa0b85ed1f73557d87bfaf34c269c00141e20a8e4fede6c76c8148b38f39593ea9b1d336460e35f225c624104259c9e8338b6f7f74322dd1b8e18091df02039f421e89714802f6be2f2652d714893299798f6f059c5a37dda0fba4bcfd13dbee90229d0771f973af9995468146472ac6aeb912116b4d8bb5ea147bfe6f234a1d1f7bc9d4f10656648269075b7268ae6a243a1a745c7c85f077f2a0fc35b52911a0984a7d2d8641e25952ec16186995a251213ce8c932d3008a05530d6923ca084b8837f15cc4d4dc0bb3c63a1921fa15ec9556ae3ff9d359b1647a0094fc9493f16cf2deb282b73f53985acb3177cfcec28a6f455ef0b43a6eddd7bbebc1214a12baf9cc2bd7a46fbc1e5204d6c192fab5db3fb53c0304c3a6e902acc812718e754faa8f3b4979311ce24e7a9510bbc1160e124e881180d6f678c2debb20001d57ebbdc54d39ebc6c72bda6004b766154578ed841d357151fe9f7b7d80c42d43197f6f6983c8e53d10ce0384d8830a6f1b2121958dab34edff2a7849253d620806617572612083635c0800000000056175726101017e927e09f71f3a2af25d161aff972a98f588d4f42f84a28d295488cc2ebbe024223147f58a7afc121215ee03e9300d5e11058ae1e7f0e80f675967c1367e8e8b250000001a00000001350800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f1c3964b2c71a0c5fb5c51687909a83cbaa4e94b907d2518bad392fc9a5a7ab7fe35190789786820fddab97684b50b4e8ce0f3595106ab256593fb1cae9ec8c9656a2f0d8e332d511e9b80f31f01eb57248a1a68fc87f8745b71b7d3c8f81982981df3189ee192b2a32bbd331fe28d70851d1d41462957f232206c470fe7c8e0be6133da394c2bb60467b7764e7648794626315f4f2ca7028fe235b0e9b47c33a974fd23cace0213c08cb20565b61ca4bcb3c0e5cdd4a20cf290b0e58d814688d0f34ff3fc478732698c85d8ddf6d0b5bd428df77b267a77999f6ab24b9728458cffa7727cd0ea5c03a212dabe51c377dbd53f0e7f0a1ddb79033fb3d7b73c1db5558455d3b6442a3da1f7827a645952460ccc5c3dd691bcae64a2d2668fe0097e9020425014b3839b51b99be80baa9dbf1a3ef01662a7ea51d6cb2da23814ae835357270a9006870fd9e022c9ac5b4de06bc198a481ae60f3909b8affe519a6c04ffed18438f3c163fa7c3cc25faf40c18eae7c40dbd5a27625fdc6646dce86a5773b6ab6d6b0806617572612083635c0800000000056175726101018c3417489b99706c04255a8b8648f2d6b6c701576dfd25ecd1de9d3b1e0cce4970616567b06ab1190b95a95572d61a4ae637ddbf7bf13bf648af9be585166785270000001c00000001050d00002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f54de495b57c7c3505c62633f1ac3a2f22be74ed497a5884379e0821607d9173beb5dd269e10d71dc754ce3fac591364afce61b007925730544bf530068087c7d38e3e2cd8bdf7fef72ad23b076e0620ab5d97d3c0a98207dd8b6af8c3becff696cd2c59aefd1a3bd654df00febe502e9f6ba788b8584c7278c47a2983fd8e87bcea2f2c3fdf7cfe328e695f1a111ef699739c5054adcfd40969c673b39080e4dfa869839757fab6bf946cf5695e1a0d9335ad95e445cd5fe9988a1c82fb53c83fedc8cf6b2555199ecc95e7092742c5959f96bce04becaebfd9266f7642c23d76e25771c2505f549b5af7734c84213bd1fd39278fa8f07298ba69da55a5c70899ece96d300d33d733840cfd4035249b50618e4e81f1cd425bd304b0cffc13b8ee902e66008704ade0c28fa58a8abc788e7b1c3ef78710408947dd4fb2f400effb2344a581900c5c07c6729c92d2b6d2dd7b5e6a05c26adc79e138d57c1b74a2d42ff7c021eb3f127490b8eef8e2c1cff1b685fc398f2dfeef4554328f288259cd9de2280e3200806617572612083635c0800000000056175726101017e7b7d496aef40f4e44a8819b2652fe2d64d286288f21f25a08b31f937d82c7ad7a48673092c23d7a2aa5cb2ca8dead00a2ace14361537ef7f338dc51f34bb842a0000001f00000000d207000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43216af2664480544590bc51a68be4ab955ba1e9d66544fb5ddd87455187539e427c0f0596d61ef285c22dc8d3e2f29bcfa542b00f0474045735c327e32b81a1e7fb4856020ebb9fb922899fe872508d3105d22f9749a0ed5cd6a2ee894140e1bc46ea832c2ab3e85936053ce6b203eb5396a696dc8d4977092004738ed02c4f5504a932e236c018a5ffcb5f0bed02fc84ee8a1d18fc7e02bd2550ea4606e043e4e6018a6818a0dc0acfb0e5ea67880a8e20dc6ef1f7399658c2fd4a7603eac9085a5574ce91797bfb2df82d4939ddd9f8aff952e1ce48b1d261c97088dcd5c86e532283647ac87830d1b136bce5fe3bad5acba67add2a89f005497d93fac9e5d2088e825d7969dad2cc6c04f8c4a6e65b5002877aaf6b7c32d0943efe5e127824089032a6b0cfbd22318888f75e0f1d6fd92d22de5cd8fb974579b68a848ee1a394979c675d0000e427f6dd8407605cc5ecb040ad322f127d040c84616ed6f41af284720d7c4e289ca21a7e551c98bed636f70900a463ebd20ae087491f8cab4b90668e7b3bc3c0c06617572612007c7b810000000000466726f6e8801b1adac139bde159ecba683741d3ecc31221e98eab5a429f3bb3f38c553018ecf00056175726101013c7952f659e18808ab2c763a25fb0c7532634085cec8d495f3030c6c3cb5b05722c5143a5dd1fad4f7d84eee22196d845e2e1309a48eba4859aba690c2e6a083030000002300000000d407000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43228919c055a0f2137f13690e949df8f7d97d322fd990946b698f985989116ba7725269c36d48994939f136e4118d4344b4ec13a8c468ea71c52848177ee200ebab55f213795cf2769a0bc7d5ece59be01b8afc921529684f158ec31c4bc58eca35e4f74b2e3c8decba237f50ffbfe45753135891432ca98e1ce2cd1aafc02e67a80d7bd3ff76b4162eb32a149d0673960080c609ace1755ec2f60d6edcdd79309b9bcefd1b379e2291be3ec29e5429c11bb5269d085ef32e86996bb6086f9528541ab122ce2a5db613f84f3b2f96a7dc6bc53ceaa18f6985f08391a449a440c6332e9b1f9c0b02e36ec11b5167c7e7a00d24222061b4769e03517ab2e2ee6170c55a25e183e83a80c3d4968040681b1d15366669926dbf45ab4d7a84e553e426389065fd3dc2ad1fe4f17b0d3bb1bc2bbb7090363c52706ca6509f14a6a128d85ef337e52d5008cc9bdf131d19272e7143953afec22aa607608e1399048c920388988e7834c68139f2af193d65a5517524c47908fc3a6a6275d581dc9661a5594a853b0aacbe810066e6d6273801ec11d2d43768a4d5d45b5611db0b3298b77621d26742547fe41ce91c0d661260672616e648101ceaf24ecf730d7e039d2de8aa45733921ffba8cb0e7c6f75bd06d2591b901c77b1e807742745efcbd5a57bf08935eb21cc1fbeb85d80ed7c615ca7d35e249a07bf6d39c123ba9ba0bd7e75318040bc489985b106d6c98c5aa5a0811ede08f9060466726f6e890101ff0a22a78c0683078446688ddeebbc95a99b1884cd22a8201bf911cabb18059908309e9c2c6a18f7387da2ee66bf312501f6b7d5c7e5f0b9a17df6a084a87d334c3022239463cef94bfd88bf8317dd9b6cab00f087cb8df769cb6bb2c0d0f1d312056e6d62730101d6fa19a093846a11dbd3b9f26dca8a0dcdba8493d6b346b86486f3c54dd7ec72b46a8f8d7d17f1192788c741d069e068c08eb0c5cc6f6aae09d7548b6faabf82040000002400000000e507000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432cc8a84b06644b0fd1e790c2de73d66c562f0cd3f6239d81b25cd278e5111266388a9171ad58bcbd15396dde9b68b6aeb9a7a6a5b5c7a47d77603f1889cfde56f1ac40ba6eb288239b7dd9c8af7f2b9fb0795cd5b28820c87180e3d735e7bcc0b51df051cf8f33419ca0f07f31f4e8dd2ad6f62bafdc1f0c47f9b727603cda6ae34a3726a20df66d660d77f1c01195a112535db1e046a4beaef91de906901911dc374d89fe1f805734c6f6144db3152748f9b0541cd6583e6c3d2894e04970082b98df5d914b951c9183bf25117b1a9072768e4df487f8e6ed918e5d6754319322d991a6158947113ff320990f38f5e37f0ece574395edfae743439824efbabd2d04f9ebc499a3c2040abe8fddc43943b8f123b71bb490e5f93c5f6093dad9f58e90231d5d69ba54e8052c9c50daa412c580711b273461ec198a7d5399fbfe614faa5ae8d9f004508b43b4a234f1cb724cce8e3e6b00c81f94bc0f321502794f4616392849994f67c842d1b63e4a18df453da38b88267d8389934b1f86bbb988e29162c71dd480806617572612083635c0800000000056175726101011c43c9dc41050f47d24f799941efe385c0b41380cb1b19fb9910ce4f2c55222a6e836b3aeb5c1c931f9c3e95dc9cd27e1d1585d69e18813f5cb889ecea1da3830c0000000100000000ee07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432021071f1207ce1d22e80903c737f4c89f2113bd1c7753de41092a70552dd6c17cffb003d8b5359ae9c274650df76ffdd14c52814ce9b5c17900bc52834e30a83ce59e7d5f163371f5d99dd3784d693dfac0e4eec4fa8accf45a881150ceebab3f42382ac9fa47baae525b7af81f2ba3125302b795ec05b0a3d9b4bca133d3a63e2c5da2612da3f1b3c8f42cd1522f6a7a48d2693d58088e5288694b90307074ef116265b6660b03112547414f40025cc4154c6eb7a6de2ad52e51a55af54b38aa1c54fa1bd03bcbd527584aa648fdd075dc0f8e79c247f5ffb1e6ac9c2be225ea60db84bb8d7ab17120d682d16696c329e958433a449faeb88b1c50464e2e4e2eaa75a54e13a8d890399906e24d00454ec4e709e4f7b939691771a23dab762bbe9023a3389663194f4d084a27298adb033bfd6a263f4d3c4c20a3e6f0e00863cb85196408b005a0aee92f8c6b9858c667067f971772855a47e11daf73a2aab1ae29e5db1dc095e8b6f463c0264370e99ac799f7b717e685218b437e4f6181e4abd56e1a0c0d60806617572612083635c08000000000561757261010122106da90907f90dfa17d639b60ab9d3aabdd7ea95daaeeccf3b4dee072fce038e61f86d7189ee821aec9a11d6ecc5c484d12229183553ca27a9d20f668af9860f0000000400000000ef07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc4327ef0f295b0fdc0c650ffebced6be72c4dd0e1176da30930364fdb01a6713d036f0831c577230924e9326d19f346e64c95e84193c52352eda105704b09d804268b5a6b9e2d162fdb73841ea9372584d9699f321a111fe6f470b89b99b07d8431bafca0227eea00a532e1484c02ec006fa6495eba21abc438584d76f48802d0a910a508a2ee6c3f905a242e92b41e1bb438c7a083504fda57a1849ddd35896c47d78a5956fe6c7531a3c8ddefd9d17c1284ba60dac9040aca954dec18f365c9b8fbe455b67d90249d0096cd35843e3d71badc12c49381bce7312852dec8a1eb64498bbf023fc9e033deee0b54e1b2e1ca8e747d2dd9cb658cc07344df196fbd222e9520eab0f4b1fa37fc4afcb93a1c0ace0cde92aa0689ebcb0c5d1245bcd2c10e9028a0cc2de076fcc8655cd5cc9ae23351591616aded6d8ecab7f2a44e5d624a8fe422bb00056c4bf23b31c58b9773346f043fb8bf5373ded1962c0fec66853e9d754bb642036900eb42f10c8e6021345c5ca5bd1ab4e22e5b8022bf38b06f66425eebf4c5c0806617572612083635c0800000000056175726101011a3c100d29a795c4fbb068012b0291991aa5db384bc0d8c775ffadb60c9a955b4e259391b7f5c22a32ed066345b09aca2fb0b06fb2254ea3723b462ee7ce478a100000000500000000fb07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432740beb55375d7c8b84577fbe1c0743965ea389fe7585d6f68975111716c1ce24eb2dadcc3c91fcb5f23b9008ea9c6f934dc261a84b3d1b5b43ae437c6aa992452aea0a684700ff36d0a8b8ebd07fecc353bda87aad24b37c8944de3ce45efcb42fd6220dd68bba2bbc6a3756154fa5cf878797dacda5fe063c16fd8436a46bc160c9820134984676bc4e14204671db0b5494513b5a7fe4df5d0ea250e554a2080e31802525806814554d3a5677af77a3673b500d3539f04afdcfd720573b608ab0b09939c11cbff67c66f806f5221a61fdcfab5c4fa11c0d7ca12988135efa54ed1d69cd74ceee75480f46a7b15b926904d12cdea281aa28e908ec00a9d07cf8a82bcf585ae95386cc747fdf003d5802d9fe7484687bbbad0448af45553ff3b58903174881b8182392f9757efb143ba61d046a0208302a7a7b3df8041059ca538fef169b8d0012fd33199e57825afe600bbfff192f2b9e0f6b72f5da7e8f1f3147e859987cc129b23e32b2278bada2bc2795d7cd6034e3afa8e9a333d01b36b4e2250e583fe20c06617572612083635c08000000000466726f6e88014920420a08c71a4b56953bf3efbae9a45e737f4cea978bdbc470de907d64e1550005617572610101b491cb7862f8d14fb0e2f6cb8d1287b83a55ee7feb468577ca78d9c120fabe5f6b909448827d93de5eb8bd7afe6c9aea63fef46254208969cdab95fe6d02f18b170000000c000000000808000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432c663d22aea82481985ee77a58f1e54bb8c64fe22c48df15aa43f69aad1c7276b53c400f7fb9008e65a12443807e49224efa495a9cfa03e6ce5298a88fc744478f3820cb625cff327e14fe2006713cce73555c4336a7d861715aa2429a7d349102f0b4f9017440cf5a06a286856c5795b974f5006aa07357854c3eb4c3892b7f5125cb08a3e444ff92b8868bb8d6d64947c84862353870b0e5121b002929c136db31e000378c0f3241a5408a49bc458bd75af5c0d16b35661e212a981ecf5be8d61707c8adc571e83812efa6aa3673e4423c1b56780c437c500583abf6839a68d096600b21370ef6b990d6922acbfc71de68d751ee2d62fbfc49125bd9709ffe33bbce32c9e23b266d24cc175dcc0d99e7c1182b6ce8824d724e9c34ad852a611e9021145925a3f018c9aaba6b3981aaa8e1e24f0c7d9b38f65643a16d3f55d77ff6ca60a4800e3f4f2125d650231ba3ecaa0a51aeda71beada9dad70479d4571b5f2ebfa480c16116166d9e35a66dcadb999da853bfcd1872563f5d0a785507bf67796e568ec0806617572612083635c080000000005617572610101de7241c718f67134d32b6b5656f8e8f3f31e8d29af28043a37c2b49429a082633c8c7abbe502084c28c4a548ac75f97732521c7e66ea9917e704e5469572558c1e00000013000000003808000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43278b266c6c3ba60a6e648093bcd62419d4ea68eec772f22b7dfc78c6b255dac57bd149cd2b1b166d73be2ed9409a0bebe842c1901d65b1fd3c5f8d98d82ea2a5c3ae10acc8770276d737e6334c59e468be878e6264c050f48ac3e4a6524b76b37c399c4a820e1a50b2bcbc805192c2609e8372e8ddd8432127f6200427dcb2d72386429023e01fcf193d96cc55f1d4d85db5b2f0a9e3a5fb6855c0e07b891d6581ea371a39cb30eaa0ea2d0b9bbe5734e8793d4db7c366277619bdff9611dfb8d4bba89ec371746a5e689ece6f2a117d2b4e7894776b7a96209e7177446c076874bde474bbe3f7bb78669eb48648bf238110f690c144c097988314989bf9b3d4ef410cd043b32cf71a25a00655ab6a0558e383e546c3728412be664273b51908f4903de6835c05f9da3c6ca7fc65846438da7947f93a152f77bb75a85e3d05385feb47e071300b797adcbfd7d3a94ba4b2e0ab454bfded856f759d2b674839d4adcacb72d2c1361edc442862859f46d384db20db351390b2d261be35211db5232e585f985291a08066e6d6273804852f3c0a603d7da194fbff174c24700f3f89d86b462760033bdcb1663c76c60056e6d62730101e2f5f706646cbfc613a98564ff9b4a958acead02fa488e1f3bbcee114d13594d75e9b79d5f5be257e9da81d3ab97cefe36a620a2384f6f1f8719ec2b23532684280000001d000000" + result := "0x9001e80300002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f3282a8119a659fb3c94c3c951e5215daa35c741d13719d0be7368ca8e089537b5b3704113bf3c0d7fafa20033cad97002e9b9cad03fb998cb35cd71a9873d87a6af72afd5fa059b18e2e13eb3ac6158212b57ba060772886bf962b12034127908e54749e8014a7525ca4eb8815d1565185b31aecb38121e4347b54ccc8e49d13e2a732f9e332e0b425c741a07206c71d801011c2c0a278c87fefbf8064e0631875d1ed14e57816dde31202e999e6e24ad0f8ae2fc830bc1d325e73c3f3dcd186be8e59074c5553d8b65ed0a7034b310abd88b894263dd5869a8cf87e5ef4f0a79985e134020e8a1e2e211afcd5ac9ec6a2fd21dfb5e1c39b3b670f4415e904061adfacb103f25340b938dbfd331ba478351f9173a81134bff8a8fa1c0fe6be68e9025ea1f9f9f24e7fa5437238b01826b451001da46638f62b334300923068d1691f42d0e400b65ae90c283a08ee958a10a0e8c33eebbcb01d137f1612e39973a10489164135f64606c111f8d5d21ec2f8ae932676beda36b07e3577c7d8103c7cf2cf878ce90806617572612083635c0800000000056175726101016f5b6937ad29ad8721ba848694820840b25d91a631d2cf19f8c63ffcf1fcef260d25513fbaeb64c090d371bdba09663f2cd3bb4a8f8f7838b6620bde5c6e5905000000002000000001e90300002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f84b5c6e57a116cba4148aaad37fbfc3edc54e7728b5192a40391d9c8ef33bc405ecd07dedf12350fca80ea9faa4288186ef3dd0b40badbbc49f858a38cfde88c2bf80adf8f3282e527e242daa821b07b2972d9630b1eea6d2ffbaeb90446a8bc62a19241993b622e6321aa73a113c354958dd7266e7e2a28acde078ae276bcf7cad7aa37dace9d97c31549cc22292b650a04cfbcdc44e20c9225d499c8241735168858f1c5382ae1cbb9ece1165e63f01471338afe7714b8928ef3b2a15e6f86fb4ae217da22aa2880ae8d874d21f8852d76ce7d32554830cb82467a66658784dcc6cda49b51efbe0fd184b974074d1258ca9f15b9fccfedc35b7dee6e1ab9e9bc06de0d02e4b3871341b268751813d0fcfbdb0bbb2ec4fa9798959ab01a48dbe9029ccf0aff2230779960fcd86efb10ab9d36ee09ed20b3404b8da50f63a2f2aaeb6e43470084a5205b111c66b80cabbd010043085f5ba73c3a4e0f19105e32274bf19fab97145aca984aa0eaaa60c4528cdfb9aecfc2dba582729ad01ebf8d72ad39f1d70e0806617572612083635c080000000005617572610101ecd027c637c53ee91d7a0e98cea0e7e72f26f69415985ee9e28509aac917565522d428904e56757639946c30eb6228f11feae3bed1e1e60458922e892f89ba8c010000002100000001d00700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f605b88b35bbbc7463cd981713be480f1e7ea1d12b6c21eacf0c120126d24347f57dd8f8b64cdf03c5a171480ed3b0718ed0d2ba49ed0bc088b33c45e9f40c929db5ceb08943ef0f0cea09c1606e0822d9bf9f0a7297ac08335d13c87f28490ad2532a4846d8b951e37ed71582b2562027373adc871ec734cf1b77fd6de383cd5a2b09b240d86f318e67f5fe77e4b3714d5267699515c6696fbf7eb8d2150826f89faadb98f6b52ca914fb474ae9d10ee57c48669ebcf6568bc6c0a8833466f8174c4eaaceb528233d6b6ca4823171880f8853b0f02e6f829444f6eac27fbfaf477bb8d6c11c2ed5ee8a4e0933aa661d2e44e03dc8823cb180cb069463128a2c766b405ebd52f05687eb3288165c4808ab492750a0c0ad69f3d29134eb883cf5de9028ad5bd67ae9e27b97131608d072644251f45c38a49ed0ac3dcdfe3e6c6c9178e8620d600c955c50fe95eecec5125170c2ee7031c13b46c6c64d26278c805e74f5d98a89770c37ca072e8a11ec0adb6e178a689d285b066c93bf63444a1be78977081c6fa0806617572612083635c0800000000056175726101017a9dd3c3f5b3c34e7804b2a4e92c08a4aba153098f51229d81be212fd0345e2be37a41cbe3265e448b8afc03475e33b2b9cb762a9df3e04bcdae19af3aef0d8c020000002200000001d60700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fa23d6b412989d9b453ba20b524d14a4932218d5d20cb57529b5d8481fd9d1717c79dc1dd9fbc475efab87f98c901499443b467cb30fef5e85ffb9429b028fb69b7632d7583557ea812404498c4c544c574b43b952c0f642f208a47c837871974d324446e0b5362729c6f287ae6781da900bf67a02a0675327c8b0c4eb716d79c12dcfed6687a9e1cbf5a58b4d4c1428cddfc93b6031fe5a45441dc6a363f43676fa41104feb13bb292af09d5929eccb40b00b1ba9856a4a7727e3a82f9689c8d58eed3e4d8a61504356c2f5f230bd53ac9ad08605c6366a65ee919decea46ef17520623e2407d6c2a89b4c660b073fbbaf0418452b0959d1018293e923cc0c70ef48a7f0993dd843c38142939ccc1d8937f7600ec33f8e203529f3c0bb741bde0d1e56f9f2bbf7b0f5b44f5a8fd26c1641938379cb13bde0d422c3e5db5675964cd736a2d500e8c1d62f574c4a67bc94e0d38ce45fa94b7fd1af9dfd8c1902f34802a4f849af258f105cc555928f36e117e2efd519ee691784304be5a7c7fdfe5ba3128576150c06617572612083635c08000000000466726f6e091b01ccd9ece066c3e5c23701aef8a8d166534049e0866bc96618feb63b27516af2bfd4c90a72b83065ae02bc073d72ec49901539e3dc74b84025913b2599c392f6daf5109eae1cef4251a2652df775975fcbd3267c254655f0623cff8d48c24d3a0f935472c4b01eeb46871659e4085d8afbb3091dd6a9559d56a889ecdd239ce4cafa23ba44589f0ec8aab1726096d29ee0c9e2676cb1b26cf2da888205cbd2dfaf1d2e87536aa7ca2330a777b9a43a8523bcfd9d9f041d661c688a8c2791fa5927ffd02ac2ea36c1f3f8a3250b94398171098e4de128bcc6333d68e8de6176f3209f66cef788ef9cf9bcdfd1560c5081311c00fa0d4a4d952bfe6c879f3752f7a1015e5ecbfcf729e0713df598b79f1b7981acd0595d8bdd4cf33f3a3b4d44bfa16b0fe8275f58a908984a0cea1fa464abe66705577c82cb660ba42391739003a6ec0dfccf329c2b6d81fe7ea47987e94b00fab2444a1c34eb3e1be1a21a31b6bf0a2c01828ca4247cdff7b0769ecbe0d186ca9af743e0ab05a823ae65bfe7fe871f7d1e5e2fe06d88139bfdc57f9169ae6f869c155bf1dab7d97ddd8ed0b31e2d7b6a1097a9e0e1ebe09539865f3abdfb20d83f39cd9a9ddbe70f2264cc5cc34cdaa45942ce51e3af015302a9a25df2ddc220657322ad6b03e843c24779d4ca45cc4ee30a6830e3c82855458becde33a4481a1e0bb4a548c244b7ecb8be06c6cd182f5e7d3e39010b0cbaff53d43f3bb471e994e01e8e79fba4dee058c59c0eb2364ef45fc1371f62f14dce74c67cafe44cba43cce596b6a37b0044ca9613180029a14a77908f74613db7650b31a2176cfd2cf7ef35e680b45d72bbf45c56a4b8a6327926f708a899548f224faa0cc95e0b58066d7a526f92bf53524d25e5e25c39a9f7523576f0af291e0ae37c7cd5282b14737a46a01b52d5b0a46b7c4674fb28551d2db05d6b6bf9ca560b49911d8087a6898b672e75d9447edf4700e7935cc0899cece13496a9f53e3533ab2e2f32814e36d2162d1316497ed6112c2b8fdb36bad16f697098f1445ccc3ff6efd641cde1b90e8012eecf0c3c5a005eed41d5a312d6ddc76c78b2ddc7219bcc62dc3c2e0dd84ee7c161a2181bd844830d8a533fe8a73ccb7af3a290f1cfd0758182572b5a4b9da22f93854ae35d0b6e79f7b289253ae05ae173ade67ee65f312577e0a1623b4c14982f33db8e10ed43874de707843f49e7d186a0b3ce48f5efa449647f230eb490ce8ab38fb460ebc8b6a26b5331a0dc5224b1914fa1c9a0e98b2092769b3e46066aabe127f3866f55d56faa702b5ce9faf3fbe22ab352469f5f86719624375497b2e9142e12b3f18dbfa0d6545c7637eb25f6f0243e14a7de2a79f5a725e484bd484cf4e8af7b2ad7e781bf6d5cc72b0f14abc95a407cba0bd01c4d47e192d9eced14bc33d509313d37ac40d2abd213d3961547fec1df1ce3450f1271575684cfaaa6867d7ac9b9fa9e939267e11f1bcece14cad2c9956fb316b8e4063db5389738faa82e1cac2685c1bb14c35f2846b1fd44076df9851ff3f6043fc3824e44ec0fd70f684d2140525e37f1ca00190672cf0d3f496d917e4e63eb23cf89aec96c62e352bae3010a165807e51ee2d8e90178f9285da18ed954fde7c7614fe88015f06cd290455c05667c58cd8210dbfb528bfeb70878776e9ace349aafe5ff9340b4598bd70097f8faa9e37a9e3caa2a628e67d83117107e99257785a45c144d29e970c424a0eda79be84fb94287e56f9fb3e746da3847a56403e9618a5420e93832989fb58116d712ef4b1d2d23659682053b38d6410322a2f07444ada2aee3ef85d631e01cfaf5ed28bec9dcb2bae747f6c63e9e4a12a8814da4ec2ac713565574227d197851422b823db3f5eb669fe9ea324f0b939835b73eab6eaf8393221ce5540462b71770bbaa8b77682198e9830f75537221146d306ad07bf3f9de76cdd485a669607d9c5c8c517cbb87730b6e90a783b0f1bad7aac92ae0a0972a8424f6683c42d78400442e9271108953f1d40e0af58e8da33c1d9fc1aa77b572f0672a3020ef1465b1687381cd70e5b1ece01a7c08be69f55b1e0683c1f742dae07de6657e6e88f97b6d3314dc30e461ae492f8e3a180ba1eeecc64a856be520f8198a1c2a4e0bc6d295a2fc13d4bb81ada3553923ece3cb67047b7347ffcd13c6bae49885be17de3d478d3aa8dd2f964ec3ede11d84348f7a40015e588ef9c9a446a3699de1cbe1afa916d10356f412c32e085c3ec0115fd488d3785f9552f893bbe0b22c3773df967b7e36713177151c7c21b9b9b1b367953ab7199fb03947c31a57a94329c6edb9b6ca20d762423fefd38b1ef2ba3f179998a5a5bce656d8b5f14dff06715909d5b7a6343003bf33c0377003d680eeafe54a348cb7815e33c842eb658ffdf3151507e496343305617572610101744acd32f811aae5d80e20534e44195d03abd773156a54dc42204e7c33370702db76b09ff7448955b79a53f0ae958312e2bdaef5a6662350349ce955b8561286050000002500000001d70700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f7efb9393ca81fe0825670473a2d400ac00ad22c1f401a14bc154c5f92ad2443192f6141b3e3c8ff6efa5a85a4433a49aa88b225d64a40a6c500854222e4957243012e86d4a295ca3422a771ca745241b2ff615dc7a71758ca806b1f48525836b78e14daf47e1789603860a916feb342edb58a2b7acb095c4e93a52b987442ad39c854c794e49072f464fd7e0a418d9c7eaa790c89320f830a4919c109dd9795bd4c96ae86882d18ae5a8edbebc1be36c269313f50ee8e1ea30ad62770fe9f88ed5f6cf4e7fe30b0808f01d7b1e9571367979d1cbb8359088cf98ae22e8abab91ccfad85a4a6ce77f402b64b0f0524a831daf156f8af91f9d5d62ce4c687947c3fef1228b81636a938a7a242ad5f78aed0a218d582faa5176c28748621c0e24b9e902757eab60aabf67c35b6f64b7dfe695fa70c9213e15d0cf39dbc547924a5b2ef9f69d630014ff54af3384cb0391d00b06d7309bf0869519cba60f2bc41be171ed2f372f3e1b71a4f5d6958d3b1fd4e43f3173218aa9092f05bac9e7f4cdd4ec490f4d177a0806617572612083635c080000000005617572610101fab1ead14c7c2cff2e1f1ba2f2c0fad3d5a5d5b6c3cfde4e88dde08d978dfa1da06bcb5daedc8e960b11f9012473e7c237b5864609cacc9b4fe9832785864b83060000002600000001d80700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fe4bd11531d6789a4478dbf7a36a3c7d23b58c5a1debdc455e1fbaf1b5b2ab412ec6a464b90ff6ada8a89e3f8d180e74e293a8b2f01c8499ddb1e994293c4c0d0779b68a85a99a3e2d4e0a792e1537c07b3a56fc0a637f1db059d9c2755625b778096d82240cfa6f9fe0dd38b9e597504a42e58cbeb7919c789a917450ee00e73fc355482abce20f5b06ae119b1a9ee79866d5b4854a389550c9d9580a0c0332260e7a1a1b7d1ec159e23065c342070603750ab953543978b4c8f018b2565948ff775ceffb1e33fabccc1c2c6ed03cc463645aa63019a0e9a8aae015cc11c6c4d370085df65a76eb880baf100b4c7401d011a1fa1648876798a747f9aa372d114a81db419e0c739689abf0882f2dc771d2b3f247cad2cff8b1630840b4892b8d5e902dd6b8d78a9a6e1651c21c2928db2b305d78290e51cfbb807ffbf93ceb6b1696b1e0d4200471f7d3b2dbab4c04349ddd829a29c58d75f91bdf56534369705c46523b29229840f9bf10916cad670f0d3727bd747cd737bfcc525bf923632dc5957c032aa800806617572612083635c080000000005617572610101164bf5fff13882bf1a85e593295939d26115f85d9539faff0d76d7be8b7eaa59ea1f86566b58362a71c19076c5ed65d72cb79994091851bd8811193bda730b8d070000002700000001db0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0c743a94cd1707ad4117ab058e336425f029d591d3a0d48e895c732013c7085053dc502546f00302e84fc41e74a7a310c556481c76ff18fc1bbb97c457866b972dc5d56deb74248c917228b08ea5774022ad965420fb4130a53edd44dbe883c91beac7ff23003ff41339e09470ba672bd4b9de9d51aa32ea9c4ca080c6f1f9820e698a3c6c6ffa8523ffd01d125f46795c6cc3c4047c60b36f44d1e89ee037319344d5b89f31dc79f5db9e5aca9ad7925ee5b750c1a78ce34ce503d4fa4f0d8dc38992403757e8242f70fa6e3898ee68b82eedcf933db38e0adfd352a1b6671ec7691f79817eeba28caf545200d0e9df486d47af1c5ac79ddd05aac62546f6f8723aa1c622a8d4a7757a130d4c7a24e2928acd073b425bab04c5e960b4ce22f7e9028813af0548dbba39f8e667b2679069aadf411ad3a194a5ca50253221be0784058e668c006cb6f4c83ba533b775447a77060f2a2fc873d79045329954a814221b7b6d52b96a216e614a1e963366a98b3e4fcb728ef8c2265b2a6a0b9fcce0ecaa41f094a00806617572612083635c080000000005617572610101d8d56b387d8b2b434c1c4d2186a48765e9ee91a39b214c4808eeb9f3461351196740631854c04bcda5980e50b7cb759df2f64ceae11f6f321ed05f8e6323aa80080000002800000001dc0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f08fc371c2ce887eb3e132908c4dd533583177847b8434f5c7c0cfabd4852c24e6c7ae7aea674dd4bf6796cdc2d337782f885482bce24c9030e87b11bca54d7f5e50b6d38ff0fb29a9e76bdfe49f6f82140d112c80a357002c99a8941a08ec62190d3eda2b3ccfeed95db0ab62327db71f640621d80c753b4e69db9868dedfa7da60ce0b09e321b053d10dff1b04e435472170d760c41282be74154810f277b1360cc17225d667bf15fb35266c8cab27968b58813ea1ce41baede882d43bc1d83e973614a3dea1a30b67783af1e57f732e89eba9958b0fcb19fee08f9a3314eb9b44a574641d090ec0cf776b81af6ac92015443353b22a7db67f42bc7347a67aa8f846aa19dcdaf075ea1af3c7f1b0f66b33bf8505b7e94862bcc0c4f6e9eeabe890371dcb58c1c4fb0f5cad90c3ca6f598d596f8e47005536da04f424868b9963e9256e1d2002610491cd018b9dc0c88d6c9790b14b4b866b6e0600feffdc0c94c667a68c14f2264ecd4a757b0f14bf0b6d9ba93cb7e2e949191c86ee32c5402d158b85fadaf0c06617572612083635c08000000000466726f6e88016d1ffba7d4ede2a4c73b3740c4a775da3a0a1fb08e3b989ec5e49684d663be2700056175726101015adb821043ece09a08d82ae2cef89f37d7ca8f4f9350efeedc12db5884a0016763c60aa38c1abfccacd5f9ba16c4a8ab93f6b9177479100d0b6c975015a82280090000002900000001dd0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fca221b74c8d32fa6a45bdc2271371109a97cdbe2c82fcbe452c548874b7dc1665af5692ca9a27a9d2c2f55affabdaa466fd435945f091b45944e0f0596984b664b7f5bee6c782d18ae489b645be2afffac110bc7bd97840260a807550ee056ca22a4b9f9c32f4c502ebe462083ec11fa689a7f3fd948fad1e3cb5ebdeb4737c7ce6a2e873ae8e530de6065dda3890084d568507ca5d9a69df19683805bf5d24ddf938c7c9decbab422bd00c4757dfe18489bff7e017b40ad9552871b9a7be88a4e315ffb734e34f9c25170faa579eebc5b74caa8cac8b1b87827e84055b256d35c644799d29d2e6f4f2c065ca606744598719d85f8c3e7c4d39abc3ea59be4a35ba689f6c0af4bcf5988a4580840e313618deb3b835c4e4a78cc56434b2ed6e6e90231a890359de5d57ef9864cf19f3a48c1fd1a63812b0765661c598856f956177cb62e8900830038feac3e62aff1f1333ad0ee8696a4558f6cc42b876e0603d703ab0d7f0eea80b0973cfd2d3a59268bf68211e1bc014bd94fd917b6e9475c3a78508c03fc0806617572612083635c080000000005617572610101b86bda32f157f1e933143a934f6505a6690c0a31dc52bda5f49d40e5e26073545851c15949664b7f55b8cb2163a3caf7f487d8b4cc87752aa3b4f40638c2ed850a0000002a00000001e30700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fac991d1eb1203b3ac74ce441fa62e97c8d7b99628a85cdab3806bc68ec92131490b0d19498a2d0ec54c48572abadcde6a5a2aa9ed3ab74314fb4dabe30ba6408d4894734e270af31d21c80c4e9e3fd540899669aed2f9bc7fe28891bc0fa6ff9a58ebfa37a19b1e8479d3d41c7b78204d9719c8ad1212ef0bae7f2cb82746ddb6816850f2467e875176ce398d1607d13d2f458526126a222d47f10c13396eb069577928443d3ca93d4582e1291c0c7caa7bef8c1f39c9863385e472ff1e9b38d85bafb3d2fe2ca2354c2fd1fd197b36bcff57292ec4e7b8ffba280227b13aa0247ba47d4824fd30328f70f64b056d4e36e3b75594d6f590e1b85e90a65f9a63ad6d42232ebb0628b11aa6a5bc31c1b8ac45f683b0290b14ea725b2b53ec8017ee90265f1561c96e26a3ac239745a0746ae6fac255bbc9a19aca4765900819e7a532c12d1760059118acf89d6a62c0f724e283081c8bcfd74a1db5435983c6cb67272699024dcc1f7c4089088d1fd7a4ece328c3611ab9219a8e0f43240841673317a5d3932a90806617572612083635c080000000005617572610101eccee865e2c48f93bf2d1ef99bf22549e3994e74b2f91cd00e742be73173cc40e5518cd480b62778a627e15268c8439cde21a27eb24fe0386645a5b11430c1820b0000000000000001ea0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0cd0c3ce103900b501fc82da6f8999bfd42354f8fc4db6230a764b7926c75118d570816caa86a63f7fdf4d0e0cae604060a1ca4d53a6bc0aeda87d1f5c28918b5f8233fecb446796519206c3b97eddddf86237cadeded98b041ef6ff4e474e53287a1697c8caf461dd58930f749d53af8832c488780a012590b005c36eda0d6e16c775b8eb42663d5517b3e9cc198e9658421ae7af2a76706d64e3324ce39240a32fc27041caffa0ead9c0064ae0ace86242f8074273018316dca50bc96a978da3883c3993b1a32b26325ff85be0b63084960a8b50132433176fdfb5c6ffc07bad1936428467f481ac53e71165512663839cf61457fba5ff17ed63e71b8c717680a10e1f33cda8f8d81c50c91152776a54b50195d6ec7f0d4bda452f9ac73012e902dc413d61ee372b7bc1305b79f10d3644a42c88cca1c4c8539760bdcced3d8c2b16819f00b2faf4d0fcf22d03a7cd76920487eeffed5b599f6cd32ccc9a64801fea2aa079feff2af002f0a71bd1fac90e9fea3a0573a5bfa2765a3a931bb5b8d55c9717290806617572612083635c08000000000561757261010166e2910c9513e1dbd2a6d3f938cd6a6253fbb2cfcf6a1f6cd76a8b7941b07b36824ead10eb5d99188c749988b49b9bb673571fac8b9317235b89b8d443a5fa860d0000000200000001f00700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0e4c8eb3dc54e5c0d1b9402f44f89137c1c2d095bed90ecbb80e38c5cf245c4828efb3599bef57b84619255f76f0aa168ba42a0c7d3a7e519bcaa784bf0c66e38b0a4168467cc53f93902feb5d97440405d82d672f86e440c362301c6283263fe870ecde7baa2895003dec3d07836c095ae4f3e4a05347dbd7d7c4eee1f811e18628cc961b32b53e4cdd3a60be566fd3ab6a686041c07a8d4750133047a6907232365380453504c52c6b96438fdabd2d972e3dfe6bd1e9bf0f254bdc07583e80acfe461dc363714109b6e04784803614ee2b00967cb51eb899327193cf485260130b0b9ac802b3db074f304ddc428950e80ee3e2a14d9f009d8376fdff493b7da24d7edadba1d6f9a8bd642f426851bab186b7aae7eb8fe526b05e362b996704e9028625ec7da0150afcd6c1431ed2e8b56be1dfdbbbcc7e3eef1275b5bcdcf5f4091622a20013b839aa611349e4450391abb30a5e0bf166d201351ff2eeb43d5057714a5b6c959ed33b8bae5fa99ba5d0154e08ce851e94502c8cd069c78c0a0d748ba782160806617572612083635c08000000000561757261010112e21a778c7c5404d9cf20fb4ecfe2c06b14e3e5ce45c76619077a2d47920b5e2d605528db37f2d4724f811429bb3bd308c9a20ac0d05b91329bb6b49b3f5a80110000000600000001f20700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fa6703abcf0fc554a4cec1cb5677c287f06e3bfc3f74bbab462dcc1062c88ce353939f9e6aaad990f2c9837dafd9f5a22c17455389a73f05570a74aed86a63b1ca65a09155dcea6eb1d458cc292968124a0f9b2bf125cb797ab96086dd3ed40da478e5401533e30c628939b081e4e383a28a6890ff949d27913939b7bf5d9c4dc0419a23af2d8a14090a06412179f31a575a917c04973f1f645d777e5ec48c938ad24670905b57cb5e29d8e2b285fd25778a69930cb1e71a366be9594f58c1a80322a31962e767ce5d6aed172950bf0d2ace5df6050df675a4e6a58a4c308372d89fd8d101e7dc06f0ee9a515dd338f2d29098485ffa2c2eff98c6bcdb6805b483ebfb1a48db52c4f8bc5cd264c2746ab4034bad57e11be369e459fdda1bc9810e9025375b7d9d546b18adc6ed91373ba5ca0a1e0e2549458ed06d4a9ff337dc4b7f11a9e9700a5ac8cecafd414c670faa4c56cc84c1efdfbdd63620fb2afb77983d5bf004a11177c31f7cac28712d992f31156ff0627678961f8ac57d3a41afede86cb1e31d30806617572612083635c080000000005617572610101e8bc4a1acbda300bdc4da4c20caa87ec14e7d91c04718c20d677ba82a2adf422e72d52c66fdfa17eb1fa426428ea9f015f8ec3b4dafe3b59e9062f0e8a4e3580120000000700000001f30700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f12528c5a9d2d33f06fe0197fd72642634a924caa92f954c84d0b30a5af9f621282ef2d609cd65387717749105fc4e7266cc29d8fa13accb72282526ac1e28f285f18f4e449efb717850369313139477445e5f16e58c14d5fb079d1e95a4c15f9bb6baaef2e82cfb97712dcbcef475efdca635371ff35d5e300090491f05aab135cfff964324889a26d9a999c5644bfab36a5f2b900df8dd33260f70ff4685c212d423273981adabcb2d89ab22068042fda0beb26bffb730348f31d3d739eef8ec6b6f7e799362b07a29726bde1d02cd6fd231852f6d0df84695832f70b69df9f724160bbde1c8a99b1f8014f200f6752e90265361f4c1e55a576e58a0a1ada06c73c69f77b4076a93404329f96cc0d9fa7ff77bfd5e457f1caf71688c95cbef6e9022b8b83e8888c042d9e2f0fb1a9bbc456a8b07a9572f1e4fafdc8d699438a9bb296be96007d6837a96593348603378036a8638aa191f7164617e732af28d26929f83245736740228224f3d42f71eafba39c8f4faa94a01a589f51929cdee85a28b7895f760806617572612083635c080000000005617572610101a2f595ba846acda337e0a6891b3f517de907a15ae96920676e7aa300c603d903091eb30a8613fa54a684f1aa488272ebce844a5f9c44a0c56990c60f6149e882130000000800000001f50700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fba252d10741845a93492f9ad5fcb431e93c51be0f71ea6a8bd164093d4fc9f06df0b8c4567e4808dbbde228cad475e6060a923c214a5c4636f556eb42a7a4ba91f04569f398c5b44d0aa5cb46a0e95f958b5a3e8352da4092daab9cd8c4859bfcfd415dec6748a823e1141a8ea36b283cf6384420f9bfb21b22579a580402394ecccae790c40a892f3417def8c361ff5a86b33779c74316c77c548c4612fb838c362ebc4332cf2a926e56af72339da43cf00bfcf190ab013df11fc575919858136699ab86fbca58f8f5aed50b70c125329af294571a4e1172e3d25b8d1c0894079c48d94b4f1140f83e68d0517db11f4d29ed81a93ba725c0516ef4d81f2543579a1430ae725802df267fe527b925ac709ea5f238c6b87cfbe7ecaf751855e688903d303d17a8af293a6d14b5f06dd6ace4d5a465ebc84d372da88b1d00fba851237864c8b00f9c1ba4d0f26ecb08528e3c156de07ee51cdbf6fe50c332a727d46f303f688f8ef451f0175c1f5902c4200a374026f4e1b73706cf03f33dc1a1a2fc0877346cb0c06617572612083635c08000000000466726f6e88014968c2fd312c9100837a25718581fa2438136bfce75918d9974e85bab2d26a6300056175726101017a5c5bd08201a067464db34a431fdd575008542f500582eb799c010c99c28f325a1092ab8501da0a0e9dcb07dc7eb849c6ade998b512282ce5786fe3b84d168c140000000900000001f70700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fe0b5632409e78aba11d0d559c96acff0247194879afad0741ae3848f61e74a02397ee4075a31cdfdf00c080c5ae192e9a8921bf216eec48cd06a0ec54f3728e627e68a325aa980ab408e110b842221f262f65fb9c9ff3bf2526d7a454e1f5bb31c4957f9abac96eaee0b0e4592b60fc6abf498f2b216099590c593fd2d6956525001477ea73bc4f27bbf93246c8ed89995f7e69d9e003c4b80bafac51cba1b7a8669945a41c3693a006a1cb8a9000b443f45cc4db5b1ccdb50ea7c8d7330768b445c9a763b1e6309dbc77d14e1e27ddb362cce7ef9e4023660b6db4e520bde91088b3f2153fdc8dedb22d5984ca5773ab7e794d3a9a6f700d1fdac1e54ca83a9455b24f78b25d8dc601e67cb9c1a60ea2e7e907576b4579a091566ce062d7b9fe90294e33d043375a9630b8b43a8176a4b8620e3341e1e22e9ea344ca3bc8b6d989e86ea5900c0bac6b93a608c8ed70554e38d2a513b20072d9f2556008e9cd917066c54e371326902973308c86b18c426b4dfe19c571cd158847f719b5b23daead339f4889a0806617572612083635c0800000000056175726101018a4d75e4d4af8ea9dcd1ee5c8d18659be74f9e3dd4af5312f566705f7fe08f03b6453775880c2d6cc9552f0c99462de4845de92be70ec21d537143377fbf4e8b150000000a00000001f80700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f30cd84fed2904f8f55b7c41d0638af65a209ed81abf76645862f999e1900273d800e3bae3d3c043d319ff1b86f66954e336dfb77f4f62e2cba632ca321a19edf3f600c334e02e5f6ffb1b0a482e3d1ff6e8da744cb98ff90f4e32f87f038cc682462c29e53670de6368795f8e42b58b565b4b0edaee2dab8a1b9e7f2c5b485b4ece9de94fb93817787e0a41ec5703599be3d47882754fd9de578996f9c23f441060bc13cea84d987edb6859731738ee0046151a27ca5d150d89d09dfc33c7b8ba56677abec76be5329edd0100932d6ad28aa84ec94ee0f38fa28dcd7428370186c113fd2ca1d93c9c59e2047eea8b9d0c6d52e15c73398d58433ecaf2c85274ccdc35e3d74de2af6b8b3a2af12ca02f9f14c0a168519ed83cce058a4409204c5e9023d756ae602b1db65712f5c037388b6162cc31b73268aff4572f0b02f706d67145aa38d009ee4491a3c7e2d63f2f2bdc16c70244435ca7f4b86b282a82aec767fac5f02f7489304e192850975b4acfbd1825ee836b803947e5704b6dd1ff7c59c44adaf950806617572612083635c080000000005617572610101d8fd11466fd2a4ea198104ce9c2d273b49e32dcac2900be2313085c941ef415464e0f1fbd3431900521af212814b266900a8a95d2ba9fd74db69092891ef1681160000000b00000001fe0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f007a3643f15ab58061fe650dddb783e26ac918157f6414ceafa7027500721f43b043862b71d1dd71242ecaaeccbfb79a5d742557eb7ea49c6f6c9f8a4d0f3057c7b4ea49c745843988fc3e575d3afe2433ae789f87be82d6aaca8f8eca674e4c2c7d5e2ea06f6b1768ca7fd09ae4f4b40866331a4da0cde2d5092394f50c7f58500047700c9e0db25489c6f932e40c357e945914ee47ca84666410e7d5f4320731aa082085acca46517147f2925244a62cf6cdc12e0d1dba722ac51ebc034988c2d2ba2d6a33d8c373a69d92f154d8b404c16f73fa872a864488126f84d3168b3f0f212826e2b9c0c9e49fcdd3d099bf3ef8d93b11c71abd2601da09acf1f8fb139a332d9a5601f727c537d8edba21117d7be408a87d6b9279dad0d31da1dea289033d2444574e1a1ea77abf1d1183b53dd83993c39fe1c82e21a2c331e84673c2d10e7e0400e6bc71df504d3496437a3c4851298d686579cdcd6a0eb507d3bb3807b10b483abda468fe3b2e3f5c42ee4223b991b3a15f0f52c7e847691a692c36791391980d0c06617572612083635c08000000000466726f6e880127856dcce783370e0f2f8d245e6962e65da80ac30e97fb2fbe2fed1b290f77910005617572610101e6ee0eb043a6b5ef5dd2060a1280d0c51cb63c1cdd386c77f1b03fbfea95741e8e4f7f250c9e031120c116a69f5091690ac472b19bc082d2b8955711c28d508d180000000d00000001000800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f4c31488e9125c86f7c78b1174f11bc54e10e24d63b075bf9edb77d7a521b8a7c72aa802d70982fe9261673dfbde97a4e0085892f7e826784a62e974449168d280cc6780f3f88b07267c5bd28035c1ea8d3c7d57bd46c7aea9f3686d5dcbf0e5cd67ae5a926a93a34221dfa7965bb1bf5bdfe550eb4302b952a19747373223929defaaaac2a4312b976551770dd90b277a0fea279f4e133172053e186276ea502a4c071f88e10a9fea38468083ada172cf4c4b71fb676cc911d061b1182557483e9bf72a5cb0332c44eb9f1c9e7621ad6edb850cea38d14550d91a326c4501a9201ed82c8a883f444d0300947104879b646d005468d5cf853725170f9b358bd5ad59c197ab76485206c59f36a6036994dc543aa252b11a3c056814311d27f1404e9024f2df319184d0dfbb1db4f4259dd717a98a856adc2a8c8912efcc98fdf4abdfa2e002d00399fa53f7c1f185d8427c874a8f23b13afc475e5cee1f760d46974e71a54ccb2d353e4aa9bb6d3b4a641c9472a2faefe5adac9bd04b36beefb4168050b77a7f70806617572612083635c08000000000561757261010132730fe531d29230b22a9a0935ef83d80e40aff7efd8db34ce12604e23492d3ca79135c8bd2a4df2849c018629b7aa544222db8ad821d0f04720ee11e255a48c190000000e00000001030800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f48c1b5e26d4c749374e8f69ead4a5b953951cafcbc541903b9ff0496ce82796005d8114aa42d92f25e4aab90e7c0e5bcaf8e0b27364123b0a0442634aa351e0df5c0abdb50c18e3c20d85c1c0d85ffe9fc4b3d2fa6334a888f89fda67fd34125075303600635530959cfa99e3dab3e4e48746930e6c4b416c857d7974b5dfd703c0ad6dcc383bf87f8204dd9c4204e7586a5048bf43854682d5e6753e824c0358e2e245bd9ffa05c64f572f7ff97753222ace44ed6d7599503a4d5b0bb4674819ade986462caf64eb706b9dc9cac0f23d5a9ac8784f067d43663b936525e949c99823eaf56a8d5abc4a8efb4cdcf6f72330a94b423b765fb0267f6be2fd343d2e68724dfd57dc416a9e429bfea4c4265c30f8f3420f1dc6e7ee002b7d73edf0de9027005ab65c401c5eaafe10bac663bad41901d29b6303401251affd054103b251c22b24400e801ed65820b0cd6e8deebbac787b371c89060775a0decfc2a7112b01c51ef7c1e616da83f89c8305d421b535e08d1b33570743958df7c712c4adf9c96cddd330806617572612083635c08000000000561757261010146354b89f12715e609b5e0a272b1e790070fae3c06593211bcb1fc0c40d9806fa21be4cec44a86a847982f6598f92ea1895acbebe39ee857012ef88fc80eb9891a0000000f000000010a0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fc00ba151fa23caf3a11590fe480f8713e26df35213521f26010a50d2da4d7c7356448cf00a57c405a2759052775a9ab72ef3975fbbfaa8c972b777958774db6c053837856a44c2ba69cb62bb627f28404b1de1f564f254f1a9b3d34d5b698f697ca16b1f5bb61e5b6cbbc9414a5bf0621ed419b43cc72ec90edd901a648d92f0b65504c69ee4a2793b9566effe4685816cc9e9b5afbeb574617a44181f56f84e9485fd594e5a541005820e3fbdaed7713dcedd4ba1c39ee31e386cdab27ea68b95d5c4474278dcea31832321ab93eb6b9d8f2cb5fb75a8e03cbcfba0dc6d495a900f07dfc7cfa4567f2f8ee94fb18793c79d46f233331913516c82a8ea379095c06172eb64373f8e6e622f61cc963278de4558aebbfcef14e1146d85964197e89501ef226b220d0a9f3ce159cd9fe3ce808391b3b90055c3960918277984e45f4c249e9a01006070e574c692886332a9cdfdd2bdbd972889c16e16354f1e470e52bf36db81d2bc7851c7622decd220c83b3668e028145434255ec44cd50cef9c25e5b868e92c001f0000001400000001260800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fead4b15c40389b68b80da252f1c64ccdff8b7deda378cad3bc2040df93bc0b5e7252eaa94a54db1b10710b81df91791d58a801e17ac7e6c5be9558f6ddbd3c555b19f587cb3e1436049a1e54564e1539f558a5641e3822542ef04a8029f6c03c7cb08847b3ec399f336d9532afb4a312db3b0226c3e740d12b274eb378aec9f87c169bc67da0715fb92c783b5b8fa646489179f8bf7e4a4271fa7d6edee05e74605c69aee2333339e8a08abafeb357a0281a206a64d184dceec971d6d55f248b741ed705f509eb20a558dd1772cd34ff1359d80a4c176982169f7a7f44e8250f9027b2b9d48451380121cdfc5a041491c3fb5eefc07009d1aee921df7a0599bc01034b5e0124a5042e25c42f67aa1303afd59571d83ea865eb1a3aee512467d6e9025befd6bf43197109f64511896b4ab95b2bd221e6810459242b4053c8284686e822d3e200a8f49a3d18ac36932f3608c00c7e004147b3868fdb6d9fa0d431f2ac5c180bbff6f0a28f55b64489087c1e2e91989c0b886fa55e5ca22989fec8626754b531320806617572612083635c0800000000056175726101016c40c4eb4eba5a7917edb38b4813bd5160442f44c16f743b1ab83fbca0aab837686b92638dc57ff1280973721c79102295a43260c4dcd93a6b6dea614077ff812000000015000000012b0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f7ec2f69737ac6304d9b45fc7bdad23a6e8b6b8c35c77226a9270a105205d5816f8f871b0e0903970117dac29c057cd2d5090f7381019703f20ef82e38de9484d4487ceaa35c2b85da43887dd27238c4a77a28d76326c0bb44244f2fd51fa8ec2298c0bd4ee975e581149da8c6b891bb511a5ae7f5b1794b58a133adba5beb7a75ec607a812b0ef58815e341279396158ae4d5234e03f750c7039bbf2b8b31c2ec4e675c6f7dd170b2fb31de633e340a39fba599e45cc13275825f7c505bc8088f059c6fb23e2e6148346053ee02154cfb8f1eae02f04419e59d9e23ec672d96610883519517ecee74ee2ca4c3a7d47ce8dea260ccfa1542ec8255ba9eca949a06f1c283dba5bef677dbbbe5b25fe5171ac3f48bebf64747f70bb7f689c57ecade90254ea986a37d66353e404a2f75415fe3470a1b41fd447a220d33953b9284c16d83ea543000d8737c8c55fcd4c37ab87b7558e052dfaeacdd7cb168de9064e583276e1a7046e68b68199397af29e1c83f02e4083890c222e4da2b762463e62a870cb327adb0806617572612083635c080000000005617572610101e6ab5f369c205dfda284a6744f7a74a83d94369526a4126c20161c5d273c81053f65482be2ac6e762d95a8a5f0e0474385b10e52bcff0b4e2116d9128108c6892200000017000000012c0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f8eabe2f87cf524db949c7ce4a300c9943d5ce7cb61eaf056407256614567cf6808599ad0612f70b2011e286f46bb6499e08a50a483fd8f6dd0af19e1596945f877d87e4f34c7c2a362ad3ab7860336ef91c50037eb839a57418f6989b347c701e0b8c7d6d75a732aaa50c303c7c411e87bbb8479f3afc1e31fd7713002d275bb7a0ca5e2cb228b6e38d1806487741429d1dc70ee946a51c3ba3285432ccd0b3dd07663c15018b3931889fc09646632be942a7ec9e4764e9aaeb031663f6fc380401dfb396fe48d83b1d0d25eab92e1dcbc61365db4fc2178436ef2b7b9ab29b50cf12be580eb72539ac227b4fe392c8868b2feb21de9067224d77fae5f6769e46c526f8430531d3b87d1abd12f8df54b0fe7d2e5c6c68c7d45c88eb6a8266ad24903339562159a30ba82f5e54db05cfcf1b517c911492234e3698b3a25410f07a55beee0af0018bc9c144df2b89cf89269120ac2db451dca153e63509b970e86778f340bab743fa69abcba4b75ffe19442f27b7522589c8dca513b1bbfa2ceb2dea2358fefb908066e6d62738088197ec695687b3c54268b18d071a0ebb4323e84179ba664894124beefc56f52056e6d627301016609447513272ebcb0271154883e924a6165a990dbe10ac8f63c33dd71124432c2bb3550926a2c1edf8d3f392c22046af6f1e86347864de3465660969b55a3832300000018000000012d0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f66064f3465604d64246bf810b9fe8e49a1cf470be7263b11a699edc83a9f352d4c87742fc24e8aeb858e82d633c5d21aaf645efce69123d14a5bf10cf2e87b829b622d5143362571270ca3f4f451bda43be9f870145afb34e3c3a25c97960a255c35ea9c5f11d8b5b87d7eca9b38db17bba211193fcb4df872dc755078e4bdf096a0b786e3efadc128eba8062eb163b018b1763689f1765872b64a88a4c3103c4796565257c6f24d0ee68e26627947ae8d033d2dbabd19d2f6796fab2a3488814af90dc6120f52e8b176ec45828b93ab9ed570537cb311f3006eb17a4b04add9aaf8b111859be1b3d33934ee9bc8a6fdc2bd674f5236099d42bf469cae8e9dde924db656504ab1637673c75be1d51e171906c6e8c12c51a06f6f89e712f7fa19e902f00e5727bb4eb555d4a4f5140b82f4d72ded6eff3506cef9f2eb8b57e36d13f732d41c00310b800ce61efabc623f074c2f728d6c7c2cfbd7c2be565b5bc4943a7a3bb2794ce3e5a2cae2afbc804926c92b104ba1e8eebb2fae209f6b244ced22de968a4e0806617572612083635c080000000005617572610101e81f196b8d3114ddeaf9eaf15d34be8e9ff43db5e25d1aad1774d6a819da913919f6f0b6a16dd668e2880547df0716338b7d0a8bf27203dd8b8d03c90adea88f2400000019000000012e0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f723e5619fa775cfa0b85ed1f73557d87bfaf34c269c00141e20a8e4fede6c76c8148b38f39593ea9b1d336460e35f225c624104259c9e8338b6f7f74322dd1b8e18091df02039f421e89714802f6be2f2652d714893299798f6f059c5a37dda0fba4bcfd13dbee90229d0771f973af9995468146472ac6aeb912116b4d8bb5ea147bfe6f234a1d1f7bc9d4f10656648269075b7268ae6a243a1a745c7c85f077f2a0fc35b52911a0984a7d2d8641e25952ec16186995a251213ce8c932d3008a05530d6923ca084b8837f15cc4d4dc0bb3c63a1921fa15ec9556ae3ff9d359b1647a0094fc9493f16cf2deb282b73f53985acb3177cfcec28a6f455ef0b43a6eddd7bbebc1214a12baf9cc2bd7a46fbc1e5204d6c192fab5db3fb53c0304c3a6e902acc812718e754faa8f3b4979311ce24e7a9510bbc1160e124e881180d6f678c2debb20001d57ebbdc54d39ebc6c72bda6004b766154578ed841d357151fe9f7b7d80c42d43197f6f6983c8e53d10ce0384d8830a6f1b2121958dab34edff2a7849253d620806617572612083635c0800000000056175726101017e927e09f71f3a2af25d161aff972a98f588d4f42f84a28d295488cc2ebbe024223147f58a7afc121215ee03e9300d5e11058ae1e7f0e80f675967c1367e8e8b250000001a00000001350800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f1c3964b2c71a0c5fb5c51687909a83cbaa4e94b907d2518bad392fc9a5a7ab7fe35190789786820fddab97684b50b4e8ce0f3595106ab256593fb1cae9ec8c9656a2f0d8e332d511e9b80f31f01eb57248a1a68fc87f8745b71b7d3c8f81982981df3189ee192b2a32bbd331fe28d70851d1d41462957f232206c470fe7c8e0be6133da394c2bb60467b7764e7648794626315f4f2ca7028fe235b0e9b47c33a974fd23cace0213c08cb20565b61ca4bcb3c0e5cdd4a20cf290b0e58d814688d0f34ff3fc478732698c85d8ddf6d0b5bd428df77b267a77999f6ab24b9728458cffa7727cd0ea5c03a212dabe51c377dbd53f0e7f0a1ddb79033fb3d7b73c1db5558455d3b6442a3da1f7827a645952460ccc5c3dd691bcae64a2d2668fe0097e9020425014b3839b51b99be80baa9dbf1a3ef01662a7ea51d6cb2da23814ae835357270a9006870fd9e022c9ac5b4de06bc198a481ae60f3909b8affe519a6c04ffed18438f3c163fa7c3cc25faf40c18eae7c40dbd5a27625fdc6646dce86a5773b6ab6d6b0806617572612083635c0800000000056175726101018c3417489b99706c04255a8b8648f2d6b6c701576dfd25ecd1de9d3b1e0cce4970616567b06ab1190b95a95572d61a4ae637ddbf7bf13bf648af9be585166785270000001c00000001050d00002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f54de495b57c7c3505c62633f1ac3a2f22be74ed497a5884379e0821607d9173beb5dd269e10d71dc754ce3fac591364afce61b007925730544bf530068087c7d38e3e2cd8bdf7fef72ad23b076e0620ab5d97d3c0a98207dd8b6af8c3becff696cd2c59aefd1a3bd654df00febe502e9f6ba788b8584c7278c47a2983fd8e87bcea2f2c3fdf7cfe328e695f1a111ef699739c5054adcfd40969c673b39080e4dfa869839757fab6bf946cf5695e1a0d9335ad95e445cd5fe9988a1c82fb53c83fedc8cf6b2555199ecc95e7092742c5959f96bce04becaebfd9266f7642c23d76e25771c2505f549b5af7734c84213bd1fd39278fa8f07298ba69da55a5c70899ece96d300d33d733840cfd4035249b50618e4e81f1cd425bd304b0cffc13b8ee902e66008704ade0c28fa58a8abc788e7b1c3ef78710408947dd4fb2f400effb2344a581900c5c07c6729c92d2b6d2dd7b5e6a05c26adc79e138d57c1b74a2d42ff7c021eb3f127490b8eef8e2c1cff1b685fc398f2dfeef4554328f288259cd9de2280e3200806617572612083635c0800000000056175726101017e7b7d496aef40f4e44a8819b2652fe2d64d286288f21f25a08b31f937d82c7ad7a48673092c23d7a2aa5cb2ca8dead00a2ace14361537ef7f338dc51f34bb842a0000001f00000000d207000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43216af2664480544590bc51a68be4ab955ba1e9d66544fb5ddd87455187539e427c0f0596d61ef285c22dc8d3e2f29bcfa542b00f0474045735c327e32b81a1e7fb4856020ebb9fb922899fe872508d3105d22f9749a0ed5cd6a2ee894140e1bc46ea832c2ab3e85936053ce6b203eb5396a696dc8d4977092004738ed02c4f5504a932e236c018a5ffcb5f0bed02fc84ee8a1d18fc7e02bd2550ea4606e043e4e6018a6818a0dc0acfb0e5ea67880a8e20dc6ef1f7399658c2fd4a7603eac9085a5574ce91797bfb2df82d4939ddd9f8aff952e1ce48b1d261c97088dcd5c86e532283647ac87830d1b136bce5fe3bad5acba67add2a89f005497d93fac9e5d2088e825d7969dad2cc6c04f8c4a6e65b5002877aaf6b7c32d0943efe5e127824089032a6b0cfbd22318888f75e0f1d6fd92d22de5cd8fb974579b68a848ee1a394979c675d0000e427f6dd8407605cc5ecb040ad322f127d040c84616ed6f41af284720d7c4e289ca21a7e551c98bed636f70900a463ebd20ae087491f8cab4b90668e7b3bc3c0c06617572612007c7b810000000000466726f6e8801b1adac139bde159ecba683741d3ecc31221e98eab5a429f3bb3f38c553018ecf00056175726101013c7952f659e18808ab2c763a25fb0c7532634085cec8d495f3030c6c3cb5b05722c5143a5dd1fad4f7d84eee22196d845e2e1309a48eba4859aba690c2e6a083030000002300000000d407000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43228919c055a0f2137f13690e949df8f7d97d322fd990946b698f985989116ba7725269c36d48994939f136e4118d4344b4ec13a8c468ea71c52848177ee200ebab55f213795cf2769a0bc7d5ece59be01b8afc921529684f158ec31c4bc58eca35e4f74b2e3c8decba237f50ffbfe45753135891432ca98e1ce2cd1aafc02e67a80d7bd3ff76b4162eb32a149d0673960080c609ace1755ec2f60d6edcdd79309b9bcefd1b379e2291be3ec29e5429c11bb5269d085ef32e86996bb6086f9528541ab122ce2a5db613f84f3b2f96a7dc6bc53ceaa18f6985f08391a449a440c6332e9b1f9c0b02e36ec11b5167c7e7a00d24222061b4769e03517ab2e2ee6170c55a25e183e83a80c3d4968040681b1d15366669926dbf45ab4d7a84e553e426389065fd3dc2ad1fe4f17b0d3bb1bc2bbb7090363c52706ca6509f14a6a128d85ef337e52d5008cc9bdf131d19272e7143953afec22aa607608e1399048c920388988e7834c68139f2af193d65a5517524c47908fc3a6a6275d581dc9661a5594a853b0aacbe810066e6d6273801ec11d2d43768a4d5d45b5611db0b3298b77621d26742547fe41ce91c0d661260672616e648101ceaf24ecf730d7e039d2de8aa45733921ffba8cb0e7c6f75bd06d2591b901c77b1e807742745efcbd5a57bf08935eb21cc1fbeb85d80ed7c615ca7d35e249a07bf6d39c123ba9ba0bd7e75318040bc489985b106d6c98c5aa5a0811ede08f9060466726f6e890101ff0a22a78c0683078446688ddeebbc95a99b1884cd22a8201bf911cabb18059908309e9c2c6a18f7387da2ee66bf312501f6b7d5c7e5f0b9a17df6a084a87d334c3022239463cef94bfd88bf8317dd9b6cab00f087cb8df769cb6bb2c0d0f1d312056e6d62730101d6fa19a093846a11dbd3b9f26dca8a0dcdba8493d6b346b86486f3c54dd7ec72b46a8f8d7d17f1192788c741d069e068c08eb0c5cc6f6aae09d7548b6faabf82040000002400000000e507000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432cc8a84b06644b0fd1e790c2de73d66c562f0cd3f6239d81b25cd278e5111266388a9171ad58bcbd15396dde9b68b6aeb9a7a6a5b5c7a47d77603f1889cfde56f1ac40ba6eb288239b7dd9c8af7f2b9fb0795cd5b28820c87180e3d735e7bcc0b51df051cf8f33419ca0f07f31f4e8dd2ad6f62bafdc1f0c47f9b727603cda6ae34a3726a20df66d660d77f1c01195a112535db1e046a4beaef91de906901911dc374d89fe1f805734c6f6144db3152748f9b0541cd6583e6c3d2894e04970082b98df5d914b951c9183bf25117b1a9072768e4df487f8e6ed918e5d6754319322d991a6158947113ff320990f38f5e37f0ece574395edfae743439824efbabd2d04f9ebc499a3c2040abe8fddc43943b8f123b71bb490e5f93c5f6093dad9f58e90231d5d69ba54e8052c9c50daa412c580711b273461ec198a7d5399fbfe614faa5ae8d9f004508b43b4a234f1cb724cce8e3e6b00c81f94bc0f321502794f4616392849994f67c842d1b63e4a18df453da38b88267d8389934b1f86bbb988e29162c71dd480806617572612083635c0800000000056175726101011c43c9dc41050f47d24f799941efe385c0b41380cb1b19fb9910ce4f2c55222a6e836b3aeb5c1c931f9c3e95dc9cd27e1d1585d69e18813f5cb889ecea1da3830c0000000100000000ee07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432021071f1207ce1d22e80903c737f4c89f2113bd1c7753de41092a70552dd6c17cffb003d8b5359ae9c274650df76ffdd14c52814ce9b5c17900bc52834e30a83ce59e7d5f163371f5d99dd3784d693dfac0e4eec4fa8accf45a881150ceebab3f42382ac9fa47baae525b7af81f2ba3125302b795ec05b0a3d9b4bca133d3a63e2c5da2612da3f1b3c8f42cd1522f6a7a48d2693d58088e5288694b90307074ef116265b6660b03112547414f40025cc4154c6eb7a6de2ad52e51a55af54b38aa1c54fa1bd03bcbd527584aa648fdd075dc0f8e79c247f5ffb1e6ac9c2be225ea60db84bb8d7ab17120d682d16696c329e958433a449faeb88b1c50464e2e4e2eaa75a54e13a8d890399906e24d00454ec4e709e4f7b939691771a23dab762bbe9023a3389663194f4d084a27298adb033bfd6a263f4d3c4c20a3e6f0e00863cb85196408b005a0aee92f8c6b9858c667067f971772855a47e11daf73a2aab1ae29e5db1dc095e8b6f463c0264370e99ac799f7b717e685218b437e4f6181e4abd56e1a0c0d60806617572612083635c08000000000561757261010122106da90907f90dfa17d639b60ab9d3aabdd7ea95daaeeccf3b4dee072fce038e61f86d7189ee821aec9a11d6ecc5c484d12229183553ca27a9d20f668af9860f0000000400000000ef07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc4327ef0f295b0fdc0c650ffebced6be72c4dd0e1176da30930364fdb01a6713d036f0831c577230924e9326d19f346e64c95e84193c52352eda105704b09d804268b5a6b9e2d162fdb73841ea9372584d9699f321a111fe6f470b89b99b07d8431bafca0227eea00a532e1484c02ec006fa6495eba21abc438584d76f48802d0a910a508a2ee6c3f905a242e92b41e1bb438c7a083504fda57a1849ddd35896c47d78a5956fe6c7531a3c8ddefd9d17c1284ba60dac9040aca954dec18f365c9b8fbe455b67d90249d0096cd35843e3d71badc12c49381bce7312852dec8a1eb64498bbf023fc9e033deee0b54e1b2e1ca8e747d2dd9cb658cc07344df196fbd222e9520eab0f4b1fa37fc4afcb93a1c0ace0cde92aa0689ebcb0c5d1245bcd2c10e9028a0cc2de076fcc8655cd5cc9ae23351591616aded6d8ecab7f2a44e5d624a8fe422bb00056c4bf23b31c58b9773346f043fb8bf5373ded1962c0fec66853e9d754bb642036900eb42f10c8e6021345c5ca5bd1ab4e22e5b8022bf38b06f66425eebf4c5c0806617572612083635c0800000000056175726101011a3c100d29a795c4fbb068012b0291991aa5db384bc0d8c775ffadb60c9a955b4e259391b7f5c22a32ed066345b09aca2fb0b06fb2254ea3723b462ee7ce478a100000000500000000fb07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432740beb55375d7c8b84577fbe1c0743965ea389fe7585d6f68975111716c1ce24eb2dadcc3c91fcb5f23b9008ea9c6f934dc261a84b3d1b5b43ae437c6aa992452aea0a684700ff36d0a8b8ebd07fecc353bda87aad24b37c8944de3ce45efcb42fd6220dd68bba2bbc6a3756154fa5cf878797dacda5fe063c16fd8436a46bc160c9820134984676bc4e14204671db0b5494513b5a7fe4df5d0ea250e554a2080e31802525806814554d3a5677af77a3673b500d3539f04afdcfd720573b608ab0b09939c11cbff67c66f806f5221a61fdcfab5c4fa11c0d7ca12988135efa54ed1d69cd74ceee75480f46a7b15b926904d12cdea281aa28e908ec00a9d07cf8a82bcf585ae95386cc747fdf003d5802d9fe7484687bbbad0448af45553ff3b58903174881b8182392f9757efb143ba61d046a0208302a7a7b3df8041059ca538fef169b8d0012fd33199e57825afe600bbfff192f2b9e0f6b72f5da7e8f1f3147e859987cc129b23e32b2278bada2bc2795d7cd6034e3afa8e9a333d01b36b4e2250e583fe20c06617572612083635c08000000000466726f6e88014920420a08c71a4b56953bf3efbae9a45e737f4cea978bdbc470de907d64e1550005617572610101b491cb7862f8d14fb0e2f6cb8d1287b83a55ee7feb468577ca78d9c120fabe5f6b909448827d93de5eb8bd7afe6c9aea63fef46254208969cdab95fe6d02f18b170000000c000000000808000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432c663d22aea82481985ee77a58f1e54bb8c64fe22c48df15aa43f69aad1c7276b53c400f7fb9008e65a12443807e49224efa495a9cfa03e6ce5298a88fc744478f3820cb625cff327e14fe2006713cce73555c4336a7d861715aa2429a7d349102f0b4f9017440cf5a06a286856c5795b974f5006aa07357854c3eb4c3892b7f5125cb08a3e444ff92b8868bb8d6d64947c84862353870b0e5121b002929c136db31e000378c0f3241a5408a49bc458bd75af5c0d16b35661e212a981ecf5be8d61707c8adc571e83812efa6aa3673e4423c1b56780c437c500583abf6839a68d096600b21370ef6b990d6922acbfc71de68d751ee2d62fbfc49125bd9709ffe33bbce32c9e23b266d24cc175dcc0d99e7c1182b6ce8824d724e9c34ad852a611e9021145925a3f018c9aaba6b3981aaa8e1e24f0c7d9b38f65643a16d3f55d77ff6ca60a4800e3f4f2125d650231ba3ecaa0a51aeda71beada9dad70479d4571b5f2ebfa480c16116166d9e35a66dcadb999da853bfcd1872563f5d0a785507bf67796e568ec0806617572612083635c080000000005617572610101de7241c718f67134d32b6b5656f8e8f3f31e8d29af28043a37c2b49429a082633c8c7abbe502084c28c4a548ac75f97732521c7e66ea9917e704e5469572558c1e00000013000000003808000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43278b266c6c3ba60a6e648093bcd62419d4ea68eec772f22b7dfc78c6b255dac57bd149cd2b1b166d73be2ed9409a0bebe842c1901d65b1fd3c5f8d98d82ea2a5c3ae10acc8770276d737e6334c59e468be878e6264c050f48ac3e4a6524b76b37c399c4a820e1a50b2bcbc805192c2609e8372e8ddd8432127f6200427dcb2d72386429023e01fcf193d96cc55f1d4d85db5b2f0a9e3a5fb6855c0e07b891d6581ea371a39cb30eaa0ea2d0b9bbe5734e8793d4db7c366277619bdff9611dfb8d4bba89ec371746a5e689ece6f2a117d2b4e7894776b7a96209e7177446c076874bde474bbe3f7bb78669eb48648bf238110f690c144c097988314989bf9b3d4ef410cd043b32cf71a25a00655ab6a0558e383e546c3728412be664273b51908f4903de6835c05f9da3c6ca7fc65846438da7947f93a152f77bb75a85e3d05385feb47e071300b797adcbfd7d3a94ba4b2e0ab454bfded856f759d2b674839d4adcacb72d2c1361edc442862859f46d384db20db351390b2d261be35211db5232e585f985291a08066e6d6273804852f3c0a603d7da194fbff174c24700f3f89d86b462760033bdcb1663c76c60056e6d62730101e2f5f706646cbfc613a98564ff9b4a958acead02fa488e1f3bbcee114d13594d75e9b79d5f5be257e9da81d3ab97cefe36a620a2384f6f1f8719ec2b23532684280000001d000000" //nolint:all resultBytes, err := common.HexToBytes(result) require.NoError(t, err) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 841ff72742..17f8ad83a0 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -404,7 +404,10 @@ func (in *Instance) ParachainHostAvailabilityCores() (*types.AvailabilityCores, // ParachainHostCheckValidationOutputs Checks the validation outputs of a candidate. // Returns true if the candidate is valid. -func (in *Instance) ParachainHostCheckValidationOutputs(parachainID types.ParaID, outputs types.CandidateCommitments) (bool, error) { +func (in *Instance) ParachainHostCheckValidationOutputs( + parachainID types.ParaID, + outputs types.CandidateCommitments, +) (bool, error) { buffer := bytes.NewBuffer(nil) encoder := scale.NewEncoder(buffer) err := encoder.Encode(parachainID) @@ -446,8 +449,11 @@ func (in *Instance) ParachainHostSessionIndexForChild() (types.SessionIndex, err return sessionIndex, nil } -// ParachainHostCandidatePendingAvailability Returns the receipt of a candidate pending availability for any parachain assigned to an occupied availability core. -func (in *Instance) ParachainHostCandidatePendingAvailability(parachainID types.ParaID) (*types.CommittedCandidateReceipt, error) { +// ParachainHostCandidatePendingAvailability Returns the receipt of a candidate pending availability +// for any parachain assigned to an occupied availability core. +func (in *Instance) ParachainHostCandidatePendingAvailability( + parachainID types.ParaID, +) (*types.CommittedCandidateReceipt, error) { buffer := bytes.NewBuffer(nil) encoder := scale.NewEncoder(buffer) err := encoder.Encode(parachainID) @@ -514,7 +520,8 @@ func (in *Instance) ParachainHostSessionInfo(sessionIndex types.SessionIndex) (* return &sessionInfo, nil } -// ParachainHostDMQContents Returns all the pending inbound messages in the downward message queue for a given parachain. +// ParachainHostDMQContents Returns all the pending inbound messages +// in the downward message queue for a given parachain. func (in *Instance) ParachainHostDMQContents(parachainID types.ParaID) ([]types.DownwardMessage, error) { buffer := bytes.NewBuffer(nil) encoder := scale.NewEncoder(buffer) @@ -539,7 +546,9 @@ func (in *Instance) ParachainHostDMQContents(parachainID types.ParaID) ([]types. // ParachainHostInboundHrmpChannelsContents Returns the contents of all channels addressed to the given recipient. // Channels that have no messages in them are also included. -func (in *Instance) ParachainHostInboundHrmpChannelsContents(recipient types.ParaID) ([]types.InboundHrmpMessage, error) { +func (in *Instance) ParachainHostInboundHrmpChannelsContents( + recipient types.ParaID, +) ([]types.InboundHrmpMessage, error) { buffer := bytes.NewBuffer(nil) encoder := scale.NewEncoder(buffer) err := encoder.Encode(recipient) diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index a00074b5ab..4ad65711e4 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -956,7 +956,6 @@ func TestInstance_PaymentQueryInfo(t *testing.T) { continue } require.NoError(t, err) - require.NoError(t, err) require.NotNil(t, info) require.Equal(t, test.expect, info) } From 1f83d792d90635b4644d47a356dd3b006d99132f Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 5 May 2023 18:44:57 +0530 Subject: [PATCH 42/65] fix lint --- dot/types/parachain.go | 4 ++-- dot/types/parachain_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dot/types/parachain.go b/dot/types/parachain.go index c9a3e1968c..a3a06ce21e 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -312,8 +312,8 @@ type SessionInfo struct { // DownwardMessage A message sent from the relay-chain down to a parachain. type DownwardMessage []byte -// InboundDownwardMessage A wrapped version of `DownwardMessage`. The difference is that it has attached the block number when -// the message was sent. +// InboundDownwardMessage A wrapped version of `DownwardMessage`. +// The difference is that it has attached the block number when the message was sent. type InboundDownwardMessage struct { // The block number at which these messages were put into the downward message queue. SentAt BlockNumber `scale:"1"` diff --git a/dot/types/parachain_test.go b/dot/types/parachain_test.go index 2fc0eae0bf..bcdb8b2e1c 100644 --- a/dot/types/parachain_test.go +++ b/dot/types/parachain_test.go @@ -173,7 +173,7 @@ func TestCommittedCandidateReceipt(t *testing.T) { //func TestSessionInfo(t *testing.T) { // t.Parallel() // -// result := "0x01210350000000fe0000008000000096000000d200000000000000b0000000bf00000021010000ab000000970000008500000051000000c40000000800000028010000a700000032000000e200000016010000bc000000f9000000780000000c00000088000000f2000000ad000000260000009400000046000000120100004d0000002300000009010000cb00000082000000750000000e0000008f0000002f000000f8000000100100003d000000a000000006000000c90000000f0000000501000065000000540000003f00000098000000d600000047000000b7000000df000000380000004400000007000000b9000000e70000008c000000900000000a0100000b0000001901000042000000af000000020000007c0000007a000000240100004c000000010000004f00000063000000f0000000c7000000e60000006100000025010000d70000009c0000008d000000e30000001800000019000000030000006a00000003010000ec000000fc00000008010000ff00000058000000b10000006c00000043000000290000005f000000fb000000a1000000c20000002a000000be000000c3000000600000003c0000001e0000004a0000005e000000200100003e000000c800000093000000ed00000073000000040100004500000009000000d50000009200000076000000110000003300000055000000a6000000fa000000d40000002000000086000000aa000000560000007b000000a500000015010000bd000000b30000000a0000006f0000005d00000005000000180100001c0100001300000069000000e500000028000000a3000000d30000000b0100001500000079000000b500000068000000350000000d00000031000000e80000005b000000260100001200000011010000db0000001b000000d100000059000000070100003000000016000000870000002c000000240000000001000070000000360000007d000000480000009e0000008a000000270100004000000057000000cf00000067000000fd000000f5000000060100001d0100009d000000cc000000130100002d0000007f0000001e010000b200000021000000e900000025000000ac000000ea24d73b1607c8fd7d6542870c2563c7891a9085b74ddd253d4322a9b3d3d1560600000021034a3487dc0c46f976d352e5e152e120d2d23774f921583d1f2c128f7cf9f66529d49f031c94d9c3b33494849eb9682c0311b3c283b17373f18b9ca02d94e2c05c969ae5d9d6efa40c6255ec4b27b0a4752d7f4068163116e76cd0d4041c471431e8c13e37a4d00135dbe7699d91507f5a53a7b8ed36a3be29cb2fddab9f7a286c347964127e9d8bcd119989a92646c80886c2eb8440c87dd7dd94437873a3ce286432533fdbdd1a739c62733cb36ac48c821dcb0311978f1027bc1e39d4c8964e6a6570b80ba0a90a857ef4ebdabfbf958898bdb12ea1edbb17eb903b00746a14e059357312bfd525317b4f93e5eee1de639872edfaec9d2a320a6fac04d6105188fe28737bdbfec193327886b5c4906675d2a49ed43fe8cfb4e079698de82d2d042cd5a9d8624860310a963ed20c4192a19a9d163bcf366e48122c00a1e9744c5cac0ffa042ee550a3bf70d380dc032d11eabe311e0796c5143341600ef626644eed0663b1d15bcbf9e99c372c041ef118de7d179c68899a645a0fa0983b473eb2a1fefc7a956231a446a575db2e31f7c084c2945094f3927519617d7b913712c60cc4d544536a7190ec68525a70fde1309723986ab984a1e97aca4092ad721c744c3b91b676828a5f884e79d9c02d6f23ec246c3a1a8adcfa9dc1e531a9a5310e2d777330aba66c9558434a592fa5e5aec49c3a70f49f66017f194d41240d66148f2b835556a0c8d3b51ae0e823655bd4aa20fdadc6b4189de9f32cf2288700d8eff37aca87eea6637118337fb1704bc33f1fc685aec019c8e9eec48b62a728a8cb454f4e75ed6d28c458cd8df1c2bdce6101e09b650fe22d139e360fb809200ed18130a0ed0513b2a2bfa7ed6c9090cb350983746b1936c6a92f7304a7005450b1f33df75af8dfeca1cd7e94fcce445c6d55651259fdca2972a4d62f6732561af7dc55da09babaf097d1304b4cde14562506f4db4897644895324b542d8f573c39b3f67c487c1df902d0397792b7cdf987b657b2d27920bc6846eca466c155c4b778017656b9a7d69d3e69159852f38adf971f5a25df65f9950e97411c1c36e8bb9f2665b217df30a15bcd22f231f66f4f21711363cb0b0da8b3594003ae014e8c22d93dbca83c05bc5222ae72b85617956f04eded477369ec95312c7c78353256f3f643ebc6300f32561a0a5583813bb3b42844d1ad3d3779a438771a295e306daa91a5a25590d2290fd262d40f239f87d37e1c03a2494035a42961db2f33407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71482cdc214f825dc7085e54a984230a753d66d08425f9763f52f8f68911120260d4d65053a5ef2ab1152c72f3b15d4f24d4bced3b7e277735eb49450dd867c115263ad657e55682de826f6137dedd2d246971fd8c5d318034940160fc179efa63701058e68510bdf68a3678d32145780e13c29b88fe77b27440bdf3ea9762a63964675cc62a59886ce5fc12d2f48694c7ac836a0157e0e6630d694d11faa605034c51def135330ddca851fcb670c865235dc1b405242cf9f7ccb728e449e09f4ad614110699b5642a4b726cbcb74bee77642ec7b4f17b06db88ee461848ead17c906f769166b3ff9b0fb13c1ccb36358d9dda3f25bfa18e2857fe01a92328eb70cacb5514b570b9338c8602cd4a49128006a902494029c2728056b02a900dcc7798b499a9c38970f6f3dbee7e6220ee0e12a582a76ae036347816baa6cd7c9a7b9662caa1a29ff92ad66794001cfaaebbdf4071f4db6d74ee767ba59cca4cb36cac6854840b7eb103ce5723aa0d6625709d4c4378c46903ff236d9d8d61f21f76b22d6245ef2ea126366dae7f9c072d2d6e0e71a54c9bbafaed36448a4a552b51f02a182d14b38906ce1f4693cd9b87d0369e6af514cf7ec91455b26cd4c0d71bc2d3f9f9f499e04d2f27dbe47ffbce115afd1bac9fe116ce7fae719325e4082460c09defe1f43c8591655101dd3dc806c7b07762c97ad21e4142705e46a1e17306b888519767218eed7b884fb221f597a2d4edb69c094961ace2e65a7e40913c0658f8f3a64ec6949a26916ae2cd976fe531947a9c9e93e6d587bac746cb0826e4b23b64b0eaea19cab0333369b93e11693d2b4334306ee579360814adfc1339524dad3d2adfad0b2db5fc2de781a22fc63dbc4e30a5fcba2c63c2fcbda238668e06587bec427bd5b5cc33da6f7cabaebcb7688de50b59125434493fadcaa94d1e0560d2b374b7d6e1380b6b88ee8ef92cdde7edbd9a48d66f5e219840a1155818b9272f50007b87be88422e3da9599286087f5e578c0d1c2a3db9a77110f9173a69e0e58185dd4e76aa52804b2de15ebff8c3f3237e29dc7157e61b30b9b00a30f93bce6916b6b78ce4f7d550c39c7947c6860502333717d541fdb6697ab447aadd01c0f366ff1c65d331da120ca3ac630ea6e8d7339e7317518920d710e3325edbe8dcd591d30511a0fc08bc5172ff58ff98fa848387b25f99205361348105f6c138e9e4061b3a799bf7987ef5c820c1e534df298f3328e1093c5d0758d434280f6162242be89d139d52f449e2bad667d7d974cb80d0edbce7237185b11475fcd9b0171f73154a0734c1cc95ae552d9f3180d7d64e8b50d3837b14b5afd2221808dfb6c44ce63a08d4567cef4b2a9aff1b408d2c99fa4adef25724cce85368b429d0687fef75f26e5503379a61920777ef1f254af024922e382dd19e752e69784ff2911acf10ffcf4b1d795df6d8b55f38eceeadffe577cf5bc0360f35005940c73278b76425a158be63207452b1a8018f53309f47486a273b9bf60cb51c48d67770af6f19ab75537f06388373ec17a3c88ff1714806c0c99ad44e6dbdfa713ea7825552b7f76db8f2ba2fce0e546d7e7abab7d59e7afee2bfe438bad6091934cc7903dcaaeddb2bd99fd6b36ab15fc32ee001bd1d95e87020019f7c88be2e74afd1a3a66e44e8b7845e7f63923b706dae49eb96cdc73b04c9e6cfd1459d06d6f02e6854e6df29f08f7e015d511ff48d7bbb13bacc9aab1b06ab73c1f3350ce6a864e68dc99758ce2920256f75bdbe8c918c556a5a2467a3aa13a306808740484d1bff4961f87c7ff6a6a68beac9264665f87ba1a5fab9802f1cd729391a718a7477bdafa88e49f5c8cd88fbcbc1724d8e227935eabce71ec303d832c4ab27aafd3f8056d3462eda0083ac22241db692c4671249a14a04c2f0a2959aab412660bb493e536e83addf98be8cb2a0158cf18c6d5ba06ab586a2cb56cf1ad4cd099ef1e3e727f41ebeb3aea2815f004002d27714db121fd6f92fac8bedbb97160976c4d221bfc6da82c7055e469a1405eca842b4b8efd101e984a2482e526ecb085229a5a3f09f444f6d39d71e0b936cfed125e87883db8876444288d0cbd17642ce97b61a3cb7d20f9048830a34520de889098b4435dfc79a73a0518ba9f61924de365e70f8503654e384a4524c1c16900873792541ef023019a68f62250b7c219a149b9b68af793ab31f83f500126e0fffa71469e78e22e754f3b49db1dbe631f286ac449dbc94282864e76dac48fb9bce48124189d2d45e2b2e16b8084c022bcc90ef1acebf194c7b9820968e554e2ec4d34346eedf80cacdafcdbf118a3f158e45e6a8766869e2e5418499d3cfbe215762a4a0cffe4315edea5ef47c60c163be4aa5196c5241f5c772f3f90c57a3580fa0735a7340e37372048c1f60a20531f830d60634a177f3974d5399fca046417a6e4327c4c569d8f4f5b47b263b0f07408b1d453ae31f699e53904605cfdbaa72639138cea3e544258e0484a532216372ca569751b32be145716eac8ee5e731a1db2b1dae4b9023b05876077cdd78084c79e58d16ecbaecee3965ad4685c1780154b678bbfcf725fb2e91be3cc0864ba0f682ce1460eff27c8518451b3a9ec811e18b8839808256e18a89219fda2772c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416da5bd7647f8d8388c2b4dbc138e36b8679284eadc49370ce0a16a4e0be28804b04f9b593ec5987c0608e3913acb29a322355a554e010d33acf155e6ab9bad337c4bc688653010a7720d44168b4552bf75974219788ac1cf3fb440c67ff692d499e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd93257121806eb5dcaff87a28d25de336e240731a375be04c4bbff6be6a5ba4f1042a067086008bd1c894c74e4ab0b16dd36effafc8f04a4617aefa7f68b40df033149c0a98bd89778f1276a0ee404b17d81b96c524a8aeda9f671be9e724f090c397977714f425d45bda5f3373c374e9b2710f477e2e923a0f0b2b259c941965f6e88c0334fe5947d75ed7ce18612988df5f227b149c66f371593a8c248206f1b59e10248e650f7e08ac882d65fb09141fc5c7d252da9b1d8ca2ae311752ddce977137229ab3993dc198b5cfee52c273f6145c25afaaa6de14670eccdc1b61fd53821513fa519134b630c1d53b78cbb67e8b8414c30247101be5de118662237b8388cc7d3c50b2fab9b87f1a6228df23e9507c90bec51b8e3be978b526c0e0c7704c7334dc8495596755b6b5a83796315f9e316bb871c0465cac91290b34812c5f0e34120ce455c4566893481e7afa89c0c425533fb4eecab574f0399ca29b162a4c78053405a94626a6d3cecc0492a268e974e9864826f8745403fbb98f55bf45c0b620da0f2b6e2eb2808b3e713d1a3f774966e3e00f81226887d5e1c165af998d6e57645c3b5a2e17df20f698507190332c6951d761c5f46e0dcf997c7337c0bb7e54e232d9f4c8884a9f53a999e8ce7a27f68e9108a4fde15bc51a350774c22b2a1480fc5fd10948cd231f68ec00397e22a19042578431aad63546679e72efa3cc619c9564390d54bd989ac1fb089a57964ee4313f857411373d34161939633c8f4230930357b8b54ce94dfac3276daca91ccbab9b944bdd9754fb27d2b786427b30b6d3a029d0c998a49c406fb0778936c3bbd0708774bbf21b400aa8a41e604401c8e5f3c9fe54712dfa93b8f223c4bf30e2d037a36a768f160cf0c6e6a8c42a45908fdba40941f018589894c721ae6eddb3ad080bfca4aae349a8e7ae261f0a0f18d3fcd225254bfac8ee7f94e5f505496773b69c49697eb79ef8523530c55511106827b00917fd22c6b8e62eda5e130344c9214f2565b92ddcd6b6edfa18e95f8afa23b3c8f159391a3ffb6dda5ce3c9f6b40f25c1dc7a742186b7b693f30111e4b9ad468b9d1e0cf4f79c5078c9cc4e409f8a0fb170d7c4f421ed5fcf597e3f061f1060d5207533b44b4977f128acd44bfe1bfe235f2f4b2d042a87c7da4d1d526a096e110f710d48d0a0bb58b06ceb1d6ba2189ac3dc984dc24e80fb6522431e282ef8862f121223f6aa19fc1f929106d7a916747f21e1973eec1e8c5b7f78cc3ceec15a5af2b64d5a43ae54fcccd31ddabe95461fdcb5be506267404ba432e41161e6df14443df6eadfb3c5ad5228291d1383cdaaef20c9cc8125f7952f249a0de7093e895f4c599aeb4b0310673b00785b33fb9cacd556acc9abdc3de57fc056df4318d12a052ab505db7d06dfe03767eb5f46cf0d271393db1db2516c52aca4be351c39cc0bd557e7afe547a479f8a7218cad2c784e197f3494dbb9436292833db878c0dab763cdeac36e752c7cda12c98686c05704a8b2a695a315bb1146b3d1cb07cfb8d2e13fa9158734dc2bd1ea554fd3032bdbf9e9871d2937060236da4573a6c20044052b270916290b13a30adf3a821b467c4038a14026badd09126d6621e31b47269829a47f9be24a0d63c4bd7ae112b395498ec2502c3b4f46547b4c766e40db6b1685c455de210347c5757ebb7d463d1910eb70fb290b5c7bc63163ac00341573dfc794b0d53e6bab40a84e60ffb1dc3f6642aa1a246ee579703579df75d2c2dd3d53003f55ebbefeb59446d476d0a722ef8ed1954fae9d6ddc2f1b5a31a3e46efe8097d83d7f80ec284bc72a48b7916a74a1cad145eed554722609bff1c0970e439f19fff06a080a67677712b09762b90a82fd9f97bbc50c12b2408a440f2c91824179203d689db4245fa3087e8b01a9316ba973c6ed1a7556aee499b2dffa90a79b118a646aec6b79e6766dc25665db73a98e173fa6381ae47c9de57628b53ed9958a889d278fe707b4284327bc582599019bfc4630616b78f186de80c5d2d0669404118ff1591ff141a606e05e2835889a5f42a32e9a1f34d4c6438f429028ba64818bedeff64b1db1ebdd89f2c2b2fe3336942a03036b9e86a336aeeee1b94c5d5a821e4ab4c136cbf2766a43dd37078e02927ca8a562d2ebb6671ff854613aa3ad169250e037aadbf0ea14c87982d7382f09c7b8c96770d2ffd3b72525806a645e5abd09a51d257c30dcf016435c114d26d3d3be170800af2466b5e4a434ad5ef602a77f311fa22300a5a6ebf03bdcc04f92fdf0da3c74f0c1461d8bef6e668a2cd0c95fdfc9ef30cf9133619aeb9c3d5187f23bd83c765478a56c4b3708da965c36dac2e8caca9398d50bff836219540b179bae7667aa091181db267cc8ff6c5201acaad6fc2c3a2cd18eb729ad0c1526c6c348e330ce5d949162cbc728667ecce548da5efe0448823e928463418342d41883dc6e20d8e45f1d6d02c43c3e38d6e7871f18ee80f60415adc76fdf4c8ad2c67ac7d11682942ab79f74656a8f51ab8c1b088f33ddfa20992eaaae491dc3dfff9742fe32c4428233d691dfb69a1713087e4fbfef8f7c96df760e85354069eef1ddbaa01d52f9664fbed82ddb5cd6ceec78143f1e27ee7a0fa73873d01e80e368825e3b05bef7cb0005833a9d0ae360c420a66a5353836acf1fa3c65578c9c5b3b9c7831e944ae887694e9fc6a8634f213d8d061cc2a34a00f214d9f67cd17effc527a07e060bea20b143a7bf515a130000f93cba10536a1204f0a14cdba7b627412d383c308672a7e2974b837e4a89d54e63c47966b36fcfa3efa5854046d3ce09d45f226c36aa9c0762a59eada83c70e1049d5d09f7f7304c465f2ff56dbe21687ece20ae9fcd9ab8a7020a1f967780a1ef49b13b40fc3cfd208e29f4d5d5ee9bb63c5fc81fafe5d47c4ee373a54a64d267c497c59f4c15077374317b91566d44c82f74167e6d847ad207f3a1221ce1f958946317e77ba146d16aa7bd82810c5e913c4da0bc5d3a5923a156f0990c79f01317a3140ef3aff708acfdcd30a838706db819dc3a5a9fa2b1bed2a4a48fb21792b44c5772f888132d414d13a98bb5bbbbd70ac42afa68950568131a449e70574ae0f45f28b87210c1ff7df1adee5576d03950b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d9a53c2f9f5f55bd687e359ef37196cd288fcd1a14adf6cad53c6704445a1f1212270467b0c03fcfd8bac09473161c6eba9c25369a853193b472eb2f113a3d333181e6b71b981059fa265cd76422e52fe175db6983c6ebdd0fea1a3075166b9291619ab90bff00f89ea8055f0d7d45f8c8aa9c04b7fc1d06468837c6c563a6529ba846878e4f157741703bb4c3ab4f3ff2e9b99916624a9965a4256d893c84e152c19794d20de22edc9c4c1514f4f4e29ac16e6b421d3620ec6545f737100f0134c29c11128e193f06c866e165662d903d9f799508e617920d786ebf75acd267462237ad2bb39f6a5a03a46c5a1dfdd3766a49e6c864ac5d45afa6400ce3a9809de464459b18deeea6f02d5882e80a8696b00c9f703da84bc5769921053ecc749b0cfe1745dd408f6dfa0ceaa1780ad4ae1747a8912a589a754ed86373a08ff5540a471d9a8272b09df08db1f998000cccef325d072ad79df6c1936cf0ccdeb77a0d9c323ea08a0551f96c28b05ac0c7b0e338cc5004bac22d06feea5a8f5c00104906813ee195100f82600e56bb5756831a260e4cf6e5ad275364130dbafba4ed4f9db6adcdce67708905276a01347cc1c800bf6ba246c3770a81c3c754fd65bee13fa85260215c5235169fea113546e7b4aa7a1c936c47a14e81d3df912601a2eb8ece17888100536bf7183c579eab3e6daa14e5e01602a2fc3a64b563f591f0828f0bfffc49973cd14329675728a2d243102ab486601f1581b1e741bb5c77526552839c17a5dbf3b2f90875abc9959553b320da9f07f1392fa3065315a8b1744a7e5b271f9394d6e23bdab9ae03491f51bbf21014364d919388b7fba4b5341bc4b759fa4234adb292ab984f7b69d3aac2e0afdc7dc075e18ad22f4456dfa48b0acf62c24bb58eeb0a71365ba5f890a594cc046a483d9b306a487ea4eb5e80572d3ac8b4dbb4b6a02692af692160b113da09d4ae9f0464c5522b7236a59b70d3667fd3b0c5fdf2c30cccdd640a7297da408b6aff82ee9651f889910fda9f24c706a617b082d626dfc74a657c5d17c5a763044f0230972fbe47c907a5a8fb75df4afa9726d496332a25823148258bf60b189ac898c92b9be15965a199a45ad563efc761392b915b58613f9fb99f45c9a78fdaa4358874f739cee7ebf2a5cbc2fbee73e2731e18f347de520f1878f0eab3a38f377a9263ad17333135c991d560da02f9a012221d644717e2f1361ddfd9e6b5d0043f3a47eeffab15e43d7d45e1f6e07945d95fb46ef5346bb3a502da9f005d1cdc956e1b96258fba48dc793f50b7eeab48cb88c51118ced6c65368c5197ec7f014c443b47d898627cdb7781351442c44398d0ea4ca4b697ffd505665531e7d4b4406431f2328943e8b72d030842128714ed41e3d13b8aad0d076b7ad34af4946866f552568eadd3d3582b4c4f50d816c065e65b3583c8309e3465db95b458d0b42619e1ea75ca546e966d761c53645771381f31a42a1e0bca62f752fb49e8d2a49f942cd48a03129a709e763d23aa4dc84c88423861d1ef31f5df99006156570aca69e571067899ddb156a2027e0acb8f278b4e156f96ecf0eb2658c6504fcd39e4e20bfb5905be7cfa05ed907aa5041e202a49166a5e267724e5bbd0d9efe57d34d8cd7a2e536cc7aee14f12726065cc08d547840066bb56916d9bb9761e05133fd18a68324492ad7b9f9caa1668038a3ae897ec528be2ca7c977eca6cfc08a00266e96fd43a723fc7226b66aaa86fb8c0ff0094b6feeb0707b5cd61797ca034755fa42aab8c5c9e245157f5425f5d9c2de89a454439ff9ddadea199ac62ed47b9326a4a08c06859dc6aa56cf5af62a035f7c6b0546f536c07cfd7a2d8e3be9ac2c7b7e854ebf59eaeda5edad7dc23e83eb30dfa3dd91753614a811769d6a564e5e2b27c43c70d7497a0834ea96e50b6edef3369e8da5f707e530fcf611301be6bab8187386d130d1f8c94e5c3602ec613f83c1ce2708d6fceff206d25c511772a85eec3fe2b4ee066681cc6c58313ac304e37b46e43a844db9b7bcda351e09ad1efc57db99dc2a7c12e553ca9a60412dd6bdedd4ded92b9647ecd2ce31eda2a6f5a4ef9df833b9b4c70ec0924a92a7067757484a42e2e39a2c58cf41f683c3646c0e993fdb61ba33306f7524ee2733c1d970403cebabf7a1af318743767411fda52e046b2fdbee1680978da2f66413a00a72c2f0fd68497472feb62d2481dfa1ae93b14895fd3773d48635738847d32c4252393c6cb8e07655646eca309a1481552ecbd9569e94a0cbb6905c45717f0097f3dac95ce491ef6f07d89dd7a409b0f13475eeef708fbb0cac0f200cd31c296fc0f38221dca15bbd3ad95092e6a4f38b8ef8e9f3b9992d57409c7833c0e2e85194adb91496335138d5815f82e01ebc93b757c1ff94620f3a87ef48ca064b8daa8790dd2fda2c3493f33b66804385212b1c3747f61ba6de535688b2ec24db2b9bb22f1c69337d131a4c91c2b70f1b45fa522eb556b7960f937e6fba63e1a5c832c850ec9d476fa68c807d36d09edf0c1eb9b2995a3812cec5092b90c4c724a2e1e42195049ba8878f1d05a2e30251a57f7f4662d4bbe42ecc98b7399c13a00c82090e61c34b4675c01815b7e25a1fd09d2fc60f60ec1f3f435096790681cd676c3554c66ecb08ee954d3de09ddaa2e3d11f5fa4f9d4c89cbdce2c3accd6f9495757f069ede7b956256595c7d083b47c610efce658762467518bdb11be9597e37db2ce13f8b1b0cc42acf317bf5a8f948dd3977725de1590421117c9ffd003a836e898f478234d26fc7d8bf866a6a308f8f7cdaab738bc98b879669911a26d87f69b187cd620e910289b9d5c2704d332359fce4040b4978eb1527e743dc15407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d7162fa40d6ad22c0bd13811d9555f4b2adb0f639cf7ace8468db36e557c1e1176e4ac7db719c3be3a8a8fb077e5aaa181f69f89547570b88ecaba644b0c8623f793abe63296589646fa4fd48c7d15548b46fe4f60435bf69fb31260205482eab0226b7a3b02d5edba566f82d3f949278d4d0660165857965f123b1ff5aa680a62c6c7b8a1064cbfd234f3e26fcd14b1eb52a0b46a47e8a8d38027bb3fa2cba947124c41b6ccc361bdd655dbd0f0a5b5e7c86fb1bf779a912921794e17746c37f40e0e4451bfef8b6e07bc00ff6fe17cdd12d45db9f816cace50b0682291a8dc257ac131413580ad09206331a67387cdfbf12cee28aab9a8b0aefc03d6d1f2fde70a8c597075eec72c0adb7c050db76ed8d86e7785f056db19e02775ea099672c7f447c7d787652ba7c318efbd758620236476ecd6df6abc2cadf3488c7e6416c12b8a2bb40ce3658b1d71c42e68495a5504986f38696e56ba0fc2df70182a5b11fea0d61d2472c21da757115c4aeb85f1ad06831b0b41779a118995340fe6c352e6cbeabce345363e57dc45931c6bf8f278f704cf252234e0e580741af38024e1536d3b2112224e3432e605d698c7809f9599544725f3bbd89e076742a2e33631e2caf02567c87ef2729ac221651de0efa7ccc8de802d0ced1036b68b51868bd3686a8ecbd7b1a217342e937037c0bebc6a026371b85698d124c09998e5a531b6cb276cf5c2ddbf28d010e2a6976cf03488c0d1d11c5c1f9b23d7ac44ed221724baa63a6245db826d277bf7bed80169db1bccdc7a3eb0ae7852317a5fb2628982aa0fff7c6916548204396e77dd2fc044e2a37c192789053627b2c81fa1c0f3d1f7482ad1abb0ef6ca6488989637ea1d44a918f062b169f1b802c9ee6d05a2fe34fe3fdf6285d91ddb739bc5c2481ed4d77589febde82e624d0af0ff9796e5993242f7de325ac001c0d50c4d27c15248ae2023cbc52e2ee969b16fbef249ee2542026074c387dc5714b8038735a05a39459797ad1f591aede76adbce55e99ed94a98b68d8ce62060e2c77262da54a918fe5942925597cad811f00d13599f0062784e528241405f8618bcc663a513318815f67de9a13e6786615542b715d6d2bb3d82580e61b8d0dc0c1652fcb6ad0fe74186d4f30f931ded5712a16e9724b9993cd0d505f36fdd6c1f2f87ae7f7b7d2a84caf41d8db3d926a728904ffc98ade114aa146708071810254fb2b5fd49243a64bc29a6cf8638150988ebd9756b917719664e74f116e47c0991afa7bc43d0b4aaf085d205ced8ea01235b224e9e2a575626a39cb65fb8a0456f4f5380b87473b2c6d3ae6c36664af57171130202317f567e7a89975b0683a31b08cabf966ecc62d48ac257c297ac4825c75e59c4271562da9a7597e0b1d1e880416c0a36fd5d9a8a1a0e277025e81af122c541ead22d78609154fd9334b34c1b724aafefb4de93d02e360bcd69f4d179b8f973f0a229525c681a841ce65fe1848e33fe6c929cfdb09181ed6f10f9b5d42b079890c93f6cb63489fe6ca5926a30f68d89fea2985c600a9114516a6c29aa1a9a390358ae11d4c2addda665d13fc93f613f8de4ae6526a7ec8bcc418d9d190bff5fb2bf8a57d4d02ae9d39b49dafea09bc363a28395b90f0c0482be2642d693c65b1dabd51d6456d129d5c987093349056b99398c6c59efe7949aa90e6480719aa04ad8816124b5eaccc793902c3f48b7529b6d116f4e7418406b6dfcabf008b65268d1b3757c713863c80e960241776adfb775052d810b59fbc83edabf4b607bd44c6a610788c1cfeb3f21e0b94d5a12f2615ed49cf7d67abf18a93af7ba649cd0ac29680d9eb19a6e461dc5fcce21ea03fdc88fe1a67bdd4b67671794d5348a1b481ad45e86635f0474f0fe3f7138dbd0c961b000d0c14707c9c3037792e2b59632bef200305908aceeb3388deb21c5ceaa4c1dae6b8ef3ef9ccfca9bc6523b609bcddd0b66f5b305293c5ce2538e4d8e773a6d51cb10adc0c50d9b9cba83e8429a2e2e1e4e1f947c0be485986af1fefb306419c6fc3cc203303517dedafea231dd90856df4af58129352adfbd4c714e33aa5cea74c6e39a097a1155bb8a0f59242addc542e1ce485f81eb5df11ba9bf4e0267aba89ad594b06066c4a7f52ca7947de90772864f98b6fd26bbf80abe1a9ecef909810ecefd129f3a73bd3296a2999b9bb455ebb74bbc3f5ea7cc6eb966a566123ce03005a73c0294531cdb87e6f4e95a515a4533e0224cd2cf5426a5cdcab8c30caba2a0a36831bce623b526cac663bf76f269e3d114a73a0229bbc06b4f53b1f5c0ca2198e418a49af03440d375ae7c76e24cc7c0c46b93aa96c8e69afd833d5c5f4ee23346e35053b1fa6044421208a5fc47074d544333068438bbce32a53bc0117d123ddb9718eb62baa88f7a7bc786758ecfa2acaff06cdc5d550de264d6d61988290e84649f3faef516f21a36b403490b980074580512dc2e7d3e2b87a063a5da17648602d66ed743cf227b0ef5a34067bba03c1df0cbc3cfea77b39ee77b49d8b425455e45a27a245c1963853bd35689e5192515b7b99cfd14d624ea54dbe5eea6c8f22b59babc3c6a3ce22286f1a628b901883b088d7b9dedc64dc86f636e337839c21edf802b526c26346ff314ac02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c24165804d109d88647def7d8362b09e103f65285c88ff5ac9329ca40a9c29dca4e073034a4c23a5fe2e1a82fe0b885d736e57a0883291961a087a2719664020a574cd8db813d1070487f577a18b9e163ed125ed818c0d13dde40503a10ed6c8d3e6a9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712132d3fdefa1807e6bf9c14050d63d2c37bf357802a7d8e813baee24cefa76b229d471496a02cc87ca65544c0ef979e7f4c1f0a7269e3eb21fea4e0d91ec4fe86ba67e4ee5cc212e44e3488e61c6c1ce07e25614b8c23cb4d0442b35e6b0d8ab3744512e70a1dd7110e04b778646d4f7b399d36712e40bd06a6907f25046639e4f9a632636d4945986ce97bc67ea13897025c220e7297598460ccd7cedb8a0c54792f097884bc8751c88ee126bd1f3682449da8181bc9cc5b90f0bd9dce1cb0d19441bd6bd7dd64756c6cb272ce5ea2a934c56dec8f3be010f8ea74cc61f20d1309a1fcf68fc3da9660e86c1189f879b8c9cb6611d57d470765dec4c3514243009923ef8cdfac92e83ce444c9a2b61fe92d6043d108129649a3c6ea306c5d9db7b924eb791afc0aacb141b54f0d75fcde46e4682e806926114b2ec7ee5a1a5626a3a524e56e2044349643bea61e7d9d3ae3dc19e660d754e6cac3fa4f24ae46d794816a0ad32ac3690b658c96cc6e09d9510a57c8e28f32220210108791a15aa0dea2e3482714178bee78fee64d0d61e6933d06f8e8dedbfa5ec5cde870dde2d7a9880b245038d021948c6700d89443c09f207b9da66d2ec05e1c567a8ae5fe5023a414b00e01850a90adb945205173ed44279aeb17ca7ebf9a239d5f6ecc9306a868b391a7c49dbde0913228107a7795db90a5e3e91e505d9922c2914d7755e0ca47af8f394eabf539adc4509e5958a7935179f1fe3f8c22b4cc2e2a345933f59d65e0318bcca6caafcefeb3452d68d6197c8ea0b26b971962e201405c4c157653c2f2d4af59046fba73c6d72ca8cc525648416b9b2143dac665457204258b81bbad3d109701bd807e75845178590a4c5b8d44421e0225d9fd994af2aa1d0c65590a7bfeb5fd893b53578b04160e3162b0aae5d6f67dfcb75abbcf01b2ebb106906d47dbbbde1bdb9b1bfa8dab1989c600610422ddba5fabd57a54dc955ccfc7e5810293b5345958abc5f84808fd97351d481e6809e00bee6538408aea7c6c074c26b68e2002ea0633e6c3d7484493771c50eeb727d6fcea84ed9c26bdaddaf73d8ac7ad5aa36f30863234f789eb1d0092f42deb6ca72061146b920d71b457700dc5012547ee806376f3ffab1e2780f491f33a0cb355ea6b677c4ea1b54ab6e5698d2853047a428891a431d89979492f261809be176ccc6f09660d5cd4b624f339e961df7e2cd5aa3f816fe8950ecc0c2c9838fbf68bca5d4955de8719bb6cf79e8afbc8632efb5aabfcaa6e749cd45043ecb13046ce3209fa85ef21441ec2d1a0ac63a273f4213225773647e8a739187223eaf5c9f0f2e3d1b12e229fa77e65bfaa2a0487a29d08064960b2068be68c3c830254caee33d9436053af9fd028474bacd43a231dadc4f4116e333fc9f88fbcb64abea30e650a11ac56a1988eca459d858087e220893ac87e5b5203582ed469929c865ca6e35cafc0886f8e5a9f813f011fb08ba33475f7e9b64397ce8355542f0d31bebdb5238414fbc41ab88fe2abea69d9e769a9b465041255b591fe2708f1193c6a0d7e83e929c167d0f672a6cf8bf480b21d5fcfdf7c0ed21b4968982c3b4798fe04b9e9462fe2bd8fb6c511b1c153d0637fd584e30e35b6a07aa739ca4f37d82d9c8e4369606257edbbb2f6ee4e6047dd8e85212633fba991cea2364c746d0ec558d0fdfd64f2ca44bcc97637e3af5596f09c8a333cc19880d51fcd11a73c7b8eb1b02485903f9c3b3d15b56b6dbcce848e56c21d870a965f61bc53894462a6997e78f55f20ebf32f8f4de37a05611860ed6704be9587f1a0c12bf329f83fadd02c191a288925cf1aa151d387686eed59f920597a10643f36f40b821f85fc2e6b62569c88b32189a52966c52301f029b0c231c81ba02285edfcf032a441c296500e2a2979e4b4b0caff11b6656d131b61a171c4554591d3c74fbc8fb899600114d3a61951d7af36bb8e6460ba61b0015878e7e28903dbcdb802b63c5e6c895e2619c6511dfa0723fc48f796952690fc3626bb5c1a0757a19226c7db6e42ec243932a2503b9b257fa271f933ec2dc395f40b62b11adfb0a552412447e35ac364bee1f8ce0ad23a72daad14944e49b18cc3d5ecb36f4a8dfd602319507ba7dade07e22ca3a895e9ce0a2f59d7f581d176f5b8f880047f3803efbbcd442b7f8b1fe158353183f03d3f6acf46865281439426e64348199839d84de5c3d2441a5dd9c75bd064c1385ca083cd1df6ef46dacd30ba7bc9797085a143f0fcdd6b0c7ffdde124bace833b758ee4ddfe5072a558406365b77652cb2bd1ccf651da71b0b22bf789af3d24014217fea74522e694c399bc8bd5f07c0db8fab186d5ee762d33a5debc1902bed79a68d8420d06fa2810bfcd09e53dad5f37258fa86f46560785713ec711c9f5ab98c631bb3e3b6c5a293370fec522d61149c7bb09bd4256e55a71487db84f95cffaefd2c4a3058c62c3e73695bc27a72c21d264daa0d40c012083c581e4a0dfc7f168b722b237a0ede4e40a7b352f38ccd532d1a416ffb5207d68c2b7b3a6cfd957d7efa5b71446ce84fba254aa25005dd08c988f4dbdcc3dc795d3487566e587f8f99fa6d222c406942f33c9a694d0a5b974d247fd6d4a37727a7eeb184f4139d300cb9d2264e4bc1869026d0ca9966cfa34a5506577dd7eaa826a1dbd86bf3e8ae5fe73cd591837a5d6075a386bea6701e431ace3f383154ebf64ff61e2e4b520bf3a723908aa855ffca926ec6b18bc48a7dc48b52b839507453def5fd2898cbce2c611ba2af0d2434a7152607d997781ffdbd8987c5b14b6f20449493fdab89717e43a14153845b97698e2511195a1fbb646bd896dad04547a95f1941a1df510c4f7990062c0d4fd794bc886625c783228e520fde1dbed723fc9779bef796e04307444ff32c210cfc2275da1aba94d5bd2b963fbd80dda7a9c8ff88271f152875d7cccd664a44c8d3067a4034b5d6101af80d9a2970f3443536302525e41dceba23d8862006a1893e47f69018c2ed81677b4c43016ddd24ba54311aa590562ce1ad6991a1736d972bf0421adc4a00cd631414f1cbecb646e0008529253e9c0169822efb33ce421d77953121b3efeb10cd44d504b5cf47a9807dacce8eb24d53ce62e145835b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d32ed1f9d70028c2001ede3fb28ac4db0b0215889cb331f8bc637d8cd27d4443570c84f2e19c4aa5a2610030e19ea4093bd118f72e066ba44693db5cef94f3905a6740f6b046ac8d7b77f5451a405975c2588b5b82cfb70843359010be8b7f32870641d3606bc050e0383940f0e25880e6b183b137ab86e3ddd52a0ea7024db44fc4458e5fe418d5a7ed1c33878563e44403bf194507c93079ff9105b433e6078faba26ef3daab055a97199108ceea0d3b0dfee6ef4f8ad55f1eca9c15771251d0cf33eead0be3cea163831560bf46c98931a1dd530301d054fad074fb22e5d6ad86e5f79ca0607a6108ef6030015ee05ed6229bafe13806894461b51199f5b3d2ef6d9024f2194253e89d0ed237b1903f89dc510bbdfd982b518c3576659cd39120b53fc4e51e100e83a51da1239f64947e10f158bc42d10a3b20a366b4311370e2e5c4b8c303383b3e579cd1196f3dd13db99c99a48397fe1df8987a58b942b02fcf424a1223968027d877793bf9f4636cdba3b47dfac921296a818d1b08821f45e5edff6c3c216a16d4b6539790325daae1a6400ee446c2b4fd1852c409d43d0bfb72b3c0946f9edc151873293bcf16d1360b340d7b98eda07f00b1333fa020c5b2ab0a4db4d0a259bc517898153957166f01726a25d2012da74a8fcfec104b6ba6b02f41eb730989a90ffe2f8948b98eda9bb5bdaddacaba1ac1877ea8c77247f876b27b3d89aa71714f55561cbdd0ebbc4b24d39b044ca3e3ef42bf8f63b8c642ebb1fcbeccda9a1e3aed8762eaf0d9ed97308e08e7489424c321f49af5ff24bc10f697dde29bb97031ff65fc6cea39036367972d5627a48c4f9cb8ec56d22a8f95b4c20b4a2545baa5879a817128101c28cc253f3a7a73cb74f0c43d609d08eca7f936f1a8a1fd902a4395ac8be7312d9eaf784c761cb1354dd40baf3012e85eadf3fb86959768990ad2c8625a553c4d920338ebe25de23761c085102555e30cb812643fc1d2857c220dcb944c423397264da353d5131d0c70933d72b55d021a519c3d7a9c5614710da694bc1e1b7d5cfe40931ce3f0e1f35d253566b238265670dbf08b30c63410be69245689bbfb89a17eca0f6c9542454b1e92ed9421ab1827a2f0013b37d7a0653c54a480e1adb20f4d6621955b8b41b7fc0dc7f66309c890258c6702ea0943d8a32748f67d8dfa4a29fd85282d949f1cff5faba27a8336309a4f867baccec1e6369b73bdf4b757c1049448f4bb3999ee0d8ffcf0014a49f30a2a2f680daeab96ba080e9436779e88da9f35f1df28aa84992e99a0beab3c9bc2858788c7077ea13728eed4debededfd07f1672798856c3a055a13408241a7531f1edd8411be59bcddf843f745850a77afe6ac8984ce9110aae0cd6008ca6874a522c58bc897c403a860cd5d05b731add09f9e24a465d0da6417d00000bc1f800f46d8c06a9861b5ebb82ee710a67a28a410942c343c5385210af2235887221563f3ead0d53f19846cb8c3345403ba3f7209d78da91196896a687824d8afb71dfa6f71d993f900470493108fe9db363bf82126d7af537072262fd8208ab0488b72ddc27a4f9dbb2c191e699746de264af70e8325a3a8040652d3cc3e86f8e7ead704ea80c6fabc0641fdb53599f2e2532b2733e93514058b042af10bd004e87da3ee9342f44b433ff1b8535e3f1928f927eaf8bdf52e31c589467317ee797d349e052a0edd93134d2a7c57ee3fdacad7f8e00de15fee3a091b2c8e51c87f228bd61350ac8ebe6922fbe3db9b1f1c95cc6fad66daca76115c222bee077e98797f7d5a383fdf3eba7a9d9f91ef76bca8a1f5e028013db30143acb3e55096b4d63a9ba75c34b652b711c471606219755a72fc7db90eca93c617bac3191bb231b7a7a68d58e125aada1bdc72c94363a3d8c1e3ff72da6102d37790dbdd1172e42327ed298ddac2fc87c59442d545b0ff476caed9e785f2bed1bff26b0333a6b7893cfcd6ddb8a9ff65313caf6456f2ad2188feb5ba8dc102539e94beba58707699d560bbcce83134bc3f92ffca813e62865f3d2d56680b0ddfaedcac5d5d84dcacf83ad61a2b13644eba1c459299b7a92a42c735c24fe9a4b2e2e9fd6a003c6761b167ab56948265b496cb7529b01cc4e53c3cd9a39384643996beac7e7e8c5b9548bb53ebf8bbca632e490bedf7f4c1de2fe41bcb746afd7380a6ba561610e880b38007beeaff985e007a1460051bb827ffb24970b0fbf79cde0264cf0292305be0faf22877173da64f6bb647b3a636b831df365b7c3394915ca6209d753a2cdcb143ba3e7fa41dccf5534c6fd36ef91187d55e35dac9d3925ac08e2c22c80dda4c60aa6e074cbad95a68215cc134e03ac7e516179bae944ce17cb54d086ea75184c3c36dcddad7c1a570d4167525f3f53d8d39ebaf2d239bc1f9e7572cbce85b1fa08568230c663866d47c3af0c12e609217ab0284f8b8694563933a48ae23e707c1df21527ba79fb2c6cb074d51ed0b90e361b2cbda0637c074415c3e4eb13b75b149505ccf56ad08a10df211eba48ffd7a2d0d42a1bd943dcc12f86e3e9052ee1ea8f6f1a8fd7b2262bfb86110b06210c25e7fac37b49198155c2471aad8190353d85860814a81887509424d72a79cef1534ea7655db318a424d6a036c7aa614ce9faa7901f55f64b0b0bf1c084f52e7069e5bf1097a9889ff9773079eb30a9abe2de835e3229d8c3cd6b00e936d5339b325684a5c483b15420e123c221c6faa48e432e6ad29d22301073d3dcd3dad319399258dae99d20eb634bd69867ef8695bedf1478abdea28e97985ba68b3810318e3cb12ef946594ef5447668e76d655032dad5ed688567ea02cd741c0f1684f271e1e6f57e70339d949187f9cc5ed830203c45863ffda2b704a0bfc77cd4cbaf3279e937c9415d47635c23582b2cc0e19d01abf7b442930cab1acb6b6d1c87fcbabb93d1ee778339fc75b0aa674b0b9ebcc31efa34cdc88d6209367d7c9cb38d96a9ceb0b51e8e2364399650074af6bb1098b22b21e3b9d12bfcf4ba0ee5e9c3cf8820ef6061d10c3648d73c6d22bb9a4502c3b263699d0ea24baa448b12d24f501412d09da75d99714c914e0bac941c2e9591a1af974b9d7ed718ae8c2c5246458375efb92aa04a645b615f261ebad3748d4e586cf4bb52da7a9c3a306113046efec9210cdac01dd254b6f9444d4186539c1983075c1100c45b2a80ec93371fb04da55a70d7e4064542210bed2bab603e428eba5d241504949b6d4c4f02b543fd709a15be42ee92b6bd37baa61bc2904832a15e7077176451dbb49a688cf55649c5637bab364126c473c49dcbcfb064b2f296cbed17603820bbd3a5e93ec52e82e67ab2760735d2fc915122c09b76fc9de21fd95de63f8e5b0276a7fe25efa62bedecf69ceb278c8309d1c5ccae18338cd298c2ce4780f31255dd1321fbd0dbb6f8f64f321e0e0b665130b8a0379aaf5aa6bdafe07af1312f637e3911b8d18fbcdee38fc22ca35094f912decea24e409eec05550dd35c62be25a1612ab90b268015b40eaed9fa0717aab769e193b2d7bd2a55e7e715c64e67d0be4b76086d9cc31c11ec35caeb68634eb554ed5f55ec45727a57e2d8d6914f6d2acffb17b9515d347ba045067502a0b14022a269560e0d95cb168c7097ea8eccca5aecb328a24b1eda37bdb600fffb212178ec0923744a6402d58d7d738f233ce9b64b6a9f1dbfeec1505db36c5a06eab73142a86b27dc175155cb30310da6295a7fb1a7fd6e4ef00c998b82ab8b3300133c6af14e5077c26aa202e6fc5e69a792012590d42ae2694b82fc1efc68ebf7b5df2574cb85143f66a0bc2ff2a9811e62cca6fe559c14e606a1c9ac2753af2050d14b924dfc217dbc5b9b44e89d25f35314db49b096287a77d1734d0f8f8d168467849008fc52de08473191d53f8cff9c54059406398e89683d41db5ca287bb379e463c7df481005fcaa51f86223229d9aa3f1dc10b0bc97f9814eedae2d1a0d48826da8fea991d14f1358e94badeb070719ef7e1ff2021c1cb5acd297695c34310474feb95e86dd6e211cd2e6f65ced4fbfff3817ccb8c25dae508502d4df393b421e7f92dcd88622e35e35994021fd95c368ce30d455831b8d7b5431f33a73278cc9567892bccaa9f0d0d4410a411d42de63d1e2908e4ebbcafdb25c1a4ee00238cdf73e322686f01341d26623c2491c6340204508a421b5978d8f7f698b473aa842dc9eca0e5774a6374ed583ce8605795f084731e95e368d039b6ac539d614882e89471f99ad0b367c55273a7a4a3dfff10ea4c7816a44c1cad69137741b64deffde56148294271b50d17c8ecfec51791fde88bb15b07ef5a9f0f13b9ee20cee21322f3a6fd0783089d9dd32a9344cb0a89e9746bd35c0bc36f37afacb5e35fa47643df9b11a50e4f6f2c820c284d4c147481412e5e4945115040df81511233a8f81e4731205cf0af72285f08cdaf87f9cda4cd3c7c7d51bce592ea15d692e2a1700f5467da9707838a1feff9c989cf84c7b2a3965f146be7fadff1b72aa0338c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e8529585eeb7d466f7e38b980536e62c00fd3dc5c703c3bbd721c9491e6eb85c32a44a4b8c95221524a3c23c6b5401c00b5030ac5fc9d0a0463ad9e34009a00ad426a782939a3e4f8394ef0f1c9a8f811a7f5ea333cadd30d3404352aedbd7a2a743020670a8d1c3fef7c3cee5b34ea05aee62597374b2d6143e51039b706bc660f371ea75d41bd9ef4da3a7a5ee404600a4880f8915d2a0d4943210c8e5e71277e7fb0a75847a0e9f3e97824f457206271c9147e2862e8728b4d69cbe84e785d92608878e367fea06978192e6e69d4b8acadd42ac1133fb3a9e9e1dc50e281254144a0fe07efe8476c462860a01a5e4180a4de0249f05648c23f8e6e3bc49809eb27d2c7ee29fd05b5cab4d8ea4b8868446d4562a8b2d6f182d818b448b165d8497a72c623880702eed40e35aadcfcf6b09f67040effbeddd2b22af32c2978da711f60d3a60f115c98e714b9ca80bb1bfbe16704fb841cbfb0bedad90d8ee5106d2178980cf59e6836eed32dc22ec231e5556dde151c0081a83bf4389916868f9a5c9eb394a00dd88f01a451ade235d634484a9c56c595224495874fbdbdfdc1e93220adc754722bc8f182a697c43e34c44782ead62b2b4d01ed046ac0d7187fdf4ec246361396ba03e69055b5347faa6c1cb9929766e4f2a7b41911e25448678f4820e4764775b18b4c0668fa3ca1e9183ed8e57c30c211e97e7cfdc685e6c082448e0595ca52e08fe5b0d37ac52bda3dc4c8a0b7d3e9d1812d5530ebcf9df0ca539c809855b617cec1498a8e2313908d070839a80574b129b24245eded44df2d131e43dc9142274e0b70a75a903791928a1bfcec374626d3c6136c409de439066c72ccb9ad0332fc9b36d3a24c6173a23014f684d0f1666b8331d108ff33986354061399848cc96c7a631da2855f503865eb732fd4e5c3976571cde050a1777e67603fe0045e0a581002149e02f12f72a340fcd78d5723d10b6869cb54bc64940dc20e2c4e3989890f61c5b1df09c72d8a70b5e5a161c0077f73c816b17f59d9533c2e6ab0c7a26dd2cad7646133b739b24e20159d38cb2e11faad8ea174305417860ff18be0bfcefdb413d281ebc034b8b5f8722b041e90ec772e1e9449f61650a27e810f57d102788527c3e274dddc99f094edf73a09544cf3f162573d6da4798895daec9986a41222047ae0d3ce9b6d84c6e91ff5abd4296b1e777b8e22b077a6aea2e843cde25869445dce969fda78091938b3cfdd6f1ab376e62e9f94ff0456171e270fec0156069e8006f48956683abccd1427e3ec9df93abc4fbee9170e9ac11dd9ca793e7d4ad05cfe205d6ba0969f8e965d571cfbf51f54a8e3317b795c76523eec774719d38f8ecbbb192bc298fdca9b0a9304386b0791c671fa441d2103a8e2b2f015072895fe33d26bdf621bc4357610234e563f1f6dbf1584d21aac7bc2a1f4c8869fd97e805ab0157b6325650d1e03909ae85ae3751e582cd823db5394add842eb339426c7a1f44fe90370fb00c10664c8f2c9515800831c45fb5248387358534d37a9b2bc6b9ec84bbcda7f2f8fc16f848423e1dae978e729d4886f44e1b21418fc96c9b11246ec54148661fd7515be3636f5d3fb5e2723cfb1a7253ebc10064373d6227daca15f68a54710eea722a4c7ac9d8cb34c289634b7a831c0d58ff0c5654f9edf692e49403f40a9b1b1bd4acaebd7c2ed9d02378c9a9b763a41b5a85c0e978d30601e32bfa02697f9eab6f756a1d83440c49028baa4607d4ec080ace306ea6094d615cc220736fadb0bddb33b4d7381d35d265c13e35b0d829219ad12e42d1b56bc54f1fea860b18d6440a9c44c56c41dbadd6085d0e3707ee4eeeb4e3410a8326cab9ea1eb95213475d669589cc8b1331ccc7d65eed9559e0ea0f5bfff13843f2b4a2067c577278af1558bddd481e153602c11d5c81a424e2a1e946483bdda59d530949954fc0d7e42afce9454b6faa5b7575f6fa1d2374efafe1363b36df330d958bfa12b5efdf7d274943cf6dd8c5448e3d30bd0d05afaf86a2d30c068ff63e9fd065e1f84362827c46ccb49a8ec04049d1e04db6f7b88c193400ee5818956472db1a5d3ab044e18f4e918b2547eb275d8910d103c13a8704ed2503421465b1e68c51817ae25727b7b72f3817febe4ec7451fc241d7794b8a63f1317707c329bed6bfb2a0023bef0917a4f8944b2023efbe2fe3d2131c41ab066ec2eacaf389834b55ec862fcbca7862a3addeb9a4fd147bd07f480464e395013f2599efd1c800bb1a8d30d5f57f82ac1df5056e7ab4b9b21cf69a97916c8a50072a9fa50439bf52d8ca7aaf50f5bd9591a5422b079114f0bfe4acf561c826ce665878ade3dace990e64ecfb1ba367f4c3c0a61d4aa1dad084d5c3279ceb5a4343f16894ba217fb7c1bb67c328dc7a5834ea59c48d0db9f4a5d9ad304bc46c0d63e2847067350555940f33ffa238dc7137ea04ecb81d9abc5b068794756c4f812d1c5af309231bfb4b27281eb33f8df6c7152ec14ed6fc9a8a644e174ba754247a7319d29a2d250be22ad5e7494d649b11898276a964aafd01459781278f83a80e6764aa6f07eaa4e22d1741ed853c68c6ab19999edb739487eaaee49b05113ccb3c725993fb28e76ac53f00b9ed3ab5f6912e0786fc1138fdd9eb43b407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71d68496b94fdfed16540c30b13d0d7e65a4ff1bb1b73ae867b96e7c912b00ff6a0ae752dca9264748a313dc53b63231d29e9fad3bf5e6ec9134177e105125ee610a1f9b915d9b65deb6f9add45e7b03240fec592fd59851a1fced2bf84b59977cde42db08d3a2ae3363169cf1de0faac09b586e3da4527c94f3e773341a31864c9cbe171e9d2dee147797d4242195bb40ac11e174db2328fe1eb75af660ac3467a41c20b10ebaf33b287cca0bd628c8e0776b9bf95584947c130993f4560f6f01a417c3a364675ca3cb6a8235ce24cfc39325150995dd367ebed4e2adba7efd67f631073311641d31a868698b9453e88b51df1f6dce9144da9ebea27285a1260bd849ef59e925c176159e087d784b4c571ff12c63386066a9565234ceabc1d14242383c5e1385b87afd269b475a6fde0ffb7bd90e239d010036426a9102aab37b5e7822263c75b2709c939073244489a929410cd8eaf39549a7f7e39808fb43114cccaaeacc16d611dd34b249acc4f8bc2276ac510bf3052b08e057425c87fd10a6c6f7979f5044137535fe3f4335ab4d53ff7a251b2d799539e0852b557861591858ca58ee54562ddd8ce1604479185664a744017e539e3a7737b7eba00d76750ec72e68159e3a59b6311dca75e37ce70329997f97069f11df50dfcfd9f0527d72a5f91327ba5470d80b2854a57596101f5dd528153c8e07bc10fd47d0ec9c6b3ca84536e7b0ef7109b756252405947adb4dfeaf4712a116940f296667427b1c3451595f904e1bcc1ecaffb327a9375f9f09251fd12a66f7cbd6faf86fe9024394f1eb3df27c88e651042254b623a6d4f21c9d4ff62f4819dbe9e6a4ef2e243a664589311423742fae46323f94994ab346ac1582f51747493b32611a563ad057baea8cd9643b8d548fe547146d615bee842aed92fc83470ae7116abdf4ab1944e02a488e8df0f2c1a026bdcb1c9e5e273773626b603e9c7ff6b9bf0beb5a573c6e918efa944501d59226cf102566661ea103bbe11febe431a1ff61e7c44a9852e25b13c8f1bb89f75aa4f297f36eff83fb89c7fd7627643fafbb62323508202f6cde95375caf3e05b69ec9d53a3c3d46d2c269274d4c297ea4c1849854c73f6f6841ca230369c180417f4a65f648b88e8a5dd04c309f31d09161a0207dee3469783daaa9274a0ebb267618be37418eb65bd822d1caac9f77229bb6c60962c515e8b207b02674157f4b2fac359d2595191b18223ef8d7a62f203c30dfb407d3017a45f5b334202ec3bdf629961bee8974b2e756e4c7b638ddcb558e8b8fe0e802bef767d681dba2b2af833aada512c7f867dbe6e01b2a7eb49c7b6e50bb8d9e6cfa8ed1321b415771d5535b817beb8831160ffb5f256a040d662f90742d2be25580185bd09edd014de26223b5f1a82e054dfebb79336d891b767f8be214f88151b8a8ed8bf99febaa10c51a9b07f80b130f73cfd4d1de282f6d7f5ccefcccb64a4ae407d0c8e29650b1c0c1c00c292d0afc5ebed5da7e7a9d0eced3c6894548043aa537407a69dfbfe0fd4dffdf896a363d75ac5707eda016347a63abfaa6435132d554abf826a19340bd0f7c5984343cb49e89936f55f2256bfc32871448794ea44303147839275ddbe891c2ce4f93b4e51ba2a2709de73de8b659f9ad0d8a6aa8e2f1c300418e07035b4a39936ac69772520c167ef33f576198a70bea1a3e6a4810868fffb8bf70abb870ece4fd40a2c286d65a1a768776bcdddba218f6854236270d550b0acdb1e87c0a647026b5982426dc8bfd02bbfbe5ecf33fdef0b048ee02ee85779a0ee900ad2e02300ecc774f73ec419fdd15546141233308dd4e05e0bd98aef19726d7d2749d8f316b798b87ac700de86806c0586e96d5fa35d908728d9a044cfc98d6435f5a73643ddfa896ed51671f0a76359ad302d329a7d6489c3cb77d7a563214f32cae5c3ab5a379198c36ac46ef0f151a21bb0db55720418ac16e2487ae411a37a41f7a086824b2efd39c94b3494efa7c1b708e360b380cd65c6b0300db4259152800ab8a88f85e276b32399f0746cdbfd93182863a850da4404584a8ed17f70aec3cb4412c17b854cbeb6e4ed1e94d97bf16f7b343ff7b1c0d02b11555ae20d30819e6ccccbb44b7538770c3aecbe7351ded9dff5a0a7c66c2be38a68a4f8d2cb06766b1cec3242cf191ff9ecec987893588a89b042c2034534af2f0c4e38ba3617ddd1c70bbd23365639fa7cd5f191861c7fbed74a809b4577184b74582b4774b8ddc3f186fdab84f01e0f988b74bacfe932f46aa7023309f130f7d93dc434d02fa0318a7a63dcb6fc7a8cccb8eb8452ee3c1cb6540512a78cc5ebbb671f9ad9a244567471923ff0a04fb615834380caaf01494ebc73ca0d5c640440be29f2206fae788ece44aca654e36a2ea1777e93e939111387068eae8a7ac652da78f63545288ebe0eeaa2eef9ec82ba6bacc11acc6e110d82f4a1c698336cca9cda4ce660b4873e19098521277c6167a5090ebc2df903b9e682728b4a3ba320237b20444e34f94f2c8f9d5e0173b28a2dea1a88f7e40403b113752a6f9aa0b49ca6a5c34a2b92b2d2bc5f480ee94faab28f01dc0d7ad19392060a4f0a8a95ad318982f081ab3c35895f83a6d4611d888a1a0d0a8ac62075ca703c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416aeec5145d93ca5215998b118cd43fe6f953be84cdf704bda68dec68fb14c3e6490399277cafd3b75630f0b826e2dd6d287a161cf892fbdd889e0c6b19cc0be4bb41fcd121741e20510209b0740cb89c118f190cae98339b07e65df9cc9dd126b9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712122d254e33b7c35d78ed4f76db5578f07a6c1bcb7dc46199c567c4a61f84c574fc4ed042b0f2c8397da95d7dfafa615f163ee77de3725afe64561d65a370b3430bc9746fc125c950f425b970da866f8944bf368a765eea617c7ae949c214c405a9250eaeb7dff21e3804b3656037370d9b2694a83536a4e924c9f3dedf1ba083962d04439175a2d98c3e54aba79db4b5fbc425c1ae4d759878086569d2afcba33ee7757f605a7b0d7d518a7751ffc17479ef2cdbec637e4bfb3dad4d8993a553d0ccbb191f4be4cff5ad204d9ef12e321d851b431a0487b9b00a71213f2c95a3e48a1025c18a4bb04dbe9c259e0ec5a57863699f0eb5efd7767175b02b9bebf4eda442aa4ea276a4e1cad5e196a6945f4f9feb7e434a747a9244eab3dce1ed9534262c8fbfdc245ad9dcf846980488cb4d18a79606fce942d48063f0455392e5d825f515af082f6906036c246bb7b1f3b75d1344466e45c96967f8cb73049970c100538397589fa07b331c10ff03ffcf5cac1691840ba63344882cad3a161b135fc74cd2834b4d7d555117ffd19bb23e6ce26d31a3c34bb5626688c2388f32937ea6edb9107df7695cf745e061c1c8b98f078d88f50881eda8dea89dc75b6633f1c7fb016c01016f8225393bfbb03533db594d4e1f289484f7c5eaf4babc9ff19d827a1b3dd1a3cd1ff4732a3826ac5a468c6464286aca145027df161442843522e2ea9f89b72832b1d5fe563cc115c44ce2ba0c383e5d6824f8260f9697397660eecf2766560b1c77937fcec07555c995ffa2eb97e7bed217c46cc798a407a054e3e8c342de20d821c684b2529a9260b8c75b32c9e0232f6870db100b286915baa9ddfef29ba03584ca140af25d0ae285191427484dfca3a722f8729a0c76d7fec1a9c987bfb111cc69796ebd1976ad4ebcf4b3560c1bf2662f77a10271993092016aa2a13c0e05dabd3e3754bbf0e87775ff06bdca2da1382448fbabfde07755a6313b77aea6326c8a3ce609b67aa4b2de89a10da711cc35cf593e91f701a0fa8e27969e0a4642d03481c477ea3219946b9e8b8b1271dd6fbc2da017b45d3210095667544b271eedf036d8b2ffe8d5f903ac79718d2bda2a14a9fb3cba6911012d8f0e3c51c77bd269f51b501bc3056358b894a4efd94d6f3ab31c60a2e6d42022e0b1f1daae90dcba1b96d681a018636a09bfbc8381cf40a502de14de2b67adc4b5aa9706a54c576dd1caad7fb29bdca6dbbce5cac2eb1e65d89633e3dfa60aae7bb0cc818fc18b6ffff18592e8e8671eb94ceb0c2e15b33f9f54415cc9e626a339aaedb6cdac744b85af70456c65c9025b86a7426169cda4490dc7f20d0220467f6af1ed61d0b39bd7cc4f9e94861a28fa6f27709921625b455c2a5981634b644f122be630c593c15b16fb21e9cab0fc7b0140c981652059d2310ea20e463dc56e7b203c1dbcce46929b2013bff2270b86d4951584ef7bc2472febdcca611282f3dd2a3026e65945ed13d52e629d6d6a120b1f6442b75e0b2660e0f05824ce468bd570a388c6eda0d4b98552d27b9aacca2bcdf7f90b75243f624e0181f20683e701c397f4118ddc67c11ade82127f6d66ca2b4137aa4876cf62bc50a203954cb3460a6f509b816726d7b0427c7552a24e1ad207087af15ff6e5619ec37622a69b1d98b990ab979c98b9a66995d1665017790168ae8b5dd1608ad0bf62c35c2ac54ee3c95f27faeedf474fcf1fa50ca27f2087b110a88585c255830f56048944d2868c4978492fa514359fd3ca4231f9a3b7689833643ca183622e8cd9639ead81d38d3c3ef6a38a08f0415e8f2569d4b698449bf2c5ca74346454838e92bf4ef4200963a061b35007b1a77d0b68fe244fc7a65c339aa06f8fc468150d649eee8dd05156213b4b376830067601b89c2f3ecac6db895a8078e65ff80e7d04e60ab0ec43fca15dc14d5312371e0b26d5cf58477961dbd96fcdf2b31d78c450fdaad5e9bb9248f6bb0cb58946f2e01dbe23224e6af11e5eaaa5b6d43d700a8083e97f57984a6c431796df3d153e6b310d25c37fd451bb16e2ed028aa7b09e42e10f820389a6e253f09f99692ffc4359b494a30096a3eb8a5b97c3aba02933a37cc732e055d41a2acf695dfa9d59dfd5627864efeed20c24ad2ecac463db3c12b4ae5233ea7370c02412b04da5cecbbb9154f804dc0c8e74e2ac9daca31a3b872cc38779f9c7b1a6ca93f2c4f6d04a6b0f3e699c8a40511a2e3b9fb7f8972661796817ee864c2396b7b2a9f349d959b6fae1d66ec9104ff9c942f030e65a8aa546173676eee3beca7af1636aca17582f30829782e2c9b1b9c72aaf8060563ab378657bf91d13f2dd4f1bb6adc1d6da398e1d9b2a4884c63631d46aeeac4ca7348887106b8f07b427790d1cf4a2713ad56af6e1e1629ef93edf14348535e50013d4a33f70273ba18c23050e010109645dd600bbb52809754ddeaf668a72b443d63901a6c759e4cffd958b68736a9a1ee2ebdff616811e63d43b100947549aef12a6caa34d62c1fee27f253562286a466c2b2f91a711cbfaebc527f705bc8bc7351cc7bd57d0af9f150e6466174f1da6ac71c79a2a4df82d44f585a3865f7364024c6f9a7ec7442cd32dc7566e2531fe4366ce5e22aa6931f8d2cd5f258b334011fba79242837b662646211a788b62ff54a6e9bf54761372954bc5b1503cc1b49403054b96be468c1f8b22ec177da74fc851f7562a10a49417b5b6a76168f52931be46aafc2211ceb98056a1bd1102545401d8698944771e079f3aa93974eaf9960d6bcbf23b14834f0d7034f8d5e6589e4a7f13f65e72705884ee8dcbf1360274ec269f1e31a344f8884e5ae3450628689e6356669e7a94e43ea1ac65578a8a21d8cf64b22197ab966b1a20a098fe08768b0f5e53e25c71864a657cb42ea209e757e475ac343e5f8f85b776ea6276755f5d9069447d01bf34604c0389a5a80b7687ca74dd548b3c5d98e4f70c9a85d29ddd2296fa1cb8be37e5d8701af88c70c55baf0ef059358fb8506ab8dabcb8642da7052e6493cc40a035dc86b8d5c88164976f31fc1f72c9a86eccbe29a1060e2a5b0d6abf7c452613018b69e8385b7ab509e460dbd802cd49164665229340e29a14dcadf345f493f00ebe1d829515c6528b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d5e8fcf6841f2e94ebd740f848a2b4e72c31c7a21aea6ae8917400c81d43bb522b64c2aaa0a1986e68954e4ca7b5784088392fda54f4dfbac75e454458e01583df2218fc25708efa7679c23d318c33cdbfce6be7e9125002352d34948fa8b3a67aed933b6c623a04853e8e76cab3219c59d5ed56410b366482128627181b5aa4eceec7f1352a57bf84ff4eb62099a8875cc61b06d7c3dc6094fe96948c881c60eea50f1aa4ca2c2c57af4783c613dfe8392229ee5fdf145d7506ef3d9e559246558463ea4005ea0f83e358d15a789493bea81664169d09e26df8e8e3a2361e6226a54c73b0bb645b846c9bf3c2883b4936fcd3f629f9d24086d9ce4c20cd226199884cef69623c717e7aade3c1f270584fa38cd0d9b6a56045e318ec49ba8a9615abed39d47633eeccd98be10042d5d03d852c5bd930a89f0ce256a9332521f287c5b3a221df63628851acb241908838bac9774b28721290f082f7b143e8d102756d8e06152648b0c9f937d26c08490a5752ece4b16ced9ed97d75143de35326b6e46ad517f13ce464516302d89289478f09e15905bf5d8326d95437860df2f72c0d2cc0f3c40972b07c54745de572f912a58b2bba9c42f105f09be83e69491690a5ef93a98dbe72b55880c843da199106393fa4db8a6f659207f6f419b31a678ceaadcc3330cf95892fe9ec136744640751b38026e009740867b10de8eb67f15a03477bcfddddd9319bcfa6de112cd37ab5040bc19e0b3a52f039a6ba60d2045f834a3195e89e19ae67d96b45a0bee0beb3ec45595def5f6e8fc37ba73c0515e6ade7566e5eda3fe184f22a89211634ed256471c1f3e0f3ad64717fb58cd0a44709a330f39d5e8cdb773ee71afdd2f9d57b44fa579937be3aeaa1adae3b57d047ef28d1fe4a0ee885dea9edf31e01e23e896796b8fcdecd44b4b180dc7e02617563ee5edebece3368fcbf345b930c92fca7072eceb55222b960c5f7e0fd54d58b2a296fc8053d12508a47fa99f2cbd5b7fcea38d04fb896e5421661613af2b53ae7f9cf9da7141efb199d0830298feeb364ff4ad75fad31d8e7285e6d63e4c3f149c65a859747611e99d8cb5d06bd5eb20c5121ccc64e431ffb0c6981f059d02a6924cd1ad196dfff80d76bf99383b20bee491a49cbe9a66f16ad93859533515ecaf1ce37791cdfdcdadec44734ab9a4e4d16a25f18d2e207f66037bed355c32f0b6a53e8785a5b3392bb92c3a0e904b1c0e100735390c8676dd2da11747fd6014c06cdef71226f89708e71ef9c6ab3d95def2dd7f487e42efa411f4eb05a33bd833c6d57f623b8f0c8ed846045cf44fea32bcbe0bc04e118f3922c6a45c890e469de71ef3008558f64ece794dff8660ca2d18a49e2e7b3beaf1e6c903da7e0e8af4d2400c18023b5de425d219f9efcafb72aa555fd994cf9f67ebeb5de47b6a84256e12aea7e877a8b9b5cbcc01119aa6a8e732f551d99dfa4fc239739c0c1d9c415bb13419d4c73469ba912eb7d346b91629642940f117e1aa50a09fd5dd48caa48fe936563f4a200c29d77a80f5657781f6849373684b82a029b1fa3d2c566173676ed7bb07c67c2bc80e7d5ba4623f8ef0d565d266723ec60497f0375b3bac140000000001000000020000000300000004000000140500000006000000070000000800000009000000140a0000000b0000000c0000000d0000000e000000140f0000001000000011000000120000001300000014140000001500000016000000170000001800000014190000001a0000001b0000001c0000001d000000141e0000001f0000002000000021000000220000001423000000240000002500000026000000270000001428000000290000002a0000002b0000002c000000142d0000002e0000002f0000003000000031000000143200000033000000340000003500000036000000143700000038000000390000003a0000003b000000143c0000003d0000003e0000003f0000004000000014410000004200000043000000440000004500000014460000004700000048000000490000004a000000144b0000004c0000004d0000004e0000004f000000145000000051000000520000005300000054000000145500000056000000570000005800000059000000145a0000005b0000005c0000005d0000005e000000145f0000006000000061000000620000006300000014640000006500000066000000670000006800000014690000006a0000006b0000006c0000006d000000146e0000006f0000007000000071000000720000001473000000740000007500000076000000770000001478000000790000007a0000007b0000007c000000147d0000007e0000007f0000008000000081000000148200000083000000840000008500000086000000148700000088000000890000008a0000008b000000108c0000008d0000008e0000008f000000109000000091000000920000009300000010940000009500000096000000970000001098000000990000009a0000009b000000109c0000009d0000009e0000009f00000010a0000000a1000000a2000000a300000010a4000000a5000000a6000000a700000010a8000000a9000000aa000000ab00000010ac000000ad000000ae000000af00000010b0000000b1000000b2000000b300000010b4000000b5000000b6000000b700000010b8000000b9000000ba000000bb00000010bc000000bd000000be000000bf00000010c0000000c1000000c2000000c300000010c4000000c5000000c6000000c70000002b000000000000002800000059000000020000001e000000" +// result := "0x01210350000000fe0000008000000096000000d200000000000000b0000000bf00000021010000ab000000970000008500000051000000c40000000800000028010000a700000032000000e200000016010000bc000000f9000000780000000c00000088000000f2000000ad000000260000009400000046000000120100004d0000002300000009010000cb00000082000000750000000e0000008f0000002f000000f8000000100100003d000000a000000006000000c90000000f0000000501000065000000540000003f00000098000000d600000047000000b7000000df000000380000004400000007000000b9000000e70000008c000000900000000a0100000b0000001901000042000000af000000020000007c0000007a000000240100004c000000010000004f00000063000000f0000000c7000000e60000006100000025010000d70000009c0000008d000000e30000001800000019000000030000006a00000003010000ec000000fc00000008010000ff00000058000000b10000006c00000043000000290000005f000000fb000000a1000000c20000002a000000be000000c3000000600000003c0000001e0000004a0000005e000000200100003e000000c800000093000000ed00000073000000040100004500000009000000d50000009200000076000000110000003300000055000000a6000000fa000000d40000002000000086000000aa000000560000007b000000a500000015010000bd000000b30000000a0000006f0000005d00000005000000180100001c0100001300000069000000e500000028000000a3000000d30000000b0100001500000079000000b500000068000000350000000d00000031000000e80000005b000000260100001200000011010000db0000001b000000d100000059000000070100003000000016000000870000002c000000240000000001000070000000360000007d000000480000009e0000008a000000270100004000000057000000cf00000067000000fd000000f5000000060100001d0100009d000000cc000000130100002d0000007f0000001e010000b200000021000000e900000025000000ac000000ea24d73b1607c8fd7d6542870c2563c7891a9085b74ddd253d4322a9b3d3d1560600000021034a3487dc0c46f976d352e5e152e120d2d23774f921583d1f2c128f7cf9f66529d49f031c94d9c3b33494849eb9682c0311b3c283b17373f18b9ca02d94e2c05c969ae5d9d6efa40c6255ec4b27b0a4752d7f4068163116e76cd0d4041c471431e8c13e37a4d00135dbe7699d91507f5a53a7b8ed36a3be29cb2fddab9f7a286c347964127e9d8bcd119989a92646c80886c2eb8440c87dd7dd94437873a3ce286432533fdbdd1a739c62733cb36ac48c821dcb0311978f1027bc1e39d4c8964e6a6570b80ba0a90a857ef4ebdabfbf958898bdb12ea1edbb17eb903b00746a14e059357312bfd525317b4f93e5eee1de639872edfaec9d2a320a6fac04d6105188fe28737bdbfec193327886b5c4906675d2a49ed43fe8cfb4e079698de82d2d042cd5a9d8624860310a963ed20c4192a19a9d163bcf366e48122c00a1e9744c5cac0ffa042ee550a3bf70d380dc032d11eabe311e0796c5143341600ef626644eed0663b1d15bcbf9e99c372c041ef118de7d179c68899a645a0fa0983b473eb2a1fefc7a956231a446a575db2e31f7c084c2945094f3927519617d7b913712c60cc4d544536a7190ec68525a70fde1309723986ab984a1e97aca4092ad721c744c3b91b676828a5f884e79d9c02d6f23ec246c3a1a8adcfa9dc1e531a9a5310e2d777330aba66c9558434a592fa5e5aec49c3a70f49f66017f194d41240d66148f2b835556a0c8d3b51ae0e823655bd4aa20fdadc6b4189de9f32cf2288700d8eff37aca87eea6637118337fb1704bc33f1fc685aec019c8e9eec48b62a728a8cb454f4e75ed6d28c458cd8df1c2bdce6101e09b650fe22d139e360fb809200ed18130a0ed0513b2a2bfa7ed6c9090cb350983746b1936c6a92f7304a7005450b1f33df75af8dfeca1cd7e94fcce445c6d55651259fdca2972a4d62f6732561af7dc55da09babaf097d1304b4cde14562506f4db4897644895324b542d8f573c39b3f67c487c1df902d0397792b7cdf987b657b2d27920bc6846eca466c155c4b778017656b9a7d69d3e69159852f38adf971f5a25df65f9950e97411c1c36e8bb9f2665b217df30a15bcd22f231f66f4f21711363cb0b0da8b3594003ae014e8c22d93dbca83c05bc5222ae72b85617956f04eded477369ec95312c7c78353256f3f643ebc6300f32561a0a5583813bb3b42844d1ad3d3779a438771a295e306daa91a5a25590d2290fd262d40f239f87d37e1c03a2494035a42961db2f33407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71482cdc214f825dc7085e54a984230a753d66d08425f9763f52f8f68911120260d4d65053a5ef2ab1152c72f3b15d4f24d4bced3b7e277735eb49450dd867c115263ad657e55682de826f6137dedd2d246971fd8c5d318034940160fc179efa63701058e68510bdf68a3678d32145780e13c29b88fe77b27440bdf3ea9762a63964675cc62a59886ce5fc12d2f48694c7ac836a0157e0e6630d694d11faa605034c51def135330ddca851fcb670c865235dc1b405242cf9f7ccb728e449e09f4ad614110699b5642a4b726cbcb74bee77642ec7b4f17b06db88ee461848ead17c906f769166b3ff9b0fb13c1ccb36358d9dda3f25bfa18e2857fe01a92328eb70cacb5514b570b9338c8602cd4a49128006a902494029c2728056b02a900dcc7798b499a9c38970f6f3dbee7e6220ee0e12a582a76ae036347816baa6cd7c9a7b9662caa1a29ff92ad66794001cfaaebbdf4071f4db6d74ee767ba59cca4cb36cac6854840b7eb103ce5723aa0d6625709d4c4378c46903ff236d9d8d61f21f76b22d6245ef2ea126366dae7f9c072d2d6e0e71a54c9bbafaed36448a4a552b51f02a182d14b38906ce1f4693cd9b87d0369e6af514cf7ec91455b26cd4c0d71bc2d3f9f9f499e04d2f27dbe47ffbce115afd1bac9fe116ce7fae719325e4082460c09defe1f43c8591655101dd3dc806c7b07762c97ad21e4142705e46a1e17306b888519767218eed7b884fb221f597a2d4edb69c094961ace2e65a7e40913c0658f8f3a64ec6949a26916ae2cd976fe531947a9c9e93e6d587bac746cb0826e4b23b64b0eaea19cab0333369b93e11693d2b4334306ee579360814adfc1339524dad3d2adfad0b2db5fc2de781a22fc63dbc4e30a5fcba2c63c2fcbda238668e06587bec427bd5b5cc33da6f7cabaebcb7688de50b59125434493fadcaa94d1e0560d2b374b7d6e1380b6b88ee8ef92cdde7edbd9a48d66f5e219840a1155818b9272f50007b87be88422e3da9599286087f5e578c0d1c2a3db9a77110f9173a69e0e58185dd4e76aa52804b2de15ebff8c3f3237e29dc7157e61b30b9b00a30f93bce6916b6b78ce4f7d550c39c7947c6860502333717d541fdb6697ab447aadd01c0f366ff1c65d331da120ca3ac630ea6e8d7339e7317518920d710e3325edbe8dcd591d30511a0fc08bc5172ff58ff98fa848387b25f99205361348105f6c138e9e4061b3a799bf7987ef5c820c1e534df298f3328e1093c5d0758d434280f6162242be89d139d52f449e2bad667d7d974cb80d0edbce7237185b11475fcd9b0171f73154a0734c1cc95ae552d9f3180d7d64e8b50d3837b14b5afd2221808dfb6c44ce63a08d4567cef4b2a9aff1b408d2c99fa4adef25724cce85368b429d0687fef75f26e5503379a61920777ef1f254af024922e382dd19e752e69784ff2911acf10ffcf4b1d795df6d8b55f38eceeadffe577cf5bc0360f35005940c73278b76425a158be63207452b1a8018f53309f47486a273b9bf60cb51c48d67770af6f19ab75537f06388373ec17a3c88ff1714806c0c99ad44e6dbdfa713ea7825552b7f76db8f2ba2fce0e546d7e7abab7d59e7afee2bfe438bad6091934cc7903dcaaeddb2bd99fd6b36ab15fc32ee001bd1d95e87020019f7c88be2e74afd1a3a66e44e8b7845e7f63923b706dae49eb96cdc73b04c9e6cfd1459d06d6f02e6854e6df29f08f7e015d511ff48d7bbb13bacc9aab1b06ab73c1f3350ce6a864e68dc99758ce2920256f75bdbe8c918c556a5a2467a3aa13a306808740484d1bff4961f87c7ff6a6a68beac9264665f87ba1a5fab9802f1cd729391a718a7477bdafa88e49f5c8cd88fbcbc1724d8e227935eabce71ec303d832c4ab27aafd3f8056d3462eda0083ac22241db692c4671249a14a04c2f0a2959aab412660bb493e536e83addf98be8cb2a0158cf18c6d5ba06ab586a2cb56cf1ad4cd099ef1e3e727f41ebeb3aea2815f004002d27714db121fd6f92fac8bedbb97160976c4d221bfc6da82c7055e469a1405eca842b4b8efd101e984a2482e526ecb085229a5a3f09f444f6d39d71e0b936cfed125e87883db8876444288d0cbd17642ce97b61a3cb7d20f9048830a34520de889098b4435dfc79a73a0518ba9f61924de365e70f8503654e384a4524c1c16900873792541ef023019a68f62250b7c219a149b9b68af793ab31f83f500126e0fffa71469e78e22e754f3b49db1dbe631f286ac449dbc94282864e76dac48fb9bce48124189d2d45e2b2e16b8084c022bcc90ef1acebf194c7b9820968e554e2ec4d34346eedf80cacdafcdbf118a3f158e45e6a8766869e2e5418499d3cfbe215762a4a0cffe4315edea5ef47c60c163be4aa5196c5241f5c772f3f90c57a3580fa0735a7340e37372048c1f60a20531f830d60634a177f3974d5399fca046417a6e4327c4c569d8f4f5b47b263b0f07408b1d453ae31f699e53904605cfdbaa72639138cea3e544258e0484a532216372ca569751b32be145716eac8ee5e731a1db2b1dae4b9023b05876077cdd78084c79e58d16ecbaecee3965ad4685c1780154b678bbfcf725fb2e91be3cc0864ba0f682ce1460eff27c8518451b3a9ec811e18b8839808256e18a89219fda2772c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416da5bd7647f8d8388c2b4dbc138e36b8679284eadc49370ce0a16a4e0be28804b04f9b593ec5987c0608e3913acb29a322355a554e010d33acf155e6ab9bad337c4bc688653010a7720d44168b4552bf75974219788ac1cf3fb440c67ff692d499e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd93257121806eb5dcaff87a28d25de336e240731a375be04c4bbff6be6a5ba4f1042a067086008bd1c894c74e4ab0b16dd36effafc8f04a4617aefa7f68b40df033149c0a98bd89778f1276a0ee404b17d81b96c524a8aeda9f671be9e724f090c397977714f425d45bda5f3373c374e9b2710f477e2e923a0f0b2b259c941965f6e88c0334fe5947d75ed7ce18612988df5f227b149c66f371593a8c248206f1b59e10248e650f7e08ac882d65fb09141fc5c7d252da9b1d8ca2ae311752ddce977137229ab3993dc198b5cfee52c273f6145c25afaaa6de14670eccdc1b61fd53821513fa519134b630c1d53b78cbb67e8b8414c30247101be5de118662237b8388cc7d3c50b2fab9b87f1a6228df23e9507c90bec51b8e3be978b526c0e0c7704c7334dc8495596755b6b5a83796315f9e316bb871c0465cac91290b34812c5f0e34120ce455c4566893481e7afa89c0c425533fb4eecab574f0399ca29b162a4c78053405a94626a6d3cecc0492a268e974e9864826f8745403fbb98f55bf45c0b620da0f2b6e2eb2808b3e713d1a3f774966e3e00f81226887d5e1c165af998d6e57645c3b5a2e17df20f698507190332c6951d761c5f46e0dcf997c7337c0bb7e54e232d9f4c8884a9f53a999e8ce7a27f68e9108a4fde15bc51a350774c22b2a1480fc5fd10948cd231f68ec00397e22a19042578431aad63546679e72efa3cc619c9564390d54bd989ac1fb089a57964ee4313f857411373d34161939633c8f4230930357b8b54ce94dfac3276daca91ccbab9b944bdd9754fb27d2b786427b30b6d3a029d0c998a49c406fb0778936c3bbd0708774bbf21b400aa8a41e604401c8e5f3c9fe54712dfa93b8f223c4bf30e2d037a36a768f160cf0c6e6a8c42a45908fdba40941f018589894c721ae6eddb3ad080bfca4aae349a8e7ae261f0a0f18d3fcd225254bfac8ee7f94e5f505496773b69c49697eb79ef8523530c55511106827b00917fd22c6b8e62eda5e130344c9214f2565b92ddcd6b6edfa18e95f8afa23b3c8f159391a3ffb6dda5ce3c9f6b40f25c1dc7a742186b7b693f30111e4b9ad468b9d1e0cf4f79c5078c9cc4e409f8a0fb170d7c4f421ed5fcf597e3f061f1060d5207533b44b4977f128acd44bfe1bfe235f2f4b2d042a87c7da4d1d526a096e110f710d48d0a0bb58b06ceb1d6ba2189ac3dc984dc24e80fb6522431e282ef8862f121223f6aa19fc1f929106d7a916747f21e1973eec1e8c5b7f78cc3ceec15a5af2b64d5a43ae54fcccd31ddabe95461fdcb5be506267404ba432e41161e6df14443df6eadfb3c5ad5228291d1383cdaaef20c9cc8125f7952f249a0de7093e895f4c599aeb4b0310673b00785b33fb9cacd556acc9abdc3de57fc056df4318d12a052ab505db7d06dfe03767eb5f46cf0d271393db1db2516c52aca4be351c39cc0bd557e7afe547a479f8a7218cad2c784e197f3494dbb9436292833db878c0dab763cdeac36e752c7cda12c98686c05704a8b2a695a315bb1146b3d1cb07cfb8d2e13fa9158734dc2bd1ea554fd3032bdbf9e9871d2937060236da4573a6c20044052b270916290b13a30adf3a821b467c4038a14026badd09126d6621e31b47269829a47f9be24a0d63c4bd7ae112b395498ec2502c3b4f46547b4c766e40db6b1685c455de210347c5757ebb7d463d1910eb70fb290b5c7bc63163ac00341573dfc794b0d53e6bab40a84e60ffb1dc3f6642aa1a246ee579703579df75d2c2dd3d53003f55ebbefeb59446d476d0a722ef8ed1954fae9d6ddc2f1b5a31a3e46efe8097d83d7f80ec284bc72a48b7916a74a1cad145eed554722609bff1c0970e439f19fff06a080a67677712b09762b90a82fd9f97bbc50c12b2408a440f2c91824179203d689db4245fa3087e8b01a9316ba973c6ed1a7556aee499b2dffa90a79b118a646aec6b79e6766dc25665db73a98e173fa6381ae47c9de57628b53ed9958a889d278fe707b4284327bc582599019bfc4630616b78f186de80c5d2d0669404118ff1591ff141a606e05e2835889a5f42a32e9a1f34d4c6438f429028ba64818bedeff64b1db1ebdd89f2c2b2fe3336942a03036b9e86a336aeeee1b94c5d5a821e4ab4c136cbf2766a43dd37078e02927ca8a562d2ebb6671ff854613aa3ad169250e037aadbf0ea14c87982d7382f09c7b8c96770d2ffd3b72525806a645e5abd09a51d257c30dcf016435c114d26d3d3be170800af2466b5e4a434ad5ef602a77f311fa22300a5a6ebf03bdcc04f92fdf0da3c74f0c1461d8bef6e668a2cd0c95fdfc9ef30cf9133619aeb9c3d5187f23bd83c765478a56c4b3708da965c36dac2e8caca9398d50bff836219540b179bae7667aa091181db267cc8ff6c5201acaad6fc2c3a2cd18eb729ad0c1526c6c348e330ce5d949162cbc728667ecce548da5efe0448823e928463418342d41883dc6e20d8e45f1d6d02c43c3e38d6e7871f18ee80f60415adc76fdf4c8ad2c67ac7d11682942ab79f74656a8f51ab8c1b088f33ddfa20992eaaae491dc3dfff9742fe32c4428233d691dfb69a1713087e4fbfef8f7c96df760e85354069eef1ddbaa01d52f9664fbed82ddb5cd6ceec78143f1e27ee7a0fa73873d01e80e368825e3b05bef7cb0005833a9d0ae360c420a66a5353836acf1fa3c65578c9c5b3b9c7831e944ae887694e9fc6a8634f213d8d061cc2a34a00f214d9f67cd17effc527a07e060bea20b143a7bf515a130000f93cba10536a1204f0a14cdba7b627412d383c308672a7e2974b837e4a89d54e63c47966b36fcfa3efa5854046d3ce09d45f226c36aa9c0762a59eada83c70e1049d5d09f7f7304c465f2ff56dbe21687ece20ae9fcd9ab8a7020a1f967780a1ef49b13b40fc3cfd208e29f4d5d5ee9bb63c5fc81fafe5d47c4ee373a54a64d267c497c59f4c15077374317b91566d44c82f74167e6d847ad207f3a1221ce1f958946317e77ba146d16aa7bd82810c5e913c4da0bc5d3a5923a156f0990c79f01317a3140ef3aff708acfdcd30a838706db819dc3a5a9fa2b1bed2a4a48fb21792b44c5772f888132d414d13a98bb5bbbbd70ac42afa68950568131a449e70574ae0f45f28b87210c1ff7df1adee5576d03950b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d9a53c2f9f5f55bd687e359ef37196cd288fcd1a14adf6cad53c6704445a1f1212270467b0c03fcfd8bac09473161c6eba9c25369a853193b472eb2f113a3d333181e6b71b981059fa265cd76422e52fe175db6983c6ebdd0fea1a3075166b9291619ab90bff00f89ea8055f0d7d45f8c8aa9c04b7fc1d06468837c6c563a6529ba846878e4f157741703bb4c3ab4f3ff2e9b99916624a9965a4256d893c84e152c19794d20de22edc9c4c1514f4f4e29ac16e6b421d3620ec6545f737100f0134c29c11128e193f06c866e165662d903d9f799508e617920d786ebf75acd267462237ad2bb39f6a5a03a46c5a1dfdd3766a49e6c864ac5d45afa6400ce3a9809de464459b18deeea6f02d5882e80a8696b00c9f703da84bc5769921053ecc749b0cfe1745dd408f6dfa0ceaa1780ad4ae1747a8912a589a754ed86373a08ff5540a471d9a8272b09df08db1f998000cccef325d072ad79df6c1936cf0ccdeb77a0d9c323ea08a0551f96c28b05ac0c7b0e338cc5004bac22d06feea5a8f5c00104906813ee195100f82600e56bb5756831a260e4cf6e5ad275364130dbafba4ed4f9db6adcdce67708905276a01347cc1c800bf6ba246c3770a81c3c754fd65bee13fa85260215c5235169fea113546e7b4aa7a1c936c47a14e81d3df912601a2eb8ece17888100536bf7183c579eab3e6daa14e5e01602a2fc3a64b563f591f0828f0bfffc49973cd14329675728a2d243102ab486601f1581b1e741bb5c77526552839c17a5dbf3b2f90875abc9959553b320da9f07f1392fa3065315a8b1744a7e5b271f9394d6e23bdab9ae03491f51bbf21014364d919388b7fba4b5341bc4b759fa4234adb292ab984f7b69d3aac2e0afdc7dc075e18ad22f4456dfa48b0acf62c24bb58eeb0a71365ba5f890a594cc046a483d9b306a487ea4eb5e80572d3ac8b4dbb4b6a02692af692160b113da09d4ae9f0464c5522b7236a59b70d3667fd3b0c5fdf2c30cccdd640a7297da408b6aff82ee9651f889910fda9f24c706a617b082d626dfc74a657c5d17c5a763044f0230972fbe47c907a5a8fb75df4afa9726d496332a25823148258bf60b189ac898c92b9be15965a199a45ad563efc761392b915b58613f9fb99f45c9a78fdaa4358874f739cee7ebf2a5cbc2fbee73e2731e18f347de520f1878f0eab3a38f377a9263ad17333135c991d560da02f9a012221d644717e2f1361ddfd9e6b5d0043f3a47eeffab15e43d7d45e1f6e07945d95fb46ef5346bb3a502da9f005d1cdc956e1b96258fba48dc793f50b7eeab48cb88c51118ced6c65368c5197ec7f014c443b47d898627cdb7781351442c44398d0ea4ca4b697ffd505665531e7d4b4406431f2328943e8b72d030842128714ed41e3d13b8aad0d076b7ad34af4946866f552568eadd3d3582b4c4f50d816c065e65b3583c8309e3465db95b458d0b42619e1ea75ca546e966d761c53645771381f31a42a1e0bca62f752fb49e8d2a49f942cd48a03129a709e763d23aa4dc84c88423861d1ef31f5df99006156570aca69e571067899ddb156a2027e0acb8f278b4e156f96ecf0eb2658c6504fcd39e4e20bfb5905be7cfa05ed907aa5041e202a49166a5e267724e5bbd0d9efe57d34d8cd7a2e536cc7aee14f12726065cc08d547840066bb56916d9bb9761e05133fd18a68324492ad7b9f9caa1668038a3ae897ec528be2ca7c977eca6cfc08a00266e96fd43a723fc7226b66aaa86fb8c0ff0094b6feeb0707b5cd61797ca034755fa42aab8c5c9e245157f5425f5d9c2de89a454439ff9ddadea199ac62ed47b9326a4a08c06859dc6aa56cf5af62a035f7c6b0546f536c07cfd7a2d8e3be9ac2c7b7e854ebf59eaeda5edad7dc23e83eb30dfa3dd91753614a811769d6a564e5e2b27c43c70d7497a0834ea96e50b6edef3369e8da5f707e530fcf611301be6bab8187386d130d1f8c94e5c3602ec613f83c1ce2708d6fceff206d25c511772a85eec3fe2b4ee066681cc6c58313ac304e37b46e43a844db9b7bcda351e09ad1efc57db99dc2a7c12e553ca9a60412dd6bdedd4ded92b9647ecd2ce31eda2a6f5a4ef9df833b9b4c70ec0924a92a7067757484a42e2e39a2c58cf41f683c3646c0e993fdb61ba33306f7524ee2733c1d970403cebabf7a1af318743767411fda52e046b2fdbee1680978da2f66413a00a72c2f0fd68497472feb62d2481dfa1ae93b14895fd3773d48635738847d32c4252393c6cb8e07655646eca309a1481552ecbd9569e94a0cbb6905c45717f0097f3dac95ce491ef6f07d89dd7a409b0f13475eeef708fbb0cac0f200cd31c296fc0f38221dca15bbd3ad95092e6a4f38b8ef8e9f3b9992d57409c7833c0e2e85194adb91496335138d5815f82e01ebc93b757c1ff94620f3a87ef48ca064b8daa8790dd2fda2c3493f33b66804385212b1c3747f61ba6de535688b2ec24db2b9bb22f1c69337d131a4c91c2b70f1b45fa522eb556b7960f937e6fba63e1a5c832c850ec9d476fa68c807d36d09edf0c1eb9b2995a3812cec5092b90c4c724a2e1e42195049ba8878f1d05a2e30251a57f7f4662d4bbe42ecc98b7399c13a00c82090e61c34b4675c01815b7e25a1fd09d2fc60f60ec1f3f435096790681cd676c3554c66ecb08ee954d3de09ddaa2e3d11f5fa4f9d4c89cbdce2c3accd6f9495757f069ede7b956256595c7d083b47c610efce658762467518bdb11be9597e37db2ce13f8b1b0cc42acf317bf5a8f948dd3977725de1590421117c9ffd003a836e898f478234d26fc7d8bf866a6a308f8f7cdaab738bc98b879669911a26d87f69b187cd620e910289b9d5c2704d332359fce4040b4978eb1527e743dc15407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d7162fa40d6ad22c0bd13811d9555f4b2adb0f639cf7ace8468db36e557c1e1176e4ac7db719c3be3a8a8fb077e5aaa181f69f89547570b88ecaba644b0c8623f793abe63296589646fa4fd48c7d15548b46fe4f60435bf69fb31260205482eab0226b7a3b02d5edba566f82d3f949278d4d0660165857965f123b1ff5aa680a62c6c7b8a1064cbfd234f3e26fcd14b1eb52a0b46a47e8a8d38027bb3fa2cba947124c41b6ccc361bdd655dbd0f0a5b5e7c86fb1bf779a912921794e17746c37f40e0e4451bfef8b6e07bc00ff6fe17cdd12d45db9f816cace50b0682291a8dc257ac131413580ad09206331a67387cdfbf12cee28aab9a8b0aefc03d6d1f2fde70a8c597075eec72c0adb7c050db76ed8d86e7785f056db19e02775ea099672c7f447c7d787652ba7c318efbd758620236476ecd6df6abc2cadf3488c7e6416c12b8a2bb40ce3658b1d71c42e68495a5504986f38696e56ba0fc2df70182a5b11fea0d61d2472c21da757115c4aeb85f1ad06831b0b41779a118995340fe6c352e6cbeabce345363e57dc45931c6bf8f278f704cf252234e0e580741af38024e1536d3b2112224e3432e605d698c7809f9599544725f3bbd89e076742a2e33631e2caf02567c87ef2729ac221651de0efa7ccc8de802d0ced1036b68b51868bd3686a8ecbd7b1a217342e937037c0bebc6a026371b85698d124c09998e5a531b6cb276cf5c2ddbf28d010e2a6976cf03488c0d1d11c5c1f9b23d7ac44ed221724baa63a6245db826d277bf7bed80169db1bccdc7a3eb0ae7852317a5fb2628982aa0fff7c6916548204396e77dd2fc044e2a37c192789053627b2c81fa1c0f3d1f7482ad1abb0ef6ca6488989637ea1d44a918f062b169f1b802c9ee6d05a2fe34fe3fdf6285d91ddb739bc5c2481ed4d77589febde82e624d0af0ff9796e5993242f7de325ac001c0d50c4d27c15248ae2023cbc52e2ee969b16fbef249ee2542026074c387dc5714b8038735a05a39459797ad1f591aede76adbce55e99ed94a98b68d8ce62060e2c77262da54a918fe5942925597cad811f00d13599f0062784e528241405f8618bcc663a513318815f67de9a13e6786615542b715d6d2bb3d82580e61b8d0dc0c1652fcb6ad0fe74186d4f30f931ded5712a16e9724b9993cd0d505f36fdd6c1f2f87ae7f7b7d2a84caf41d8db3d926a728904ffc98ade114aa146708071810254fb2b5fd49243a64bc29a6cf8638150988ebd9756b917719664e74f116e47c0991afa7bc43d0b4aaf085d205ced8ea01235b224e9e2a575626a39cb65fb8a0456f4f5380b87473b2c6d3ae6c36664af57171130202317f567e7a89975b0683a31b08cabf966ecc62d48ac257c297ac4825c75e59c4271562da9a7597e0b1d1e880416c0a36fd5d9a8a1a0e277025e81af122c541ead22d78609154fd9334b34c1b724aafefb4de93d02e360bcd69f4d179b8f973f0a229525c681a841ce65fe1848e33fe6c929cfdb09181ed6f10f9b5d42b079890c93f6cb63489fe6ca5926a30f68d89fea2985c600a9114516a6c29aa1a9a390358ae11d4c2addda665d13fc93f613f8de4ae6526a7ec8bcc418d9d190bff5fb2bf8a57d4d02ae9d39b49dafea09bc363a28395b90f0c0482be2642d693c65b1dabd51d6456d129d5c987093349056b99398c6c59efe7949aa90e6480719aa04ad8816124b5eaccc793902c3f48b7529b6d116f4e7418406b6dfcabf008b65268d1b3757c713863c80e960241776adfb775052d810b59fbc83edabf4b607bd44c6a610788c1cfeb3f21e0b94d5a12f2615ed49cf7d67abf18a93af7ba649cd0ac29680d9eb19a6e461dc5fcce21ea03fdc88fe1a67bdd4b67671794d5348a1b481ad45e86635f0474f0fe3f7138dbd0c961b000d0c14707c9c3037792e2b59632bef200305908aceeb3388deb21c5ceaa4c1dae6b8ef3ef9ccfca9bc6523b609bcddd0b66f5b305293c5ce2538e4d8e773a6d51cb10adc0c50d9b9cba83e8429a2e2e1e4e1f947c0be485986af1fefb306419c6fc3cc203303517dedafea231dd90856df4af58129352adfbd4c714e33aa5cea74c6e39a097a1155bb8a0f59242addc542e1ce485f81eb5df11ba9bf4e0267aba89ad594b06066c4a7f52ca7947de90772864f98b6fd26bbf80abe1a9ecef909810ecefd129f3a73bd3296a2999b9bb455ebb74bbc3f5ea7cc6eb966a566123ce03005a73c0294531cdb87e6f4e95a515a4533e0224cd2cf5426a5cdcab8c30caba2a0a36831bce623b526cac663bf76f269e3d114a73a0229bbc06b4f53b1f5c0ca2198e418a49af03440d375ae7c76e24cc7c0c46b93aa96c8e69afd833d5c5f4ee23346e35053b1fa6044421208a5fc47074d544333068438bbce32a53bc0117d123ddb9718eb62baa88f7a7bc786758ecfa2acaff06cdc5d550de264d6d61988290e84649f3faef516f21a36b403490b980074580512dc2e7d3e2b87a063a5da17648602d66ed743cf227b0ef5a34067bba03c1df0cbc3cfea77b39ee77b49d8b425455e45a27a245c1963853bd35689e5192515b7b99cfd14d624ea54dbe5eea6c8f22b59babc3c6a3ce22286f1a628b901883b088d7b9dedc64dc86f636e337839c21edf802b526c26346ff314ac02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c24165804d109d88647def7d8362b09e103f65285c88ff5ac9329ca40a9c29dca4e073034a4c23a5fe2e1a82fe0b885d736e57a0883291961a087a2719664020a574cd8db813d1070487f577a18b9e163ed125ed818c0d13dde40503a10ed6c8d3e6a9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712132d3fdefa1807e6bf9c14050d63d2c37bf357802a7d8e813baee24cefa76b229d471496a02cc87ca65544c0ef979e7f4c1f0a7269e3eb21fea4e0d91ec4fe86ba67e4ee5cc212e44e3488e61c6c1ce07e25614b8c23cb4d0442b35e6b0d8ab3744512e70a1dd7110e04b778646d4f7b399d36712e40bd06a6907f25046639e4f9a632636d4945986ce97bc67ea13897025c220e7297598460ccd7cedb8a0c54792f097884bc8751c88ee126bd1f3682449da8181bc9cc5b90f0bd9dce1cb0d19441bd6bd7dd64756c6cb272ce5ea2a934c56dec8f3be010f8ea74cc61f20d1309a1fcf68fc3da9660e86c1189f879b8c9cb6611d57d470765dec4c3514243009923ef8cdfac92e83ce444c9a2b61fe92d6043d108129649a3c6ea306c5d9db7b924eb791afc0aacb141b54f0d75fcde46e4682e806926114b2ec7ee5a1a5626a3a524e56e2044349643bea61e7d9d3ae3dc19e660d754e6cac3fa4f24ae46d794816a0ad32ac3690b658c96cc6e09d9510a57c8e28f32220210108791a15aa0dea2e3482714178bee78fee64d0d61e6933d06f8e8dedbfa5ec5cde870dde2d7a9880b245038d021948c6700d89443c09f207b9da66d2ec05e1c567a8ae5fe5023a414b00e01850a90adb945205173ed44279aeb17ca7ebf9a239d5f6ecc9306a868b391a7c49dbde0913228107a7795db90a5e3e91e505d9922c2914d7755e0ca47af8f394eabf539adc4509e5958a7935179f1fe3f8c22b4cc2e2a345933f59d65e0318bcca6caafcefeb3452d68d6197c8ea0b26b971962e201405c4c157653c2f2d4af59046fba73c6d72ca8cc525648416b9b2143dac665457204258b81bbad3d109701bd807e75845178590a4c5b8d44421e0225d9fd994af2aa1d0c65590a7bfeb5fd893b53578b04160e3162b0aae5d6f67dfcb75abbcf01b2ebb106906d47dbbbde1bdb9b1bfa8dab1989c600610422ddba5fabd57a54dc955ccfc7e5810293b5345958abc5f84808fd97351d481e6809e00bee6538408aea7c6c074c26b68e2002ea0633e6c3d7484493771c50eeb727d6fcea84ed9c26bdaddaf73d8ac7ad5aa36f30863234f789eb1d0092f42deb6ca72061146b920d71b457700dc5012547ee806376f3ffab1e2780f491f33a0cb355ea6b677c4ea1b54ab6e5698d2853047a428891a431d89979492f261809be176ccc6f09660d5cd4b624f339e961df7e2cd5aa3f816fe8950ecc0c2c9838fbf68bca5d4955de8719bb6cf79e8afbc8632efb5aabfcaa6e749cd45043ecb13046ce3209fa85ef21441ec2d1a0ac63a273f4213225773647e8a739187223eaf5c9f0f2e3d1b12e229fa77e65bfaa2a0487a29d08064960b2068be68c3c830254caee33d9436053af9fd028474bacd43a231dadc4f4116e333fc9f88fbcb64abea30e650a11ac56a1988eca459d858087e220893ac87e5b5203582ed469929c865ca6e35cafc0886f8e5a9f813f011fb08ba33475f7e9b64397ce8355542f0d31bebdb5238414fbc41ab88fe2abea69d9e769a9b465041255b591fe2708f1193c6a0d7e83e929c167d0f672a6cf8bf480b21d5fcfdf7c0ed21b4968982c3b4798fe04b9e9462fe2bd8fb6c511b1c153d0637fd584e30e35b6a07aa739ca4f37d82d9c8e4369606257edbbb2f6ee4e6047dd8e85212633fba991cea2364c746d0ec558d0fdfd64f2ca44bcc97637e3af5596f09c8a333cc19880d51fcd11a73c7b8eb1b02485903f9c3b3d15b56b6dbcce848e56c21d870a965f61bc53894462a6997e78f55f20ebf32f8f4de37a05611860ed6704be9587f1a0c12bf329f83fadd02c191a288925cf1aa151d387686eed59f920597a10643f36f40b821f85fc2e6b62569c88b32189a52966c52301f029b0c231c81ba02285edfcf032a441c296500e2a2979e4b4b0caff11b6656d131b61a171c4554591d3c74fbc8fb899600114d3a61951d7af36bb8e6460ba61b0015878e7e28903dbcdb802b63c5e6c895e2619c6511dfa0723fc48f796952690fc3626bb5c1a0757a19226c7db6e42ec243932a2503b9b257fa271f933ec2dc395f40b62b11adfb0a552412447e35ac364bee1f8ce0ad23a72daad14944e49b18cc3d5ecb36f4a8dfd602319507ba7dade07e22ca3a895e9ce0a2f59d7f581d176f5b8f880047f3803efbbcd442b7f8b1fe158353183f03d3f6acf46865281439426e64348199839d84de5c3d2441a5dd9c75bd064c1385ca083cd1df6ef46dacd30ba7bc9797085a143f0fcdd6b0c7ffdde124bace833b758ee4ddfe5072a558406365b77652cb2bd1ccf651da71b0b22bf789af3d24014217fea74522e694c399bc8bd5f07c0db8fab186d5ee762d33a5debc1902bed79a68d8420d06fa2810bfcd09e53dad5f37258fa86f46560785713ec711c9f5ab98c631bb3e3b6c5a293370fec522d61149c7bb09bd4256e55a71487db84f95cffaefd2c4a3058c62c3e73695bc27a72c21d264daa0d40c012083c581e4a0dfc7f168b722b237a0ede4e40a7b352f38ccd532d1a416ffb5207d68c2b7b3a6cfd957d7efa5b71446ce84fba254aa25005dd08c988f4dbdcc3dc795d3487566e587f8f99fa6d222c406942f33c9a694d0a5b974d247fd6d4a37727a7eeb184f4139d300cb9d2264e4bc1869026d0ca9966cfa34a5506577dd7eaa826a1dbd86bf3e8ae5fe73cd591837a5d6075a386bea6701e431ace3f383154ebf64ff61e2e4b520bf3a723908aa855ffca926ec6b18bc48a7dc48b52b839507453def5fd2898cbce2c611ba2af0d2434a7152607d997781ffdbd8987c5b14b6f20449493fdab89717e43a14153845b97698e2511195a1fbb646bd896dad04547a95f1941a1df510c4f7990062c0d4fd794bc886625c783228e520fde1dbed723fc9779bef796e04307444ff32c210cfc2275da1aba94d5bd2b963fbd80dda7a9c8ff88271f152875d7cccd664a44c8d3067a4034b5d6101af80d9a2970f3443536302525e41dceba23d8862006a1893e47f69018c2ed81677b4c43016ddd24ba54311aa590562ce1ad6991a1736d972bf0421adc4a00cd631414f1cbecb646e0008529253e9c0169822efb33ce421d77953121b3efeb10cd44d504b5cf47a9807dacce8eb24d53ce62e145835b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d32ed1f9d70028c2001ede3fb28ac4db0b0215889cb331f8bc637d8cd27d4443570c84f2e19c4aa5a2610030e19ea4093bd118f72e066ba44693db5cef94f3905a6740f6b046ac8d7b77f5451a405975c2588b5b82cfb70843359010be8b7f32870641d3606bc050e0383940f0e25880e6b183b137ab86e3ddd52a0ea7024db44fc4458e5fe418d5a7ed1c33878563e44403bf194507c93079ff9105b433e6078faba26ef3daab055a97199108ceea0d3b0dfee6ef4f8ad55f1eca9c15771251d0cf33eead0be3cea163831560bf46c98931a1dd530301d054fad074fb22e5d6ad86e5f79ca0607a6108ef6030015ee05ed6229bafe13806894461b51199f5b3d2ef6d9024f2194253e89d0ed237b1903f89dc510bbdfd982b518c3576659cd39120b53fc4e51e100e83a51da1239f64947e10f158bc42d10a3b20a366b4311370e2e5c4b8c303383b3e579cd1196f3dd13db99c99a48397fe1df8987a58b942b02fcf424a1223968027d877793bf9f4636cdba3b47dfac921296a818d1b08821f45e5edff6c3c216a16d4b6539790325daae1a6400ee446c2b4fd1852c409d43d0bfb72b3c0946f9edc151873293bcf16d1360b340d7b98eda07f00b1333fa020c5b2ab0a4db4d0a259bc517898153957166f01726a25d2012da74a8fcfec104b6ba6b02f41eb730989a90ffe2f8948b98eda9bb5bdaddacaba1ac1877ea8c77247f876b27b3d89aa71714f55561cbdd0ebbc4b24d39b044ca3e3ef42bf8f63b8c642ebb1fcbeccda9a1e3aed8762eaf0d9ed97308e08e7489424c321f49af5ff24bc10f697dde29bb97031ff65fc6cea39036367972d5627a48c4f9cb8ec56d22a8f95b4c20b4a2545baa5879a817128101c28cc253f3a7a73cb74f0c43d609d08eca7f936f1a8a1fd902a4395ac8be7312d9eaf784c761cb1354dd40baf3012e85eadf3fb86959768990ad2c8625a553c4d920338ebe25de23761c085102555e30cb812643fc1d2857c220dcb944c423397264da353d5131d0c70933d72b55d021a519c3d7a9c5614710da694bc1e1b7d5cfe40931ce3f0e1f35d253566b238265670dbf08b30c63410be69245689bbfb89a17eca0f6c9542454b1e92ed9421ab1827a2f0013b37d7a0653c54a480e1adb20f4d6621955b8b41b7fc0dc7f66309c890258c6702ea0943d8a32748f67d8dfa4a29fd85282d949f1cff5faba27a8336309a4f867baccec1e6369b73bdf4b757c1049448f4bb3999ee0d8ffcf0014a49f30a2a2f680daeab96ba080e9436779e88da9f35f1df28aa84992e99a0beab3c9bc2858788c7077ea13728eed4debededfd07f1672798856c3a055a13408241a7531f1edd8411be59bcddf843f745850a77afe6ac8984ce9110aae0cd6008ca6874a522c58bc897c403a860cd5d05b731add09f9e24a465d0da6417d00000bc1f800f46d8c06a9861b5ebb82ee710a67a28a410942c343c5385210af2235887221563f3ead0d53f19846cb8c3345403ba3f7209d78da91196896a687824d8afb71dfa6f71d993f900470493108fe9db363bf82126d7af537072262fd8208ab0488b72ddc27a4f9dbb2c191e699746de264af70e8325a3a8040652d3cc3e86f8e7ead704ea80c6fabc0641fdb53599f2e2532b2733e93514058b042af10bd004e87da3ee9342f44b433ff1b8535e3f1928f927eaf8bdf52e31c589467317ee797d349e052a0edd93134d2a7c57ee3fdacad7f8e00de15fee3a091b2c8e51c87f228bd61350ac8ebe6922fbe3db9b1f1c95cc6fad66daca76115c222bee077e98797f7d5a383fdf3eba7a9d9f91ef76bca8a1f5e028013db30143acb3e55096b4d63a9ba75c34b652b711c471606219755a72fc7db90eca93c617bac3191bb231b7a7a68d58e125aada1bdc72c94363a3d8c1e3ff72da6102d37790dbdd1172e42327ed298ddac2fc87c59442d545b0ff476caed9e785f2bed1bff26b0333a6b7893cfcd6ddb8a9ff65313caf6456f2ad2188feb5ba8dc102539e94beba58707699d560bbcce83134bc3f92ffca813e62865f3d2d56680b0ddfaedcac5d5d84dcacf83ad61a2b13644eba1c459299b7a92a42c735c24fe9a4b2e2e9fd6a003c6761b167ab56948265b496cb7529b01cc4e53c3cd9a39384643996beac7e7e8c5b9548bb53ebf8bbca632e490bedf7f4c1de2fe41bcb746afd7380a6ba561610e880b38007beeaff985e007a1460051bb827ffb24970b0fbf79cde0264cf0292305be0faf22877173da64f6bb647b3a636b831df365b7c3394915ca6209d753a2cdcb143ba3e7fa41dccf5534c6fd36ef91187d55e35dac9d3925ac08e2c22c80dda4c60aa6e074cbad95a68215cc134e03ac7e516179bae944ce17cb54d086ea75184c3c36dcddad7c1a570d4167525f3f53d8d39ebaf2d239bc1f9e7572cbce85b1fa08568230c663866d47c3af0c12e609217ab0284f8b8694563933a48ae23e707c1df21527ba79fb2c6cb074d51ed0b90e361b2cbda0637c074415c3e4eb13b75b149505ccf56ad08a10df211eba48ffd7a2d0d42a1bd943dcc12f86e3e9052ee1ea8f6f1a8fd7b2262bfb86110b06210c25e7fac37b49198155c2471aad8190353d85860814a81887509424d72a79cef1534ea7655db318a424d6a036c7aa614ce9faa7901f55f64b0b0bf1c084f52e7069e5bf1097a9889ff9773079eb30a9abe2de835e3229d8c3cd6b00e936d5339b325684a5c483b15420e123c221c6faa48e432e6ad29d22301073d3dcd3dad319399258dae99d20eb634bd69867ef8695bedf1478abdea28e97985ba68b3810318e3cb12ef946594ef5447668e76d655032dad5ed688567ea02cd741c0f1684f271e1e6f57e70339d949187f9cc5ed830203c45863ffda2b704a0bfc77cd4cbaf3279e937c9415d47635c23582b2cc0e19d01abf7b442930cab1acb6b6d1c87fcbabb93d1ee778339fc75b0aa674b0b9ebcc31efa34cdc88d6209367d7c9cb38d96a9ceb0b51e8e2364399650074af6bb1098b22b21e3b9d12bfcf4ba0ee5e9c3cf8820ef6061d10c3648d73c6d22bb9a4502c3b263699d0ea24baa448b12d24f501412d09da75d99714c914e0bac941c2e9591a1af974b9d7ed718ae8c2c5246458375efb92aa04a645b615f261ebad3748d4e586cf4bb52da7a9c3a306113046efec9210cdac01dd254b6f9444d4186539c1983075c1100c45b2a80ec93371fb04da55a70d7e4064542210bed2bab603e428eba5d241504949b6d4c4f02b543fd709a15be42ee92b6bd37baa61bc2904832a15e7077176451dbb49a688cf55649c5637bab364126c473c49dcbcfb064b2f296cbed17603820bbd3a5e93ec52e82e67ab2760735d2fc915122c09b76fc9de21fd95de63f8e5b0276a7fe25efa62bedecf69ceb278c8309d1c5ccae18338cd298c2ce4780f31255dd1321fbd0dbb6f8f64f321e0e0b665130b8a0379aaf5aa6bdafe07af1312f637e3911b8d18fbcdee38fc22ca35094f912decea24e409eec05550dd35c62be25a1612ab90b268015b40eaed9fa0717aab769e193b2d7bd2a55e7e715c64e67d0be4b76086d9cc31c11ec35caeb68634eb554ed5f55ec45727a57e2d8d6914f6d2acffb17b9515d347ba045067502a0b14022a269560e0d95cb168c7097ea8eccca5aecb328a24b1eda37bdb600fffb212178ec0923744a6402d58d7d738f233ce9b64b6a9f1dbfeec1505db36c5a06eab73142a86b27dc175155cb30310da6295a7fb1a7fd6e4ef00c998b82ab8b3300133c6af14e5077c26aa202e6fc5e69a792012590d42ae2694b82fc1efc68ebf7b5df2574cb85143f66a0bc2ff2a9811e62cca6fe559c14e606a1c9ac2753af2050d14b924dfc217dbc5b9b44e89d25f35314db49b096287a77d1734d0f8f8d168467849008fc52de08473191d53f8cff9c54059406398e89683d41db5ca287bb379e463c7df481005fcaa51f86223229d9aa3f1dc10b0bc97f9814eedae2d1a0d48826da8fea991d14f1358e94badeb070719ef7e1ff2021c1cb5acd297695c34310474feb95e86dd6e211cd2e6f65ced4fbfff3817ccb8c25dae508502d4df393b421e7f92dcd88622e35e35994021fd95c368ce30d455831b8d7b5431f33a73278cc9567892bccaa9f0d0d4410a411d42de63d1e2908e4ebbcafdb25c1a4ee00238cdf73e322686f01341d26623c2491c6340204508a421b5978d8f7f698b473aa842dc9eca0e5774a6374ed583ce8605795f084731e95e368d039b6ac539d614882e89471f99ad0b367c55273a7a4a3dfff10ea4c7816a44c1cad69137741b64deffde56148294271b50d17c8ecfec51791fde88bb15b07ef5a9f0f13b9ee20cee21322f3a6fd0783089d9dd32a9344cb0a89e9746bd35c0bc36f37afacb5e35fa47643df9b11a50e4f6f2c820c284d4c147481412e5e4945115040df81511233a8f81e4731205cf0af72285f08cdaf87f9cda4cd3c7c7d51bce592ea15d692e2a1700f5467da9707838a1feff9c989cf84c7b2a3965f146be7fadff1b72aa0338c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e8529585eeb7d466f7e38b980536e62c00fd3dc5c703c3bbd721c9491e6eb85c32a44a4b8c95221524a3c23c6b5401c00b5030ac5fc9d0a0463ad9e34009a00ad426a782939a3e4f8394ef0f1c9a8f811a7f5ea333cadd30d3404352aedbd7a2a743020670a8d1c3fef7c3cee5b34ea05aee62597374b2d6143e51039b706bc660f371ea75d41bd9ef4da3a7a5ee404600a4880f8915d2a0d4943210c8e5e71277e7fb0a75847a0e9f3e97824f457206271c9147e2862e8728b4d69cbe84e785d92608878e367fea06978192e6e69d4b8acadd42ac1133fb3a9e9e1dc50e281254144a0fe07efe8476c462860a01a5e4180a4de0249f05648c23f8e6e3bc49809eb27d2c7ee29fd05b5cab4d8ea4b8868446d4562a8b2d6f182d818b448b165d8497a72c623880702eed40e35aadcfcf6b09f67040effbeddd2b22af32c2978da711f60d3a60f115c98e714b9ca80bb1bfbe16704fb841cbfb0bedad90d8ee5106d2178980cf59e6836eed32dc22ec231e5556dde151c0081a83bf4389916868f9a5c9eb394a00dd88f01a451ade235d634484a9c56c595224495874fbdbdfdc1e93220adc754722bc8f182a697c43e34c44782ead62b2b4d01ed046ac0d7187fdf4ec246361396ba03e69055b5347faa6c1cb9929766e4f2a7b41911e25448678f4820e4764775b18b4c0668fa3ca1e9183ed8e57c30c211e97e7cfdc685e6c082448e0595ca52e08fe5b0d37ac52bda3dc4c8a0b7d3e9d1812d5530ebcf9df0ca539c809855b617cec1498a8e2313908d070839a80574b129b24245eded44df2d131e43dc9142274e0b70a75a903791928a1bfcec374626d3c6136c409de439066c72ccb9ad0332fc9b36d3a24c6173a23014f684d0f1666b8331d108ff33986354061399848cc96c7a631da2855f503865eb732fd4e5c3976571cde050a1777e67603fe0045e0a581002149e02f12f72a340fcd78d5723d10b6869cb54bc64940dc20e2c4e3989890f61c5b1df09c72d8a70b5e5a161c0077f73c816b17f59d9533c2e6ab0c7a26dd2cad7646133b739b24e20159d38cb2e11faad8ea174305417860ff18be0bfcefdb413d281ebc034b8b5f8722b041e90ec772e1e9449f61650a27e810f57d102788527c3e274dddc99f094edf73a09544cf3f162573d6da4798895daec9986a41222047ae0d3ce9b6d84c6e91ff5abd4296b1e777b8e22b077a6aea2e843cde25869445dce969fda78091938b3cfdd6f1ab376e62e9f94ff0456171e270fec0156069e8006f48956683abccd1427e3ec9df93abc4fbee9170e9ac11dd9ca793e7d4ad05cfe205d6ba0969f8e965d571cfbf51f54a8e3317b795c76523eec774719d38f8ecbbb192bc298fdca9b0a9304386b0791c671fa441d2103a8e2b2f015072895fe33d26bdf621bc4357610234e563f1f6dbf1584d21aac7bc2a1f4c8869fd97e805ab0157b6325650d1e03909ae85ae3751e582cd823db5394add842eb339426c7a1f44fe90370fb00c10664c8f2c9515800831c45fb5248387358534d37a9b2bc6b9ec84bbcda7f2f8fc16f848423e1dae978e729d4886f44e1b21418fc96c9b11246ec54148661fd7515be3636f5d3fb5e2723cfb1a7253ebc10064373d6227daca15f68a54710eea722a4c7ac9d8cb34c289634b7a831c0d58ff0c5654f9edf692e49403f40a9b1b1bd4acaebd7c2ed9d02378c9a9b763a41b5a85c0e978d30601e32bfa02697f9eab6f756a1d83440c49028baa4607d4ec080ace306ea6094d615cc220736fadb0bddb33b4d7381d35d265c13e35b0d829219ad12e42d1b56bc54f1fea860b18d6440a9c44c56c41dbadd6085d0e3707ee4eeeb4e3410a8326cab9ea1eb95213475d669589cc8b1331ccc7d65eed9559e0ea0f5bfff13843f2b4a2067c577278af1558bddd481e153602c11d5c81a424e2a1e946483bdda59d530949954fc0d7e42afce9454b6faa5b7575f6fa1d2374efafe1363b36df330d958bfa12b5efdf7d274943cf6dd8c5448e3d30bd0d05afaf86a2d30c068ff63e9fd065e1f84362827c46ccb49a8ec04049d1e04db6f7b88c193400ee5818956472db1a5d3ab044e18f4e918b2547eb275d8910d103c13a8704ed2503421465b1e68c51817ae25727b7b72f3817febe4ec7451fc241d7794b8a63f1317707c329bed6bfb2a0023bef0917a4f8944b2023efbe2fe3d2131c41ab066ec2eacaf389834b55ec862fcbca7862a3addeb9a4fd147bd07f480464e395013f2599efd1c800bb1a8d30d5f57f82ac1df5056e7ab4b9b21cf69a97916c8a50072a9fa50439bf52d8ca7aaf50f5bd9591a5422b079114f0bfe4acf561c826ce665878ade3dace990e64ecfb1ba367f4c3c0a61d4aa1dad084d5c3279ceb5a4343f16894ba217fb7c1bb67c328dc7a5834ea59c48d0db9f4a5d9ad304bc46c0d63e2847067350555940f33ffa238dc7137ea04ecb81d9abc5b068794756c4f812d1c5af309231bfb4b27281eb33f8df6c7152ec14ed6fc9a8a644e174ba754247a7319d29a2d250be22ad5e7494d649b11898276a964aafd01459781278f83a80e6764aa6f07eaa4e22d1741ed853c68c6ab19999edb739487eaaee49b05113ccb3c725993fb28e76ac53f00b9ed3ab5f6912e0786fc1138fdd9eb43b407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71d68496b94fdfed16540c30b13d0d7e65a4ff1bb1b73ae867b96e7c912b00ff6a0ae752dca9264748a313dc53b63231d29e9fad3bf5e6ec9134177e105125ee610a1f9b915d9b65deb6f9add45e7b03240fec592fd59851a1fced2bf84b59977cde42db08d3a2ae3363169cf1de0faac09b586e3da4527c94f3e773341a31864c9cbe171e9d2dee147797d4242195bb40ac11e174db2328fe1eb75af660ac3467a41c20b10ebaf33b287cca0bd628c8e0776b9bf95584947c130993f4560f6f01a417c3a364675ca3cb6a8235ce24cfc39325150995dd367ebed4e2adba7efd67f631073311641d31a868698b9453e88b51df1f6dce9144da9ebea27285a1260bd849ef59e925c176159e087d784b4c571ff12c63386066a9565234ceabc1d14242383c5e1385b87afd269b475a6fde0ffb7bd90e239d010036426a9102aab37b5e7822263c75b2709c939073244489a929410cd8eaf39549a7f7e39808fb43114cccaaeacc16d611dd34b249acc4f8bc2276ac510bf3052b08e057425c87fd10a6c6f7979f5044137535fe3f4335ab4d53ff7a251b2d799539e0852b557861591858ca58ee54562ddd8ce1604479185664a744017e539e3a7737b7eba00d76750ec72e68159e3a59b6311dca75e37ce70329997f97069f11df50dfcfd9f0527d72a5f91327ba5470d80b2854a57596101f5dd528153c8e07bc10fd47d0ec9c6b3ca84536e7b0ef7109b756252405947adb4dfeaf4712a116940f296667427b1c3451595f904e1bcc1ecaffb327a9375f9f09251fd12a66f7cbd6faf86fe9024394f1eb3df27c88e651042254b623a6d4f21c9d4ff62f4819dbe9e6a4ef2e243a664589311423742fae46323f94994ab346ac1582f51747493b32611a563ad057baea8cd9643b8d548fe547146d615bee842aed92fc83470ae7116abdf4ab1944e02a488e8df0f2c1a026bdcb1c9e5e273773626b603e9c7ff6b9bf0beb5a573c6e918efa944501d59226cf102566661ea103bbe11febe431a1ff61e7c44a9852e25b13c8f1bb89f75aa4f297f36eff83fb89c7fd7627643fafbb62323508202f6cde95375caf3e05b69ec9d53a3c3d46d2c269274d4c297ea4c1849854c73f6f6841ca230369c180417f4a65f648b88e8a5dd04c309f31d09161a0207dee3469783daaa9274a0ebb267618be37418eb65bd822d1caac9f77229bb6c60962c515e8b207b02674157f4b2fac359d2595191b18223ef8d7a62f203c30dfb407d3017a45f5b334202ec3bdf629961bee8974b2e756e4c7b638ddcb558e8b8fe0e802bef767d681dba2b2af833aada512c7f867dbe6e01b2a7eb49c7b6e50bb8d9e6cfa8ed1321b415771d5535b817beb8831160ffb5f256a040d662f90742d2be25580185bd09edd014de26223b5f1a82e054dfebb79336d891b767f8be214f88151b8a8ed8bf99febaa10c51a9b07f80b130f73cfd4d1de282f6d7f5ccefcccb64a4ae407d0c8e29650b1c0c1c00c292d0afc5ebed5da7e7a9d0eced3c6894548043aa537407a69dfbfe0fd4dffdf896a363d75ac5707eda016347a63abfaa6435132d554abf826a19340bd0f7c5984343cb49e89936f55f2256bfc32871448794ea44303147839275ddbe891c2ce4f93b4e51ba2a2709de73de8b659f9ad0d8a6aa8e2f1c300418e07035b4a39936ac69772520c167ef33f576198a70bea1a3e6a4810868fffb8bf70abb870ece4fd40a2c286d65a1a768776bcdddba218f6854236270d550b0acdb1e87c0a647026b5982426dc8bfd02bbfbe5ecf33fdef0b048ee02ee85779a0ee900ad2e02300ecc774f73ec419fdd15546141233308dd4e05e0bd98aef19726d7d2749d8f316b798b87ac700de86806c0586e96d5fa35d908728d9a044cfc98d6435f5a73643ddfa896ed51671f0a76359ad302d329a7d6489c3cb77d7a563214f32cae5c3ab5a379198c36ac46ef0f151a21bb0db55720418ac16e2487ae411a37a41f7a086824b2efd39c94b3494efa7c1b708e360b380cd65c6b0300db4259152800ab8a88f85e276b32399f0746cdbfd93182863a850da4404584a8ed17f70aec3cb4412c17b854cbeb6e4ed1e94d97bf16f7b343ff7b1c0d02b11555ae20d30819e6ccccbb44b7538770c3aecbe7351ded9dff5a0a7c66c2be38a68a4f8d2cb06766b1cec3242cf191ff9ecec987893588a89b042c2034534af2f0c4e38ba3617ddd1c70bbd23365639fa7cd5f191861c7fbed74a809b4577184b74582b4774b8ddc3f186fdab84f01e0f988b74bacfe932f46aa7023309f130f7d93dc434d02fa0318a7a63dcb6fc7a8cccb8eb8452ee3c1cb6540512a78cc5ebbb671f9ad9a244567471923ff0a04fb615834380caaf01494ebc73ca0d5c640440be29f2206fae788ece44aca654e36a2ea1777e93e939111387068eae8a7ac652da78f63545288ebe0eeaa2eef9ec82ba6bacc11acc6e110d82f4a1c698336cca9cda4ce660b4873e19098521277c6167a5090ebc2df903b9e682728b4a3ba320237b20444e34f94f2c8f9d5e0173b28a2dea1a88f7e40403b113752a6f9aa0b49ca6a5c34a2b92b2d2bc5f480ee94faab28f01dc0d7ad19392060a4f0a8a95ad318982f081ab3c35895f83a6d4611d888a1a0d0a8ac62075ca703c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416aeec5145d93ca5215998b118cd43fe6f953be84cdf704bda68dec68fb14c3e6490399277cafd3b75630f0b826e2dd6d287a161cf892fbdd889e0c6b19cc0be4bb41fcd121741e20510209b0740cb89c118f190cae98339b07e65df9cc9dd126b9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712122d254e33b7c35d78ed4f76db5578f07a6c1bcb7dc46199c567c4a61f84c574fc4ed042b0f2c8397da95d7dfafa615f163ee77de3725afe64561d65a370b3430bc9746fc125c950f425b970da866f8944bf368a765eea617c7ae949c214c405a9250eaeb7dff21e3804b3656037370d9b2694a83536a4e924c9f3dedf1ba083962d04439175a2d98c3e54aba79db4b5fbc425c1ae4d759878086569d2afcba33ee7757f605a7b0d7d518a7751ffc17479ef2cdbec637e4bfb3dad4d8993a553d0ccbb191f4be4cff5ad204d9ef12e321d851b431a0487b9b00a71213f2c95a3e48a1025c18a4bb04dbe9c259e0ec5a57863699f0eb5efd7767175b02b9bebf4eda442aa4ea276a4e1cad5e196a6945f4f9feb7e434a747a9244eab3dce1ed9534262c8fbfdc245ad9dcf846980488cb4d18a79606fce942d48063f0455392e5d825f515af082f6906036c246bb7b1f3b75d1344466e45c96967f8cb73049970c100538397589fa07b331c10ff03ffcf5cac1691840ba63344882cad3a161b135fc74cd2834b4d7d555117ffd19bb23e6ce26d31a3c34bb5626688c2388f32937ea6edb9107df7695cf745e061c1c8b98f078d88f50881eda8dea89dc75b6633f1c7fb016c01016f8225393bfbb03533db594d4e1f289484f7c5eaf4babc9ff19d827a1b3dd1a3cd1ff4732a3826ac5a468c6464286aca145027df161442843522e2ea9f89b72832b1d5fe563cc115c44ce2ba0c383e5d6824f8260f9697397660eecf2766560b1c77937fcec07555c995ffa2eb97e7bed217c46cc798a407a054e3e8c342de20d821c684b2529a9260b8c75b32c9e0232f6870db100b286915baa9ddfef29ba03584ca140af25d0ae285191427484dfca3a722f8729a0c76d7fec1a9c987bfb111cc69796ebd1976ad4ebcf4b3560c1bf2662f77a10271993092016aa2a13c0e05dabd3e3754bbf0e87775ff06bdca2da1382448fbabfde07755a6313b77aea6326c8a3ce609b67aa4b2de89a10da711cc35cf593e91f701a0fa8e27969e0a4642d03481c477ea3219946b9e8b8b1271dd6fbc2da017b45d3210095667544b271eedf036d8b2ffe8d5f903ac79718d2bda2a14a9fb3cba6911012d8f0e3c51c77bd269f51b501bc3056358b894a4efd94d6f3ab31c60a2e6d42022e0b1f1daae90dcba1b96d681a018636a09bfbc8381cf40a502de14de2b67adc4b5aa9706a54c576dd1caad7fb29bdca6dbbce5cac2eb1e65d89633e3dfa60aae7bb0cc818fc18b6ffff18592e8e8671eb94ceb0c2e15b33f9f54415cc9e626a339aaedb6cdac744b85af70456c65c9025b86a7426169cda4490dc7f20d0220467f6af1ed61d0b39bd7cc4f9e94861a28fa6f27709921625b455c2a5981634b644f122be630c593c15b16fb21e9cab0fc7b0140c981652059d2310ea20e463dc56e7b203c1dbcce46929b2013bff2270b86d4951584ef7bc2472febdcca611282f3dd2a3026e65945ed13d52e629d6d6a120b1f6442b75e0b2660e0f05824ce468bd570a388c6eda0d4b98552d27b9aacca2bcdf7f90b75243f624e0181f20683e701c397f4118ddc67c11ade82127f6d66ca2b4137aa4876cf62bc50a203954cb3460a6f509b816726d7b0427c7552a24e1ad207087af15ff6e5619ec37622a69b1d98b990ab979c98b9a66995d1665017790168ae8b5dd1608ad0bf62c35c2ac54ee3c95f27faeedf474fcf1fa50ca27f2087b110a88585c255830f56048944d2868c4978492fa514359fd3ca4231f9a3b7689833643ca183622e8cd9639ead81d38d3c3ef6a38a08f0415e8f2569d4b698449bf2c5ca74346454838e92bf4ef4200963a061b35007b1a77d0b68fe244fc7a65c339aa06f8fc468150d649eee8dd05156213b4b376830067601b89c2f3ecac6db895a8078e65ff80e7d04e60ab0ec43fca15dc14d5312371e0b26d5cf58477961dbd96fcdf2b31d78c450fdaad5e9bb9248f6bb0cb58946f2e01dbe23224e6af11e5eaaa5b6d43d700a8083e97f57984a6c431796df3d153e6b310d25c37fd451bb16e2ed028aa7b09e42e10f820389a6e253f09f99692ffc4359b494a30096a3eb8a5b97c3aba02933a37cc732e055d41a2acf695dfa9d59dfd5627864efeed20c24ad2ecac463db3c12b4ae5233ea7370c02412b04da5cecbbb9154f804dc0c8e74e2ac9daca31a3b872cc38779f9c7b1a6ca93f2c4f6d04a6b0f3e699c8a40511a2e3b9fb7f8972661796817ee864c2396b7b2a9f349d959b6fae1d66ec9104ff9c942f030e65a8aa546173676eee3beca7af1636aca17582f30829782e2c9b1b9c72aaf8060563ab378657bf91d13f2dd4f1bb6adc1d6da398e1d9b2a4884c63631d46aeeac4ca7348887106b8f07b427790d1cf4a2713ad56af6e1e1629ef93edf14348535e50013d4a33f70273ba18c23050e010109645dd600bbb52809754ddeaf668a72b443d63901a6c759e4cffd958b68736a9a1ee2ebdff616811e63d43b100947549aef12a6caa34d62c1fee27f253562286a466c2b2f91a711cbfaebc527f705bc8bc7351cc7bd57d0af9f150e6466174f1da6ac71c79a2a4df82d44f585a3865f7364024c6f9a7ec7442cd32dc7566e2531fe4366ce5e22aa6931f8d2cd5f258b334011fba79242837b662646211a788b62ff54a6e9bf54761372954bc5b1503cc1b49403054b96be468c1f8b22ec177da74fc851f7562a10a49417b5b6a76168f52931be46aafc2211ceb98056a1bd1102545401d8698944771e079f3aa93974eaf9960d6bcbf23b14834f0d7034f8d5e6589e4a7f13f65e72705884ee8dcbf1360274ec269f1e31a344f8884e5ae3450628689e6356669e7a94e43ea1ac65578a8a21d8cf64b22197ab966b1a20a098fe08768b0f5e53e25c71864a657cb42ea209e757e475ac343e5f8f85b776ea6276755f5d9069447d01bf34604c0389a5a80b7687ca74dd548b3c5d98e4f70c9a85d29ddd2296fa1cb8be37e5d8701af88c70c55baf0ef059358fb8506ab8dabcb8642da7052e6493cc40a035dc86b8d5c88164976f31fc1f72c9a86eccbe29a1060e2a5b0d6abf7c452613018b69e8385b7ab509e460dbd802cd49164665229340e29a14dcadf345f493f00ebe1d829515c6528b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d5e8fcf6841f2e94ebd740f848a2b4e72c31c7a21aea6ae8917400c81d43bb522b64c2aaa0a1986e68954e4ca7b5784088392fda54f4dfbac75e454458e01583df2218fc25708efa7679c23d318c33cdbfce6be7e9125002352d34948fa8b3a67aed933b6c623a04853e8e76cab3219c59d5ed56410b366482128627181b5aa4eceec7f1352a57bf84ff4eb62099a8875cc61b06d7c3dc6094fe96948c881c60eea50f1aa4ca2c2c57af4783c613dfe8392229ee5fdf145d7506ef3d9e559246558463ea4005ea0f83e358d15a789493bea81664169d09e26df8e8e3a2361e6226a54c73b0bb645b846c9bf3c2883b4936fcd3f629f9d24086d9ce4c20cd226199884cef69623c717e7aade3c1f270584fa38cd0d9b6a56045e318ec49ba8a9615abed39d47633eeccd98be10042d5d03d852c5bd930a89f0ce256a9332521f287c5b3a221df63628851acb241908838bac9774b28721290f082f7b143e8d102756d8e06152648b0c9f937d26c08490a5752ece4b16ced9ed97d75143de35326b6e46ad517f13ce464516302d89289478f09e15905bf5d8326d95437860df2f72c0d2cc0f3c40972b07c54745de572f912a58b2bba9c42f105f09be83e69491690a5ef93a98dbe72b55880c843da199106393fa4db8a6f659207f6f419b31a678ceaadcc3330cf95892fe9ec136744640751b38026e009740867b10de8eb67f15a03477bcfddddd9319bcfa6de112cd37ab5040bc19e0b3a52f039a6ba60d2045f834a3195e89e19ae67d96b45a0bee0beb3ec45595def5f6e8fc37ba73c0515e6ade7566e5eda3fe184f22a89211634ed256471c1f3e0f3ad64717fb58cd0a44709a330f39d5e8cdb773ee71afdd2f9d57b44fa579937be3aeaa1adae3b57d047ef28d1fe4a0ee885dea9edf31e01e23e896796b8fcdecd44b4b180dc7e02617563ee5edebece3368fcbf345b930c92fca7072eceb55222b960c5f7e0fd54d58b2a296fc8053d12508a47fa99f2cbd5b7fcea38d04fb896e5421661613af2b53ae7f9cf9da7141efb199d0830298feeb364ff4ad75fad31d8e7285e6d63e4c3f149c65a859747611e99d8cb5d06bd5eb20c5121ccc64e431ffb0c6981f059d02a6924cd1ad196dfff80d76bf99383b20bee491a49cbe9a66f16ad93859533515ecaf1ce37791cdfdcdadec44734ab9a4e4d16a25f18d2e207f66037bed355c32f0b6a53e8785a5b3392bb92c3a0e904b1c0e100735390c8676dd2da11747fd6014c06cdef71226f89708e71ef9c6ab3d95def2dd7f487e42efa411f4eb05a33bd833c6d57f623b8f0c8ed846045cf44fea32bcbe0bc04e118f3922c6a45c890e469de71ef3008558f64ece794dff8660ca2d18a49e2e7b3beaf1e6c903da7e0e8af4d2400c18023b5de425d219f9efcafb72aa555fd994cf9f67ebeb5de47b6a84256e12aea7e877a8b9b5cbcc01119aa6a8e732f551d99dfa4fc239739c0c1d9c415bb13419d4c73469ba912eb7d346b91629642940f117e1aa50a09fd5dd48caa48fe936563f4a200c29d77a80f5657781f6849373684b82a029b1fa3d2c566173676ed7bb07c67c2bc80e7d5ba4623f8ef0d565d266723ec60497f0375b3bac140000000001000000020000000300000004000000140500000006000000070000000800000009000000140a0000000b0000000c0000000d0000000e000000140f0000001000000011000000120000001300000014140000001500000016000000170000001800000014190000001a0000001b0000001c0000001d000000141e0000001f0000002000000021000000220000001423000000240000002500000026000000270000001428000000290000002a0000002b0000002c000000142d0000002e0000002f0000003000000031000000143200000033000000340000003500000036000000143700000038000000390000003a0000003b000000143c0000003d0000003e0000003f0000004000000014410000004200000043000000440000004500000014460000004700000048000000490000004a000000144b0000004c0000004d0000004e0000004f000000145000000051000000520000005300000054000000145500000056000000570000005800000059000000145a0000005b0000005c0000005d0000005e000000145f0000006000000061000000620000006300000014640000006500000066000000670000006800000014690000006a0000006b0000006c0000006d000000146e0000006f0000007000000071000000720000001473000000740000007500000076000000770000001478000000790000007a0000007b0000007c000000147d0000007e0000007f0000008000000081000000148200000083000000840000008500000086000000148700000088000000890000008a0000008b000000108c0000008d0000008e0000008f000000109000000091000000920000009300000010940000009500000096000000970000001098000000990000009a0000009b000000109c0000009d0000009e0000009f00000010a0000000a1000000a2000000a300000010a4000000a5000000a6000000a700000010a8000000a9000000aa000000ab00000010ac000000ad000000ae000000af00000010b0000000b1000000b2000000b300000010b4000000b5000000b6000000b700000010b8000000b9000000ba000000bb00000010bc000000bd000000be000000bf00000010c0000000c1000000c2000000c300000010c4000000c5000000c6000000c70000002b000000000000002800000059000000020000001e000000" //nolint:all // resultBytes, err := common.HexToBytes(result) // require.NoError(t, err) // From 8ce531c618b7683df663c66849a5c021a74af3d0 Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 5 May 2023 18:48:30 +0530 Subject: [PATCH 43/65] fix lint --- dot/types/parachain_test.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/dot/types/parachain_test.go b/dot/types/parachain_test.go index bcdb8b2e1c..0b42dd864c 100644 --- a/dot/types/parachain_test.go +++ b/dot/types/parachain_test.go @@ -170,23 +170,23 @@ func TestCommittedCandidateReceipt(t *testing.T) { // TestSessionInfo tests the SessionInfo encoding and decoding. // TODO: fix the test -//func TestSessionInfo(t *testing.T) { -// t.Parallel() -// -// result := "0x01210350000000fe0000008000000096000000d200000000000000b0000000bf00000021010000ab000000970000008500000051000000c40000000800000028010000a700000032000000e200000016010000bc000000f9000000780000000c00000088000000f2000000ad000000260000009400000046000000120100004d0000002300000009010000cb00000082000000750000000e0000008f0000002f000000f8000000100100003d000000a000000006000000c90000000f0000000501000065000000540000003f00000098000000d600000047000000b7000000df000000380000004400000007000000b9000000e70000008c000000900000000a0100000b0000001901000042000000af000000020000007c0000007a000000240100004c000000010000004f00000063000000f0000000c7000000e60000006100000025010000d70000009c0000008d000000e30000001800000019000000030000006a00000003010000ec000000fc00000008010000ff00000058000000b10000006c00000043000000290000005f000000fb000000a1000000c20000002a000000be000000c3000000600000003c0000001e0000004a0000005e000000200100003e000000c800000093000000ed00000073000000040100004500000009000000d50000009200000076000000110000003300000055000000a6000000fa000000d40000002000000086000000aa000000560000007b000000a500000015010000bd000000b30000000a0000006f0000005d00000005000000180100001c0100001300000069000000e500000028000000a3000000d30000000b0100001500000079000000b500000068000000350000000d00000031000000e80000005b000000260100001200000011010000db0000001b000000d100000059000000070100003000000016000000870000002c000000240000000001000070000000360000007d000000480000009e0000008a000000270100004000000057000000cf00000067000000fd000000f5000000060100001d0100009d000000cc000000130100002d0000007f0000001e010000b200000021000000e900000025000000ac000000ea24d73b1607c8fd7d6542870c2563c7891a9085b74ddd253d4322a9b3d3d1560600000021034a3487dc0c46f976d352e5e152e120d2d23774f921583d1f2c128f7cf9f66529d49f031c94d9c3b33494849eb9682c0311b3c283b17373f18b9ca02d94e2c05c969ae5d9d6efa40c6255ec4b27b0a4752d7f4068163116e76cd0d4041c471431e8c13e37a4d00135dbe7699d91507f5a53a7b8ed36a3be29cb2fddab9f7a286c347964127e9d8bcd119989a92646c80886c2eb8440c87dd7dd94437873a3ce286432533fdbdd1a739c62733cb36ac48c821dcb0311978f1027bc1e39d4c8964e6a6570b80ba0a90a857ef4ebdabfbf958898bdb12ea1edbb17eb903b00746a14e059357312bfd525317b4f93e5eee1de639872edfaec9d2a320a6fac04d6105188fe28737bdbfec193327886b5c4906675d2a49ed43fe8cfb4e079698de82d2d042cd5a9d8624860310a963ed20c4192a19a9d163bcf366e48122c00a1e9744c5cac0ffa042ee550a3bf70d380dc032d11eabe311e0796c5143341600ef626644eed0663b1d15bcbf9e99c372c041ef118de7d179c68899a645a0fa0983b473eb2a1fefc7a956231a446a575db2e31f7c084c2945094f3927519617d7b913712c60cc4d544536a7190ec68525a70fde1309723986ab984a1e97aca4092ad721c744c3b91b676828a5f884e79d9c02d6f23ec246c3a1a8adcfa9dc1e531a9a5310e2d777330aba66c9558434a592fa5e5aec49c3a70f49f66017f194d41240d66148f2b835556a0c8d3b51ae0e823655bd4aa20fdadc6b4189de9f32cf2288700d8eff37aca87eea6637118337fb1704bc33f1fc685aec019c8e9eec48b62a728a8cb454f4e75ed6d28c458cd8df1c2bdce6101e09b650fe22d139e360fb809200ed18130a0ed0513b2a2bfa7ed6c9090cb350983746b1936c6a92f7304a7005450b1f33df75af8dfeca1cd7e94fcce445c6d55651259fdca2972a4d62f6732561af7dc55da09babaf097d1304b4cde14562506f4db4897644895324b542d8f573c39b3f67c487c1df902d0397792b7cdf987b657b2d27920bc6846eca466c155c4b778017656b9a7d69d3e69159852f38adf971f5a25df65f9950e97411c1c36e8bb9f2665b217df30a15bcd22f231f66f4f21711363cb0b0da8b3594003ae014e8c22d93dbca83c05bc5222ae72b85617956f04eded477369ec95312c7c78353256f3f643ebc6300f32561a0a5583813bb3b42844d1ad3d3779a438771a295e306daa91a5a25590d2290fd262d40f239f87d37e1c03a2494035a42961db2f33407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71482cdc214f825dc7085e54a984230a753d66d08425f9763f52f8f68911120260d4d65053a5ef2ab1152c72f3b15d4f24d4bced3b7e277735eb49450dd867c115263ad657e55682de826f6137dedd2d246971fd8c5d318034940160fc179efa63701058e68510bdf68a3678d32145780e13c29b88fe77b27440bdf3ea9762a63964675cc62a59886ce5fc12d2f48694c7ac836a0157e0e6630d694d11faa605034c51def135330ddca851fcb670c865235dc1b405242cf9f7ccb728e449e09f4ad614110699b5642a4b726cbcb74bee77642ec7b4f17b06db88ee461848ead17c906f769166b3ff9b0fb13c1ccb36358d9dda3f25bfa18e2857fe01a92328eb70cacb5514b570b9338c8602cd4a49128006a902494029c2728056b02a900dcc7798b499a9c38970f6f3dbee7e6220ee0e12a582a76ae036347816baa6cd7c9a7b9662caa1a29ff92ad66794001cfaaebbdf4071f4db6d74ee767ba59cca4cb36cac6854840b7eb103ce5723aa0d6625709d4c4378c46903ff236d9d8d61f21f76b22d6245ef2ea126366dae7f9c072d2d6e0e71a54c9bbafaed36448a4a552b51f02a182d14b38906ce1f4693cd9b87d0369e6af514cf7ec91455b26cd4c0d71bc2d3f9f9f499e04d2f27dbe47ffbce115afd1bac9fe116ce7fae719325e4082460c09defe1f43c8591655101dd3dc806c7b07762c97ad21e4142705e46a1e17306b888519767218eed7b884fb221f597a2d4edb69c094961ace2e65a7e40913c0658f8f3a64ec6949a26916ae2cd976fe531947a9c9e93e6d587bac746cb0826e4b23b64b0eaea19cab0333369b93e11693d2b4334306ee579360814adfc1339524dad3d2adfad0b2db5fc2de781a22fc63dbc4e30a5fcba2c63c2fcbda238668e06587bec427bd5b5cc33da6f7cabaebcb7688de50b59125434493fadcaa94d1e0560d2b374b7d6e1380b6b88ee8ef92cdde7edbd9a48d66f5e219840a1155818b9272f50007b87be88422e3da9599286087f5e578c0d1c2a3db9a77110f9173a69e0e58185dd4e76aa52804b2de15ebff8c3f3237e29dc7157e61b30b9b00a30f93bce6916b6b78ce4f7d550c39c7947c6860502333717d541fdb6697ab447aadd01c0f366ff1c65d331da120ca3ac630ea6e8d7339e7317518920d710e3325edbe8dcd591d30511a0fc08bc5172ff58ff98fa848387b25f99205361348105f6c138e9e4061b3a799bf7987ef5c820c1e534df298f3328e1093c5d0758d434280f6162242be89d139d52f449e2bad667d7d974cb80d0edbce7237185b11475fcd9b0171f73154a0734c1cc95ae552d9f3180d7d64e8b50d3837b14b5afd2221808dfb6c44ce63a08d4567cef4b2a9aff1b408d2c99fa4adef25724cce85368b429d0687fef75f26e5503379a61920777ef1f254af024922e382dd19e752e69784ff2911acf10ffcf4b1d795df6d8b55f38eceeadffe577cf5bc0360f35005940c73278b76425a158be63207452b1a8018f53309f47486a273b9bf60cb51c48d67770af6f19ab75537f06388373ec17a3c88ff1714806c0c99ad44e6dbdfa713ea7825552b7f76db8f2ba2fce0e546d7e7abab7d59e7afee2bfe438bad6091934cc7903dcaaeddb2bd99fd6b36ab15fc32ee001bd1d95e87020019f7c88be2e74afd1a3a66e44e8b7845e7f63923b706dae49eb96cdc73b04c9e6cfd1459d06d6f02e6854e6df29f08f7e015d511ff48d7bbb13bacc9aab1b06ab73c1f3350ce6a864e68dc99758ce2920256f75bdbe8c918c556a5a2467a3aa13a306808740484d1bff4961f87c7ff6a6a68beac9264665f87ba1a5fab9802f1cd729391a718a7477bdafa88e49f5c8cd88fbcbc1724d8e227935eabce71ec303d832c4ab27aafd3f8056d3462eda0083ac22241db692c4671249a14a04c2f0a2959aab412660bb493e536e83addf98be8cb2a0158cf18c6d5ba06ab586a2cb56cf1ad4cd099ef1e3e727f41ebeb3aea2815f004002d27714db121fd6f92fac8bedbb97160976c4d221bfc6da82c7055e469a1405eca842b4b8efd101e984a2482e526ecb085229a5a3f09f444f6d39d71e0b936cfed125e87883db8876444288d0cbd17642ce97b61a3cb7d20f9048830a34520de889098b4435dfc79a73a0518ba9f61924de365e70f8503654e384a4524c1c16900873792541ef023019a68f62250b7c219a149b9b68af793ab31f83f500126e0fffa71469e78e22e754f3b49db1dbe631f286ac449dbc94282864e76dac48fb9bce48124189d2d45e2b2e16b8084c022bcc90ef1acebf194c7b9820968e554e2ec4d34346eedf80cacdafcdbf118a3f158e45e6a8766869e2e5418499d3cfbe215762a4a0cffe4315edea5ef47c60c163be4aa5196c5241f5c772f3f90c57a3580fa0735a7340e37372048c1f60a20531f830d60634a177f3974d5399fca046417a6e4327c4c569d8f4f5b47b263b0f07408b1d453ae31f699e53904605cfdbaa72639138cea3e544258e0484a532216372ca569751b32be145716eac8ee5e731a1db2b1dae4b9023b05876077cdd78084c79e58d16ecbaecee3965ad4685c1780154b678bbfcf725fb2e91be3cc0864ba0f682ce1460eff27c8518451b3a9ec811e18b8839808256e18a89219fda2772c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416da5bd7647f8d8388c2b4dbc138e36b8679284eadc49370ce0a16a4e0be28804b04f9b593ec5987c0608e3913acb29a322355a554e010d33acf155e6ab9bad337c4bc688653010a7720d44168b4552bf75974219788ac1cf3fb440c67ff692d499e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd93257121806eb5dcaff87a28d25de336e240731a375be04c4bbff6be6a5ba4f1042a067086008bd1c894c74e4ab0b16dd36effafc8f04a4617aefa7f68b40df033149c0a98bd89778f1276a0ee404b17d81b96c524a8aeda9f671be9e724f090c397977714f425d45bda5f3373c374e9b2710f477e2e923a0f0b2b259c941965f6e88c0334fe5947d75ed7ce18612988df5f227b149c66f371593a8c248206f1b59e10248e650f7e08ac882d65fb09141fc5c7d252da9b1d8ca2ae311752ddce977137229ab3993dc198b5cfee52c273f6145c25afaaa6de14670eccdc1b61fd53821513fa519134b630c1d53b78cbb67e8b8414c30247101be5de118662237b8388cc7d3c50b2fab9b87f1a6228df23e9507c90bec51b8e3be978b526c0e0c7704c7334dc8495596755b6b5a83796315f9e316bb871c0465cac91290b34812c5f0e34120ce455c4566893481e7afa89c0c425533fb4eecab574f0399ca29b162a4c78053405a94626a6d3cecc0492a268e974e9864826f8745403fbb98f55bf45c0b620da0f2b6e2eb2808b3e713d1a3f774966e3e00f81226887d5e1c165af998d6e57645c3b5a2e17df20f698507190332c6951d761c5f46e0dcf997c7337c0bb7e54e232d9f4c8884a9f53a999e8ce7a27f68e9108a4fde15bc51a350774c22b2a1480fc5fd10948cd231f68ec00397e22a19042578431aad63546679e72efa3cc619c9564390d54bd989ac1fb089a57964ee4313f857411373d34161939633c8f4230930357b8b54ce94dfac3276daca91ccbab9b944bdd9754fb27d2b786427b30b6d3a029d0c998a49c406fb0778936c3bbd0708774bbf21b400aa8a41e604401c8e5f3c9fe54712dfa93b8f223c4bf30e2d037a36a768f160cf0c6e6a8c42a45908fdba40941f018589894c721ae6eddb3ad080bfca4aae349a8e7ae261f0a0f18d3fcd225254bfac8ee7f94e5f505496773b69c49697eb79ef8523530c55511106827b00917fd22c6b8e62eda5e130344c9214f2565b92ddcd6b6edfa18e95f8afa23b3c8f159391a3ffb6dda5ce3c9f6b40f25c1dc7a742186b7b693f30111e4b9ad468b9d1e0cf4f79c5078c9cc4e409f8a0fb170d7c4f421ed5fcf597e3f061f1060d5207533b44b4977f128acd44bfe1bfe235f2f4b2d042a87c7da4d1d526a096e110f710d48d0a0bb58b06ceb1d6ba2189ac3dc984dc24e80fb6522431e282ef8862f121223f6aa19fc1f929106d7a916747f21e1973eec1e8c5b7f78cc3ceec15a5af2b64d5a43ae54fcccd31ddabe95461fdcb5be506267404ba432e41161e6df14443df6eadfb3c5ad5228291d1383cdaaef20c9cc8125f7952f249a0de7093e895f4c599aeb4b0310673b00785b33fb9cacd556acc9abdc3de57fc056df4318d12a052ab505db7d06dfe03767eb5f46cf0d271393db1db2516c52aca4be351c39cc0bd557e7afe547a479f8a7218cad2c784e197f3494dbb9436292833db878c0dab763cdeac36e752c7cda12c98686c05704a8b2a695a315bb1146b3d1cb07cfb8d2e13fa9158734dc2bd1ea554fd3032bdbf9e9871d2937060236da4573a6c20044052b270916290b13a30adf3a821b467c4038a14026badd09126d6621e31b47269829a47f9be24a0d63c4bd7ae112b395498ec2502c3b4f46547b4c766e40db6b1685c455de210347c5757ebb7d463d1910eb70fb290b5c7bc63163ac00341573dfc794b0d53e6bab40a84e60ffb1dc3f6642aa1a246ee579703579df75d2c2dd3d53003f55ebbefeb59446d476d0a722ef8ed1954fae9d6ddc2f1b5a31a3e46efe8097d83d7f80ec284bc72a48b7916a74a1cad145eed554722609bff1c0970e439f19fff06a080a67677712b09762b90a82fd9f97bbc50c12b2408a440f2c91824179203d689db4245fa3087e8b01a9316ba973c6ed1a7556aee499b2dffa90a79b118a646aec6b79e6766dc25665db73a98e173fa6381ae47c9de57628b53ed9958a889d278fe707b4284327bc582599019bfc4630616b78f186de80c5d2d0669404118ff1591ff141a606e05e2835889a5f42a32e9a1f34d4c6438f429028ba64818bedeff64b1db1ebdd89f2c2b2fe3336942a03036b9e86a336aeeee1b94c5d5a821e4ab4c136cbf2766a43dd37078e02927ca8a562d2ebb6671ff854613aa3ad169250e037aadbf0ea14c87982d7382f09c7b8c96770d2ffd3b72525806a645e5abd09a51d257c30dcf016435c114d26d3d3be170800af2466b5e4a434ad5ef602a77f311fa22300a5a6ebf03bdcc04f92fdf0da3c74f0c1461d8bef6e668a2cd0c95fdfc9ef30cf9133619aeb9c3d5187f23bd83c765478a56c4b3708da965c36dac2e8caca9398d50bff836219540b179bae7667aa091181db267cc8ff6c5201acaad6fc2c3a2cd18eb729ad0c1526c6c348e330ce5d949162cbc728667ecce548da5efe0448823e928463418342d41883dc6e20d8e45f1d6d02c43c3e38d6e7871f18ee80f60415adc76fdf4c8ad2c67ac7d11682942ab79f74656a8f51ab8c1b088f33ddfa20992eaaae491dc3dfff9742fe32c4428233d691dfb69a1713087e4fbfef8f7c96df760e85354069eef1ddbaa01d52f9664fbed82ddb5cd6ceec78143f1e27ee7a0fa73873d01e80e368825e3b05bef7cb0005833a9d0ae360c420a66a5353836acf1fa3c65578c9c5b3b9c7831e944ae887694e9fc6a8634f213d8d061cc2a34a00f214d9f67cd17effc527a07e060bea20b143a7bf515a130000f93cba10536a1204f0a14cdba7b627412d383c308672a7e2974b837e4a89d54e63c47966b36fcfa3efa5854046d3ce09d45f226c36aa9c0762a59eada83c70e1049d5d09f7f7304c465f2ff56dbe21687ece20ae9fcd9ab8a7020a1f967780a1ef49b13b40fc3cfd208e29f4d5d5ee9bb63c5fc81fafe5d47c4ee373a54a64d267c497c59f4c15077374317b91566d44c82f74167e6d847ad207f3a1221ce1f958946317e77ba146d16aa7bd82810c5e913c4da0bc5d3a5923a156f0990c79f01317a3140ef3aff708acfdcd30a838706db819dc3a5a9fa2b1bed2a4a48fb21792b44c5772f888132d414d13a98bb5bbbbd70ac42afa68950568131a449e70574ae0f45f28b87210c1ff7df1adee5576d03950b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d9a53c2f9f5f55bd687e359ef37196cd288fcd1a14adf6cad53c6704445a1f1212270467b0c03fcfd8bac09473161c6eba9c25369a853193b472eb2f113a3d333181e6b71b981059fa265cd76422e52fe175db6983c6ebdd0fea1a3075166b9291619ab90bff00f89ea8055f0d7d45f8c8aa9c04b7fc1d06468837c6c563a6529ba846878e4f157741703bb4c3ab4f3ff2e9b99916624a9965a4256d893c84e152c19794d20de22edc9c4c1514f4f4e29ac16e6b421d3620ec6545f737100f0134c29c11128e193f06c866e165662d903d9f799508e617920d786ebf75acd267462237ad2bb39f6a5a03a46c5a1dfdd3766a49e6c864ac5d45afa6400ce3a9809de464459b18deeea6f02d5882e80a8696b00c9f703da84bc5769921053ecc749b0cfe1745dd408f6dfa0ceaa1780ad4ae1747a8912a589a754ed86373a08ff5540a471d9a8272b09df08db1f998000cccef325d072ad79df6c1936cf0ccdeb77a0d9c323ea08a0551f96c28b05ac0c7b0e338cc5004bac22d06feea5a8f5c00104906813ee195100f82600e56bb5756831a260e4cf6e5ad275364130dbafba4ed4f9db6adcdce67708905276a01347cc1c800bf6ba246c3770a81c3c754fd65bee13fa85260215c5235169fea113546e7b4aa7a1c936c47a14e81d3df912601a2eb8ece17888100536bf7183c579eab3e6daa14e5e01602a2fc3a64b563f591f0828f0bfffc49973cd14329675728a2d243102ab486601f1581b1e741bb5c77526552839c17a5dbf3b2f90875abc9959553b320da9f07f1392fa3065315a8b1744a7e5b271f9394d6e23bdab9ae03491f51bbf21014364d919388b7fba4b5341bc4b759fa4234adb292ab984f7b69d3aac2e0afdc7dc075e18ad22f4456dfa48b0acf62c24bb58eeb0a71365ba5f890a594cc046a483d9b306a487ea4eb5e80572d3ac8b4dbb4b6a02692af692160b113da09d4ae9f0464c5522b7236a59b70d3667fd3b0c5fdf2c30cccdd640a7297da408b6aff82ee9651f889910fda9f24c706a617b082d626dfc74a657c5d17c5a763044f0230972fbe47c907a5a8fb75df4afa9726d496332a25823148258bf60b189ac898c92b9be15965a199a45ad563efc761392b915b58613f9fb99f45c9a78fdaa4358874f739cee7ebf2a5cbc2fbee73e2731e18f347de520f1878f0eab3a38f377a9263ad17333135c991d560da02f9a012221d644717e2f1361ddfd9e6b5d0043f3a47eeffab15e43d7d45e1f6e07945d95fb46ef5346bb3a502da9f005d1cdc956e1b96258fba48dc793f50b7eeab48cb88c51118ced6c65368c5197ec7f014c443b47d898627cdb7781351442c44398d0ea4ca4b697ffd505665531e7d4b4406431f2328943e8b72d030842128714ed41e3d13b8aad0d076b7ad34af4946866f552568eadd3d3582b4c4f50d816c065e65b3583c8309e3465db95b458d0b42619e1ea75ca546e966d761c53645771381f31a42a1e0bca62f752fb49e8d2a49f942cd48a03129a709e763d23aa4dc84c88423861d1ef31f5df99006156570aca69e571067899ddb156a2027e0acb8f278b4e156f96ecf0eb2658c6504fcd39e4e20bfb5905be7cfa05ed907aa5041e202a49166a5e267724e5bbd0d9efe57d34d8cd7a2e536cc7aee14f12726065cc08d547840066bb56916d9bb9761e05133fd18a68324492ad7b9f9caa1668038a3ae897ec528be2ca7c977eca6cfc08a00266e96fd43a723fc7226b66aaa86fb8c0ff0094b6feeb0707b5cd61797ca034755fa42aab8c5c9e245157f5425f5d9c2de89a454439ff9ddadea199ac62ed47b9326a4a08c06859dc6aa56cf5af62a035f7c6b0546f536c07cfd7a2d8e3be9ac2c7b7e854ebf59eaeda5edad7dc23e83eb30dfa3dd91753614a811769d6a564e5e2b27c43c70d7497a0834ea96e50b6edef3369e8da5f707e530fcf611301be6bab8187386d130d1f8c94e5c3602ec613f83c1ce2708d6fceff206d25c511772a85eec3fe2b4ee066681cc6c58313ac304e37b46e43a844db9b7bcda351e09ad1efc57db99dc2a7c12e553ca9a60412dd6bdedd4ded92b9647ecd2ce31eda2a6f5a4ef9df833b9b4c70ec0924a92a7067757484a42e2e39a2c58cf41f683c3646c0e993fdb61ba33306f7524ee2733c1d970403cebabf7a1af318743767411fda52e046b2fdbee1680978da2f66413a00a72c2f0fd68497472feb62d2481dfa1ae93b14895fd3773d48635738847d32c4252393c6cb8e07655646eca309a1481552ecbd9569e94a0cbb6905c45717f0097f3dac95ce491ef6f07d89dd7a409b0f13475eeef708fbb0cac0f200cd31c296fc0f38221dca15bbd3ad95092e6a4f38b8ef8e9f3b9992d57409c7833c0e2e85194adb91496335138d5815f82e01ebc93b757c1ff94620f3a87ef48ca064b8daa8790dd2fda2c3493f33b66804385212b1c3747f61ba6de535688b2ec24db2b9bb22f1c69337d131a4c91c2b70f1b45fa522eb556b7960f937e6fba63e1a5c832c850ec9d476fa68c807d36d09edf0c1eb9b2995a3812cec5092b90c4c724a2e1e42195049ba8878f1d05a2e30251a57f7f4662d4bbe42ecc98b7399c13a00c82090e61c34b4675c01815b7e25a1fd09d2fc60f60ec1f3f435096790681cd676c3554c66ecb08ee954d3de09ddaa2e3d11f5fa4f9d4c89cbdce2c3accd6f9495757f069ede7b956256595c7d083b47c610efce658762467518bdb11be9597e37db2ce13f8b1b0cc42acf317bf5a8f948dd3977725de1590421117c9ffd003a836e898f478234d26fc7d8bf866a6a308f8f7cdaab738bc98b879669911a26d87f69b187cd620e910289b9d5c2704d332359fce4040b4978eb1527e743dc15407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d7162fa40d6ad22c0bd13811d9555f4b2adb0f639cf7ace8468db36e557c1e1176e4ac7db719c3be3a8a8fb077e5aaa181f69f89547570b88ecaba644b0c8623f793abe63296589646fa4fd48c7d15548b46fe4f60435bf69fb31260205482eab0226b7a3b02d5edba566f82d3f949278d4d0660165857965f123b1ff5aa680a62c6c7b8a1064cbfd234f3e26fcd14b1eb52a0b46a47e8a8d38027bb3fa2cba947124c41b6ccc361bdd655dbd0f0a5b5e7c86fb1bf779a912921794e17746c37f40e0e4451bfef8b6e07bc00ff6fe17cdd12d45db9f816cace50b0682291a8dc257ac131413580ad09206331a67387cdfbf12cee28aab9a8b0aefc03d6d1f2fde70a8c597075eec72c0adb7c050db76ed8d86e7785f056db19e02775ea099672c7f447c7d787652ba7c318efbd758620236476ecd6df6abc2cadf3488c7e6416c12b8a2bb40ce3658b1d71c42e68495a5504986f38696e56ba0fc2df70182a5b11fea0d61d2472c21da757115c4aeb85f1ad06831b0b41779a118995340fe6c352e6cbeabce345363e57dc45931c6bf8f278f704cf252234e0e580741af38024e1536d3b2112224e3432e605d698c7809f9599544725f3bbd89e076742a2e33631e2caf02567c87ef2729ac221651de0efa7ccc8de802d0ced1036b68b51868bd3686a8ecbd7b1a217342e937037c0bebc6a026371b85698d124c09998e5a531b6cb276cf5c2ddbf28d010e2a6976cf03488c0d1d11c5c1f9b23d7ac44ed221724baa63a6245db826d277bf7bed80169db1bccdc7a3eb0ae7852317a5fb2628982aa0fff7c6916548204396e77dd2fc044e2a37c192789053627b2c81fa1c0f3d1f7482ad1abb0ef6ca6488989637ea1d44a918f062b169f1b802c9ee6d05a2fe34fe3fdf6285d91ddb739bc5c2481ed4d77589febde82e624d0af0ff9796e5993242f7de325ac001c0d50c4d27c15248ae2023cbc52e2ee969b16fbef249ee2542026074c387dc5714b8038735a05a39459797ad1f591aede76adbce55e99ed94a98b68d8ce62060e2c77262da54a918fe5942925597cad811f00d13599f0062784e528241405f8618bcc663a513318815f67de9a13e6786615542b715d6d2bb3d82580e61b8d0dc0c1652fcb6ad0fe74186d4f30f931ded5712a16e9724b9993cd0d505f36fdd6c1f2f87ae7f7b7d2a84caf41d8db3d926a728904ffc98ade114aa146708071810254fb2b5fd49243a64bc29a6cf8638150988ebd9756b917719664e74f116e47c0991afa7bc43d0b4aaf085d205ced8ea01235b224e9e2a575626a39cb65fb8a0456f4f5380b87473b2c6d3ae6c36664af57171130202317f567e7a89975b0683a31b08cabf966ecc62d48ac257c297ac4825c75e59c4271562da9a7597e0b1d1e880416c0a36fd5d9a8a1a0e277025e81af122c541ead22d78609154fd9334b34c1b724aafefb4de93d02e360bcd69f4d179b8f973f0a229525c681a841ce65fe1848e33fe6c929cfdb09181ed6f10f9b5d42b079890c93f6cb63489fe6ca5926a30f68d89fea2985c600a9114516a6c29aa1a9a390358ae11d4c2addda665d13fc93f613f8de4ae6526a7ec8bcc418d9d190bff5fb2bf8a57d4d02ae9d39b49dafea09bc363a28395b90f0c0482be2642d693c65b1dabd51d6456d129d5c987093349056b99398c6c59efe7949aa90e6480719aa04ad8816124b5eaccc793902c3f48b7529b6d116f4e7418406b6dfcabf008b65268d1b3757c713863c80e960241776adfb775052d810b59fbc83edabf4b607bd44c6a610788c1cfeb3f21e0b94d5a12f2615ed49cf7d67abf18a93af7ba649cd0ac29680d9eb19a6e461dc5fcce21ea03fdc88fe1a67bdd4b67671794d5348a1b481ad45e86635f0474f0fe3f7138dbd0c961b000d0c14707c9c3037792e2b59632bef200305908aceeb3388deb21c5ceaa4c1dae6b8ef3ef9ccfca9bc6523b609bcddd0b66f5b305293c5ce2538e4d8e773a6d51cb10adc0c50d9b9cba83e8429a2e2e1e4e1f947c0be485986af1fefb306419c6fc3cc203303517dedafea231dd90856df4af58129352adfbd4c714e33aa5cea74c6e39a097a1155bb8a0f59242addc542e1ce485f81eb5df11ba9bf4e0267aba89ad594b06066c4a7f52ca7947de90772864f98b6fd26bbf80abe1a9ecef909810ecefd129f3a73bd3296a2999b9bb455ebb74bbc3f5ea7cc6eb966a566123ce03005a73c0294531cdb87e6f4e95a515a4533e0224cd2cf5426a5cdcab8c30caba2a0a36831bce623b526cac663bf76f269e3d114a73a0229bbc06b4f53b1f5c0ca2198e418a49af03440d375ae7c76e24cc7c0c46b93aa96c8e69afd833d5c5f4ee23346e35053b1fa6044421208a5fc47074d544333068438bbce32a53bc0117d123ddb9718eb62baa88f7a7bc786758ecfa2acaff06cdc5d550de264d6d61988290e84649f3faef516f21a36b403490b980074580512dc2e7d3e2b87a063a5da17648602d66ed743cf227b0ef5a34067bba03c1df0cbc3cfea77b39ee77b49d8b425455e45a27a245c1963853bd35689e5192515b7b99cfd14d624ea54dbe5eea6c8f22b59babc3c6a3ce22286f1a628b901883b088d7b9dedc64dc86f636e337839c21edf802b526c26346ff314ac02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c24165804d109d88647def7d8362b09e103f65285c88ff5ac9329ca40a9c29dca4e073034a4c23a5fe2e1a82fe0b885d736e57a0883291961a087a2719664020a574cd8db813d1070487f577a18b9e163ed125ed818c0d13dde40503a10ed6c8d3e6a9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712132d3fdefa1807e6bf9c14050d63d2c37bf357802a7d8e813baee24cefa76b229d471496a02cc87ca65544c0ef979e7f4c1f0a7269e3eb21fea4e0d91ec4fe86ba67e4ee5cc212e44e3488e61c6c1ce07e25614b8c23cb4d0442b35e6b0d8ab3744512e70a1dd7110e04b778646d4f7b399d36712e40bd06a6907f25046639e4f9a632636d4945986ce97bc67ea13897025c220e7297598460ccd7cedb8a0c54792f097884bc8751c88ee126bd1f3682449da8181bc9cc5b90f0bd9dce1cb0d19441bd6bd7dd64756c6cb272ce5ea2a934c56dec8f3be010f8ea74cc61f20d1309a1fcf68fc3da9660e86c1189f879b8c9cb6611d57d470765dec4c3514243009923ef8cdfac92e83ce444c9a2b61fe92d6043d108129649a3c6ea306c5d9db7b924eb791afc0aacb141b54f0d75fcde46e4682e806926114b2ec7ee5a1a5626a3a524e56e2044349643bea61e7d9d3ae3dc19e660d754e6cac3fa4f24ae46d794816a0ad32ac3690b658c96cc6e09d9510a57c8e28f32220210108791a15aa0dea2e3482714178bee78fee64d0d61e6933d06f8e8dedbfa5ec5cde870dde2d7a9880b245038d021948c6700d89443c09f207b9da66d2ec05e1c567a8ae5fe5023a414b00e01850a90adb945205173ed44279aeb17ca7ebf9a239d5f6ecc9306a868b391a7c49dbde0913228107a7795db90a5e3e91e505d9922c2914d7755e0ca47af8f394eabf539adc4509e5958a7935179f1fe3f8c22b4cc2e2a345933f59d65e0318bcca6caafcefeb3452d68d6197c8ea0b26b971962e201405c4c157653c2f2d4af59046fba73c6d72ca8cc525648416b9b2143dac665457204258b81bbad3d109701bd807e75845178590a4c5b8d44421e0225d9fd994af2aa1d0c65590a7bfeb5fd893b53578b04160e3162b0aae5d6f67dfcb75abbcf01b2ebb106906d47dbbbde1bdb9b1bfa8dab1989c600610422ddba5fabd57a54dc955ccfc7e5810293b5345958abc5f84808fd97351d481e6809e00bee6538408aea7c6c074c26b68e2002ea0633e6c3d7484493771c50eeb727d6fcea84ed9c26bdaddaf73d8ac7ad5aa36f30863234f789eb1d0092f42deb6ca72061146b920d71b457700dc5012547ee806376f3ffab1e2780f491f33a0cb355ea6b677c4ea1b54ab6e5698d2853047a428891a431d89979492f261809be176ccc6f09660d5cd4b624f339e961df7e2cd5aa3f816fe8950ecc0c2c9838fbf68bca5d4955de8719bb6cf79e8afbc8632efb5aabfcaa6e749cd45043ecb13046ce3209fa85ef21441ec2d1a0ac63a273f4213225773647e8a739187223eaf5c9f0f2e3d1b12e229fa77e65bfaa2a0487a29d08064960b2068be68c3c830254caee33d9436053af9fd028474bacd43a231dadc4f4116e333fc9f88fbcb64abea30e650a11ac56a1988eca459d858087e220893ac87e5b5203582ed469929c865ca6e35cafc0886f8e5a9f813f011fb08ba33475f7e9b64397ce8355542f0d31bebdb5238414fbc41ab88fe2abea69d9e769a9b465041255b591fe2708f1193c6a0d7e83e929c167d0f672a6cf8bf480b21d5fcfdf7c0ed21b4968982c3b4798fe04b9e9462fe2bd8fb6c511b1c153d0637fd584e30e35b6a07aa739ca4f37d82d9c8e4369606257edbbb2f6ee4e6047dd8e85212633fba991cea2364c746d0ec558d0fdfd64f2ca44bcc97637e3af5596f09c8a333cc19880d51fcd11a73c7b8eb1b02485903f9c3b3d15b56b6dbcce848e56c21d870a965f61bc53894462a6997e78f55f20ebf32f8f4de37a05611860ed6704be9587f1a0c12bf329f83fadd02c191a288925cf1aa151d387686eed59f920597a10643f36f40b821f85fc2e6b62569c88b32189a52966c52301f029b0c231c81ba02285edfcf032a441c296500e2a2979e4b4b0caff11b6656d131b61a171c4554591d3c74fbc8fb899600114d3a61951d7af36bb8e6460ba61b0015878e7e28903dbcdb802b63c5e6c895e2619c6511dfa0723fc48f796952690fc3626bb5c1a0757a19226c7db6e42ec243932a2503b9b257fa271f933ec2dc395f40b62b11adfb0a552412447e35ac364bee1f8ce0ad23a72daad14944e49b18cc3d5ecb36f4a8dfd602319507ba7dade07e22ca3a895e9ce0a2f59d7f581d176f5b8f880047f3803efbbcd442b7f8b1fe158353183f03d3f6acf46865281439426e64348199839d84de5c3d2441a5dd9c75bd064c1385ca083cd1df6ef46dacd30ba7bc9797085a143f0fcdd6b0c7ffdde124bace833b758ee4ddfe5072a558406365b77652cb2bd1ccf651da71b0b22bf789af3d24014217fea74522e694c399bc8bd5f07c0db8fab186d5ee762d33a5debc1902bed79a68d8420d06fa2810bfcd09e53dad5f37258fa86f46560785713ec711c9f5ab98c631bb3e3b6c5a293370fec522d61149c7bb09bd4256e55a71487db84f95cffaefd2c4a3058c62c3e73695bc27a72c21d264daa0d40c012083c581e4a0dfc7f168b722b237a0ede4e40a7b352f38ccd532d1a416ffb5207d68c2b7b3a6cfd957d7efa5b71446ce84fba254aa25005dd08c988f4dbdcc3dc795d3487566e587f8f99fa6d222c406942f33c9a694d0a5b974d247fd6d4a37727a7eeb184f4139d300cb9d2264e4bc1869026d0ca9966cfa34a5506577dd7eaa826a1dbd86bf3e8ae5fe73cd591837a5d6075a386bea6701e431ace3f383154ebf64ff61e2e4b520bf3a723908aa855ffca926ec6b18bc48a7dc48b52b839507453def5fd2898cbce2c611ba2af0d2434a7152607d997781ffdbd8987c5b14b6f20449493fdab89717e43a14153845b97698e2511195a1fbb646bd896dad04547a95f1941a1df510c4f7990062c0d4fd794bc886625c783228e520fde1dbed723fc9779bef796e04307444ff32c210cfc2275da1aba94d5bd2b963fbd80dda7a9c8ff88271f152875d7cccd664a44c8d3067a4034b5d6101af80d9a2970f3443536302525e41dceba23d8862006a1893e47f69018c2ed81677b4c43016ddd24ba54311aa590562ce1ad6991a1736d972bf0421adc4a00cd631414f1cbecb646e0008529253e9c0169822efb33ce421d77953121b3efeb10cd44d504b5cf47a9807dacce8eb24d53ce62e145835b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d32ed1f9d70028c2001ede3fb28ac4db0b0215889cb331f8bc637d8cd27d4443570c84f2e19c4aa5a2610030e19ea4093bd118f72e066ba44693db5cef94f3905a6740f6b046ac8d7b77f5451a405975c2588b5b82cfb70843359010be8b7f32870641d3606bc050e0383940f0e25880e6b183b137ab86e3ddd52a0ea7024db44fc4458e5fe418d5a7ed1c33878563e44403bf194507c93079ff9105b433e6078faba26ef3daab055a97199108ceea0d3b0dfee6ef4f8ad55f1eca9c15771251d0cf33eead0be3cea163831560bf46c98931a1dd530301d054fad074fb22e5d6ad86e5f79ca0607a6108ef6030015ee05ed6229bafe13806894461b51199f5b3d2ef6d9024f2194253e89d0ed237b1903f89dc510bbdfd982b518c3576659cd39120b53fc4e51e100e83a51da1239f64947e10f158bc42d10a3b20a366b4311370e2e5c4b8c303383b3e579cd1196f3dd13db99c99a48397fe1df8987a58b942b02fcf424a1223968027d877793bf9f4636cdba3b47dfac921296a818d1b08821f45e5edff6c3c216a16d4b6539790325daae1a6400ee446c2b4fd1852c409d43d0bfb72b3c0946f9edc151873293bcf16d1360b340d7b98eda07f00b1333fa020c5b2ab0a4db4d0a259bc517898153957166f01726a25d2012da74a8fcfec104b6ba6b02f41eb730989a90ffe2f8948b98eda9bb5bdaddacaba1ac1877ea8c77247f876b27b3d89aa71714f55561cbdd0ebbc4b24d39b044ca3e3ef42bf8f63b8c642ebb1fcbeccda9a1e3aed8762eaf0d9ed97308e08e7489424c321f49af5ff24bc10f697dde29bb97031ff65fc6cea39036367972d5627a48c4f9cb8ec56d22a8f95b4c20b4a2545baa5879a817128101c28cc253f3a7a73cb74f0c43d609d08eca7f936f1a8a1fd902a4395ac8be7312d9eaf784c761cb1354dd40baf3012e85eadf3fb86959768990ad2c8625a553c4d920338ebe25de23761c085102555e30cb812643fc1d2857c220dcb944c423397264da353d5131d0c70933d72b55d021a519c3d7a9c5614710da694bc1e1b7d5cfe40931ce3f0e1f35d253566b238265670dbf08b30c63410be69245689bbfb89a17eca0f6c9542454b1e92ed9421ab1827a2f0013b37d7a0653c54a480e1adb20f4d6621955b8b41b7fc0dc7f66309c890258c6702ea0943d8a32748f67d8dfa4a29fd85282d949f1cff5faba27a8336309a4f867baccec1e6369b73bdf4b757c1049448f4bb3999ee0d8ffcf0014a49f30a2a2f680daeab96ba080e9436779e88da9f35f1df28aa84992e99a0beab3c9bc2858788c7077ea13728eed4debededfd07f1672798856c3a055a13408241a7531f1edd8411be59bcddf843f745850a77afe6ac8984ce9110aae0cd6008ca6874a522c58bc897c403a860cd5d05b731add09f9e24a465d0da6417d00000bc1f800f46d8c06a9861b5ebb82ee710a67a28a410942c343c5385210af2235887221563f3ead0d53f19846cb8c3345403ba3f7209d78da91196896a687824d8afb71dfa6f71d993f900470493108fe9db363bf82126d7af537072262fd8208ab0488b72ddc27a4f9dbb2c191e699746de264af70e8325a3a8040652d3cc3e86f8e7ead704ea80c6fabc0641fdb53599f2e2532b2733e93514058b042af10bd004e87da3ee9342f44b433ff1b8535e3f1928f927eaf8bdf52e31c589467317ee797d349e052a0edd93134d2a7c57ee3fdacad7f8e00de15fee3a091b2c8e51c87f228bd61350ac8ebe6922fbe3db9b1f1c95cc6fad66daca76115c222bee077e98797f7d5a383fdf3eba7a9d9f91ef76bca8a1f5e028013db30143acb3e55096b4d63a9ba75c34b652b711c471606219755a72fc7db90eca93c617bac3191bb231b7a7a68d58e125aada1bdc72c94363a3d8c1e3ff72da6102d37790dbdd1172e42327ed298ddac2fc87c59442d545b0ff476caed9e785f2bed1bff26b0333a6b7893cfcd6ddb8a9ff65313caf6456f2ad2188feb5ba8dc102539e94beba58707699d560bbcce83134bc3f92ffca813e62865f3d2d56680b0ddfaedcac5d5d84dcacf83ad61a2b13644eba1c459299b7a92a42c735c24fe9a4b2e2e9fd6a003c6761b167ab56948265b496cb7529b01cc4e53c3cd9a39384643996beac7e7e8c5b9548bb53ebf8bbca632e490bedf7f4c1de2fe41bcb746afd7380a6ba561610e880b38007beeaff985e007a1460051bb827ffb24970b0fbf79cde0264cf0292305be0faf22877173da64f6bb647b3a636b831df365b7c3394915ca6209d753a2cdcb143ba3e7fa41dccf5534c6fd36ef91187d55e35dac9d3925ac08e2c22c80dda4c60aa6e074cbad95a68215cc134e03ac7e516179bae944ce17cb54d086ea75184c3c36dcddad7c1a570d4167525f3f53d8d39ebaf2d239bc1f9e7572cbce85b1fa08568230c663866d47c3af0c12e609217ab0284f8b8694563933a48ae23e707c1df21527ba79fb2c6cb074d51ed0b90e361b2cbda0637c074415c3e4eb13b75b149505ccf56ad08a10df211eba48ffd7a2d0d42a1bd943dcc12f86e3e9052ee1ea8f6f1a8fd7b2262bfb86110b06210c25e7fac37b49198155c2471aad8190353d85860814a81887509424d72a79cef1534ea7655db318a424d6a036c7aa614ce9faa7901f55f64b0b0bf1c084f52e7069e5bf1097a9889ff9773079eb30a9abe2de835e3229d8c3cd6b00e936d5339b325684a5c483b15420e123c221c6faa48e432e6ad29d22301073d3dcd3dad319399258dae99d20eb634bd69867ef8695bedf1478abdea28e97985ba68b3810318e3cb12ef946594ef5447668e76d655032dad5ed688567ea02cd741c0f1684f271e1e6f57e70339d949187f9cc5ed830203c45863ffda2b704a0bfc77cd4cbaf3279e937c9415d47635c23582b2cc0e19d01abf7b442930cab1acb6b6d1c87fcbabb93d1ee778339fc75b0aa674b0b9ebcc31efa34cdc88d6209367d7c9cb38d96a9ceb0b51e8e2364399650074af6bb1098b22b21e3b9d12bfcf4ba0ee5e9c3cf8820ef6061d10c3648d73c6d22bb9a4502c3b263699d0ea24baa448b12d24f501412d09da75d99714c914e0bac941c2e9591a1af974b9d7ed718ae8c2c5246458375efb92aa04a645b615f261ebad3748d4e586cf4bb52da7a9c3a306113046efec9210cdac01dd254b6f9444d4186539c1983075c1100c45b2a80ec93371fb04da55a70d7e4064542210bed2bab603e428eba5d241504949b6d4c4f02b543fd709a15be42ee92b6bd37baa61bc2904832a15e7077176451dbb49a688cf55649c5637bab364126c473c49dcbcfb064b2f296cbed17603820bbd3a5e93ec52e82e67ab2760735d2fc915122c09b76fc9de21fd95de63f8e5b0276a7fe25efa62bedecf69ceb278c8309d1c5ccae18338cd298c2ce4780f31255dd1321fbd0dbb6f8f64f321e0e0b665130b8a0379aaf5aa6bdafe07af1312f637e3911b8d18fbcdee38fc22ca35094f912decea24e409eec05550dd35c62be25a1612ab90b268015b40eaed9fa0717aab769e193b2d7bd2a55e7e715c64e67d0be4b76086d9cc31c11ec35caeb68634eb554ed5f55ec45727a57e2d8d6914f6d2acffb17b9515d347ba045067502a0b14022a269560e0d95cb168c7097ea8eccca5aecb328a24b1eda37bdb600fffb212178ec0923744a6402d58d7d738f233ce9b64b6a9f1dbfeec1505db36c5a06eab73142a86b27dc175155cb30310da6295a7fb1a7fd6e4ef00c998b82ab8b3300133c6af14e5077c26aa202e6fc5e69a792012590d42ae2694b82fc1efc68ebf7b5df2574cb85143f66a0bc2ff2a9811e62cca6fe559c14e606a1c9ac2753af2050d14b924dfc217dbc5b9b44e89d25f35314db49b096287a77d1734d0f8f8d168467849008fc52de08473191d53f8cff9c54059406398e89683d41db5ca287bb379e463c7df481005fcaa51f86223229d9aa3f1dc10b0bc97f9814eedae2d1a0d48826da8fea991d14f1358e94badeb070719ef7e1ff2021c1cb5acd297695c34310474feb95e86dd6e211cd2e6f65ced4fbfff3817ccb8c25dae508502d4df393b421e7f92dcd88622e35e35994021fd95c368ce30d455831b8d7b5431f33a73278cc9567892bccaa9f0d0d4410a411d42de63d1e2908e4ebbcafdb25c1a4ee00238cdf73e322686f01341d26623c2491c6340204508a421b5978d8f7f698b473aa842dc9eca0e5774a6374ed583ce8605795f084731e95e368d039b6ac539d614882e89471f99ad0b367c55273a7a4a3dfff10ea4c7816a44c1cad69137741b64deffde56148294271b50d17c8ecfec51791fde88bb15b07ef5a9f0f13b9ee20cee21322f3a6fd0783089d9dd32a9344cb0a89e9746bd35c0bc36f37afacb5e35fa47643df9b11a50e4f6f2c820c284d4c147481412e5e4945115040df81511233a8f81e4731205cf0af72285f08cdaf87f9cda4cd3c7c7d51bce592ea15d692e2a1700f5467da9707838a1feff9c989cf84c7b2a3965f146be7fadff1b72aa0338c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e8529585eeb7d466f7e38b980536e62c00fd3dc5c703c3bbd721c9491e6eb85c32a44a4b8c95221524a3c23c6b5401c00b5030ac5fc9d0a0463ad9e34009a00ad426a782939a3e4f8394ef0f1c9a8f811a7f5ea333cadd30d3404352aedbd7a2a743020670a8d1c3fef7c3cee5b34ea05aee62597374b2d6143e51039b706bc660f371ea75d41bd9ef4da3a7a5ee404600a4880f8915d2a0d4943210c8e5e71277e7fb0a75847a0e9f3e97824f457206271c9147e2862e8728b4d69cbe84e785d92608878e367fea06978192e6e69d4b8acadd42ac1133fb3a9e9e1dc50e281254144a0fe07efe8476c462860a01a5e4180a4de0249f05648c23f8e6e3bc49809eb27d2c7ee29fd05b5cab4d8ea4b8868446d4562a8b2d6f182d818b448b165d8497a72c623880702eed40e35aadcfcf6b09f67040effbeddd2b22af32c2978da711f60d3a60f115c98e714b9ca80bb1bfbe16704fb841cbfb0bedad90d8ee5106d2178980cf59e6836eed32dc22ec231e5556dde151c0081a83bf4389916868f9a5c9eb394a00dd88f01a451ade235d634484a9c56c595224495874fbdbdfdc1e93220adc754722bc8f182a697c43e34c44782ead62b2b4d01ed046ac0d7187fdf4ec246361396ba03e69055b5347faa6c1cb9929766e4f2a7b41911e25448678f4820e4764775b18b4c0668fa3ca1e9183ed8e57c30c211e97e7cfdc685e6c082448e0595ca52e08fe5b0d37ac52bda3dc4c8a0b7d3e9d1812d5530ebcf9df0ca539c809855b617cec1498a8e2313908d070839a80574b129b24245eded44df2d131e43dc9142274e0b70a75a903791928a1bfcec374626d3c6136c409de439066c72ccb9ad0332fc9b36d3a24c6173a23014f684d0f1666b8331d108ff33986354061399848cc96c7a631da2855f503865eb732fd4e5c3976571cde050a1777e67603fe0045e0a581002149e02f12f72a340fcd78d5723d10b6869cb54bc64940dc20e2c4e3989890f61c5b1df09c72d8a70b5e5a161c0077f73c816b17f59d9533c2e6ab0c7a26dd2cad7646133b739b24e20159d38cb2e11faad8ea174305417860ff18be0bfcefdb413d281ebc034b8b5f8722b041e90ec772e1e9449f61650a27e810f57d102788527c3e274dddc99f094edf73a09544cf3f162573d6da4798895daec9986a41222047ae0d3ce9b6d84c6e91ff5abd4296b1e777b8e22b077a6aea2e843cde25869445dce969fda78091938b3cfdd6f1ab376e62e9f94ff0456171e270fec0156069e8006f48956683abccd1427e3ec9df93abc4fbee9170e9ac11dd9ca793e7d4ad05cfe205d6ba0969f8e965d571cfbf51f54a8e3317b795c76523eec774719d38f8ecbbb192bc298fdca9b0a9304386b0791c671fa441d2103a8e2b2f015072895fe33d26bdf621bc4357610234e563f1f6dbf1584d21aac7bc2a1f4c8869fd97e805ab0157b6325650d1e03909ae85ae3751e582cd823db5394add842eb339426c7a1f44fe90370fb00c10664c8f2c9515800831c45fb5248387358534d37a9b2bc6b9ec84bbcda7f2f8fc16f848423e1dae978e729d4886f44e1b21418fc96c9b11246ec54148661fd7515be3636f5d3fb5e2723cfb1a7253ebc10064373d6227daca15f68a54710eea722a4c7ac9d8cb34c289634b7a831c0d58ff0c5654f9edf692e49403f40a9b1b1bd4acaebd7c2ed9d02378c9a9b763a41b5a85c0e978d30601e32bfa02697f9eab6f756a1d83440c49028baa4607d4ec080ace306ea6094d615cc220736fadb0bddb33b4d7381d35d265c13e35b0d829219ad12e42d1b56bc54f1fea860b18d6440a9c44c56c41dbadd6085d0e3707ee4eeeb4e3410a8326cab9ea1eb95213475d669589cc8b1331ccc7d65eed9559e0ea0f5bfff13843f2b4a2067c577278af1558bddd481e153602c11d5c81a424e2a1e946483bdda59d530949954fc0d7e42afce9454b6faa5b7575f6fa1d2374efafe1363b36df330d958bfa12b5efdf7d274943cf6dd8c5448e3d30bd0d05afaf86a2d30c068ff63e9fd065e1f84362827c46ccb49a8ec04049d1e04db6f7b88c193400ee5818956472db1a5d3ab044e18f4e918b2547eb275d8910d103c13a8704ed2503421465b1e68c51817ae25727b7b72f3817febe4ec7451fc241d7794b8a63f1317707c329bed6bfb2a0023bef0917a4f8944b2023efbe2fe3d2131c41ab066ec2eacaf389834b55ec862fcbca7862a3addeb9a4fd147bd07f480464e395013f2599efd1c800bb1a8d30d5f57f82ac1df5056e7ab4b9b21cf69a97916c8a50072a9fa50439bf52d8ca7aaf50f5bd9591a5422b079114f0bfe4acf561c826ce665878ade3dace990e64ecfb1ba367f4c3c0a61d4aa1dad084d5c3279ceb5a4343f16894ba217fb7c1bb67c328dc7a5834ea59c48d0db9f4a5d9ad304bc46c0d63e2847067350555940f33ffa238dc7137ea04ecb81d9abc5b068794756c4f812d1c5af309231bfb4b27281eb33f8df6c7152ec14ed6fc9a8a644e174ba754247a7319d29a2d250be22ad5e7494d649b11898276a964aafd01459781278f83a80e6764aa6f07eaa4e22d1741ed853c68c6ab19999edb739487eaaee49b05113ccb3c725993fb28e76ac53f00b9ed3ab5f6912e0786fc1138fdd9eb43b407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71d68496b94fdfed16540c30b13d0d7e65a4ff1bb1b73ae867b96e7c912b00ff6a0ae752dca9264748a313dc53b63231d29e9fad3bf5e6ec9134177e105125ee610a1f9b915d9b65deb6f9add45e7b03240fec592fd59851a1fced2bf84b59977cde42db08d3a2ae3363169cf1de0faac09b586e3da4527c94f3e773341a31864c9cbe171e9d2dee147797d4242195bb40ac11e174db2328fe1eb75af660ac3467a41c20b10ebaf33b287cca0bd628c8e0776b9bf95584947c130993f4560f6f01a417c3a364675ca3cb6a8235ce24cfc39325150995dd367ebed4e2adba7efd67f631073311641d31a868698b9453e88b51df1f6dce9144da9ebea27285a1260bd849ef59e925c176159e087d784b4c571ff12c63386066a9565234ceabc1d14242383c5e1385b87afd269b475a6fde0ffb7bd90e239d010036426a9102aab37b5e7822263c75b2709c939073244489a929410cd8eaf39549a7f7e39808fb43114cccaaeacc16d611dd34b249acc4f8bc2276ac510bf3052b08e057425c87fd10a6c6f7979f5044137535fe3f4335ab4d53ff7a251b2d799539e0852b557861591858ca58ee54562ddd8ce1604479185664a744017e539e3a7737b7eba00d76750ec72e68159e3a59b6311dca75e37ce70329997f97069f11df50dfcfd9f0527d72a5f91327ba5470d80b2854a57596101f5dd528153c8e07bc10fd47d0ec9c6b3ca84536e7b0ef7109b756252405947adb4dfeaf4712a116940f296667427b1c3451595f904e1bcc1ecaffb327a9375f9f09251fd12a66f7cbd6faf86fe9024394f1eb3df27c88e651042254b623a6d4f21c9d4ff62f4819dbe9e6a4ef2e243a664589311423742fae46323f94994ab346ac1582f51747493b32611a563ad057baea8cd9643b8d548fe547146d615bee842aed92fc83470ae7116abdf4ab1944e02a488e8df0f2c1a026bdcb1c9e5e273773626b603e9c7ff6b9bf0beb5a573c6e918efa944501d59226cf102566661ea103bbe11febe431a1ff61e7c44a9852e25b13c8f1bb89f75aa4f297f36eff83fb89c7fd7627643fafbb62323508202f6cde95375caf3e05b69ec9d53a3c3d46d2c269274d4c297ea4c1849854c73f6f6841ca230369c180417f4a65f648b88e8a5dd04c309f31d09161a0207dee3469783daaa9274a0ebb267618be37418eb65bd822d1caac9f77229bb6c60962c515e8b207b02674157f4b2fac359d2595191b18223ef8d7a62f203c30dfb407d3017a45f5b334202ec3bdf629961bee8974b2e756e4c7b638ddcb558e8b8fe0e802bef767d681dba2b2af833aada512c7f867dbe6e01b2a7eb49c7b6e50bb8d9e6cfa8ed1321b415771d5535b817beb8831160ffb5f256a040d662f90742d2be25580185bd09edd014de26223b5f1a82e054dfebb79336d891b767f8be214f88151b8a8ed8bf99febaa10c51a9b07f80b130f73cfd4d1de282f6d7f5ccefcccb64a4ae407d0c8e29650b1c0c1c00c292d0afc5ebed5da7e7a9d0eced3c6894548043aa537407a69dfbfe0fd4dffdf896a363d75ac5707eda016347a63abfaa6435132d554abf826a19340bd0f7c5984343cb49e89936f55f2256bfc32871448794ea44303147839275ddbe891c2ce4f93b4e51ba2a2709de73de8b659f9ad0d8a6aa8e2f1c300418e07035b4a39936ac69772520c167ef33f576198a70bea1a3e6a4810868fffb8bf70abb870ece4fd40a2c286d65a1a768776bcdddba218f6854236270d550b0acdb1e87c0a647026b5982426dc8bfd02bbfbe5ecf33fdef0b048ee02ee85779a0ee900ad2e02300ecc774f73ec419fdd15546141233308dd4e05e0bd98aef19726d7d2749d8f316b798b87ac700de86806c0586e96d5fa35d908728d9a044cfc98d6435f5a73643ddfa896ed51671f0a76359ad302d329a7d6489c3cb77d7a563214f32cae5c3ab5a379198c36ac46ef0f151a21bb0db55720418ac16e2487ae411a37a41f7a086824b2efd39c94b3494efa7c1b708e360b380cd65c6b0300db4259152800ab8a88f85e276b32399f0746cdbfd93182863a850da4404584a8ed17f70aec3cb4412c17b854cbeb6e4ed1e94d97bf16f7b343ff7b1c0d02b11555ae20d30819e6ccccbb44b7538770c3aecbe7351ded9dff5a0a7c66c2be38a68a4f8d2cb06766b1cec3242cf191ff9ecec987893588a89b042c2034534af2f0c4e38ba3617ddd1c70bbd23365639fa7cd5f191861c7fbed74a809b4577184b74582b4774b8ddc3f186fdab84f01e0f988b74bacfe932f46aa7023309f130f7d93dc434d02fa0318a7a63dcb6fc7a8cccb8eb8452ee3c1cb6540512a78cc5ebbb671f9ad9a244567471923ff0a04fb615834380caaf01494ebc73ca0d5c640440be29f2206fae788ece44aca654e36a2ea1777e93e939111387068eae8a7ac652da78f63545288ebe0eeaa2eef9ec82ba6bacc11acc6e110d82f4a1c698336cca9cda4ce660b4873e19098521277c6167a5090ebc2df903b9e682728b4a3ba320237b20444e34f94f2c8f9d5e0173b28a2dea1a88f7e40403b113752a6f9aa0b49ca6a5c34a2b92b2d2bc5f480ee94faab28f01dc0d7ad19392060a4f0a8a95ad318982f081ab3c35895f83a6d4611d888a1a0d0a8ac62075ca703c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416aeec5145d93ca5215998b118cd43fe6f953be84cdf704bda68dec68fb14c3e6490399277cafd3b75630f0b826e2dd6d287a161cf892fbdd889e0c6b19cc0be4bb41fcd121741e20510209b0740cb89c118f190cae98339b07e65df9cc9dd126b9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712122d254e33b7c35d78ed4f76db5578f07a6c1bcb7dc46199c567c4a61f84c574fc4ed042b0f2c8397da95d7dfafa615f163ee77de3725afe64561d65a370b3430bc9746fc125c950f425b970da866f8944bf368a765eea617c7ae949c214c405a9250eaeb7dff21e3804b3656037370d9b2694a83536a4e924c9f3dedf1ba083962d04439175a2d98c3e54aba79db4b5fbc425c1ae4d759878086569d2afcba33ee7757f605a7b0d7d518a7751ffc17479ef2cdbec637e4bfb3dad4d8993a553d0ccbb191f4be4cff5ad204d9ef12e321d851b431a0487b9b00a71213f2c95a3e48a1025c18a4bb04dbe9c259e0ec5a57863699f0eb5efd7767175b02b9bebf4eda442aa4ea276a4e1cad5e196a6945f4f9feb7e434a747a9244eab3dce1ed9534262c8fbfdc245ad9dcf846980488cb4d18a79606fce942d48063f0455392e5d825f515af082f6906036c246bb7b1f3b75d1344466e45c96967f8cb73049970c100538397589fa07b331c10ff03ffcf5cac1691840ba63344882cad3a161b135fc74cd2834b4d7d555117ffd19bb23e6ce26d31a3c34bb5626688c2388f32937ea6edb9107df7695cf745e061c1c8b98f078d88f50881eda8dea89dc75b6633f1c7fb016c01016f8225393bfbb03533db594d4e1f289484f7c5eaf4babc9ff19d827a1b3dd1a3cd1ff4732a3826ac5a468c6464286aca145027df161442843522e2ea9f89b72832b1d5fe563cc115c44ce2ba0c383e5d6824f8260f9697397660eecf2766560b1c77937fcec07555c995ffa2eb97e7bed217c46cc798a407a054e3e8c342de20d821c684b2529a9260b8c75b32c9e0232f6870db100b286915baa9ddfef29ba03584ca140af25d0ae285191427484dfca3a722f8729a0c76d7fec1a9c987bfb111cc69796ebd1976ad4ebcf4b3560c1bf2662f77a10271993092016aa2a13c0e05dabd3e3754bbf0e87775ff06bdca2da1382448fbabfde07755a6313b77aea6326c8a3ce609b67aa4b2de89a10da711cc35cf593e91f701a0fa8e27969e0a4642d03481c477ea3219946b9e8b8b1271dd6fbc2da017b45d3210095667544b271eedf036d8b2ffe8d5f903ac79718d2bda2a14a9fb3cba6911012d8f0e3c51c77bd269f51b501bc3056358b894a4efd94d6f3ab31c60a2e6d42022e0b1f1daae90dcba1b96d681a018636a09bfbc8381cf40a502de14de2b67adc4b5aa9706a54c576dd1caad7fb29bdca6dbbce5cac2eb1e65d89633e3dfa60aae7bb0cc818fc18b6ffff18592e8e8671eb94ceb0c2e15b33f9f54415cc9e626a339aaedb6cdac744b85af70456c65c9025b86a7426169cda4490dc7f20d0220467f6af1ed61d0b39bd7cc4f9e94861a28fa6f27709921625b455c2a5981634b644f122be630c593c15b16fb21e9cab0fc7b0140c981652059d2310ea20e463dc56e7b203c1dbcce46929b2013bff2270b86d4951584ef7bc2472febdcca611282f3dd2a3026e65945ed13d52e629d6d6a120b1f6442b75e0b2660e0f05824ce468bd570a388c6eda0d4b98552d27b9aacca2bcdf7f90b75243f624e0181f20683e701c397f4118ddc67c11ade82127f6d66ca2b4137aa4876cf62bc50a203954cb3460a6f509b816726d7b0427c7552a24e1ad207087af15ff6e5619ec37622a69b1d98b990ab979c98b9a66995d1665017790168ae8b5dd1608ad0bf62c35c2ac54ee3c95f27faeedf474fcf1fa50ca27f2087b110a88585c255830f56048944d2868c4978492fa514359fd3ca4231f9a3b7689833643ca183622e8cd9639ead81d38d3c3ef6a38a08f0415e8f2569d4b698449bf2c5ca74346454838e92bf4ef4200963a061b35007b1a77d0b68fe244fc7a65c339aa06f8fc468150d649eee8dd05156213b4b376830067601b89c2f3ecac6db895a8078e65ff80e7d04e60ab0ec43fca15dc14d5312371e0b26d5cf58477961dbd96fcdf2b31d78c450fdaad5e9bb9248f6bb0cb58946f2e01dbe23224e6af11e5eaaa5b6d43d700a8083e97f57984a6c431796df3d153e6b310d25c37fd451bb16e2ed028aa7b09e42e10f820389a6e253f09f99692ffc4359b494a30096a3eb8a5b97c3aba02933a37cc732e055d41a2acf695dfa9d59dfd5627864efeed20c24ad2ecac463db3c12b4ae5233ea7370c02412b04da5cecbbb9154f804dc0c8e74e2ac9daca31a3b872cc38779f9c7b1a6ca93f2c4f6d04a6b0f3e699c8a40511a2e3b9fb7f8972661796817ee864c2396b7b2a9f349d959b6fae1d66ec9104ff9c942f030e65a8aa546173676eee3beca7af1636aca17582f30829782e2c9b1b9c72aaf8060563ab378657bf91d13f2dd4f1bb6adc1d6da398e1d9b2a4884c63631d46aeeac4ca7348887106b8f07b427790d1cf4a2713ad56af6e1e1629ef93edf14348535e50013d4a33f70273ba18c23050e010109645dd600bbb52809754ddeaf668a72b443d63901a6c759e4cffd958b68736a9a1ee2ebdff616811e63d43b100947549aef12a6caa34d62c1fee27f253562286a466c2b2f91a711cbfaebc527f705bc8bc7351cc7bd57d0af9f150e6466174f1da6ac71c79a2a4df82d44f585a3865f7364024c6f9a7ec7442cd32dc7566e2531fe4366ce5e22aa6931f8d2cd5f258b334011fba79242837b662646211a788b62ff54a6e9bf54761372954bc5b1503cc1b49403054b96be468c1f8b22ec177da74fc851f7562a10a49417b5b6a76168f52931be46aafc2211ceb98056a1bd1102545401d8698944771e079f3aa93974eaf9960d6bcbf23b14834f0d7034f8d5e6589e4a7f13f65e72705884ee8dcbf1360274ec269f1e31a344f8884e5ae3450628689e6356669e7a94e43ea1ac65578a8a21d8cf64b22197ab966b1a20a098fe08768b0f5e53e25c71864a657cb42ea209e757e475ac343e5f8f85b776ea6276755f5d9069447d01bf34604c0389a5a80b7687ca74dd548b3c5d98e4f70c9a85d29ddd2296fa1cb8be37e5d8701af88c70c55baf0ef059358fb8506ab8dabcb8642da7052e6493cc40a035dc86b8d5c88164976f31fc1f72c9a86eccbe29a1060e2a5b0d6abf7c452613018b69e8385b7ab509e460dbd802cd49164665229340e29a14dcadf345f493f00ebe1d829515c6528b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d5e8fcf6841f2e94ebd740f848a2b4e72c31c7a21aea6ae8917400c81d43bb522b64c2aaa0a1986e68954e4ca7b5784088392fda54f4dfbac75e454458e01583df2218fc25708efa7679c23d318c33cdbfce6be7e9125002352d34948fa8b3a67aed933b6c623a04853e8e76cab3219c59d5ed56410b366482128627181b5aa4eceec7f1352a57bf84ff4eb62099a8875cc61b06d7c3dc6094fe96948c881c60eea50f1aa4ca2c2c57af4783c613dfe8392229ee5fdf145d7506ef3d9e559246558463ea4005ea0f83e358d15a789493bea81664169d09e26df8e8e3a2361e6226a54c73b0bb645b846c9bf3c2883b4936fcd3f629f9d24086d9ce4c20cd226199884cef69623c717e7aade3c1f270584fa38cd0d9b6a56045e318ec49ba8a9615abed39d47633eeccd98be10042d5d03d852c5bd930a89f0ce256a9332521f287c5b3a221df63628851acb241908838bac9774b28721290f082f7b143e8d102756d8e06152648b0c9f937d26c08490a5752ece4b16ced9ed97d75143de35326b6e46ad517f13ce464516302d89289478f09e15905bf5d8326d95437860df2f72c0d2cc0f3c40972b07c54745de572f912a58b2bba9c42f105f09be83e69491690a5ef93a98dbe72b55880c843da199106393fa4db8a6f659207f6f419b31a678ceaadcc3330cf95892fe9ec136744640751b38026e009740867b10de8eb67f15a03477bcfddddd9319bcfa6de112cd37ab5040bc19e0b3a52f039a6ba60d2045f834a3195e89e19ae67d96b45a0bee0beb3ec45595def5f6e8fc37ba73c0515e6ade7566e5eda3fe184f22a89211634ed256471c1f3e0f3ad64717fb58cd0a44709a330f39d5e8cdb773ee71afdd2f9d57b44fa579937be3aeaa1adae3b57d047ef28d1fe4a0ee885dea9edf31e01e23e896796b8fcdecd44b4b180dc7e02617563ee5edebece3368fcbf345b930c92fca7072eceb55222b960c5f7e0fd54d58b2a296fc8053d12508a47fa99f2cbd5b7fcea38d04fb896e5421661613af2b53ae7f9cf9da7141efb199d0830298feeb364ff4ad75fad31d8e7285e6d63e4c3f149c65a859747611e99d8cb5d06bd5eb20c5121ccc64e431ffb0c6981f059d02a6924cd1ad196dfff80d76bf99383b20bee491a49cbe9a66f16ad93859533515ecaf1ce37791cdfdcdadec44734ab9a4e4d16a25f18d2e207f66037bed355c32f0b6a53e8785a5b3392bb92c3a0e904b1c0e100735390c8676dd2da11747fd6014c06cdef71226f89708e71ef9c6ab3d95def2dd7f487e42efa411f4eb05a33bd833c6d57f623b8f0c8ed846045cf44fea32bcbe0bc04e118f3922c6a45c890e469de71ef3008558f64ece794dff8660ca2d18a49e2e7b3beaf1e6c903da7e0e8af4d2400c18023b5de425d219f9efcafb72aa555fd994cf9f67ebeb5de47b6a84256e12aea7e877a8b9b5cbcc01119aa6a8e732f551d99dfa4fc239739c0c1d9c415bb13419d4c73469ba912eb7d346b91629642940f117e1aa50a09fd5dd48caa48fe936563f4a200c29d77a80f5657781f6849373684b82a029b1fa3d2c566173676ed7bb07c67c2bc80e7d5ba4623f8ef0d565d266723ec60497f0375b3bac140000000001000000020000000300000004000000140500000006000000070000000800000009000000140a0000000b0000000c0000000d0000000e000000140f0000001000000011000000120000001300000014140000001500000016000000170000001800000014190000001a0000001b0000001c0000001d000000141e0000001f0000002000000021000000220000001423000000240000002500000026000000270000001428000000290000002a0000002b0000002c000000142d0000002e0000002f0000003000000031000000143200000033000000340000003500000036000000143700000038000000390000003a0000003b000000143c0000003d0000003e0000003f0000004000000014410000004200000043000000440000004500000014460000004700000048000000490000004a000000144b0000004c0000004d0000004e0000004f000000145000000051000000520000005300000054000000145500000056000000570000005800000059000000145a0000005b0000005c0000005d0000005e000000145f0000006000000061000000620000006300000014640000006500000066000000670000006800000014690000006a0000006b0000006c0000006d000000146e0000006f0000007000000071000000720000001473000000740000007500000076000000770000001478000000790000007a0000007b0000007c000000147d0000007e0000007f0000008000000081000000148200000083000000840000008500000086000000148700000088000000890000008a0000008b000000108c0000008d0000008e0000008f000000109000000091000000920000009300000010940000009500000096000000970000001098000000990000009a0000009b000000109c0000009d0000009e0000009f00000010a0000000a1000000a2000000a300000010a4000000a5000000a6000000a700000010a8000000a9000000aa000000ab00000010ac000000ad000000ae000000af00000010b0000000b1000000b2000000b300000010b4000000b5000000b6000000b700000010b8000000b9000000ba000000bb00000010bc000000bd000000be000000bf00000010c0000000c1000000c2000000c300000010c4000000c5000000c6000000c70000002b000000000000002800000059000000020000001e000000" //nolint:all -// resultBytes, err := common.HexToBytes(result) -// require.NoError(t, err) -// -// var sessionInfo *SessionInfo -// err = scale.Unmarshal(resultBytes, &sessionInfo) -// require.NoError(t, err) -// -// //require.Equal(t, SessionInfo{}, sessionInfo) -// -// encoded, err := scale.Marshal(sessionInfo) -// require.NoError(t, err) -// require.Equal(t, result, common.BytesToHex(encoded)) -//} +func TestSessionInfo(t *testing.T) { + t.Parallel() + + result := "0x01210350000000fe0000008000000096000000d200000000000000b0000000bf00000021010000ab000000970000008500000051000000c40000000800000028010000a700000032000000e200000016010000bc000000f9000000780000000c00000088000000f2000000ad000000260000009400000046000000120100004d0000002300000009010000cb00000082000000750000000e0000008f0000002f000000f8000000100100003d000000a000000006000000c90000000f0000000501000065000000540000003f00000098000000d600000047000000b7000000df000000380000004400000007000000b9000000e70000008c000000900000000a0100000b0000001901000042000000af000000020000007c0000007a000000240100004c000000010000004f00000063000000f0000000c7000000e60000006100000025010000d70000009c0000008d000000e30000001800000019000000030000006a00000003010000ec000000fc00000008010000ff00000058000000b10000006c00000043000000290000005f000000fb000000a1000000c20000002a000000be000000c3000000600000003c0000001e0000004a0000005e000000200100003e000000c800000093000000ed00000073000000040100004500000009000000d50000009200000076000000110000003300000055000000a6000000fa000000d40000002000000086000000aa000000560000007b000000a500000015010000bd000000b30000000a0000006f0000005d00000005000000180100001c0100001300000069000000e500000028000000a3000000d30000000b0100001500000079000000b500000068000000350000000d00000031000000e80000005b000000260100001200000011010000db0000001b000000d100000059000000070100003000000016000000870000002c000000240000000001000070000000360000007d000000480000009e0000008a000000270100004000000057000000cf00000067000000fd000000f5000000060100001d0100009d000000cc000000130100002d0000007f0000001e010000b200000021000000e900000025000000ac000000ea24d73b1607c8fd7d6542870c2563c7891a9085b74ddd253d4322a9b3d3d1560600000021034a3487dc0c46f976d352e5e152e120d2d23774f921583d1f2c128f7cf9f66529d49f031c94d9c3b33494849eb9682c0311b3c283b17373f18b9ca02d94e2c05c969ae5d9d6efa40c6255ec4b27b0a4752d7f4068163116e76cd0d4041c471431e8c13e37a4d00135dbe7699d91507f5a53a7b8ed36a3be29cb2fddab9f7a286c347964127e9d8bcd119989a92646c80886c2eb8440c87dd7dd94437873a3ce286432533fdbdd1a739c62733cb36ac48c821dcb0311978f1027bc1e39d4c8964e6a6570b80ba0a90a857ef4ebdabfbf958898bdb12ea1edbb17eb903b00746a14e059357312bfd525317b4f93e5eee1de639872edfaec9d2a320a6fac04d6105188fe28737bdbfec193327886b5c4906675d2a49ed43fe8cfb4e079698de82d2d042cd5a9d8624860310a963ed20c4192a19a9d163bcf366e48122c00a1e9744c5cac0ffa042ee550a3bf70d380dc032d11eabe311e0796c5143341600ef626644eed0663b1d15bcbf9e99c372c041ef118de7d179c68899a645a0fa0983b473eb2a1fefc7a956231a446a575db2e31f7c084c2945094f3927519617d7b913712c60cc4d544536a7190ec68525a70fde1309723986ab984a1e97aca4092ad721c744c3b91b676828a5f884e79d9c02d6f23ec246c3a1a8adcfa9dc1e531a9a5310e2d777330aba66c9558434a592fa5e5aec49c3a70f49f66017f194d41240d66148f2b835556a0c8d3b51ae0e823655bd4aa20fdadc6b4189de9f32cf2288700d8eff37aca87eea6637118337fb1704bc33f1fc685aec019c8e9eec48b62a728a8cb454f4e75ed6d28c458cd8df1c2bdce6101e09b650fe22d139e360fb809200ed18130a0ed0513b2a2bfa7ed6c9090cb350983746b1936c6a92f7304a7005450b1f33df75af8dfeca1cd7e94fcce445c6d55651259fdca2972a4d62f6732561af7dc55da09babaf097d1304b4cde14562506f4db4897644895324b542d8f573c39b3f67c487c1df902d0397792b7cdf987b657b2d27920bc6846eca466c155c4b778017656b9a7d69d3e69159852f38adf971f5a25df65f9950e97411c1c36e8bb9f2665b217df30a15bcd22f231f66f4f21711363cb0b0da8b3594003ae014e8c22d93dbca83c05bc5222ae72b85617956f04eded477369ec95312c7c78353256f3f643ebc6300f32561a0a5583813bb3b42844d1ad3d3779a438771a295e306daa91a5a25590d2290fd262d40f239f87d37e1c03a2494035a42961db2f33407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71482cdc214f825dc7085e54a984230a753d66d08425f9763f52f8f68911120260d4d65053a5ef2ab1152c72f3b15d4f24d4bced3b7e277735eb49450dd867c115263ad657e55682de826f6137dedd2d246971fd8c5d318034940160fc179efa63701058e68510bdf68a3678d32145780e13c29b88fe77b27440bdf3ea9762a63964675cc62a59886ce5fc12d2f48694c7ac836a0157e0e6630d694d11faa605034c51def135330ddca851fcb670c865235dc1b405242cf9f7ccb728e449e09f4ad614110699b5642a4b726cbcb74bee77642ec7b4f17b06db88ee461848ead17c906f769166b3ff9b0fb13c1ccb36358d9dda3f25bfa18e2857fe01a92328eb70cacb5514b570b9338c8602cd4a49128006a902494029c2728056b02a900dcc7798b499a9c38970f6f3dbee7e6220ee0e12a582a76ae036347816baa6cd7c9a7b9662caa1a29ff92ad66794001cfaaebbdf4071f4db6d74ee767ba59cca4cb36cac6854840b7eb103ce5723aa0d6625709d4c4378c46903ff236d9d8d61f21f76b22d6245ef2ea126366dae7f9c072d2d6e0e71a54c9bbafaed36448a4a552b51f02a182d14b38906ce1f4693cd9b87d0369e6af514cf7ec91455b26cd4c0d71bc2d3f9f9f499e04d2f27dbe47ffbce115afd1bac9fe116ce7fae719325e4082460c09defe1f43c8591655101dd3dc806c7b07762c97ad21e4142705e46a1e17306b888519767218eed7b884fb221f597a2d4edb69c094961ace2e65a7e40913c0658f8f3a64ec6949a26916ae2cd976fe531947a9c9e93e6d587bac746cb0826e4b23b64b0eaea19cab0333369b93e11693d2b4334306ee579360814adfc1339524dad3d2adfad0b2db5fc2de781a22fc63dbc4e30a5fcba2c63c2fcbda238668e06587bec427bd5b5cc33da6f7cabaebcb7688de50b59125434493fadcaa94d1e0560d2b374b7d6e1380b6b88ee8ef92cdde7edbd9a48d66f5e219840a1155818b9272f50007b87be88422e3da9599286087f5e578c0d1c2a3db9a77110f9173a69e0e58185dd4e76aa52804b2de15ebff8c3f3237e29dc7157e61b30b9b00a30f93bce6916b6b78ce4f7d550c39c7947c6860502333717d541fdb6697ab447aadd01c0f366ff1c65d331da120ca3ac630ea6e8d7339e7317518920d710e3325edbe8dcd591d30511a0fc08bc5172ff58ff98fa848387b25f99205361348105f6c138e9e4061b3a799bf7987ef5c820c1e534df298f3328e1093c5d0758d434280f6162242be89d139d52f449e2bad667d7d974cb80d0edbce7237185b11475fcd9b0171f73154a0734c1cc95ae552d9f3180d7d64e8b50d3837b14b5afd2221808dfb6c44ce63a08d4567cef4b2a9aff1b408d2c99fa4adef25724cce85368b429d0687fef75f26e5503379a61920777ef1f254af024922e382dd19e752e69784ff2911acf10ffcf4b1d795df6d8b55f38eceeadffe577cf5bc0360f35005940c73278b76425a158be63207452b1a8018f53309f47486a273b9bf60cb51c48d67770af6f19ab75537f06388373ec17a3c88ff1714806c0c99ad44e6dbdfa713ea7825552b7f76db8f2ba2fce0e546d7e7abab7d59e7afee2bfe438bad6091934cc7903dcaaeddb2bd99fd6b36ab15fc32ee001bd1d95e87020019f7c88be2e74afd1a3a66e44e8b7845e7f63923b706dae49eb96cdc73b04c9e6cfd1459d06d6f02e6854e6df29f08f7e015d511ff48d7bbb13bacc9aab1b06ab73c1f3350ce6a864e68dc99758ce2920256f75bdbe8c918c556a5a2467a3aa13a306808740484d1bff4961f87c7ff6a6a68beac9264665f87ba1a5fab9802f1cd729391a718a7477bdafa88e49f5c8cd88fbcbc1724d8e227935eabce71ec303d832c4ab27aafd3f8056d3462eda0083ac22241db692c4671249a14a04c2f0a2959aab412660bb493e536e83addf98be8cb2a0158cf18c6d5ba06ab586a2cb56cf1ad4cd099ef1e3e727f41ebeb3aea2815f004002d27714db121fd6f92fac8bedbb97160976c4d221bfc6da82c7055e469a1405eca842b4b8efd101e984a2482e526ecb085229a5a3f09f444f6d39d71e0b936cfed125e87883db8876444288d0cbd17642ce97b61a3cb7d20f9048830a34520de889098b4435dfc79a73a0518ba9f61924de365e70f8503654e384a4524c1c16900873792541ef023019a68f62250b7c219a149b9b68af793ab31f83f500126e0fffa71469e78e22e754f3b49db1dbe631f286ac449dbc94282864e76dac48fb9bce48124189d2d45e2b2e16b8084c022bcc90ef1acebf194c7b9820968e554e2ec4d34346eedf80cacdafcdbf118a3f158e45e6a8766869e2e5418499d3cfbe215762a4a0cffe4315edea5ef47c60c163be4aa5196c5241f5c772f3f90c57a3580fa0735a7340e37372048c1f60a20531f830d60634a177f3974d5399fca046417a6e4327c4c569d8f4f5b47b263b0f07408b1d453ae31f699e53904605cfdbaa72639138cea3e544258e0484a532216372ca569751b32be145716eac8ee5e731a1db2b1dae4b9023b05876077cdd78084c79e58d16ecbaecee3965ad4685c1780154b678bbfcf725fb2e91be3cc0864ba0f682ce1460eff27c8518451b3a9ec811e18b8839808256e18a89219fda2772c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416da5bd7647f8d8388c2b4dbc138e36b8679284eadc49370ce0a16a4e0be28804b04f9b593ec5987c0608e3913acb29a322355a554e010d33acf155e6ab9bad337c4bc688653010a7720d44168b4552bf75974219788ac1cf3fb440c67ff692d499e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd93257121806eb5dcaff87a28d25de336e240731a375be04c4bbff6be6a5ba4f1042a067086008bd1c894c74e4ab0b16dd36effafc8f04a4617aefa7f68b40df033149c0a98bd89778f1276a0ee404b17d81b96c524a8aeda9f671be9e724f090c397977714f425d45bda5f3373c374e9b2710f477e2e923a0f0b2b259c941965f6e88c0334fe5947d75ed7ce18612988df5f227b149c66f371593a8c248206f1b59e10248e650f7e08ac882d65fb09141fc5c7d252da9b1d8ca2ae311752ddce977137229ab3993dc198b5cfee52c273f6145c25afaaa6de14670eccdc1b61fd53821513fa519134b630c1d53b78cbb67e8b8414c30247101be5de118662237b8388cc7d3c50b2fab9b87f1a6228df23e9507c90bec51b8e3be978b526c0e0c7704c7334dc8495596755b6b5a83796315f9e316bb871c0465cac91290b34812c5f0e34120ce455c4566893481e7afa89c0c425533fb4eecab574f0399ca29b162a4c78053405a94626a6d3cecc0492a268e974e9864826f8745403fbb98f55bf45c0b620da0f2b6e2eb2808b3e713d1a3f774966e3e00f81226887d5e1c165af998d6e57645c3b5a2e17df20f698507190332c6951d761c5f46e0dcf997c7337c0bb7e54e232d9f4c8884a9f53a999e8ce7a27f68e9108a4fde15bc51a350774c22b2a1480fc5fd10948cd231f68ec00397e22a19042578431aad63546679e72efa3cc619c9564390d54bd989ac1fb089a57964ee4313f857411373d34161939633c8f4230930357b8b54ce94dfac3276daca91ccbab9b944bdd9754fb27d2b786427b30b6d3a029d0c998a49c406fb0778936c3bbd0708774bbf21b400aa8a41e604401c8e5f3c9fe54712dfa93b8f223c4bf30e2d037a36a768f160cf0c6e6a8c42a45908fdba40941f018589894c721ae6eddb3ad080bfca4aae349a8e7ae261f0a0f18d3fcd225254bfac8ee7f94e5f505496773b69c49697eb79ef8523530c55511106827b00917fd22c6b8e62eda5e130344c9214f2565b92ddcd6b6edfa18e95f8afa23b3c8f159391a3ffb6dda5ce3c9f6b40f25c1dc7a742186b7b693f30111e4b9ad468b9d1e0cf4f79c5078c9cc4e409f8a0fb170d7c4f421ed5fcf597e3f061f1060d5207533b44b4977f128acd44bfe1bfe235f2f4b2d042a87c7da4d1d526a096e110f710d48d0a0bb58b06ceb1d6ba2189ac3dc984dc24e80fb6522431e282ef8862f121223f6aa19fc1f929106d7a916747f21e1973eec1e8c5b7f78cc3ceec15a5af2b64d5a43ae54fcccd31ddabe95461fdcb5be506267404ba432e41161e6df14443df6eadfb3c5ad5228291d1383cdaaef20c9cc8125f7952f249a0de7093e895f4c599aeb4b0310673b00785b33fb9cacd556acc9abdc3de57fc056df4318d12a052ab505db7d06dfe03767eb5f46cf0d271393db1db2516c52aca4be351c39cc0bd557e7afe547a479f8a7218cad2c784e197f3494dbb9436292833db878c0dab763cdeac36e752c7cda12c98686c05704a8b2a695a315bb1146b3d1cb07cfb8d2e13fa9158734dc2bd1ea554fd3032bdbf9e9871d2937060236da4573a6c20044052b270916290b13a30adf3a821b467c4038a14026badd09126d6621e31b47269829a47f9be24a0d63c4bd7ae112b395498ec2502c3b4f46547b4c766e40db6b1685c455de210347c5757ebb7d463d1910eb70fb290b5c7bc63163ac00341573dfc794b0d53e6bab40a84e60ffb1dc3f6642aa1a246ee579703579df75d2c2dd3d53003f55ebbefeb59446d476d0a722ef8ed1954fae9d6ddc2f1b5a31a3e46efe8097d83d7f80ec284bc72a48b7916a74a1cad145eed554722609bff1c0970e439f19fff06a080a67677712b09762b90a82fd9f97bbc50c12b2408a440f2c91824179203d689db4245fa3087e8b01a9316ba973c6ed1a7556aee499b2dffa90a79b118a646aec6b79e6766dc25665db73a98e173fa6381ae47c9de57628b53ed9958a889d278fe707b4284327bc582599019bfc4630616b78f186de80c5d2d0669404118ff1591ff141a606e05e2835889a5f42a32e9a1f34d4c6438f429028ba64818bedeff64b1db1ebdd89f2c2b2fe3336942a03036b9e86a336aeeee1b94c5d5a821e4ab4c136cbf2766a43dd37078e02927ca8a562d2ebb6671ff854613aa3ad169250e037aadbf0ea14c87982d7382f09c7b8c96770d2ffd3b72525806a645e5abd09a51d257c30dcf016435c114d26d3d3be170800af2466b5e4a434ad5ef602a77f311fa22300a5a6ebf03bdcc04f92fdf0da3c74f0c1461d8bef6e668a2cd0c95fdfc9ef30cf9133619aeb9c3d5187f23bd83c765478a56c4b3708da965c36dac2e8caca9398d50bff836219540b179bae7667aa091181db267cc8ff6c5201acaad6fc2c3a2cd18eb729ad0c1526c6c348e330ce5d949162cbc728667ecce548da5efe0448823e928463418342d41883dc6e20d8e45f1d6d02c43c3e38d6e7871f18ee80f60415adc76fdf4c8ad2c67ac7d11682942ab79f74656a8f51ab8c1b088f33ddfa20992eaaae491dc3dfff9742fe32c4428233d691dfb69a1713087e4fbfef8f7c96df760e85354069eef1ddbaa01d52f9664fbed82ddb5cd6ceec78143f1e27ee7a0fa73873d01e80e368825e3b05bef7cb0005833a9d0ae360c420a66a5353836acf1fa3c65578c9c5b3b9c7831e944ae887694e9fc6a8634f213d8d061cc2a34a00f214d9f67cd17effc527a07e060bea20b143a7bf515a130000f93cba10536a1204f0a14cdba7b627412d383c308672a7e2974b837e4a89d54e63c47966b36fcfa3efa5854046d3ce09d45f226c36aa9c0762a59eada83c70e1049d5d09f7f7304c465f2ff56dbe21687ece20ae9fcd9ab8a7020a1f967780a1ef49b13b40fc3cfd208e29f4d5d5ee9bb63c5fc81fafe5d47c4ee373a54a64d267c497c59f4c15077374317b91566d44c82f74167e6d847ad207f3a1221ce1f958946317e77ba146d16aa7bd82810c5e913c4da0bc5d3a5923a156f0990c79f01317a3140ef3aff708acfdcd30a838706db819dc3a5a9fa2b1bed2a4a48fb21792b44c5772f888132d414d13a98bb5bbbbd70ac42afa68950568131a449e70574ae0f45f28b87210c1ff7df1adee5576d03950b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d9a53c2f9f5f55bd687e359ef37196cd288fcd1a14adf6cad53c6704445a1f1212270467b0c03fcfd8bac09473161c6eba9c25369a853193b472eb2f113a3d333181e6b71b981059fa265cd76422e52fe175db6983c6ebdd0fea1a3075166b9291619ab90bff00f89ea8055f0d7d45f8c8aa9c04b7fc1d06468837c6c563a6529ba846878e4f157741703bb4c3ab4f3ff2e9b99916624a9965a4256d893c84e152c19794d20de22edc9c4c1514f4f4e29ac16e6b421d3620ec6545f737100f0134c29c11128e193f06c866e165662d903d9f799508e617920d786ebf75acd267462237ad2bb39f6a5a03a46c5a1dfdd3766a49e6c864ac5d45afa6400ce3a9809de464459b18deeea6f02d5882e80a8696b00c9f703da84bc5769921053ecc749b0cfe1745dd408f6dfa0ceaa1780ad4ae1747a8912a589a754ed86373a08ff5540a471d9a8272b09df08db1f998000cccef325d072ad79df6c1936cf0ccdeb77a0d9c323ea08a0551f96c28b05ac0c7b0e338cc5004bac22d06feea5a8f5c00104906813ee195100f82600e56bb5756831a260e4cf6e5ad275364130dbafba4ed4f9db6adcdce67708905276a01347cc1c800bf6ba246c3770a81c3c754fd65bee13fa85260215c5235169fea113546e7b4aa7a1c936c47a14e81d3df912601a2eb8ece17888100536bf7183c579eab3e6daa14e5e01602a2fc3a64b563f591f0828f0bfffc49973cd14329675728a2d243102ab486601f1581b1e741bb5c77526552839c17a5dbf3b2f90875abc9959553b320da9f07f1392fa3065315a8b1744a7e5b271f9394d6e23bdab9ae03491f51bbf21014364d919388b7fba4b5341bc4b759fa4234adb292ab984f7b69d3aac2e0afdc7dc075e18ad22f4456dfa48b0acf62c24bb58eeb0a71365ba5f890a594cc046a483d9b306a487ea4eb5e80572d3ac8b4dbb4b6a02692af692160b113da09d4ae9f0464c5522b7236a59b70d3667fd3b0c5fdf2c30cccdd640a7297da408b6aff82ee9651f889910fda9f24c706a617b082d626dfc74a657c5d17c5a763044f0230972fbe47c907a5a8fb75df4afa9726d496332a25823148258bf60b189ac898c92b9be15965a199a45ad563efc761392b915b58613f9fb99f45c9a78fdaa4358874f739cee7ebf2a5cbc2fbee73e2731e18f347de520f1878f0eab3a38f377a9263ad17333135c991d560da02f9a012221d644717e2f1361ddfd9e6b5d0043f3a47eeffab15e43d7d45e1f6e07945d95fb46ef5346bb3a502da9f005d1cdc956e1b96258fba48dc793f50b7eeab48cb88c51118ced6c65368c5197ec7f014c443b47d898627cdb7781351442c44398d0ea4ca4b697ffd505665531e7d4b4406431f2328943e8b72d030842128714ed41e3d13b8aad0d076b7ad34af4946866f552568eadd3d3582b4c4f50d816c065e65b3583c8309e3465db95b458d0b42619e1ea75ca546e966d761c53645771381f31a42a1e0bca62f752fb49e8d2a49f942cd48a03129a709e763d23aa4dc84c88423861d1ef31f5df99006156570aca69e571067899ddb156a2027e0acb8f278b4e156f96ecf0eb2658c6504fcd39e4e20bfb5905be7cfa05ed907aa5041e202a49166a5e267724e5bbd0d9efe57d34d8cd7a2e536cc7aee14f12726065cc08d547840066bb56916d9bb9761e05133fd18a68324492ad7b9f9caa1668038a3ae897ec528be2ca7c977eca6cfc08a00266e96fd43a723fc7226b66aaa86fb8c0ff0094b6feeb0707b5cd61797ca034755fa42aab8c5c9e245157f5425f5d9c2de89a454439ff9ddadea199ac62ed47b9326a4a08c06859dc6aa56cf5af62a035f7c6b0546f536c07cfd7a2d8e3be9ac2c7b7e854ebf59eaeda5edad7dc23e83eb30dfa3dd91753614a811769d6a564e5e2b27c43c70d7497a0834ea96e50b6edef3369e8da5f707e530fcf611301be6bab8187386d130d1f8c94e5c3602ec613f83c1ce2708d6fceff206d25c511772a85eec3fe2b4ee066681cc6c58313ac304e37b46e43a844db9b7bcda351e09ad1efc57db99dc2a7c12e553ca9a60412dd6bdedd4ded92b9647ecd2ce31eda2a6f5a4ef9df833b9b4c70ec0924a92a7067757484a42e2e39a2c58cf41f683c3646c0e993fdb61ba33306f7524ee2733c1d970403cebabf7a1af318743767411fda52e046b2fdbee1680978da2f66413a00a72c2f0fd68497472feb62d2481dfa1ae93b14895fd3773d48635738847d32c4252393c6cb8e07655646eca309a1481552ecbd9569e94a0cbb6905c45717f0097f3dac95ce491ef6f07d89dd7a409b0f13475eeef708fbb0cac0f200cd31c296fc0f38221dca15bbd3ad95092e6a4f38b8ef8e9f3b9992d57409c7833c0e2e85194adb91496335138d5815f82e01ebc93b757c1ff94620f3a87ef48ca064b8daa8790dd2fda2c3493f33b66804385212b1c3747f61ba6de535688b2ec24db2b9bb22f1c69337d131a4c91c2b70f1b45fa522eb556b7960f937e6fba63e1a5c832c850ec9d476fa68c807d36d09edf0c1eb9b2995a3812cec5092b90c4c724a2e1e42195049ba8878f1d05a2e30251a57f7f4662d4bbe42ecc98b7399c13a00c82090e61c34b4675c01815b7e25a1fd09d2fc60f60ec1f3f435096790681cd676c3554c66ecb08ee954d3de09ddaa2e3d11f5fa4f9d4c89cbdce2c3accd6f9495757f069ede7b956256595c7d083b47c610efce658762467518bdb11be9597e37db2ce13f8b1b0cc42acf317bf5a8f948dd3977725de1590421117c9ffd003a836e898f478234d26fc7d8bf866a6a308f8f7cdaab738bc98b879669911a26d87f69b187cd620e910289b9d5c2704d332359fce4040b4978eb1527e743dc15407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d7162fa40d6ad22c0bd13811d9555f4b2adb0f639cf7ace8468db36e557c1e1176e4ac7db719c3be3a8a8fb077e5aaa181f69f89547570b88ecaba644b0c8623f793abe63296589646fa4fd48c7d15548b46fe4f60435bf69fb31260205482eab0226b7a3b02d5edba566f82d3f949278d4d0660165857965f123b1ff5aa680a62c6c7b8a1064cbfd234f3e26fcd14b1eb52a0b46a47e8a8d38027bb3fa2cba947124c41b6ccc361bdd655dbd0f0a5b5e7c86fb1bf779a912921794e17746c37f40e0e4451bfef8b6e07bc00ff6fe17cdd12d45db9f816cace50b0682291a8dc257ac131413580ad09206331a67387cdfbf12cee28aab9a8b0aefc03d6d1f2fde70a8c597075eec72c0adb7c050db76ed8d86e7785f056db19e02775ea099672c7f447c7d787652ba7c318efbd758620236476ecd6df6abc2cadf3488c7e6416c12b8a2bb40ce3658b1d71c42e68495a5504986f38696e56ba0fc2df70182a5b11fea0d61d2472c21da757115c4aeb85f1ad06831b0b41779a118995340fe6c352e6cbeabce345363e57dc45931c6bf8f278f704cf252234e0e580741af38024e1536d3b2112224e3432e605d698c7809f9599544725f3bbd89e076742a2e33631e2caf02567c87ef2729ac221651de0efa7ccc8de802d0ced1036b68b51868bd3686a8ecbd7b1a217342e937037c0bebc6a026371b85698d124c09998e5a531b6cb276cf5c2ddbf28d010e2a6976cf03488c0d1d11c5c1f9b23d7ac44ed221724baa63a6245db826d277bf7bed80169db1bccdc7a3eb0ae7852317a5fb2628982aa0fff7c6916548204396e77dd2fc044e2a37c192789053627b2c81fa1c0f3d1f7482ad1abb0ef6ca6488989637ea1d44a918f062b169f1b802c9ee6d05a2fe34fe3fdf6285d91ddb739bc5c2481ed4d77589febde82e624d0af0ff9796e5993242f7de325ac001c0d50c4d27c15248ae2023cbc52e2ee969b16fbef249ee2542026074c387dc5714b8038735a05a39459797ad1f591aede76adbce55e99ed94a98b68d8ce62060e2c77262da54a918fe5942925597cad811f00d13599f0062784e528241405f8618bcc663a513318815f67de9a13e6786615542b715d6d2bb3d82580e61b8d0dc0c1652fcb6ad0fe74186d4f30f931ded5712a16e9724b9993cd0d505f36fdd6c1f2f87ae7f7b7d2a84caf41d8db3d926a728904ffc98ade114aa146708071810254fb2b5fd49243a64bc29a6cf8638150988ebd9756b917719664e74f116e47c0991afa7bc43d0b4aaf085d205ced8ea01235b224e9e2a575626a39cb65fb8a0456f4f5380b87473b2c6d3ae6c36664af57171130202317f567e7a89975b0683a31b08cabf966ecc62d48ac257c297ac4825c75e59c4271562da9a7597e0b1d1e880416c0a36fd5d9a8a1a0e277025e81af122c541ead22d78609154fd9334b34c1b724aafefb4de93d02e360bcd69f4d179b8f973f0a229525c681a841ce65fe1848e33fe6c929cfdb09181ed6f10f9b5d42b079890c93f6cb63489fe6ca5926a30f68d89fea2985c600a9114516a6c29aa1a9a390358ae11d4c2addda665d13fc93f613f8de4ae6526a7ec8bcc418d9d190bff5fb2bf8a57d4d02ae9d39b49dafea09bc363a28395b90f0c0482be2642d693c65b1dabd51d6456d129d5c987093349056b99398c6c59efe7949aa90e6480719aa04ad8816124b5eaccc793902c3f48b7529b6d116f4e7418406b6dfcabf008b65268d1b3757c713863c80e960241776adfb775052d810b59fbc83edabf4b607bd44c6a610788c1cfeb3f21e0b94d5a12f2615ed49cf7d67abf18a93af7ba649cd0ac29680d9eb19a6e461dc5fcce21ea03fdc88fe1a67bdd4b67671794d5348a1b481ad45e86635f0474f0fe3f7138dbd0c961b000d0c14707c9c3037792e2b59632bef200305908aceeb3388deb21c5ceaa4c1dae6b8ef3ef9ccfca9bc6523b609bcddd0b66f5b305293c5ce2538e4d8e773a6d51cb10adc0c50d9b9cba83e8429a2e2e1e4e1f947c0be485986af1fefb306419c6fc3cc203303517dedafea231dd90856df4af58129352adfbd4c714e33aa5cea74c6e39a097a1155bb8a0f59242addc542e1ce485f81eb5df11ba9bf4e0267aba89ad594b06066c4a7f52ca7947de90772864f98b6fd26bbf80abe1a9ecef909810ecefd129f3a73bd3296a2999b9bb455ebb74bbc3f5ea7cc6eb966a566123ce03005a73c0294531cdb87e6f4e95a515a4533e0224cd2cf5426a5cdcab8c30caba2a0a36831bce623b526cac663bf76f269e3d114a73a0229bbc06b4f53b1f5c0ca2198e418a49af03440d375ae7c76e24cc7c0c46b93aa96c8e69afd833d5c5f4ee23346e35053b1fa6044421208a5fc47074d544333068438bbce32a53bc0117d123ddb9718eb62baa88f7a7bc786758ecfa2acaff06cdc5d550de264d6d61988290e84649f3faef516f21a36b403490b980074580512dc2e7d3e2b87a063a5da17648602d66ed743cf227b0ef5a34067bba03c1df0cbc3cfea77b39ee77b49d8b425455e45a27a245c1963853bd35689e5192515b7b99cfd14d624ea54dbe5eea6c8f22b59babc3c6a3ce22286f1a628b901883b088d7b9dedc64dc86f636e337839c21edf802b526c26346ff314ac02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c24165804d109d88647def7d8362b09e103f65285c88ff5ac9329ca40a9c29dca4e073034a4c23a5fe2e1a82fe0b885d736e57a0883291961a087a2719664020a574cd8db813d1070487f577a18b9e163ed125ed818c0d13dde40503a10ed6c8d3e6a9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712132d3fdefa1807e6bf9c14050d63d2c37bf357802a7d8e813baee24cefa76b229d471496a02cc87ca65544c0ef979e7f4c1f0a7269e3eb21fea4e0d91ec4fe86ba67e4ee5cc212e44e3488e61c6c1ce07e25614b8c23cb4d0442b35e6b0d8ab3744512e70a1dd7110e04b778646d4f7b399d36712e40bd06a6907f25046639e4f9a632636d4945986ce97bc67ea13897025c220e7297598460ccd7cedb8a0c54792f097884bc8751c88ee126bd1f3682449da8181bc9cc5b90f0bd9dce1cb0d19441bd6bd7dd64756c6cb272ce5ea2a934c56dec8f3be010f8ea74cc61f20d1309a1fcf68fc3da9660e86c1189f879b8c9cb6611d57d470765dec4c3514243009923ef8cdfac92e83ce444c9a2b61fe92d6043d108129649a3c6ea306c5d9db7b924eb791afc0aacb141b54f0d75fcde46e4682e806926114b2ec7ee5a1a5626a3a524e56e2044349643bea61e7d9d3ae3dc19e660d754e6cac3fa4f24ae46d794816a0ad32ac3690b658c96cc6e09d9510a57c8e28f32220210108791a15aa0dea2e3482714178bee78fee64d0d61e6933d06f8e8dedbfa5ec5cde870dde2d7a9880b245038d021948c6700d89443c09f207b9da66d2ec05e1c567a8ae5fe5023a414b00e01850a90adb945205173ed44279aeb17ca7ebf9a239d5f6ecc9306a868b391a7c49dbde0913228107a7795db90a5e3e91e505d9922c2914d7755e0ca47af8f394eabf539adc4509e5958a7935179f1fe3f8c22b4cc2e2a345933f59d65e0318bcca6caafcefeb3452d68d6197c8ea0b26b971962e201405c4c157653c2f2d4af59046fba73c6d72ca8cc525648416b9b2143dac665457204258b81bbad3d109701bd807e75845178590a4c5b8d44421e0225d9fd994af2aa1d0c65590a7bfeb5fd893b53578b04160e3162b0aae5d6f67dfcb75abbcf01b2ebb106906d47dbbbde1bdb9b1bfa8dab1989c600610422ddba5fabd57a54dc955ccfc7e5810293b5345958abc5f84808fd97351d481e6809e00bee6538408aea7c6c074c26b68e2002ea0633e6c3d7484493771c50eeb727d6fcea84ed9c26bdaddaf73d8ac7ad5aa36f30863234f789eb1d0092f42deb6ca72061146b920d71b457700dc5012547ee806376f3ffab1e2780f491f33a0cb355ea6b677c4ea1b54ab6e5698d2853047a428891a431d89979492f261809be176ccc6f09660d5cd4b624f339e961df7e2cd5aa3f816fe8950ecc0c2c9838fbf68bca5d4955de8719bb6cf79e8afbc8632efb5aabfcaa6e749cd45043ecb13046ce3209fa85ef21441ec2d1a0ac63a273f4213225773647e8a739187223eaf5c9f0f2e3d1b12e229fa77e65bfaa2a0487a29d08064960b2068be68c3c830254caee33d9436053af9fd028474bacd43a231dadc4f4116e333fc9f88fbcb64abea30e650a11ac56a1988eca459d858087e220893ac87e5b5203582ed469929c865ca6e35cafc0886f8e5a9f813f011fb08ba33475f7e9b64397ce8355542f0d31bebdb5238414fbc41ab88fe2abea69d9e769a9b465041255b591fe2708f1193c6a0d7e83e929c167d0f672a6cf8bf480b21d5fcfdf7c0ed21b4968982c3b4798fe04b9e9462fe2bd8fb6c511b1c153d0637fd584e30e35b6a07aa739ca4f37d82d9c8e4369606257edbbb2f6ee4e6047dd8e85212633fba991cea2364c746d0ec558d0fdfd64f2ca44bcc97637e3af5596f09c8a333cc19880d51fcd11a73c7b8eb1b02485903f9c3b3d15b56b6dbcce848e56c21d870a965f61bc53894462a6997e78f55f20ebf32f8f4de37a05611860ed6704be9587f1a0c12bf329f83fadd02c191a288925cf1aa151d387686eed59f920597a10643f36f40b821f85fc2e6b62569c88b32189a52966c52301f029b0c231c81ba02285edfcf032a441c296500e2a2979e4b4b0caff11b6656d131b61a171c4554591d3c74fbc8fb899600114d3a61951d7af36bb8e6460ba61b0015878e7e28903dbcdb802b63c5e6c895e2619c6511dfa0723fc48f796952690fc3626bb5c1a0757a19226c7db6e42ec243932a2503b9b257fa271f933ec2dc395f40b62b11adfb0a552412447e35ac364bee1f8ce0ad23a72daad14944e49b18cc3d5ecb36f4a8dfd602319507ba7dade07e22ca3a895e9ce0a2f59d7f581d176f5b8f880047f3803efbbcd442b7f8b1fe158353183f03d3f6acf46865281439426e64348199839d84de5c3d2441a5dd9c75bd064c1385ca083cd1df6ef46dacd30ba7bc9797085a143f0fcdd6b0c7ffdde124bace833b758ee4ddfe5072a558406365b77652cb2bd1ccf651da71b0b22bf789af3d24014217fea74522e694c399bc8bd5f07c0db8fab186d5ee762d33a5debc1902bed79a68d8420d06fa2810bfcd09e53dad5f37258fa86f46560785713ec711c9f5ab98c631bb3e3b6c5a293370fec522d61149c7bb09bd4256e55a71487db84f95cffaefd2c4a3058c62c3e73695bc27a72c21d264daa0d40c012083c581e4a0dfc7f168b722b237a0ede4e40a7b352f38ccd532d1a416ffb5207d68c2b7b3a6cfd957d7efa5b71446ce84fba254aa25005dd08c988f4dbdcc3dc795d3487566e587f8f99fa6d222c406942f33c9a694d0a5b974d247fd6d4a37727a7eeb184f4139d300cb9d2264e4bc1869026d0ca9966cfa34a5506577dd7eaa826a1dbd86bf3e8ae5fe73cd591837a5d6075a386bea6701e431ace3f383154ebf64ff61e2e4b520bf3a723908aa855ffca926ec6b18bc48a7dc48b52b839507453def5fd2898cbce2c611ba2af0d2434a7152607d997781ffdbd8987c5b14b6f20449493fdab89717e43a14153845b97698e2511195a1fbb646bd896dad04547a95f1941a1df510c4f7990062c0d4fd794bc886625c783228e520fde1dbed723fc9779bef796e04307444ff32c210cfc2275da1aba94d5bd2b963fbd80dda7a9c8ff88271f152875d7cccd664a44c8d3067a4034b5d6101af80d9a2970f3443536302525e41dceba23d8862006a1893e47f69018c2ed81677b4c43016ddd24ba54311aa590562ce1ad6991a1736d972bf0421adc4a00cd631414f1cbecb646e0008529253e9c0169822efb33ce421d77953121b3efeb10cd44d504b5cf47a9807dacce8eb24d53ce62e145835b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d32ed1f9d70028c2001ede3fb28ac4db0b0215889cb331f8bc637d8cd27d4443570c84f2e19c4aa5a2610030e19ea4093bd118f72e066ba44693db5cef94f3905a6740f6b046ac8d7b77f5451a405975c2588b5b82cfb70843359010be8b7f32870641d3606bc050e0383940f0e25880e6b183b137ab86e3ddd52a0ea7024db44fc4458e5fe418d5a7ed1c33878563e44403bf194507c93079ff9105b433e6078faba26ef3daab055a97199108ceea0d3b0dfee6ef4f8ad55f1eca9c15771251d0cf33eead0be3cea163831560bf46c98931a1dd530301d054fad074fb22e5d6ad86e5f79ca0607a6108ef6030015ee05ed6229bafe13806894461b51199f5b3d2ef6d9024f2194253e89d0ed237b1903f89dc510bbdfd982b518c3576659cd39120b53fc4e51e100e83a51da1239f64947e10f158bc42d10a3b20a366b4311370e2e5c4b8c303383b3e579cd1196f3dd13db99c99a48397fe1df8987a58b942b02fcf424a1223968027d877793bf9f4636cdba3b47dfac921296a818d1b08821f45e5edff6c3c216a16d4b6539790325daae1a6400ee446c2b4fd1852c409d43d0bfb72b3c0946f9edc151873293bcf16d1360b340d7b98eda07f00b1333fa020c5b2ab0a4db4d0a259bc517898153957166f01726a25d2012da74a8fcfec104b6ba6b02f41eb730989a90ffe2f8948b98eda9bb5bdaddacaba1ac1877ea8c77247f876b27b3d89aa71714f55561cbdd0ebbc4b24d39b044ca3e3ef42bf8f63b8c642ebb1fcbeccda9a1e3aed8762eaf0d9ed97308e08e7489424c321f49af5ff24bc10f697dde29bb97031ff65fc6cea39036367972d5627a48c4f9cb8ec56d22a8f95b4c20b4a2545baa5879a817128101c28cc253f3a7a73cb74f0c43d609d08eca7f936f1a8a1fd902a4395ac8be7312d9eaf784c761cb1354dd40baf3012e85eadf3fb86959768990ad2c8625a553c4d920338ebe25de23761c085102555e30cb812643fc1d2857c220dcb944c423397264da353d5131d0c70933d72b55d021a519c3d7a9c5614710da694bc1e1b7d5cfe40931ce3f0e1f35d253566b238265670dbf08b30c63410be69245689bbfb89a17eca0f6c9542454b1e92ed9421ab1827a2f0013b37d7a0653c54a480e1adb20f4d6621955b8b41b7fc0dc7f66309c890258c6702ea0943d8a32748f67d8dfa4a29fd85282d949f1cff5faba27a8336309a4f867baccec1e6369b73bdf4b757c1049448f4bb3999ee0d8ffcf0014a49f30a2a2f680daeab96ba080e9436779e88da9f35f1df28aa84992e99a0beab3c9bc2858788c7077ea13728eed4debededfd07f1672798856c3a055a13408241a7531f1edd8411be59bcddf843f745850a77afe6ac8984ce9110aae0cd6008ca6874a522c58bc897c403a860cd5d05b731add09f9e24a465d0da6417d00000bc1f800f46d8c06a9861b5ebb82ee710a67a28a410942c343c5385210af2235887221563f3ead0d53f19846cb8c3345403ba3f7209d78da91196896a687824d8afb71dfa6f71d993f900470493108fe9db363bf82126d7af537072262fd8208ab0488b72ddc27a4f9dbb2c191e699746de264af70e8325a3a8040652d3cc3e86f8e7ead704ea80c6fabc0641fdb53599f2e2532b2733e93514058b042af10bd004e87da3ee9342f44b433ff1b8535e3f1928f927eaf8bdf52e31c589467317ee797d349e052a0edd93134d2a7c57ee3fdacad7f8e00de15fee3a091b2c8e51c87f228bd61350ac8ebe6922fbe3db9b1f1c95cc6fad66daca76115c222bee077e98797f7d5a383fdf3eba7a9d9f91ef76bca8a1f5e028013db30143acb3e55096b4d63a9ba75c34b652b711c471606219755a72fc7db90eca93c617bac3191bb231b7a7a68d58e125aada1bdc72c94363a3d8c1e3ff72da6102d37790dbdd1172e42327ed298ddac2fc87c59442d545b0ff476caed9e785f2bed1bff26b0333a6b7893cfcd6ddb8a9ff65313caf6456f2ad2188feb5ba8dc102539e94beba58707699d560bbcce83134bc3f92ffca813e62865f3d2d56680b0ddfaedcac5d5d84dcacf83ad61a2b13644eba1c459299b7a92a42c735c24fe9a4b2e2e9fd6a003c6761b167ab56948265b496cb7529b01cc4e53c3cd9a39384643996beac7e7e8c5b9548bb53ebf8bbca632e490bedf7f4c1de2fe41bcb746afd7380a6ba561610e880b38007beeaff985e007a1460051bb827ffb24970b0fbf79cde0264cf0292305be0faf22877173da64f6bb647b3a636b831df365b7c3394915ca6209d753a2cdcb143ba3e7fa41dccf5534c6fd36ef91187d55e35dac9d3925ac08e2c22c80dda4c60aa6e074cbad95a68215cc134e03ac7e516179bae944ce17cb54d086ea75184c3c36dcddad7c1a570d4167525f3f53d8d39ebaf2d239bc1f9e7572cbce85b1fa08568230c663866d47c3af0c12e609217ab0284f8b8694563933a48ae23e707c1df21527ba79fb2c6cb074d51ed0b90e361b2cbda0637c074415c3e4eb13b75b149505ccf56ad08a10df211eba48ffd7a2d0d42a1bd943dcc12f86e3e9052ee1ea8f6f1a8fd7b2262bfb86110b06210c25e7fac37b49198155c2471aad8190353d85860814a81887509424d72a79cef1534ea7655db318a424d6a036c7aa614ce9faa7901f55f64b0b0bf1c084f52e7069e5bf1097a9889ff9773079eb30a9abe2de835e3229d8c3cd6b00e936d5339b325684a5c483b15420e123c221c6faa48e432e6ad29d22301073d3dcd3dad319399258dae99d20eb634bd69867ef8695bedf1478abdea28e97985ba68b3810318e3cb12ef946594ef5447668e76d655032dad5ed688567ea02cd741c0f1684f271e1e6f57e70339d949187f9cc5ed830203c45863ffda2b704a0bfc77cd4cbaf3279e937c9415d47635c23582b2cc0e19d01abf7b442930cab1acb6b6d1c87fcbabb93d1ee778339fc75b0aa674b0b9ebcc31efa34cdc88d6209367d7c9cb38d96a9ceb0b51e8e2364399650074af6bb1098b22b21e3b9d12bfcf4ba0ee5e9c3cf8820ef6061d10c3648d73c6d22bb9a4502c3b263699d0ea24baa448b12d24f501412d09da75d99714c914e0bac941c2e9591a1af974b9d7ed718ae8c2c5246458375efb92aa04a645b615f261ebad3748d4e586cf4bb52da7a9c3a306113046efec9210cdac01dd254b6f9444d4186539c1983075c1100c45b2a80ec93371fb04da55a70d7e4064542210bed2bab603e428eba5d241504949b6d4c4f02b543fd709a15be42ee92b6bd37baa61bc2904832a15e7077176451dbb49a688cf55649c5637bab364126c473c49dcbcfb064b2f296cbed17603820bbd3a5e93ec52e82e67ab2760735d2fc915122c09b76fc9de21fd95de63f8e5b0276a7fe25efa62bedecf69ceb278c8309d1c5ccae18338cd298c2ce4780f31255dd1321fbd0dbb6f8f64f321e0e0b665130b8a0379aaf5aa6bdafe07af1312f637e3911b8d18fbcdee38fc22ca35094f912decea24e409eec05550dd35c62be25a1612ab90b268015b40eaed9fa0717aab769e193b2d7bd2a55e7e715c64e67d0be4b76086d9cc31c11ec35caeb68634eb554ed5f55ec45727a57e2d8d6914f6d2acffb17b9515d347ba045067502a0b14022a269560e0d95cb168c7097ea8eccca5aecb328a24b1eda37bdb600fffb212178ec0923744a6402d58d7d738f233ce9b64b6a9f1dbfeec1505db36c5a06eab73142a86b27dc175155cb30310da6295a7fb1a7fd6e4ef00c998b82ab8b3300133c6af14e5077c26aa202e6fc5e69a792012590d42ae2694b82fc1efc68ebf7b5df2574cb85143f66a0bc2ff2a9811e62cca6fe559c14e606a1c9ac2753af2050d14b924dfc217dbc5b9b44e89d25f35314db49b096287a77d1734d0f8f8d168467849008fc52de08473191d53f8cff9c54059406398e89683d41db5ca287bb379e463c7df481005fcaa51f86223229d9aa3f1dc10b0bc97f9814eedae2d1a0d48826da8fea991d14f1358e94badeb070719ef7e1ff2021c1cb5acd297695c34310474feb95e86dd6e211cd2e6f65ced4fbfff3817ccb8c25dae508502d4df393b421e7f92dcd88622e35e35994021fd95c368ce30d455831b8d7b5431f33a73278cc9567892bccaa9f0d0d4410a411d42de63d1e2908e4ebbcafdb25c1a4ee00238cdf73e322686f01341d26623c2491c6340204508a421b5978d8f7f698b473aa842dc9eca0e5774a6374ed583ce8605795f084731e95e368d039b6ac539d614882e89471f99ad0b367c55273a7a4a3dfff10ea4c7816a44c1cad69137741b64deffde56148294271b50d17c8ecfec51791fde88bb15b07ef5a9f0f13b9ee20cee21322f3a6fd0783089d9dd32a9344cb0a89e9746bd35c0bc36f37afacb5e35fa47643df9b11a50e4f6f2c820c284d4c147481412e5e4945115040df81511233a8f81e4731205cf0af72285f08cdaf87f9cda4cd3c7c7d51bce592ea15d692e2a1700f5467da9707838a1feff9c989cf84c7b2a3965f146be7fadff1b72aa0338c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e8529585eeb7d466f7e38b980536e62c00fd3dc5c703c3bbd721c9491e6eb85c32a44a4b8c95221524a3c23c6b5401c00b5030ac5fc9d0a0463ad9e34009a00ad426a782939a3e4f8394ef0f1c9a8f811a7f5ea333cadd30d3404352aedbd7a2a743020670a8d1c3fef7c3cee5b34ea05aee62597374b2d6143e51039b706bc660f371ea75d41bd9ef4da3a7a5ee404600a4880f8915d2a0d4943210c8e5e71277e7fb0a75847a0e9f3e97824f457206271c9147e2862e8728b4d69cbe84e785d92608878e367fea06978192e6e69d4b8acadd42ac1133fb3a9e9e1dc50e281254144a0fe07efe8476c462860a01a5e4180a4de0249f05648c23f8e6e3bc49809eb27d2c7ee29fd05b5cab4d8ea4b8868446d4562a8b2d6f182d818b448b165d8497a72c623880702eed40e35aadcfcf6b09f67040effbeddd2b22af32c2978da711f60d3a60f115c98e714b9ca80bb1bfbe16704fb841cbfb0bedad90d8ee5106d2178980cf59e6836eed32dc22ec231e5556dde151c0081a83bf4389916868f9a5c9eb394a00dd88f01a451ade235d634484a9c56c595224495874fbdbdfdc1e93220adc754722bc8f182a697c43e34c44782ead62b2b4d01ed046ac0d7187fdf4ec246361396ba03e69055b5347faa6c1cb9929766e4f2a7b41911e25448678f4820e4764775b18b4c0668fa3ca1e9183ed8e57c30c211e97e7cfdc685e6c082448e0595ca52e08fe5b0d37ac52bda3dc4c8a0b7d3e9d1812d5530ebcf9df0ca539c809855b617cec1498a8e2313908d070839a80574b129b24245eded44df2d131e43dc9142274e0b70a75a903791928a1bfcec374626d3c6136c409de439066c72ccb9ad0332fc9b36d3a24c6173a23014f684d0f1666b8331d108ff33986354061399848cc96c7a631da2855f503865eb732fd4e5c3976571cde050a1777e67603fe0045e0a581002149e02f12f72a340fcd78d5723d10b6869cb54bc64940dc20e2c4e3989890f61c5b1df09c72d8a70b5e5a161c0077f73c816b17f59d9533c2e6ab0c7a26dd2cad7646133b739b24e20159d38cb2e11faad8ea174305417860ff18be0bfcefdb413d281ebc034b8b5f8722b041e90ec772e1e9449f61650a27e810f57d102788527c3e274dddc99f094edf73a09544cf3f162573d6da4798895daec9986a41222047ae0d3ce9b6d84c6e91ff5abd4296b1e777b8e22b077a6aea2e843cde25869445dce969fda78091938b3cfdd6f1ab376e62e9f94ff0456171e270fec0156069e8006f48956683abccd1427e3ec9df93abc4fbee9170e9ac11dd9ca793e7d4ad05cfe205d6ba0969f8e965d571cfbf51f54a8e3317b795c76523eec774719d38f8ecbbb192bc298fdca9b0a9304386b0791c671fa441d2103a8e2b2f015072895fe33d26bdf621bc4357610234e563f1f6dbf1584d21aac7bc2a1f4c8869fd97e805ab0157b6325650d1e03909ae85ae3751e582cd823db5394add842eb339426c7a1f44fe90370fb00c10664c8f2c9515800831c45fb5248387358534d37a9b2bc6b9ec84bbcda7f2f8fc16f848423e1dae978e729d4886f44e1b21418fc96c9b11246ec54148661fd7515be3636f5d3fb5e2723cfb1a7253ebc10064373d6227daca15f68a54710eea722a4c7ac9d8cb34c289634b7a831c0d58ff0c5654f9edf692e49403f40a9b1b1bd4acaebd7c2ed9d02378c9a9b763a41b5a85c0e978d30601e32bfa02697f9eab6f756a1d83440c49028baa4607d4ec080ace306ea6094d615cc220736fadb0bddb33b4d7381d35d265c13e35b0d829219ad12e42d1b56bc54f1fea860b18d6440a9c44c56c41dbadd6085d0e3707ee4eeeb4e3410a8326cab9ea1eb95213475d669589cc8b1331ccc7d65eed9559e0ea0f5bfff13843f2b4a2067c577278af1558bddd481e153602c11d5c81a424e2a1e946483bdda59d530949954fc0d7e42afce9454b6faa5b7575f6fa1d2374efafe1363b36df330d958bfa12b5efdf7d274943cf6dd8c5448e3d30bd0d05afaf86a2d30c068ff63e9fd065e1f84362827c46ccb49a8ec04049d1e04db6f7b88c193400ee5818956472db1a5d3ab044e18f4e918b2547eb275d8910d103c13a8704ed2503421465b1e68c51817ae25727b7b72f3817febe4ec7451fc241d7794b8a63f1317707c329bed6bfb2a0023bef0917a4f8944b2023efbe2fe3d2131c41ab066ec2eacaf389834b55ec862fcbca7862a3addeb9a4fd147bd07f480464e395013f2599efd1c800bb1a8d30d5f57f82ac1df5056e7ab4b9b21cf69a97916c8a50072a9fa50439bf52d8ca7aaf50f5bd9591a5422b079114f0bfe4acf561c826ce665878ade3dace990e64ecfb1ba367f4c3c0a61d4aa1dad084d5c3279ceb5a4343f16894ba217fb7c1bb67c328dc7a5834ea59c48d0db9f4a5d9ad304bc46c0d63e2847067350555940f33ffa238dc7137ea04ecb81d9abc5b068794756c4f812d1c5af309231bfb4b27281eb33f8df6c7152ec14ed6fc9a8a644e174ba754247a7319d29a2d250be22ad5e7494d649b11898276a964aafd01459781278f83a80e6764aa6f07eaa4e22d1741ed853c68c6ab19999edb739487eaaee49b05113ccb3c725993fb28e76ac53f00b9ed3ab5f6912e0786fc1138fdd9eb43b407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71d68496b94fdfed16540c30b13d0d7e65a4ff1bb1b73ae867b96e7c912b00ff6a0ae752dca9264748a313dc53b63231d29e9fad3bf5e6ec9134177e105125ee610a1f9b915d9b65deb6f9add45e7b03240fec592fd59851a1fced2bf84b59977cde42db08d3a2ae3363169cf1de0faac09b586e3da4527c94f3e773341a31864c9cbe171e9d2dee147797d4242195bb40ac11e174db2328fe1eb75af660ac3467a41c20b10ebaf33b287cca0bd628c8e0776b9bf95584947c130993f4560f6f01a417c3a364675ca3cb6a8235ce24cfc39325150995dd367ebed4e2adba7efd67f631073311641d31a868698b9453e88b51df1f6dce9144da9ebea27285a1260bd849ef59e925c176159e087d784b4c571ff12c63386066a9565234ceabc1d14242383c5e1385b87afd269b475a6fde0ffb7bd90e239d010036426a9102aab37b5e7822263c75b2709c939073244489a929410cd8eaf39549a7f7e39808fb43114cccaaeacc16d611dd34b249acc4f8bc2276ac510bf3052b08e057425c87fd10a6c6f7979f5044137535fe3f4335ab4d53ff7a251b2d799539e0852b557861591858ca58ee54562ddd8ce1604479185664a744017e539e3a7737b7eba00d76750ec72e68159e3a59b6311dca75e37ce70329997f97069f11df50dfcfd9f0527d72a5f91327ba5470d80b2854a57596101f5dd528153c8e07bc10fd47d0ec9c6b3ca84536e7b0ef7109b756252405947adb4dfeaf4712a116940f296667427b1c3451595f904e1bcc1ecaffb327a9375f9f09251fd12a66f7cbd6faf86fe9024394f1eb3df27c88e651042254b623a6d4f21c9d4ff62f4819dbe9e6a4ef2e243a664589311423742fae46323f94994ab346ac1582f51747493b32611a563ad057baea8cd9643b8d548fe547146d615bee842aed92fc83470ae7116abdf4ab1944e02a488e8df0f2c1a026bdcb1c9e5e273773626b603e9c7ff6b9bf0beb5a573c6e918efa944501d59226cf102566661ea103bbe11febe431a1ff61e7c44a9852e25b13c8f1bb89f75aa4f297f36eff83fb89c7fd7627643fafbb62323508202f6cde95375caf3e05b69ec9d53a3c3d46d2c269274d4c297ea4c1849854c73f6f6841ca230369c180417f4a65f648b88e8a5dd04c309f31d09161a0207dee3469783daaa9274a0ebb267618be37418eb65bd822d1caac9f77229bb6c60962c515e8b207b02674157f4b2fac359d2595191b18223ef8d7a62f203c30dfb407d3017a45f5b334202ec3bdf629961bee8974b2e756e4c7b638ddcb558e8b8fe0e802bef767d681dba2b2af833aada512c7f867dbe6e01b2a7eb49c7b6e50bb8d9e6cfa8ed1321b415771d5535b817beb8831160ffb5f256a040d662f90742d2be25580185bd09edd014de26223b5f1a82e054dfebb79336d891b767f8be214f88151b8a8ed8bf99febaa10c51a9b07f80b130f73cfd4d1de282f6d7f5ccefcccb64a4ae407d0c8e29650b1c0c1c00c292d0afc5ebed5da7e7a9d0eced3c6894548043aa537407a69dfbfe0fd4dffdf896a363d75ac5707eda016347a63abfaa6435132d554abf826a19340bd0f7c5984343cb49e89936f55f2256bfc32871448794ea44303147839275ddbe891c2ce4f93b4e51ba2a2709de73de8b659f9ad0d8a6aa8e2f1c300418e07035b4a39936ac69772520c167ef33f576198a70bea1a3e6a4810868fffb8bf70abb870ece4fd40a2c286d65a1a768776bcdddba218f6854236270d550b0acdb1e87c0a647026b5982426dc8bfd02bbfbe5ecf33fdef0b048ee02ee85779a0ee900ad2e02300ecc774f73ec419fdd15546141233308dd4e05e0bd98aef19726d7d2749d8f316b798b87ac700de86806c0586e96d5fa35d908728d9a044cfc98d6435f5a73643ddfa896ed51671f0a76359ad302d329a7d6489c3cb77d7a563214f32cae5c3ab5a379198c36ac46ef0f151a21bb0db55720418ac16e2487ae411a37a41f7a086824b2efd39c94b3494efa7c1b708e360b380cd65c6b0300db4259152800ab8a88f85e276b32399f0746cdbfd93182863a850da4404584a8ed17f70aec3cb4412c17b854cbeb6e4ed1e94d97bf16f7b343ff7b1c0d02b11555ae20d30819e6ccccbb44b7538770c3aecbe7351ded9dff5a0a7c66c2be38a68a4f8d2cb06766b1cec3242cf191ff9ecec987893588a89b042c2034534af2f0c4e38ba3617ddd1c70bbd23365639fa7cd5f191861c7fbed74a809b4577184b74582b4774b8ddc3f186fdab84f01e0f988b74bacfe932f46aa7023309f130f7d93dc434d02fa0318a7a63dcb6fc7a8cccb8eb8452ee3c1cb6540512a78cc5ebbb671f9ad9a244567471923ff0a04fb615834380caaf01494ebc73ca0d5c640440be29f2206fae788ece44aca654e36a2ea1777e93e939111387068eae8a7ac652da78f63545288ebe0eeaa2eef9ec82ba6bacc11acc6e110d82f4a1c698336cca9cda4ce660b4873e19098521277c6167a5090ebc2df903b9e682728b4a3ba320237b20444e34f94f2c8f9d5e0173b28a2dea1a88f7e40403b113752a6f9aa0b49ca6a5c34a2b92b2d2bc5f480ee94faab28f01dc0d7ad19392060a4f0a8a95ad318982f081ab3c35895f83a6d4611d888a1a0d0a8ac62075ca703c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416aeec5145d93ca5215998b118cd43fe6f953be84cdf704bda68dec68fb14c3e6490399277cafd3b75630f0b826e2dd6d287a161cf892fbdd889e0c6b19cc0be4bb41fcd121741e20510209b0740cb89c118f190cae98339b07e65df9cc9dd126b9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712122d254e33b7c35d78ed4f76db5578f07a6c1bcb7dc46199c567c4a61f84c574fc4ed042b0f2c8397da95d7dfafa615f163ee77de3725afe64561d65a370b3430bc9746fc125c950f425b970da866f8944bf368a765eea617c7ae949c214c405a9250eaeb7dff21e3804b3656037370d9b2694a83536a4e924c9f3dedf1ba083962d04439175a2d98c3e54aba79db4b5fbc425c1ae4d759878086569d2afcba33ee7757f605a7b0d7d518a7751ffc17479ef2cdbec637e4bfb3dad4d8993a553d0ccbb191f4be4cff5ad204d9ef12e321d851b431a0487b9b00a71213f2c95a3e48a1025c18a4bb04dbe9c259e0ec5a57863699f0eb5efd7767175b02b9bebf4eda442aa4ea276a4e1cad5e196a6945f4f9feb7e434a747a9244eab3dce1ed9534262c8fbfdc245ad9dcf846980488cb4d18a79606fce942d48063f0455392e5d825f515af082f6906036c246bb7b1f3b75d1344466e45c96967f8cb73049970c100538397589fa07b331c10ff03ffcf5cac1691840ba63344882cad3a161b135fc74cd2834b4d7d555117ffd19bb23e6ce26d31a3c34bb5626688c2388f32937ea6edb9107df7695cf745e061c1c8b98f078d88f50881eda8dea89dc75b6633f1c7fb016c01016f8225393bfbb03533db594d4e1f289484f7c5eaf4babc9ff19d827a1b3dd1a3cd1ff4732a3826ac5a468c6464286aca145027df161442843522e2ea9f89b72832b1d5fe563cc115c44ce2ba0c383e5d6824f8260f9697397660eecf2766560b1c77937fcec07555c995ffa2eb97e7bed217c46cc798a407a054e3e8c342de20d821c684b2529a9260b8c75b32c9e0232f6870db100b286915baa9ddfef29ba03584ca140af25d0ae285191427484dfca3a722f8729a0c76d7fec1a9c987bfb111cc69796ebd1976ad4ebcf4b3560c1bf2662f77a10271993092016aa2a13c0e05dabd3e3754bbf0e87775ff06bdca2da1382448fbabfde07755a6313b77aea6326c8a3ce609b67aa4b2de89a10da711cc35cf593e91f701a0fa8e27969e0a4642d03481c477ea3219946b9e8b8b1271dd6fbc2da017b45d3210095667544b271eedf036d8b2ffe8d5f903ac79718d2bda2a14a9fb3cba6911012d8f0e3c51c77bd269f51b501bc3056358b894a4efd94d6f3ab31c60a2e6d42022e0b1f1daae90dcba1b96d681a018636a09bfbc8381cf40a502de14de2b67adc4b5aa9706a54c576dd1caad7fb29bdca6dbbce5cac2eb1e65d89633e3dfa60aae7bb0cc818fc18b6ffff18592e8e8671eb94ceb0c2e15b33f9f54415cc9e626a339aaedb6cdac744b85af70456c65c9025b86a7426169cda4490dc7f20d0220467f6af1ed61d0b39bd7cc4f9e94861a28fa6f27709921625b455c2a5981634b644f122be630c593c15b16fb21e9cab0fc7b0140c981652059d2310ea20e463dc56e7b203c1dbcce46929b2013bff2270b86d4951584ef7bc2472febdcca611282f3dd2a3026e65945ed13d52e629d6d6a120b1f6442b75e0b2660e0f05824ce468bd570a388c6eda0d4b98552d27b9aacca2bcdf7f90b75243f624e0181f20683e701c397f4118ddc67c11ade82127f6d66ca2b4137aa4876cf62bc50a203954cb3460a6f509b816726d7b0427c7552a24e1ad207087af15ff6e5619ec37622a69b1d98b990ab979c98b9a66995d1665017790168ae8b5dd1608ad0bf62c35c2ac54ee3c95f27faeedf474fcf1fa50ca27f2087b110a88585c255830f56048944d2868c4978492fa514359fd3ca4231f9a3b7689833643ca183622e8cd9639ead81d38d3c3ef6a38a08f0415e8f2569d4b698449bf2c5ca74346454838e92bf4ef4200963a061b35007b1a77d0b68fe244fc7a65c339aa06f8fc468150d649eee8dd05156213b4b376830067601b89c2f3ecac6db895a8078e65ff80e7d04e60ab0ec43fca15dc14d5312371e0b26d5cf58477961dbd96fcdf2b31d78c450fdaad5e9bb9248f6bb0cb58946f2e01dbe23224e6af11e5eaaa5b6d43d700a8083e97f57984a6c431796df3d153e6b310d25c37fd451bb16e2ed028aa7b09e42e10f820389a6e253f09f99692ffc4359b494a30096a3eb8a5b97c3aba02933a37cc732e055d41a2acf695dfa9d59dfd5627864efeed20c24ad2ecac463db3c12b4ae5233ea7370c02412b04da5cecbbb9154f804dc0c8e74e2ac9daca31a3b872cc38779f9c7b1a6ca93f2c4f6d04a6b0f3e699c8a40511a2e3b9fb7f8972661796817ee864c2396b7b2a9f349d959b6fae1d66ec9104ff9c942f030e65a8aa546173676eee3beca7af1636aca17582f30829782e2c9b1b9c72aaf8060563ab378657bf91d13f2dd4f1bb6adc1d6da398e1d9b2a4884c63631d46aeeac4ca7348887106b8f07b427790d1cf4a2713ad56af6e1e1629ef93edf14348535e50013d4a33f70273ba18c23050e010109645dd600bbb52809754ddeaf668a72b443d63901a6c759e4cffd958b68736a9a1ee2ebdff616811e63d43b100947549aef12a6caa34d62c1fee27f253562286a466c2b2f91a711cbfaebc527f705bc8bc7351cc7bd57d0af9f150e6466174f1da6ac71c79a2a4df82d44f585a3865f7364024c6f9a7ec7442cd32dc7566e2531fe4366ce5e22aa6931f8d2cd5f258b334011fba79242837b662646211a788b62ff54a6e9bf54761372954bc5b1503cc1b49403054b96be468c1f8b22ec177da74fc851f7562a10a49417b5b6a76168f52931be46aafc2211ceb98056a1bd1102545401d8698944771e079f3aa93974eaf9960d6bcbf23b14834f0d7034f8d5e6589e4a7f13f65e72705884ee8dcbf1360274ec269f1e31a344f8884e5ae3450628689e6356669e7a94e43ea1ac65578a8a21d8cf64b22197ab966b1a20a098fe08768b0f5e53e25c71864a657cb42ea209e757e475ac343e5f8f85b776ea6276755f5d9069447d01bf34604c0389a5a80b7687ca74dd548b3c5d98e4f70c9a85d29ddd2296fa1cb8be37e5d8701af88c70c55baf0ef059358fb8506ab8dabcb8642da7052e6493cc40a035dc86b8d5c88164976f31fc1f72c9a86eccbe29a1060e2a5b0d6abf7c452613018b69e8385b7ab509e460dbd802cd49164665229340e29a14dcadf345f493f00ebe1d829515c6528b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d5e8fcf6841f2e94ebd740f848a2b4e72c31c7a21aea6ae8917400c81d43bb522b64c2aaa0a1986e68954e4ca7b5784088392fda54f4dfbac75e454458e01583df2218fc25708efa7679c23d318c33cdbfce6be7e9125002352d34948fa8b3a67aed933b6c623a04853e8e76cab3219c59d5ed56410b366482128627181b5aa4eceec7f1352a57bf84ff4eb62099a8875cc61b06d7c3dc6094fe96948c881c60eea50f1aa4ca2c2c57af4783c613dfe8392229ee5fdf145d7506ef3d9e559246558463ea4005ea0f83e358d15a789493bea81664169d09e26df8e8e3a2361e6226a54c73b0bb645b846c9bf3c2883b4936fcd3f629f9d24086d9ce4c20cd226199884cef69623c717e7aade3c1f270584fa38cd0d9b6a56045e318ec49ba8a9615abed39d47633eeccd98be10042d5d03d852c5bd930a89f0ce256a9332521f287c5b3a221df63628851acb241908838bac9774b28721290f082f7b143e8d102756d8e06152648b0c9f937d26c08490a5752ece4b16ced9ed97d75143de35326b6e46ad517f13ce464516302d89289478f09e15905bf5d8326d95437860df2f72c0d2cc0f3c40972b07c54745de572f912a58b2bba9c42f105f09be83e69491690a5ef93a98dbe72b55880c843da199106393fa4db8a6f659207f6f419b31a678ceaadcc3330cf95892fe9ec136744640751b38026e009740867b10de8eb67f15a03477bcfddddd9319bcfa6de112cd37ab5040bc19e0b3a52f039a6ba60d2045f834a3195e89e19ae67d96b45a0bee0beb3ec45595def5f6e8fc37ba73c0515e6ade7566e5eda3fe184f22a89211634ed256471c1f3e0f3ad64717fb58cd0a44709a330f39d5e8cdb773ee71afdd2f9d57b44fa579937be3aeaa1adae3b57d047ef28d1fe4a0ee885dea9edf31e01e23e896796b8fcdecd44b4b180dc7e02617563ee5edebece3368fcbf345b930c92fca7072eceb55222b960c5f7e0fd54d58b2a296fc8053d12508a47fa99f2cbd5b7fcea38d04fb896e5421661613af2b53ae7f9cf9da7141efb199d0830298feeb364ff4ad75fad31d8e7285e6d63e4c3f149c65a859747611e99d8cb5d06bd5eb20c5121ccc64e431ffb0c6981f059d02a6924cd1ad196dfff80d76bf99383b20bee491a49cbe9a66f16ad93859533515ecaf1ce37791cdfdcdadec44734ab9a4e4d16a25f18d2e207f66037bed355c32f0b6a53e8785a5b3392bb92c3a0e904b1c0e100735390c8676dd2da11747fd6014c06cdef71226f89708e71ef9c6ab3d95def2dd7f487e42efa411f4eb05a33bd833c6d57f623b8f0c8ed846045cf44fea32bcbe0bc04e118f3922c6a45c890e469de71ef3008558f64ece794dff8660ca2d18a49e2e7b3beaf1e6c903da7e0e8af4d2400c18023b5de425d219f9efcafb72aa555fd994cf9f67ebeb5de47b6a84256e12aea7e877a8b9b5cbcc01119aa6a8e732f551d99dfa4fc239739c0c1d9c415bb13419d4c73469ba912eb7d346b91629642940f117e1aa50a09fd5dd48caa48fe936563f4a200c29d77a80f5657781f6849373684b82a029b1fa3d2c566173676ed7bb07c67c2bc80e7d5ba4623f8ef0d565d266723ec60497f0375b3bac140000000001000000020000000300000004000000140500000006000000070000000800000009000000140a0000000b0000000c0000000d0000000e000000140f0000001000000011000000120000001300000014140000001500000016000000170000001800000014190000001a0000001b0000001c0000001d000000141e0000001f0000002000000021000000220000001423000000240000002500000026000000270000001428000000290000002a0000002b0000002c000000142d0000002e0000002f0000003000000031000000143200000033000000340000003500000036000000143700000038000000390000003a0000003b000000143c0000003d0000003e0000003f0000004000000014410000004200000043000000440000004500000014460000004700000048000000490000004a000000144b0000004c0000004d0000004e0000004f000000145000000051000000520000005300000054000000145500000056000000570000005800000059000000145a0000005b0000005c0000005d0000005e000000145f0000006000000061000000620000006300000014640000006500000066000000670000006800000014690000006a0000006b0000006c0000006d000000146e0000006f0000007000000071000000720000001473000000740000007500000076000000770000001478000000790000007a0000007b0000007c000000147d0000007e0000007f0000008000000081000000148200000083000000840000008500000086000000148700000088000000890000008a0000008b000000108c0000008d0000008e0000008f000000109000000091000000920000009300000010940000009500000096000000970000001098000000990000009a0000009b000000109c0000009d0000009e0000009f00000010a0000000a1000000a2000000a300000010a4000000a5000000a6000000a700000010a8000000a9000000aa000000ab00000010ac000000ad000000ae000000af00000010b0000000b1000000b2000000b300000010b4000000b5000000b6000000b700000010b8000000b9000000ba000000bb00000010bc000000bd000000be000000bf00000010c0000000c1000000c2000000c300000010c4000000c5000000c6000000c70000002b000000000000002800000059000000020000001e000000" //nolint:all + resultBytes, err := common.HexToBytes(result) + require.NoError(t, err) + + var sessionInfo *SessionInfo + err = scale.Unmarshal(resultBytes, &sessionInfo) + //require.NoError(t, err) + + //require.Equal(t, SessionInfo{}, sessionInfo) + + //encoded, err := scale.Marshal(sessionInfo) + //require.NoError(t, err) + //require.Equal(t, result, common.BytesToHex(encoded)) +} // TestInboundHrmpMessage tests the scale encoding of an InboundHrmpMessage func TestInboundHrmpMessage(t *testing.T) { From d20070655ce11d16f09134d38644128096c392c7 Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 5 May 2023 19:22:21 +0530 Subject: [PATCH 44/65] fix test --- dot/types/parachain_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dot/types/parachain_test.go b/dot/types/parachain_test.go index 0b42dd864c..81afad8d97 100644 --- a/dot/types/parachain_test.go +++ b/dot/types/parachain_test.go @@ -263,7 +263,7 @@ func TestCandidateEvent(t *testing.T) { err = scale.Unmarshal(resultBytes, &candidateEvents) require.NoError(t, err) - // TODO: assert candidateEvents + require.Greater(t, len(candidateEvents.Types), 0) encoded, err := scale.Marshal(candidateEvents) require.NoError(t, err) From 5baac841e3979f53d9eb3d62584d868dc72ecafb Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 5 May 2023 20:00:02 +0530 Subject: [PATCH 45/65] fix type --- dot/types/block.go | 3 +++ dot/types/parachain.go | 40 --------------------------------------- dot/types/validator.go | 43 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 40 deletions(-) create mode 100644 dot/types/validator.go diff --git a/dot/types/block.go b/dot/types/block.go index f8bacb6197..33d9b5f764 100644 --- a/dot/types/block.go +++ b/dot/types/block.go @@ -9,6 +9,9 @@ import ( "github.com/ChainSafe/gossamer/pkg/scale" ) +// BlockNumber represents a block number +type BlockNumber uint32 + // Block defines a state block type Block struct { Header Header diff --git a/dot/types/parachain.go b/dot/types/parachain.go index a3a06ce21e..7e4a262655 100644 --- a/dot/types/parachain.go +++ b/dot/types/parachain.go @@ -13,46 +13,6 @@ import ( "github.com/centrifuge/go-substrate-rpc-client/v4/types" ) -// BlockNumber represents a block number -type BlockNumber uint32 - -// ValidatorID represents a validator ID -type ValidatorID [sr25519.PublicKeyLength]byte - -// Validator represents a validator -type Validator struct { - Key crypto.PublicKey -} - -// FromRawSr25519 sets the Validator given ValidatorID. It converts the byte representations of -// the authority public keys into a sr25519.PublicKey. -func (a *Validator) FromRawSr25519(id ValidatorID) error { - key, err := sr25519.NewPublicKey(id[:]) - if err != nil { - return err - } - - a.Key = key - return nil -} - -// ValidatorIDToValidator turns a slice of ValidatorID into a slice of Validator -func ValidatorIDToValidator(ids []ValidatorID) ([]Validator, error) { - validators := make([]Validator, len(ids)) - for i, r := range ids { - validators[i] = Validator{} - err := validators[i].FromRawSr25519(r) - if err != nil { - return nil, err - } - } - - return validators, nil -} - -// ValidatorIndex represents a validator index -type ValidatorIndex uint32 - // GroupRotationInfo represents the group rotation info type GroupRotationInfo struct { // SessionStartBlock is the block number at which the session started diff --git a/dot/types/validator.go b/dot/types/validator.go new file mode 100644 index 0000000000..279c218a42 --- /dev/null +++ b/dot/types/validator.go @@ -0,0 +1,43 @@ +package types + +import ( + "github.com/ChainSafe/gossamer/lib/crypto" + "github.com/ChainSafe/gossamer/lib/crypto/sr25519" +) + +// ValidatorID represents a validator ID +type ValidatorID [sr25519.PublicKeyLength]byte + +// Validator represents a validator +type Validator struct { + Key crypto.PublicKey +} + +// FromRawSr25519 sets the Validator given ValidatorID. It converts the byte representations of +// the authority public keys into a sr25519.PublicKey. +func (a *Validator) FromRawSr25519(id ValidatorID) error { + key, err := sr25519.NewPublicKey(id[:]) + if err != nil { + return err + } + + a.Key = key + return nil +} + +// ValidatorIDToValidator turns a slice of ValidatorID into a slice of Validator +func ValidatorIDToValidator(ids []ValidatorID) ([]Validator, error) { + validators := make([]Validator, len(ids)) + for i, r := range ids { + validators[i] = Validator{} + err := validators[i].FromRawSr25519(r) + if err != nil { + return nil, err + } + } + + return validators, nil +} + +// ValidatorIndex represents a validator index +type ValidatorIndex uint32 From d93e2683491f9b267d64dcf705a6affb3fc4e5c3 Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 5 May 2023 20:02:28 +0530 Subject: [PATCH 46/65] fix type --- dot/types/validator.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dot/types/validator.go b/dot/types/validator.go index 279c218a42..6d2917f4fc 100644 --- a/dot/types/validator.go +++ b/dot/types/validator.go @@ -1,3 +1,6 @@ +// Copyright 2023 ChainSafe Systems (ON) +// SPDX-License-Identifier: LGPL-3.0-only + package types import ( From 52b3b02aed5a73ec5f4a5793035fe2131218d3c5 Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 5 May 2023 20:09:20 +0530 Subject: [PATCH 47/65] fix err --- lib/runtime/wasmer/exports.go | 56 +++++++++++++++++------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 17f8ad83a0..57a7cd4352 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -351,13 +351,13 @@ func (in *Instance) GrandpaSubmitReportEquivocationUnsignedExtrinsic( func (in *Instance) ParachainHostValidators() ([]types.Validator, error) { ret, err := in.Exec(runtime.ParachainHostValidators, []byte{}) if err != nil { - return nil, err + return nil, fmt.Errorf("exec: %w", err) } var validatorIDs []types.ValidatorID err = scale.Unmarshal(ret, &validatorIDs) if err != nil { - return nil, err + return nil, fmt.Errorf("unmarshal: %w", err) } return types.ValidatorIDToValidator(validatorIDs) @@ -368,13 +368,13 @@ func (in *Instance) ParachainHostValidators() ([]types.Validator, error) { func (in *Instance) ParachainHostValidatorGroups() (*types.ValidatorGroups, error) { ret, err := in.Exec(runtime.ParachainHostValidatorGroups, []byte{}) if err != nil { - return nil, err + return nil, fmt.Errorf("exec: %w", err) } var validatorGroups types.ValidatorGroups err = scale.Unmarshal(ret, &validatorGroups) if err != nil { - return nil, err + return nil, fmt.Errorf("unmarshal: %w", err) } return &validatorGroups, nil @@ -384,18 +384,18 @@ func (in *Instance) ParachainHostValidatorGroups() (*types.ValidatorGroups, erro func (in *Instance) ParachainHostAvailabilityCores() (*types.AvailabilityCores, error) { ret, err := in.Exec(runtime.ParachainHostAvailabilityCores, []byte{}) if err != nil { - return nil, err + return nil, fmt.Errorf("exec: %w", err) } coreStateVDT, err := types.NewCoreStateVDT() if err != nil { - return nil, err + return nil, fmt.Errorf("new vdt: %w", err) } vdtSlice := scale.NewVaryingDataTypeSlice(coreStateVDT) err = scale.Unmarshal(ret, &vdtSlice) if err != nil { - return nil, err + return nil, fmt.Errorf("unmarshal: %w", err) } availabilityCores := types.AvailabilityCores(vdtSlice) @@ -412,22 +412,22 @@ func (in *Instance) ParachainHostCheckValidationOutputs( encoder := scale.NewEncoder(buffer) err := encoder.Encode(parachainID) if err != nil { - return false, fmt.Errorf("error while encoding parachainID: %w", err) + return false, fmt.Errorf("encode parachainID: %w", err) } err = encoder.Encode(outputs) if err != nil { - return false, fmt.Errorf("error while encoding outputs: %w", err) + return false, fmt.Errorf("encode outputs: %w", err) } encodedPersistedValidationData, err := in.Exec(runtime.ParachainHostCheckValidationOutputs, buffer.Bytes()) if err != nil { - return false, fmt.Errorf("error while executing runtime: %w", err) + return false, fmt.Errorf("exec: %w", err) } var isValid bool err = scale.Unmarshal(encodedPersistedValidationData, &isValid) if err != nil { - return false, fmt.Errorf("error while scale decoding: %w", err) + return false, fmt.Errorf("unmarshal: %w", err) } return isValid, nil @@ -437,13 +437,13 @@ func (in *Instance) ParachainHostCheckValidationOutputs( func (in *Instance) ParachainHostSessionIndexForChild() (types.SessionIndex, error) { ret, err := in.Exec(runtime.ParachainHostSessionIndexForChild, []byte{}) if err != nil { - return 0, err + return 0, fmt.Errorf("exec: %w", err) } var sessionIndex types.SessionIndex err = scale.Unmarshal(ret, &sessionIndex) if err != nil { - return 0, err + return 0, fmt.Errorf("unmarshal: %w", err) } return sessionIndex, nil @@ -458,18 +458,18 @@ func (in *Instance) ParachainHostCandidatePendingAvailability( encoder := scale.NewEncoder(buffer) err := encoder.Encode(parachainID) if err != nil { - return nil, fmt.Errorf("error while encoding parachainID: %w", err) + return nil, fmt.Errorf("encode parachainID: %w", err) } encodedCandidateReceipt, err := in.Exec(runtime.ParachainHostCandidatePendingAvailability, buffer.Bytes()) if err != nil { - return nil, fmt.Errorf("error while executing runtime: %w", err) + return nil, fmt.Errorf("exec: %w", err) } var candidateReceipt types.CommittedCandidateReceipt err = scale.Unmarshal(encodedCandidateReceipt, &candidateReceipt) if err != nil { - return nil, fmt.Errorf("error while scale decoding: %w", err) + return nil, fmt.Errorf("unmarshal: %w", err) } return &candidateReceipt, nil @@ -479,18 +479,18 @@ func (in *Instance) ParachainHostCandidatePendingAvailability( func (in *Instance) ParachainHostCandidateEvents() (*types.CandidateEvents, error) { ret, err := in.Exec(runtime.ParachainHostCandidateEvents, []byte{}) if err != nil { - return nil, err + return nil, fmt.Errorf("exec: %w", err) } candidateEvent, err := types.NewCandidateEventVDT() if err != nil { - return nil, err + return nil, fmt.Errorf("new vdt: %w", err) } vdts := scale.NewVaryingDataTypeSlice(candidateEvent) err = scale.Unmarshal(ret, &vdts) if err != nil { - return nil, err + return nil, fmt.Errorf("unmarshal: %w", err) } candidateEvents := types.CandidateEvents(vdts) @@ -503,18 +503,18 @@ func (in *Instance) ParachainHostSessionInfo(sessionIndex types.SessionIndex) (* encoder := scale.NewEncoder(buffer) err := encoder.Encode(sessionIndex) if err != nil { - return nil, fmt.Errorf("error while encoding sessionIndex: %w", err) + return nil, fmt.Errorf("encode sessionIndex: %w", err) } encodedSessionInfo, err := in.Exec(runtime.ParachainHostSessionInfo, buffer.Bytes()) if err != nil { - return nil, fmt.Errorf("error while executing runtime: %w", err) + return nil, fmt.Errorf("exec: %w", err) } var sessionInfo types.SessionInfo err = scale.Unmarshal(encodedSessionInfo, &sessionInfo) if err != nil { - return nil, fmt.Errorf("error while scale decoding: %w", err) + return nil, fmt.Errorf("unmarshal: %w", err) } return &sessionInfo, nil @@ -527,18 +527,18 @@ func (in *Instance) ParachainHostDMQContents(parachainID types.ParaID) ([]types. encoder := scale.NewEncoder(buffer) err := encoder.Encode(parachainID) if err != nil { - return nil, fmt.Errorf("error while encoding parachainID: %w", err) + return nil, fmt.Errorf("encode parachainID: %w", err) } encodedDownwardMessages, err := in.Exec(runtime.ParachainHostDMQContents, buffer.Bytes()) if err != nil { - return nil, fmt.Errorf("error while executing runtime: %w", err) + return nil, fmt.Errorf("exec: %w", err) } var downwardMessages []types.DownwardMessage err = scale.Unmarshal(encodedDownwardMessages, &downwardMessages) if err != nil { - return nil, fmt.Errorf("error while scale decoding: %w", err) + return nil, fmt.Errorf("unmarshal: %w", err) } return downwardMessages, nil @@ -553,18 +553,18 @@ func (in *Instance) ParachainHostInboundHrmpChannelsContents( encoder := scale.NewEncoder(buffer) err := encoder.Encode(recipient) if err != nil { - return nil, fmt.Errorf("error while encoding recipient: %w", err) + return nil, fmt.Errorf("encode recipient: %w", err) } encodedInboundHrmpMessages, err := in.Exec(runtime.ParachainHostInboundHrmpChannelsContents, buffer.Bytes()) if err != nil { - return nil, fmt.Errorf("error while executing runtime: %w", err) + return nil, fmt.Errorf("exec: %w", err) } var inboundHrmpMessages []types.InboundHrmpMessage err = scale.Unmarshal(encodedInboundHrmpMessages, &inboundHrmpMessages) if err != nil { - return nil, fmt.Errorf("error while scale decoding: %w", err) + return nil, fmt.Errorf("unmarshal: %w", err) } return inboundHrmpMessages, nil From 13f00ab22e5c1d3636174d701eb3f9953934f374 Mon Sep 17 00:00:00 2001 From: kanishka Date: Mon, 8 May 2023 10:49:12 +0530 Subject: [PATCH 48/65] refactor --- lib/babe/inherents/parachain_inherents.go | 82 ++++++++++++++++++- .../parachain.go => lib/parachain/types.go | 32 ++++---- .../parachain/types_test.go | 14 ++-- 3 files changed, 105 insertions(+), 23 deletions(-) rename dot/types/parachain.go => lib/parachain/types.go (95%) rename dot/types/parachain_test.go => lib/parachain/types_test.go (99%) diff --git a/lib/babe/inherents/parachain_inherents.go b/lib/babe/inherents/parachain_inherents.go index 685b69c8c3..b1731abc91 100644 --- a/lib/babe/inherents/parachain_inherents.go +++ b/lib/babe/inherents/parachain_inherents.go @@ -239,6 +239,86 @@ func newDisputeStatement() disputeStatement { //skipcq return disputeStatement(vdt) } +// collatorID is the collator's relay-chain account ID +type collatorID []byte + +// collatorSignature is the signature on a candidate's block data signed by a collator. +type collatorSignature signature + +// validationCodeHash is the blake2-256 hash of the validation code bytes. +type validationCodeHash common.Hash + +// candidateDescriptor is a unique descriptor of the candidate receipt. +type candidateDescriptor struct { + // The ID of the para this is a candidate for. + ParaID uint32 `scale:"1"` + + // RelayParent is the hash of the relay-chain block this should be executed in + // the context of. + // NOTE: the fact that the hash includes this value means that code depends + // on this for deduplication. Removing this field is likely to break things. + RelayParent common.Hash `scale:"2"` + + // Collator is the collator's relay-chain account ID + Collator collatorID `scale:"3"` + + // PersistedValidationDataHash is the blake2-256 hash of the persisted validation data. This is extra data derived from + // relay-chain state which may vary based on bitfields included before the candidate. + // Thus it cannot be derived entirely from the relay-parent. + PersistedValidationDataHash common.Hash `scale:"4"` + + // PovHash is the hash of the `pov-block`. + PovHash common.Hash `scale:"5"` + // ErasureRoot is the root of a block's erasure encoding Merkle tree. + ErasureRoot common.Hash `scale:"6"` + + // Signature on blake2-256 of components of this receipt: + // The parachain index, the relay parent, the validation data hash, and the `pov_hash`. + Signature collatorSignature `scale:"7"` + + // ParaHead is the hash of the para header that is being generated by this candidate. + ParaHead common.Hash `scale:"8"` + // ValidationCodeHash is the blake2-256 hash of the validation code bytes. + ValidationCodeHash validationCodeHash `scale:"9"` +} + +// upwardMessage is a message from a parachain to its Relay Chain. +type upwardMessage []byte + +// outboundHrmpMessage is an HRMP message seen from the perspective of a sender. +type outboundHrmpMessage struct { + Recipient uint32 `scale:"1"` + Data []byte `scale:"2"` +} + +// validationCode is Parachain validation code. +type validationCode []byte + +// headData is Parachain head data included in the chain. +type headData []byte + +// candidateCommitments are Commitments made in a `CandidateReceipt`. Many of these are outputs of validation. +type candidateCommitments struct { + // Messages destined to be interpreted by the Relay chain itself. + UpwardMessages []upwardMessage `scale:"1"` + // Horizontal messages sent by the parachain. + HorizontalMessages []outboundHrmpMessage `scale:"2"` + // New validation code. + NewValidationCode *validationCode `scale:"3"` + // The head-data produced as a result of execution. + HeadData headData `scale:"4"` + // The number of messages processed from the DMQ. + ProcessedDownwardMessages uint32 `scale:"5"` + // The mark which specifies the block number up to which all inbound HRMP messages are processed. + HrmpWatermark uint32 `scale:"6"` +} + +// committedCandidateReceipt is a candidate-receipt with commitments directly included. +type committedCandidateReceipt struct { + Descriptor candidateDescriptor `scale:"1"` + Commitments candidateCommitments `scale:"2"` +} + // uncheckedSignedAvailabilityBitfield is a set of unchecked signed availability bitfields. // Should be sorted by validator index, ascending. type uncheckedSignedAvailabilityBitfield struct { @@ -254,7 +334,7 @@ type uncheckedSignedAvailabilityBitfield struct { // backedCandidate is a backed (or backable, depending on context) candidate. type backedCandidate struct { // The candidate referred to. - Candidate types.CommittedCandidateReceipt `scale:"1"` + Candidate committedCandidateReceipt `scale:"1"` // The validity votes themselves, expressed as signatures. ValidityVotes []validityAttestation `scale:"2"` // The indices of the validators within the group, expressed as a bitfield. diff --git a/dot/types/parachain.go b/lib/parachain/types.go similarity index 95% rename from dot/types/parachain.go rename to lib/parachain/types.go index 7e4a262655..de7f36a4be 100644 --- a/dot/types/parachain.go +++ b/lib/parachain/types.go @@ -1,19 +1,20 @@ // Copyright 2023 ChainSafe Systems (ON) // SPDX-License-Identifier: LGPL-3.0-only -package types +package parachain import ( "fmt" + "github.com/ChainSafe/gossamer/dot/types" + "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/crypto" "github.com/ChainSafe/gossamer/lib/crypto/sr25519" "github.com/ChainSafe/gossamer/pkg/scale" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" ) -// GroupRotationInfo represents the group rotation info +// GroupRotationInfo A helper data-type for tracking validator-group rotations. type GroupRotationInfo struct { // SessionStartBlock is the block number at which the session started SessionStartBlock uint32 `scale:"1"` @@ -26,18 +27,18 @@ type GroupRotationInfo struct { // ValidatorGroups represents the validator groups type ValidatorGroups struct { // Validators is an array of validator set Ids - Validators [][]ValidatorIndex `scale:"1"` + Validators [][]types.ValidatorIndex `scale:"1"` // GroupRotationInfo is the group rotation info GroupRotationInfo GroupRotationInfo `scale:"2"` } -// ParaID The ID of a para scheduled. +// ParaID The ID of a parachain. type ParaID uint32 // GroupIndex The unique (during session) index of a validator group. type GroupIndex uint32 -// CollatorID represents a collator ID +// CollatorID represents the public key of a collator type CollatorID [sr25519.PublicKeyLength]byte // Collator represents a collator @@ -103,7 +104,6 @@ type OccupiedCore struct { // A bitfield with 1 bit for each validator in the set. `1` bits mean that the corresponding // validators has attested to availability on-chain. A 2/3+ majority of `1` bits means that // this will be available. - // TODO: this should be a bitvec Availability []byte `scale:"5"` // The group assigned to distribute availability pieces of this candidate. GroupResponsible GroupIndex `scale:"6"` @@ -222,14 +222,14 @@ type AssignmentID [32]byte // IndexedValidator A validator with its index. type IndexedValidator struct { - Index []ValidatorIndex `scale:"-"` - Validator []ValidatorID `scale:"2"` + Index []types.ValidatorIndex `scale:"-"` + Validator []types.ValidatorID `scale:"2"` } // IndexedValidatorGroup A validator group with its group index. type IndexedValidatorGroup struct { - GroupIndex []GroupIndex `scale:"1"` - Validators []ValidatorIndex `scale:"2"` + GroupIndex []GroupIndex `scale:"1"` + Validators []types.ValidatorIndex `scale:"2"` } // AuthorityDiscoveryID An authority discovery key. @@ -239,13 +239,13 @@ type AuthorityDiscoveryID [32]byte type SessionInfo struct { // All the validators actively participating in parachain consensus. // Indices are into the broader validator set. - ActiveValidatorIndices []ValidatorIndex `scale:"1"` + ActiveValidatorIndices []types.ValidatorIndex `scale:"1"` // A secure random seed for the session, gathered from BABE. RandomSeed [32]byte `scale:"2"` // The amount of sessions to keep for disputes. DisputePeriod SessionIndex `scale:"3"` // Validators in canonical ordering. - Validators []ValidatorID `scale:"4"` + Validators []types.ValidatorID `scale:"4"` // Validators' authority discovery keys for the session in canonical ordering. DiscoveryKeys []AuthorityDiscoveryID `scale:"5"` // The assignment keys for validators. @@ -253,7 +253,7 @@ type SessionInfo struct { // Validators in shuffled ordering - these are the validator groups as produced // by the `Scheduler` module for the session and are typically referred to by // `GroupIndex`. - ValidatorGroups []ValidatorIndex `scale:"7"` + ValidatorGroups []types.ValidatorIndex `scale:"7"` // The number of availability cores used by the protocol during this session. NCores uint32 `scale:"8"` // The zeroth delay tranche width. @@ -276,7 +276,7 @@ type DownwardMessage []byte // The difference is that it has attached the block number when the message was sent. type InboundDownwardMessage struct { // The block number at which these messages were put into the downward message queue. - SentAt BlockNumber `scale:"1"` + SentAt types.BlockNumber `scale:"1"` // The actual downward message to processes. Message DownwardMessage `scale:"2"` } @@ -286,7 +286,7 @@ type InboundHrmpMessage struct { // The block number at which this message was sent. // Specifically, it is the block number at which the candidate that sends this message was // enacted. - SentAt BlockNumber `scale:"1"` + SentAt types.BlockNumber `scale:"1"` // The message payload. Data []byte `scale:"2"` } diff --git a/dot/types/parachain_test.go b/lib/parachain/types_test.go similarity index 99% rename from dot/types/parachain_test.go rename to lib/parachain/types_test.go index 81afad8d97..3bdad9f78d 100644 --- a/dot/types/parachain_test.go +++ b/lib/parachain/types_test.go @@ -1,11 +1,13 @@ // Copyright 2023 ChainSafe Systems (ON) // SPDX-License-Identifier: LGPL-3.0-only -package types +package parachain import ( "testing" + "github.com/ChainSafe/gossamer/dot/types" + "github.com/ChainSafe/gossamer/pkg/scale" "github.com/stretchr/testify/require" @@ -21,12 +23,12 @@ func Test_Validators(t *testing.T) { resultBytes, err := common.HexToBytes(resultHex) require.NoError(t, err) - var validatorIDs []ValidatorID + var validatorIDs []types.ValidatorID err = scale.Unmarshal(resultBytes, &validatorIDs) require.NoError(t, err) - var validators []Validator - validators, err = ValidatorIDToValidator(validatorIDs) + var validators []types.Validator + validators, err = types.ValidatorIDToValidator(validatorIDs) require.NoError(t, err) expected := []common.Address{ @@ -68,14 +70,14 @@ func Test_ValidatorGroup(t *testing.T) { require.NoError(t, err) validatorGroups := ValidatorGroups{ - Validators: [][]ValidatorIndex{}, + Validators: [][]types.ValidatorIndex{}, GroupRotationInfo: GroupRotationInfo{}, } err = scale.Unmarshal(resultBytes, &validatorGroups) require.NoError(t, err) expected := ValidatorGroups{ - Validators: [][]ValidatorIndex{{0, 1, 2, 3, 4, 5}, {6, 7, 8, 9, 10, 11}, {12, 13, 14, 15, 16}}, + Validators: [][]types.ValidatorIndex{{0, 1, 2, 3, 4, 5}, {6, 7, 8, 9, 10, 11}, {12, 13, 14, 15, 16}}, GroupRotationInfo: GroupRotationInfo{ SessionStartBlock: 15657314, GroupRotationFrequency: 10, From 01c18ed5595bf62cc63a7bc7c834b6266231fad1 Mon Sep 17 00:00:00 2001 From: kanishka Date: Mon, 8 May 2023 10:57:34 +0530 Subject: [PATCH 49/65] refactor fix --- lib/runtime/wasmer/exports.go | 46 ++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 57a7cd4352..880a192705 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -7,6 +7,8 @@ import ( "bytes" "fmt" + "github.com/ChainSafe/gossamer/lib/parachain" + "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/lib/crypto/ed25519" "github.com/ChainSafe/gossamer/lib/runtime" @@ -365,13 +367,13 @@ func (in *Instance) ParachainHostValidators() ([]types.Validator, error) { // ParachainHostValidatorGroups Returns the validator groups used during the current session. // The validators in the groups are referred to by the validator set Id. -func (in *Instance) ParachainHostValidatorGroups() (*types.ValidatorGroups, error) { +func (in *Instance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { ret, err := in.Exec(runtime.ParachainHostValidatorGroups, []byte{}) if err != nil { return nil, fmt.Errorf("exec: %w", err) } - var validatorGroups types.ValidatorGroups + var validatorGroups parachain.ValidatorGroups err = scale.Unmarshal(ret, &validatorGroups) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) @@ -381,13 +383,13 @@ func (in *Instance) ParachainHostValidatorGroups() (*types.ValidatorGroups, erro } // ParachainHostAvailabilityCores Returns the availability cores for the current state. -func (in *Instance) ParachainHostAvailabilityCores() (*types.AvailabilityCores, error) { +func (in *Instance) ParachainHostAvailabilityCores() (*parachain.AvailabilityCores, error) { ret, err := in.Exec(runtime.ParachainHostAvailabilityCores, []byte{}) if err != nil { return nil, fmt.Errorf("exec: %w", err) } - coreStateVDT, err := types.NewCoreStateVDT() + coreStateVDT, err := parachain.NewCoreStateVDT() if err != nil { return nil, fmt.Errorf("new vdt: %w", err) } @@ -398,15 +400,15 @@ func (in *Instance) ParachainHostAvailabilityCores() (*types.AvailabilityCores, return nil, fmt.Errorf("unmarshal: %w", err) } - availabilityCores := types.AvailabilityCores(vdtSlice) + availabilityCores := parachain.AvailabilityCores(vdtSlice) return &availabilityCores, nil } // ParachainHostCheckValidationOutputs Checks the validation outputs of a candidate. // Returns true if the candidate is valid. func (in *Instance) ParachainHostCheckValidationOutputs( - parachainID types.ParaID, - outputs types.CandidateCommitments, + parachainID parachain.ParaID, + outputs parachain.CandidateCommitments, ) (bool, error) { buffer := bytes.NewBuffer(nil) encoder := scale.NewEncoder(buffer) @@ -434,13 +436,13 @@ func (in *Instance) ParachainHostCheckValidationOutputs( } // ParachainHostSessionIndexForChild Returns the session index that is expected at the child of a block. -func (in *Instance) ParachainHostSessionIndexForChild() (types.SessionIndex, error) { +func (in *Instance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { ret, err := in.Exec(runtime.ParachainHostSessionIndexForChild, []byte{}) if err != nil { return 0, fmt.Errorf("exec: %w", err) } - var sessionIndex types.SessionIndex + var sessionIndex parachain.SessionIndex err = scale.Unmarshal(ret, &sessionIndex) if err != nil { return 0, fmt.Errorf("unmarshal: %w", err) @@ -452,8 +454,8 @@ func (in *Instance) ParachainHostSessionIndexForChild() (types.SessionIndex, err // ParachainHostCandidatePendingAvailability Returns the receipt of a candidate pending availability // for any parachain assigned to an occupied availability core. func (in *Instance) ParachainHostCandidatePendingAvailability( - parachainID types.ParaID, -) (*types.CommittedCandidateReceipt, error) { + parachainID parachain.ParaID, +) (*parachain.CommittedCandidateReceipt, error) { buffer := bytes.NewBuffer(nil) encoder := scale.NewEncoder(buffer) err := encoder.Encode(parachainID) @@ -466,7 +468,7 @@ func (in *Instance) ParachainHostCandidatePendingAvailability( return nil, fmt.Errorf("exec: %w", err) } - var candidateReceipt types.CommittedCandidateReceipt + var candidateReceipt parachain.CommittedCandidateReceipt err = scale.Unmarshal(encodedCandidateReceipt, &candidateReceipt) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) @@ -476,13 +478,13 @@ func (in *Instance) ParachainHostCandidatePendingAvailability( } // ParachainHostCandidateEvents Returns an array of candidate events that occurred within the latest state. -func (in *Instance) ParachainHostCandidateEvents() (*types.CandidateEvents, error) { +func (in *Instance) ParachainHostCandidateEvents() (*parachain.CandidateEvents, error) { ret, err := in.Exec(runtime.ParachainHostCandidateEvents, []byte{}) if err != nil { return nil, fmt.Errorf("exec: %w", err) } - candidateEvent, err := types.NewCandidateEventVDT() + candidateEvent, err := parachain.NewCandidateEventVDT() if err != nil { return nil, fmt.Errorf("new vdt: %w", err) } @@ -493,12 +495,12 @@ func (in *Instance) ParachainHostCandidateEvents() (*types.CandidateEvents, erro return nil, fmt.Errorf("unmarshal: %w", err) } - candidateEvents := types.CandidateEvents(vdts) + candidateEvents := parachain.CandidateEvents(vdts) return &candidateEvents, nil } // ParachainHostSessionInfo Returns the session info of the given session, if available. -func (in *Instance) ParachainHostSessionInfo(sessionIndex types.SessionIndex) (*types.SessionInfo, error) { +func (in *Instance) ParachainHostSessionInfo(sessionIndex parachain.SessionIndex) (*parachain.SessionInfo, error) { buffer := bytes.NewBuffer(nil) encoder := scale.NewEncoder(buffer) err := encoder.Encode(sessionIndex) @@ -511,7 +513,7 @@ func (in *Instance) ParachainHostSessionInfo(sessionIndex types.SessionIndex) (* return nil, fmt.Errorf("exec: %w", err) } - var sessionInfo types.SessionInfo + var sessionInfo parachain.SessionInfo err = scale.Unmarshal(encodedSessionInfo, &sessionInfo) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) @@ -522,7 +524,7 @@ func (in *Instance) ParachainHostSessionInfo(sessionIndex types.SessionIndex) (* // ParachainHostDMQContents Returns all the pending inbound messages // in the downward message queue for a given parachain. -func (in *Instance) ParachainHostDMQContents(parachainID types.ParaID) ([]types.DownwardMessage, error) { +func (in *Instance) ParachainHostDMQContents(parachainID parachain.ParaID) ([]parachain.DownwardMessage, error) { buffer := bytes.NewBuffer(nil) encoder := scale.NewEncoder(buffer) err := encoder.Encode(parachainID) @@ -535,7 +537,7 @@ func (in *Instance) ParachainHostDMQContents(parachainID types.ParaID) ([]types. return nil, fmt.Errorf("exec: %w", err) } - var downwardMessages []types.DownwardMessage + var downwardMessages []parachain.DownwardMessage err = scale.Unmarshal(encodedDownwardMessages, &downwardMessages) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) @@ -547,8 +549,8 @@ func (in *Instance) ParachainHostDMQContents(parachainID types.ParaID) ([]types. // ParachainHostInboundHrmpChannelsContents Returns the contents of all channels addressed to the given recipient. // Channels that have no messages in them are also included. func (in *Instance) ParachainHostInboundHrmpChannelsContents( - recipient types.ParaID, -) ([]types.InboundHrmpMessage, error) { + recipient parachain.ParaID, +) ([]parachain.InboundHrmpMessage, error) { buffer := bytes.NewBuffer(nil) encoder := scale.NewEncoder(buffer) err := encoder.Encode(recipient) @@ -561,7 +563,7 @@ func (in *Instance) ParachainHostInboundHrmpChannelsContents( return nil, fmt.Errorf("exec: %w", err) } - var inboundHrmpMessages []types.InboundHrmpMessage + var inboundHrmpMessages []parachain.InboundHrmpMessage err = scale.Unmarshal(encodedInboundHrmpMessages, &inboundHrmpMessages) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) From 62de2f85a07a1722933335ad454b685aac4abf17 Mon Sep 17 00:00:00 2001 From: kanishka Date: Tue, 9 May 2023 14:52:14 +0530 Subject: [PATCH 50/65] cleanup --- dot/types/validator.go | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/dot/types/validator.go b/dot/types/validator.go index 6d2917f4fc..e9ed46f4ea 100644 --- a/dot/types/validator.go +++ b/dot/types/validator.go @@ -4,43 +4,11 @@ package types import ( - "github.com/ChainSafe/gossamer/lib/crypto" "github.com/ChainSafe/gossamer/lib/crypto/sr25519" ) // ValidatorID represents a validator ID type ValidatorID [sr25519.PublicKeyLength]byte -// Validator represents a validator -type Validator struct { - Key crypto.PublicKey -} - -// FromRawSr25519 sets the Validator given ValidatorID. It converts the byte representations of -// the authority public keys into a sr25519.PublicKey. -func (a *Validator) FromRawSr25519(id ValidatorID) error { - key, err := sr25519.NewPublicKey(id[:]) - if err != nil { - return err - } - - a.Key = key - return nil -} - -// ValidatorIDToValidator turns a slice of ValidatorID into a slice of Validator -func ValidatorIDToValidator(ids []ValidatorID) ([]Validator, error) { - validators := make([]Validator, len(ids)) - for i, r := range ids { - validators[i] = Validator{} - err := validators[i].FromRawSr25519(r) - if err != nil { - return nil, err - } - } - - return validators, nil -} - // ValidatorIndex represents a validator index type ValidatorIndex uint32 From e0f618ba9230176ba109072293f3b4e2fba35a55 Mon Sep 17 00:00:00 2001 From: kanishka Date: Tue, 9 May 2023 15:27:27 +0530 Subject: [PATCH 51/65] cleanup --- lib/parachain/types.go | 32 ++++++++++++++---- lib/parachain/types_test.go | 63 +++++++++++++++++++---------------- lib/runtime/wasmer/exports.go | 23 ++++--------- 3 files changed, 67 insertions(+), 51 deletions(-) diff --git a/lib/parachain/types.go b/lib/parachain/types.go index de7f36a4be..ba257b6c96 100644 --- a/lib/parachain/types.go +++ b/lib/parachain/types.go @@ -142,9 +142,6 @@ func (Free) Index() uint { // CoreState represents the state of a particular availability core. type CoreState scale.VaryingDataType -// AvailabilityCores represents a slice of CoreState -type AvailabilityCores scale.VaryingDataTypeSlice - // Set will set a VaryingDataTypeValue using the underlying VaryingDataType func (va *CoreState) Set(val scale.VaryingDataTypeValue) (err error) { // cast to VaryingDataType to use VaryingDataType.Set method @@ -174,6 +171,19 @@ func NewCoreStateVDT() (scale.VaryingDataType, error) { return vdt, nil } +// AvailabilityCores represents a slice of CoreState +type AvailabilityCores scale.VaryingDataTypeSlice + +// NewAvailabilityCores returns a new AvailabilityCores +func NewAvailabilityCores() (AvailabilityCores, error) { + vdt, err := NewCoreStateVDT() + if err != nil { + return AvailabilityCores{}, fmt.Errorf("create varying data type: %w", err) + } + + return AvailabilityCores(scale.NewVaryingDataTypeSlice(vdt)), nil +} + // UpwardMessage A message from a parachain to its Relay Chain. type UpwardMessage []byte @@ -374,9 +384,6 @@ func (va *CandidateEvent) Value() (scale.VaryingDataTypeValue, error) { return vdt.Value() } -// CandidateEvents is a slice of CandidateEvent -type CandidateEvents scale.VaryingDataTypeSlice - // NewCandidateEventVDT returns a new CandidateEvent VaryingDataType func NewCandidateEventVDT() (scale.VaryingDataType, error) { vdt, err := scale.NewVaryingDataType(CandidateBacked{}, CandidateIncluded{}, CandidateTimedOut{}) @@ -386,3 +393,16 @@ func NewCandidateEventVDT() (scale.VaryingDataType, error) { return vdt, nil } + +// CandidateEvents is a vdt slice of CandidateEvent +type CandidateEvents scale.VaryingDataTypeSlice + +// NewCandidateEvents returns a new CandidateEvents +func NewCandidateEvents() (CandidateEvents, error) { + vdt, err := NewCandidateEventVDT() + if err != nil { + return CandidateEvents{}, fmt.Errorf("create varying data type: %w", err) + } + + return CandidateEvents(scale.NewVaryingDataTypeSlice(vdt)), nil +} diff --git a/lib/parachain/types_test.go b/lib/parachain/types_test.go index 3bdad9f78d..87037458de 100644 --- a/lib/parachain/types_test.go +++ b/lib/parachain/types_test.go @@ -19,6 +19,7 @@ import ( func Test_Validators(t *testing.T) { t.Parallel() + // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_validators` resultHex := "0x444c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e368589360e101de266b8f5f05431dcaf63ecd936988cc348a271f42519bef19df1e9af7f4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57ecee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237ac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a" //nolint:all resultBytes, err := common.HexToBytes(resultHex) require.NoError(t, err) @@ -27,34 +28,32 @@ func Test_Validators(t *testing.T) { err = scale.Unmarshal(resultBytes, &validatorIDs) require.NoError(t, err) - var validators []types.Validator - validators, err = types.ValidatorIDToValidator(validatorIDs) - require.NoError(t, err) - - expected := []common.Address{ - "5Do5qUFfEp5CcAfdcYSj3ZyPzQcbgtTMYZozyD4VCMF4gzDb", - "5CP9KEeF9V3eyTWEStEKQyi6grLsUgEZRqHVcTTm5PbL5CWF", - "5DqujH7PVLVLE7czPhx1gNohVCPUQ5TfhqJ8wKLcZH3zjKd1", - "5Fjd1oQRcLBfEjCVyqhDK2WTEhZ5srNU3LCVB8f52PLytLs8", - "5FRz16eLxHdvCtPfZXpNW5Cn1k61tKTLVrNH36jmAeurMtzp", - "5ExvT1sWmnt2DL5KJp7QnKXsMmx2AH5YMWmGvdkrGq2ycLHd", - "5GjySVgQVLKiA3UG3bJrUHb2Q9PNvFuSBXpUb9vo5arg4jw8", - "5Fxu9xhgqcxTtTQL1HJcLqQpYhj6B4a1Usn1LtYkc7qGry7K", - "5G1BUGa4iCLLQGgypZeeUThiLk2S9Y1Yy7ddpNhPLrgYf6kj", - "5HGRWRdLehaFbJ3zczdfgHhubCygs1bME8yLc4MWidqDwPkj", - "5HBuwTWAzV1LEReH8ohsWRUeCx5ykb3CkCa2GNJKHozQ3hcK", - "5Gj5kpJCbX5oQXRTv6insZeMtMCEptqJ2A5vB5gHsdBgwYJp", - "5Fhe8H4XeYdvV31FVfxKAivKcDw9g5EMnm7oWCunnFfrxEip", - "5CFPSw1J5S9eNyUoh1oceF3inj1zPsV8csiBzR63WZrrf6sq", - "5GBV6ye2TkgNTn9ctjVx4dfxfRQYV1pcPwxrR9ARTTya7Bwc", - "5DLNXbTdnVqoHK2rhskA27e9qxVQvk1GeY1rwxn5kzBf757w", - "5EyBuSrUhLx5prt47u7R4djuhAaenABPTNVruDcVEK7K574Y", + validators := [][]byte{ + []byte("5Do5qUFfEp5CcAfdcYSj3ZyPzQcbgtTMYZozyD4VCMF4gzDb"), + []byte("5CP9KEeF9V3eyTWEStEKQyi6grLsUgEZRqHVcTTm5PbL5CWF"), + []byte("5DqujH7PVLVLE7czPhx1gNohVCPUQ5TfhqJ8wKLcZH3zjKd1"), + []byte("5Fjd1oQRcLBfEjCVyqhDK2WTEhZ5srNU3LCVB8f52PLytLs8"), + []byte("5FRz16eLxHdvCtPfZXpNW5Cn1k61tKTLVrNH36jmAeurMtzp"), + []byte("5ExvT1sWmnt2DL5KJp7QnKXsMmx2AH5YMWmGvdkrGq2ycLHd"), + []byte("5GjySVgQVLKiA3UG3bJrUHb2Q9PNvFuSBXpUb9vo5arg4jw8"), + []byte("5Fxu9xhgqcxTtTQL1HJcLqQpYhj6B4a1Usn1LtYkc7qGry7K"), + []byte("5G1BUGa4iCLLQGgypZeeUThiLk2S9Y1Yy7ddpNhPLrgYf6kj"), + []byte("5HGRWRdLehaFbJ3zczdfgHhubCygs1bME8yLc4MWidqDwPkj"), + []byte("5HBuwTWAzV1LEReH8ohsWRUeCx5ykb3CkCa2GNJKHozQ3hcK"), + []byte("5Gj5kpJCbX5oQXRTv6insZeMtMCEptqJ2A5vB5gHsdBgwYJp"), + []byte("5Fhe8H4XeYdvV31FVfxKAivKcDw9g5EMnm7oWCunnFfrxEip"), + []byte("5CFPSw1J5S9eNyUoh1oceF3inj1zPsV8csiBzR63WZrrf6sq"), + []byte("5GBV6ye2TkgNTn9ctjVx4dfxfRQYV1pcPwxrR9ARTTya7Bwc"), + []byte("5DLNXbTdnVqoHK2rhskA27e9qxVQvk1GeY1rwxn5kzBf757w"), + []byte("5EyBuSrUhLx5prt47u7R4djuhAaenABPTNVruDcVEK7K574Y"), } - var addresses []common.Address + var expected []types.ValidatorID for _, v := range validators { - addresses = append(addresses, v.Key.Address()) + var validatorID types.ValidatorID + copy(validatorID[:], v) + expected = append(expected, validatorID) } - require.Equal(t, expected, addresses) + require.Equal(t, expected, validatorIDs) encoded, err := scale.Marshal(validatorIDs) require.NoError(t, err) @@ -65,6 +64,7 @@ func Test_Validators(t *testing.T) { func Test_ValidatorGroup(t *testing.T) { t.Parallel() + // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_validator_groups` result := "0x0c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f0000001000000062e9ee000a00000054eaee00" //nolint:all resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -97,19 +97,19 @@ func Test_ValidatorGroup(t *testing.T) { func Test_AvailabilityCoresScheduled(t *testing.T) { t.Parallel() + // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_AvailabilityCores` result := "0x0c01e80300000001e90300000001ea03000000" resultBytes, err := common.HexToBytes(result) require.NoError(t, err) - availabilityCoreVDT, err := NewCoreStateVDT() + availabilityCores, err := NewAvailabilityCores() require.NoError(t, err) - availabilityCores := scale.NewVaryingDataTypeSlice(availabilityCoreVDT) err = scale.Unmarshal(resultBytes, &availabilityCores) require.NoError(t, err) - vdt, err := NewCoreStateVDT() + temp, err := NewAvailabilityCores() require.NoError(t, err) - expected := scale.NewVaryingDataTypeSlice(vdt) + expected := scale.VaryingDataTypeSlice(temp) err = expected.Add( ScheduledCore{ ParaID: 1000, @@ -136,6 +136,7 @@ func Test_AvailabilityCoresScheduled(t *testing.T) { func TestSessionIndex(t *testing.T) { t.Parallel() + // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_session_index_for_child` result := "0x0f690000" resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -155,6 +156,7 @@ func TestSessionIndex(t *testing.T) { func TestCommittedCandidateReceipt(t *testing.T) { t.Parallel() + // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_candidate_pending_availability` result := "0x01e9030000328b2b271db466af1870b5918aa43aec671de9803aeadf75013d3c78de35ceea84b5c6e57a116cba4148aaad37fbfc3edc54e7728b5192a40391d9c8ef33bc40e0a84b429996989d65526edda87a56b79f51b98cbeb347ce22a356cc7da02e38ab0e77029716d6a3e8b45e3ac27c623c347f28d433926a7f762cf0018484f58e505b19ef3223929a5ac8e2f17e5add18665a164f002b806899329b25c8da3be76c5664eb273bc0dbc3016d1304e53fc86b20d4d3583c4b72599ffe4386aa7060c9e6f1ad9699ddcc8f2bbe324c882cba6307b47e991cff013ffc307cc7d3e4831efb8e925358db3e93e466f6238871a8a29a6028279db855f0eed3fe4d7705f2dcc6cda49b51efbe0fd184b974074d1258ca9f15b9fccfedc35b7dee6e1ab9e9000000e902bc8e637ddab3bc69db43a62181e9a5807647ae518b205161b1beb25cc72bb441a6dc4600cd7190aaa808a47ac7c2cce73922a0cdde3fc639969c76d5ab44566e25e5fee50cc06625cdc46c76bd0bf8c046308022fe7b2cfd31859fcab2c7d84a2b208b1b080661757261206f495c0800000000056175726101012cd5b2805efcf8f0d7a35e05a9b3582df5af3cab0c912af9a56e83a10a42ef56b4feea6347c7c862c71ad66e0a6296cb6e46cdf10baf65dc89315f2768fd4f8100000000a18fea00" //nolint:all resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -175,6 +177,7 @@ func TestCommittedCandidateReceipt(t *testing.T) { func TestSessionInfo(t *testing.T) { t.Parallel() + // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_session_info` result := "0x01210350000000fe0000008000000096000000d200000000000000b0000000bf00000021010000ab000000970000008500000051000000c40000000800000028010000a700000032000000e200000016010000bc000000f9000000780000000c00000088000000f2000000ad000000260000009400000046000000120100004d0000002300000009010000cb00000082000000750000000e0000008f0000002f000000f8000000100100003d000000a000000006000000c90000000f0000000501000065000000540000003f00000098000000d600000047000000b7000000df000000380000004400000007000000b9000000e70000008c000000900000000a0100000b0000001901000042000000af000000020000007c0000007a000000240100004c000000010000004f00000063000000f0000000c7000000e60000006100000025010000d70000009c0000008d000000e30000001800000019000000030000006a00000003010000ec000000fc00000008010000ff00000058000000b10000006c00000043000000290000005f000000fb000000a1000000c20000002a000000be000000c3000000600000003c0000001e0000004a0000005e000000200100003e000000c800000093000000ed00000073000000040100004500000009000000d50000009200000076000000110000003300000055000000a6000000fa000000d40000002000000086000000aa000000560000007b000000a500000015010000bd000000b30000000a0000006f0000005d00000005000000180100001c0100001300000069000000e500000028000000a3000000d30000000b0100001500000079000000b500000068000000350000000d00000031000000e80000005b000000260100001200000011010000db0000001b000000d100000059000000070100003000000016000000870000002c000000240000000001000070000000360000007d000000480000009e0000008a000000270100004000000057000000cf00000067000000fd000000f5000000060100001d0100009d000000cc000000130100002d0000007f0000001e010000b200000021000000e900000025000000ac000000ea24d73b1607c8fd7d6542870c2563c7891a9085b74ddd253d4322a9b3d3d1560600000021034a3487dc0c46f976d352e5e152e120d2d23774f921583d1f2c128f7cf9f66529d49f031c94d9c3b33494849eb9682c0311b3c283b17373f18b9ca02d94e2c05c969ae5d9d6efa40c6255ec4b27b0a4752d7f4068163116e76cd0d4041c471431e8c13e37a4d00135dbe7699d91507f5a53a7b8ed36a3be29cb2fddab9f7a286c347964127e9d8bcd119989a92646c80886c2eb8440c87dd7dd94437873a3ce286432533fdbdd1a739c62733cb36ac48c821dcb0311978f1027bc1e39d4c8964e6a6570b80ba0a90a857ef4ebdabfbf958898bdb12ea1edbb17eb903b00746a14e059357312bfd525317b4f93e5eee1de639872edfaec9d2a320a6fac04d6105188fe28737bdbfec193327886b5c4906675d2a49ed43fe8cfb4e079698de82d2d042cd5a9d8624860310a963ed20c4192a19a9d163bcf366e48122c00a1e9744c5cac0ffa042ee550a3bf70d380dc032d11eabe311e0796c5143341600ef626644eed0663b1d15bcbf9e99c372c041ef118de7d179c68899a645a0fa0983b473eb2a1fefc7a956231a446a575db2e31f7c084c2945094f3927519617d7b913712c60cc4d544536a7190ec68525a70fde1309723986ab984a1e97aca4092ad721c744c3b91b676828a5f884e79d9c02d6f23ec246c3a1a8adcfa9dc1e531a9a5310e2d777330aba66c9558434a592fa5e5aec49c3a70f49f66017f194d41240d66148f2b835556a0c8d3b51ae0e823655bd4aa20fdadc6b4189de9f32cf2288700d8eff37aca87eea6637118337fb1704bc33f1fc685aec019c8e9eec48b62a728a8cb454f4e75ed6d28c458cd8df1c2bdce6101e09b650fe22d139e360fb809200ed18130a0ed0513b2a2bfa7ed6c9090cb350983746b1936c6a92f7304a7005450b1f33df75af8dfeca1cd7e94fcce445c6d55651259fdca2972a4d62f6732561af7dc55da09babaf097d1304b4cde14562506f4db4897644895324b542d8f573c39b3f67c487c1df902d0397792b7cdf987b657b2d27920bc6846eca466c155c4b778017656b9a7d69d3e69159852f38adf971f5a25df65f9950e97411c1c36e8bb9f2665b217df30a15bcd22f231f66f4f21711363cb0b0da8b3594003ae014e8c22d93dbca83c05bc5222ae72b85617956f04eded477369ec95312c7c78353256f3f643ebc6300f32561a0a5583813bb3b42844d1ad3d3779a438771a295e306daa91a5a25590d2290fd262d40f239f87d37e1c03a2494035a42961db2f33407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71482cdc214f825dc7085e54a984230a753d66d08425f9763f52f8f68911120260d4d65053a5ef2ab1152c72f3b15d4f24d4bced3b7e277735eb49450dd867c115263ad657e55682de826f6137dedd2d246971fd8c5d318034940160fc179efa63701058e68510bdf68a3678d32145780e13c29b88fe77b27440bdf3ea9762a63964675cc62a59886ce5fc12d2f48694c7ac836a0157e0e6630d694d11faa605034c51def135330ddca851fcb670c865235dc1b405242cf9f7ccb728e449e09f4ad614110699b5642a4b726cbcb74bee77642ec7b4f17b06db88ee461848ead17c906f769166b3ff9b0fb13c1ccb36358d9dda3f25bfa18e2857fe01a92328eb70cacb5514b570b9338c8602cd4a49128006a902494029c2728056b02a900dcc7798b499a9c38970f6f3dbee7e6220ee0e12a582a76ae036347816baa6cd7c9a7b9662caa1a29ff92ad66794001cfaaebbdf4071f4db6d74ee767ba59cca4cb36cac6854840b7eb103ce5723aa0d6625709d4c4378c46903ff236d9d8d61f21f76b22d6245ef2ea126366dae7f9c072d2d6e0e71a54c9bbafaed36448a4a552b51f02a182d14b38906ce1f4693cd9b87d0369e6af514cf7ec91455b26cd4c0d71bc2d3f9f9f499e04d2f27dbe47ffbce115afd1bac9fe116ce7fae719325e4082460c09defe1f43c8591655101dd3dc806c7b07762c97ad21e4142705e46a1e17306b888519767218eed7b884fb221f597a2d4edb69c094961ace2e65a7e40913c0658f8f3a64ec6949a26916ae2cd976fe531947a9c9e93e6d587bac746cb0826e4b23b64b0eaea19cab0333369b93e11693d2b4334306ee579360814adfc1339524dad3d2adfad0b2db5fc2de781a22fc63dbc4e30a5fcba2c63c2fcbda238668e06587bec427bd5b5cc33da6f7cabaebcb7688de50b59125434493fadcaa94d1e0560d2b374b7d6e1380b6b88ee8ef92cdde7edbd9a48d66f5e219840a1155818b9272f50007b87be88422e3da9599286087f5e578c0d1c2a3db9a77110f9173a69e0e58185dd4e76aa52804b2de15ebff8c3f3237e29dc7157e61b30b9b00a30f93bce6916b6b78ce4f7d550c39c7947c6860502333717d541fdb6697ab447aadd01c0f366ff1c65d331da120ca3ac630ea6e8d7339e7317518920d710e3325edbe8dcd591d30511a0fc08bc5172ff58ff98fa848387b25f99205361348105f6c138e9e4061b3a799bf7987ef5c820c1e534df298f3328e1093c5d0758d434280f6162242be89d139d52f449e2bad667d7d974cb80d0edbce7237185b11475fcd9b0171f73154a0734c1cc95ae552d9f3180d7d64e8b50d3837b14b5afd2221808dfb6c44ce63a08d4567cef4b2a9aff1b408d2c99fa4adef25724cce85368b429d0687fef75f26e5503379a61920777ef1f254af024922e382dd19e752e69784ff2911acf10ffcf4b1d795df6d8b55f38eceeadffe577cf5bc0360f35005940c73278b76425a158be63207452b1a8018f53309f47486a273b9bf60cb51c48d67770af6f19ab75537f06388373ec17a3c88ff1714806c0c99ad44e6dbdfa713ea7825552b7f76db8f2ba2fce0e546d7e7abab7d59e7afee2bfe438bad6091934cc7903dcaaeddb2bd99fd6b36ab15fc32ee001bd1d95e87020019f7c88be2e74afd1a3a66e44e8b7845e7f63923b706dae49eb96cdc73b04c9e6cfd1459d06d6f02e6854e6df29f08f7e015d511ff48d7bbb13bacc9aab1b06ab73c1f3350ce6a864e68dc99758ce2920256f75bdbe8c918c556a5a2467a3aa13a306808740484d1bff4961f87c7ff6a6a68beac9264665f87ba1a5fab9802f1cd729391a718a7477bdafa88e49f5c8cd88fbcbc1724d8e227935eabce71ec303d832c4ab27aafd3f8056d3462eda0083ac22241db692c4671249a14a04c2f0a2959aab412660bb493e536e83addf98be8cb2a0158cf18c6d5ba06ab586a2cb56cf1ad4cd099ef1e3e727f41ebeb3aea2815f004002d27714db121fd6f92fac8bedbb97160976c4d221bfc6da82c7055e469a1405eca842b4b8efd101e984a2482e526ecb085229a5a3f09f444f6d39d71e0b936cfed125e87883db8876444288d0cbd17642ce97b61a3cb7d20f9048830a34520de889098b4435dfc79a73a0518ba9f61924de365e70f8503654e384a4524c1c16900873792541ef023019a68f62250b7c219a149b9b68af793ab31f83f500126e0fffa71469e78e22e754f3b49db1dbe631f286ac449dbc94282864e76dac48fb9bce48124189d2d45e2b2e16b8084c022bcc90ef1acebf194c7b9820968e554e2ec4d34346eedf80cacdafcdbf118a3f158e45e6a8766869e2e5418499d3cfbe215762a4a0cffe4315edea5ef47c60c163be4aa5196c5241f5c772f3f90c57a3580fa0735a7340e37372048c1f60a20531f830d60634a177f3974d5399fca046417a6e4327c4c569d8f4f5b47b263b0f07408b1d453ae31f699e53904605cfdbaa72639138cea3e544258e0484a532216372ca569751b32be145716eac8ee5e731a1db2b1dae4b9023b05876077cdd78084c79e58d16ecbaecee3965ad4685c1780154b678bbfcf725fb2e91be3cc0864ba0f682ce1460eff27c8518451b3a9ec811e18b8839808256e18a89219fda2772c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416da5bd7647f8d8388c2b4dbc138e36b8679284eadc49370ce0a16a4e0be28804b04f9b593ec5987c0608e3913acb29a322355a554e010d33acf155e6ab9bad337c4bc688653010a7720d44168b4552bf75974219788ac1cf3fb440c67ff692d499e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd93257121806eb5dcaff87a28d25de336e240731a375be04c4bbff6be6a5ba4f1042a067086008bd1c894c74e4ab0b16dd36effafc8f04a4617aefa7f68b40df033149c0a98bd89778f1276a0ee404b17d81b96c524a8aeda9f671be9e724f090c397977714f425d45bda5f3373c374e9b2710f477e2e923a0f0b2b259c941965f6e88c0334fe5947d75ed7ce18612988df5f227b149c66f371593a8c248206f1b59e10248e650f7e08ac882d65fb09141fc5c7d252da9b1d8ca2ae311752ddce977137229ab3993dc198b5cfee52c273f6145c25afaaa6de14670eccdc1b61fd53821513fa519134b630c1d53b78cbb67e8b8414c30247101be5de118662237b8388cc7d3c50b2fab9b87f1a6228df23e9507c90bec51b8e3be978b526c0e0c7704c7334dc8495596755b6b5a83796315f9e316bb871c0465cac91290b34812c5f0e34120ce455c4566893481e7afa89c0c425533fb4eecab574f0399ca29b162a4c78053405a94626a6d3cecc0492a268e974e9864826f8745403fbb98f55bf45c0b620da0f2b6e2eb2808b3e713d1a3f774966e3e00f81226887d5e1c165af998d6e57645c3b5a2e17df20f698507190332c6951d761c5f46e0dcf997c7337c0bb7e54e232d9f4c8884a9f53a999e8ce7a27f68e9108a4fde15bc51a350774c22b2a1480fc5fd10948cd231f68ec00397e22a19042578431aad63546679e72efa3cc619c9564390d54bd989ac1fb089a57964ee4313f857411373d34161939633c8f4230930357b8b54ce94dfac3276daca91ccbab9b944bdd9754fb27d2b786427b30b6d3a029d0c998a49c406fb0778936c3bbd0708774bbf21b400aa8a41e604401c8e5f3c9fe54712dfa93b8f223c4bf30e2d037a36a768f160cf0c6e6a8c42a45908fdba40941f018589894c721ae6eddb3ad080bfca4aae349a8e7ae261f0a0f18d3fcd225254bfac8ee7f94e5f505496773b69c49697eb79ef8523530c55511106827b00917fd22c6b8e62eda5e130344c9214f2565b92ddcd6b6edfa18e95f8afa23b3c8f159391a3ffb6dda5ce3c9f6b40f25c1dc7a742186b7b693f30111e4b9ad468b9d1e0cf4f79c5078c9cc4e409f8a0fb170d7c4f421ed5fcf597e3f061f1060d5207533b44b4977f128acd44bfe1bfe235f2f4b2d042a87c7da4d1d526a096e110f710d48d0a0bb58b06ceb1d6ba2189ac3dc984dc24e80fb6522431e282ef8862f121223f6aa19fc1f929106d7a916747f21e1973eec1e8c5b7f78cc3ceec15a5af2b64d5a43ae54fcccd31ddabe95461fdcb5be506267404ba432e41161e6df14443df6eadfb3c5ad5228291d1383cdaaef20c9cc8125f7952f249a0de7093e895f4c599aeb4b0310673b00785b33fb9cacd556acc9abdc3de57fc056df4318d12a052ab505db7d06dfe03767eb5f46cf0d271393db1db2516c52aca4be351c39cc0bd557e7afe547a479f8a7218cad2c784e197f3494dbb9436292833db878c0dab763cdeac36e752c7cda12c98686c05704a8b2a695a315bb1146b3d1cb07cfb8d2e13fa9158734dc2bd1ea554fd3032bdbf9e9871d2937060236da4573a6c20044052b270916290b13a30adf3a821b467c4038a14026badd09126d6621e31b47269829a47f9be24a0d63c4bd7ae112b395498ec2502c3b4f46547b4c766e40db6b1685c455de210347c5757ebb7d463d1910eb70fb290b5c7bc63163ac00341573dfc794b0d53e6bab40a84e60ffb1dc3f6642aa1a246ee579703579df75d2c2dd3d53003f55ebbefeb59446d476d0a722ef8ed1954fae9d6ddc2f1b5a31a3e46efe8097d83d7f80ec284bc72a48b7916a74a1cad145eed554722609bff1c0970e439f19fff06a080a67677712b09762b90a82fd9f97bbc50c12b2408a440f2c91824179203d689db4245fa3087e8b01a9316ba973c6ed1a7556aee499b2dffa90a79b118a646aec6b79e6766dc25665db73a98e173fa6381ae47c9de57628b53ed9958a889d278fe707b4284327bc582599019bfc4630616b78f186de80c5d2d0669404118ff1591ff141a606e05e2835889a5f42a32e9a1f34d4c6438f429028ba64818bedeff64b1db1ebdd89f2c2b2fe3336942a03036b9e86a336aeeee1b94c5d5a821e4ab4c136cbf2766a43dd37078e02927ca8a562d2ebb6671ff854613aa3ad169250e037aadbf0ea14c87982d7382f09c7b8c96770d2ffd3b72525806a645e5abd09a51d257c30dcf016435c114d26d3d3be170800af2466b5e4a434ad5ef602a77f311fa22300a5a6ebf03bdcc04f92fdf0da3c74f0c1461d8bef6e668a2cd0c95fdfc9ef30cf9133619aeb9c3d5187f23bd83c765478a56c4b3708da965c36dac2e8caca9398d50bff836219540b179bae7667aa091181db267cc8ff6c5201acaad6fc2c3a2cd18eb729ad0c1526c6c348e330ce5d949162cbc728667ecce548da5efe0448823e928463418342d41883dc6e20d8e45f1d6d02c43c3e38d6e7871f18ee80f60415adc76fdf4c8ad2c67ac7d11682942ab79f74656a8f51ab8c1b088f33ddfa20992eaaae491dc3dfff9742fe32c4428233d691dfb69a1713087e4fbfef8f7c96df760e85354069eef1ddbaa01d52f9664fbed82ddb5cd6ceec78143f1e27ee7a0fa73873d01e80e368825e3b05bef7cb0005833a9d0ae360c420a66a5353836acf1fa3c65578c9c5b3b9c7831e944ae887694e9fc6a8634f213d8d061cc2a34a00f214d9f67cd17effc527a07e060bea20b143a7bf515a130000f93cba10536a1204f0a14cdba7b627412d383c308672a7e2974b837e4a89d54e63c47966b36fcfa3efa5854046d3ce09d45f226c36aa9c0762a59eada83c70e1049d5d09f7f7304c465f2ff56dbe21687ece20ae9fcd9ab8a7020a1f967780a1ef49b13b40fc3cfd208e29f4d5d5ee9bb63c5fc81fafe5d47c4ee373a54a64d267c497c59f4c15077374317b91566d44c82f74167e6d847ad207f3a1221ce1f958946317e77ba146d16aa7bd82810c5e913c4da0bc5d3a5923a156f0990c79f01317a3140ef3aff708acfdcd30a838706db819dc3a5a9fa2b1bed2a4a48fb21792b44c5772f888132d414d13a98bb5bbbbd70ac42afa68950568131a449e70574ae0f45f28b87210c1ff7df1adee5576d03950b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d9a53c2f9f5f55bd687e359ef37196cd288fcd1a14adf6cad53c6704445a1f1212270467b0c03fcfd8bac09473161c6eba9c25369a853193b472eb2f113a3d333181e6b71b981059fa265cd76422e52fe175db6983c6ebdd0fea1a3075166b9291619ab90bff00f89ea8055f0d7d45f8c8aa9c04b7fc1d06468837c6c563a6529ba846878e4f157741703bb4c3ab4f3ff2e9b99916624a9965a4256d893c84e152c19794d20de22edc9c4c1514f4f4e29ac16e6b421d3620ec6545f737100f0134c29c11128e193f06c866e165662d903d9f799508e617920d786ebf75acd267462237ad2bb39f6a5a03a46c5a1dfdd3766a49e6c864ac5d45afa6400ce3a9809de464459b18deeea6f02d5882e80a8696b00c9f703da84bc5769921053ecc749b0cfe1745dd408f6dfa0ceaa1780ad4ae1747a8912a589a754ed86373a08ff5540a471d9a8272b09df08db1f998000cccef325d072ad79df6c1936cf0ccdeb77a0d9c323ea08a0551f96c28b05ac0c7b0e338cc5004bac22d06feea5a8f5c00104906813ee195100f82600e56bb5756831a260e4cf6e5ad275364130dbafba4ed4f9db6adcdce67708905276a01347cc1c800bf6ba246c3770a81c3c754fd65bee13fa85260215c5235169fea113546e7b4aa7a1c936c47a14e81d3df912601a2eb8ece17888100536bf7183c579eab3e6daa14e5e01602a2fc3a64b563f591f0828f0bfffc49973cd14329675728a2d243102ab486601f1581b1e741bb5c77526552839c17a5dbf3b2f90875abc9959553b320da9f07f1392fa3065315a8b1744a7e5b271f9394d6e23bdab9ae03491f51bbf21014364d919388b7fba4b5341bc4b759fa4234adb292ab984f7b69d3aac2e0afdc7dc075e18ad22f4456dfa48b0acf62c24bb58eeb0a71365ba5f890a594cc046a483d9b306a487ea4eb5e80572d3ac8b4dbb4b6a02692af692160b113da09d4ae9f0464c5522b7236a59b70d3667fd3b0c5fdf2c30cccdd640a7297da408b6aff82ee9651f889910fda9f24c706a617b082d626dfc74a657c5d17c5a763044f0230972fbe47c907a5a8fb75df4afa9726d496332a25823148258bf60b189ac898c92b9be15965a199a45ad563efc761392b915b58613f9fb99f45c9a78fdaa4358874f739cee7ebf2a5cbc2fbee73e2731e18f347de520f1878f0eab3a38f377a9263ad17333135c991d560da02f9a012221d644717e2f1361ddfd9e6b5d0043f3a47eeffab15e43d7d45e1f6e07945d95fb46ef5346bb3a502da9f005d1cdc956e1b96258fba48dc793f50b7eeab48cb88c51118ced6c65368c5197ec7f014c443b47d898627cdb7781351442c44398d0ea4ca4b697ffd505665531e7d4b4406431f2328943e8b72d030842128714ed41e3d13b8aad0d076b7ad34af4946866f552568eadd3d3582b4c4f50d816c065e65b3583c8309e3465db95b458d0b42619e1ea75ca546e966d761c53645771381f31a42a1e0bca62f752fb49e8d2a49f942cd48a03129a709e763d23aa4dc84c88423861d1ef31f5df99006156570aca69e571067899ddb156a2027e0acb8f278b4e156f96ecf0eb2658c6504fcd39e4e20bfb5905be7cfa05ed907aa5041e202a49166a5e267724e5bbd0d9efe57d34d8cd7a2e536cc7aee14f12726065cc08d547840066bb56916d9bb9761e05133fd18a68324492ad7b9f9caa1668038a3ae897ec528be2ca7c977eca6cfc08a00266e96fd43a723fc7226b66aaa86fb8c0ff0094b6feeb0707b5cd61797ca034755fa42aab8c5c9e245157f5425f5d9c2de89a454439ff9ddadea199ac62ed47b9326a4a08c06859dc6aa56cf5af62a035f7c6b0546f536c07cfd7a2d8e3be9ac2c7b7e854ebf59eaeda5edad7dc23e83eb30dfa3dd91753614a811769d6a564e5e2b27c43c70d7497a0834ea96e50b6edef3369e8da5f707e530fcf611301be6bab8187386d130d1f8c94e5c3602ec613f83c1ce2708d6fceff206d25c511772a85eec3fe2b4ee066681cc6c58313ac304e37b46e43a844db9b7bcda351e09ad1efc57db99dc2a7c12e553ca9a60412dd6bdedd4ded92b9647ecd2ce31eda2a6f5a4ef9df833b9b4c70ec0924a92a7067757484a42e2e39a2c58cf41f683c3646c0e993fdb61ba33306f7524ee2733c1d970403cebabf7a1af318743767411fda52e046b2fdbee1680978da2f66413a00a72c2f0fd68497472feb62d2481dfa1ae93b14895fd3773d48635738847d32c4252393c6cb8e07655646eca309a1481552ecbd9569e94a0cbb6905c45717f0097f3dac95ce491ef6f07d89dd7a409b0f13475eeef708fbb0cac0f200cd31c296fc0f38221dca15bbd3ad95092e6a4f38b8ef8e9f3b9992d57409c7833c0e2e85194adb91496335138d5815f82e01ebc93b757c1ff94620f3a87ef48ca064b8daa8790dd2fda2c3493f33b66804385212b1c3747f61ba6de535688b2ec24db2b9bb22f1c69337d131a4c91c2b70f1b45fa522eb556b7960f937e6fba63e1a5c832c850ec9d476fa68c807d36d09edf0c1eb9b2995a3812cec5092b90c4c724a2e1e42195049ba8878f1d05a2e30251a57f7f4662d4bbe42ecc98b7399c13a00c82090e61c34b4675c01815b7e25a1fd09d2fc60f60ec1f3f435096790681cd676c3554c66ecb08ee954d3de09ddaa2e3d11f5fa4f9d4c89cbdce2c3accd6f9495757f069ede7b956256595c7d083b47c610efce658762467518bdb11be9597e37db2ce13f8b1b0cc42acf317bf5a8f948dd3977725de1590421117c9ffd003a836e898f478234d26fc7d8bf866a6a308f8f7cdaab738bc98b879669911a26d87f69b187cd620e910289b9d5c2704d332359fce4040b4978eb1527e743dc15407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d7162fa40d6ad22c0bd13811d9555f4b2adb0f639cf7ace8468db36e557c1e1176e4ac7db719c3be3a8a8fb077e5aaa181f69f89547570b88ecaba644b0c8623f793abe63296589646fa4fd48c7d15548b46fe4f60435bf69fb31260205482eab0226b7a3b02d5edba566f82d3f949278d4d0660165857965f123b1ff5aa680a62c6c7b8a1064cbfd234f3e26fcd14b1eb52a0b46a47e8a8d38027bb3fa2cba947124c41b6ccc361bdd655dbd0f0a5b5e7c86fb1bf779a912921794e17746c37f40e0e4451bfef8b6e07bc00ff6fe17cdd12d45db9f816cace50b0682291a8dc257ac131413580ad09206331a67387cdfbf12cee28aab9a8b0aefc03d6d1f2fde70a8c597075eec72c0adb7c050db76ed8d86e7785f056db19e02775ea099672c7f447c7d787652ba7c318efbd758620236476ecd6df6abc2cadf3488c7e6416c12b8a2bb40ce3658b1d71c42e68495a5504986f38696e56ba0fc2df70182a5b11fea0d61d2472c21da757115c4aeb85f1ad06831b0b41779a118995340fe6c352e6cbeabce345363e57dc45931c6bf8f278f704cf252234e0e580741af38024e1536d3b2112224e3432e605d698c7809f9599544725f3bbd89e076742a2e33631e2caf02567c87ef2729ac221651de0efa7ccc8de802d0ced1036b68b51868bd3686a8ecbd7b1a217342e937037c0bebc6a026371b85698d124c09998e5a531b6cb276cf5c2ddbf28d010e2a6976cf03488c0d1d11c5c1f9b23d7ac44ed221724baa63a6245db826d277bf7bed80169db1bccdc7a3eb0ae7852317a5fb2628982aa0fff7c6916548204396e77dd2fc044e2a37c192789053627b2c81fa1c0f3d1f7482ad1abb0ef6ca6488989637ea1d44a918f062b169f1b802c9ee6d05a2fe34fe3fdf6285d91ddb739bc5c2481ed4d77589febde82e624d0af0ff9796e5993242f7de325ac001c0d50c4d27c15248ae2023cbc52e2ee969b16fbef249ee2542026074c387dc5714b8038735a05a39459797ad1f591aede76adbce55e99ed94a98b68d8ce62060e2c77262da54a918fe5942925597cad811f00d13599f0062784e528241405f8618bcc663a513318815f67de9a13e6786615542b715d6d2bb3d82580e61b8d0dc0c1652fcb6ad0fe74186d4f30f931ded5712a16e9724b9993cd0d505f36fdd6c1f2f87ae7f7b7d2a84caf41d8db3d926a728904ffc98ade114aa146708071810254fb2b5fd49243a64bc29a6cf8638150988ebd9756b917719664e74f116e47c0991afa7bc43d0b4aaf085d205ced8ea01235b224e9e2a575626a39cb65fb8a0456f4f5380b87473b2c6d3ae6c36664af57171130202317f567e7a89975b0683a31b08cabf966ecc62d48ac257c297ac4825c75e59c4271562da9a7597e0b1d1e880416c0a36fd5d9a8a1a0e277025e81af122c541ead22d78609154fd9334b34c1b724aafefb4de93d02e360bcd69f4d179b8f973f0a229525c681a841ce65fe1848e33fe6c929cfdb09181ed6f10f9b5d42b079890c93f6cb63489fe6ca5926a30f68d89fea2985c600a9114516a6c29aa1a9a390358ae11d4c2addda665d13fc93f613f8de4ae6526a7ec8bcc418d9d190bff5fb2bf8a57d4d02ae9d39b49dafea09bc363a28395b90f0c0482be2642d693c65b1dabd51d6456d129d5c987093349056b99398c6c59efe7949aa90e6480719aa04ad8816124b5eaccc793902c3f48b7529b6d116f4e7418406b6dfcabf008b65268d1b3757c713863c80e960241776adfb775052d810b59fbc83edabf4b607bd44c6a610788c1cfeb3f21e0b94d5a12f2615ed49cf7d67abf18a93af7ba649cd0ac29680d9eb19a6e461dc5fcce21ea03fdc88fe1a67bdd4b67671794d5348a1b481ad45e86635f0474f0fe3f7138dbd0c961b000d0c14707c9c3037792e2b59632bef200305908aceeb3388deb21c5ceaa4c1dae6b8ef3ef9ccfca9bc6523b609bcddd0b66f5b305293c5ce2538e4d8e773a6d51cb10adc0c50d9b9cba83e8429a2e2e1e4e1f947c0be485986af1fefb306419c6fc3cc203303517dedafea231dd90856df4af58129352adfbd4c714e33aa5cea74c6e39a097a1155bb8a0f59242addc542e1ce485f81eb5df11ba9bf4e0267aba89ad594b06066c4a7f52ca7947de90772864f98b6fd26bbf80abe1a9ecef909810ecefd129f3a73bd3296a2999b9bb455ebb74bbc3f5ea7cc6eb966a566123ce03005a73c0294531cdb87e6f4e95a515a4533e0224cd2cf5426a5cdcab8c30caba2a0a36831bce623b526cac663bf76f269e3d114a73a0229bbc06b4f53b1f5c0ca2198e418a49af03440d375ae7c76e24cc7c0c46b93aa96c8e69afd833d5c5f4ee23346e35053b1fa6044421208a5fc47074d544333068438bbce32a53bc0117d123ddb9718eb62baa88f7a7bc786758ecfa2acaff06cdc5d550de264d6d61988290e84649f3faef516f21a36b403490b980074580512dc2e7d3e2b87a063a5da17648602d66ed743cf227b0ef5a34067bba03c1df0cbc3cfea77b39ee77b49d8b425455e45a27a245c1963853bd35689e5192515b7b99cfd14d624ea54dbe5eea6c8f22b59babc3c6a3ce22286f1a628b901883b088d7b9dedc64dc86f636e337839c21edf802b526c26346ff314ac02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c24165804d109d88647def7d8362b09e103f65285c88ff5ac9329ca40a9c29dca4e073034a4c23a5fe2e1a82fe0b885d736e57a0883291961a087a2719664020a574cd8db813d1070487f577a18b9e163ed125ed818c0d13dde40503a10ed6c8d3e6a9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712132d3fdefa1807e6bf9c14050d63d2c37bf357802a7d8e813baee24cefa76b229d471496a02cc87ca65544c0ef979e7f4c1f0a7269e3eb21fea4e0d91ec4fe86ba67e4ee5cc212e44e3488e61c6c1ce07e25614b8c23cb4d0442b35e6b0d8ab3744512e70a1dd7110e04b778646d4f7b399d36712e40bd06a6907f25046639e4f9a632636d4945986ce97bc67ea13897025c220e7297598460ccd7cedb8a0c54792f097884bc8751c88ee126bd1f3682449da8181bc9cc5b90f0bd9dce1cb0d19441bd6bd7dd64756c6cb272ce5ea2a934c56dec8f3be010f8ea74cc61f20d1309a1fcf68fc3da9660e86c1189f879b8c9cb6611d57d470765dec4c3514243009923ef8cdfac92e83ce444c9a2b61fe92d6043d108129649a3c6ea306c5d9db7b924eb791afc0aacb141b54f0d75fcde46e4682e806926114b2ec7ee5a1a5626a3a524e56e2044349643bea61e7d9d3ae3dc19e660d754e6cac3fa4f24ae46d794816a0ad32ac3690b658c96cc6e09d9510a57c8e28f32220210108791a15aa0dea2e3482714178bee78fee64d0d61e6933d06f8e8dedbfa5ec5cde870dde2d7a9880b245038d021948c6700d89443c09f207b9da66d2ec05e1c567a8ae5fe5023a414b00e01850a90adb945205173ed44279aeb17ca7ebf9a239d5f6ecc9306a868b391a7c49dbde0913228107a7795db90a5e3e91e505d9922c2914d7755e0ca47af8f394eabf539adc4509e5958a7935179f1fe3f8c22b4cc2e2a345933f59d65e0318bcca6caafcefeb3452d68d6197c8ea0b26b971962e201405c4c157653c2f2d4af59046fba73c6d72ca8cc525648416b9b2143dac665457204258b81bbad3d109701bd807e75845178590a4c5b8d44421e0225d9fd994af2aa1d0c65590a7bfeb5fd893b53578b04160e3162b0aae5d6f67dfcb75abbcf01b2ebb106906d47dbbbde1bdb9b1bfa8dab1989c600610422ddba5fabd57a54dc955ccfc7e5810293b5345958abc5f84808fd97351d481e6809e00bee6538408aea7c6c074c26b68e2002ea0633e6c3d7484493771c50eeb727d6fcea84ed9c26bdaddaf73d8ac7ad5aa36f30863234f789eb1d0092f42deb6ca72061146b920d71b457700dc5012547ee806376f3ffab1e2780f491f33a0cb355ea6b677c4ea1b54ab6e5698d2853047a428891a431d89979492f261809be176ccc6f09660d5cd4b624f339e961df7e2cd5aa3f816fe8950ecc0c2c9838fbf68bca5d4955de8719bb6cf79e8afbc8632efb5aabfcaa6e749cd45043ecb13046ce3209fa85ef21441ec2d1a0ac63a273f4213225773647e8a739187223eaf5c9f0f2e3d1b12e229fa77e65bfaa2a0487a29d08064960b2068be68c3c830254caee33d9436053af9fd028474bacd43a231dadc4f4116e333fc9f88fbcb64abea30e650a11ac56a1988eca459d858087e220893ac87e5b5203582ed469929c865ca6e35cafc0886f8e5a9f813f011fb08ba33475f7e9b64397ce8355542f0d31bebdb5238414fbc41ab88fe2abea69d9e769a9b465041255b591fe2708f1193c6a0d7e83e929c167d0f672a6cf8bf480b21d5fcfdf7c0ed21b4968982c3b4798fe04b9e9462fe2bd8fb6c511b1c153d0637fd584e30e35b6a07aa739ca4f37d82d9c8e4369606257edbbb2f6ee4e6047dd8e85212633fba991cea2364c746d0ec558d0fdfd64f2ca44bcc97637e3af5596f09c8a333cc19880d51fcd11a73c7b8eb1b02485903f9c3b3d15b56b6dbcce848e56c21d870a965f61bc53894462a6997e78f55f20ebf32f8f4de37a05611860ed6704be9587f1a0c12bf329f83fadd02c191a288925cf1aa151d387686eed59f920597a10643f36f40b821f85fc2e6b62569c88b32189a52966c52301f029b0c231c81ba02285edfcf032a441c296500e2a2979e4b4b0caff11b6656d131b61a171c4554591d3c74fbc8fb899600114d3a61951d7af36bb8e6460ba61b0015878e7e28903dbcdb802b63c5e6c895e2619c6511dfa0723fc48f796952690fc3626bb5c1a0757a19226c7db6e42ec243932a2503b9b257fa271f933ec2dc395f40b62b11adfb0a552412447e35ac364bee1f8ce0ad23a72daad14944e49b18cc3d5ecb36f4a8dfd602319507ba7dade07e22ca3a895e9ce0a2f59d7f581d176f5b8f880047f3803efbbcd442b7f8b1fe158353183f03d3f6acf46865281439426e64348199839d84de5c3d2441a5dd9c75bd064c1385ca083cd1df6ef46dacd30ba7bc9797085a143f0fcdd6b0c7ffdde124bace833b758ee4ddfe5072a558406365b77652cb2bd1ccf651da71b0b22bf789af3d24014217fea74522e694c399bc8bd5f07c0db8fab186d5ee762d33a5debc1902bed79a68d8420d06fa2810bfcd09e53dad5f37258fa86f46560785713ec711c9f5ab98c631bb3e3b6c5a293370fec522d61149c7bb09bd4256e55a71487db84f95cffaefd2c4a3058c62c3e73695bc27a72c21d264daa0d40c012083c581e4a0dfc7f168b722b237a0ede4e40a7b352f38ccd532d1a416ffb5207d68c2b7b3a6cfd957d7efa5b71446ce84fba254aa25005dd08c988f4dbdcc3dc795d3487566e587f8f99fa6d222c406942f33c9a694d0a5b974d247fd6d4a37727a7eeb184f4139d300cb9d2264e4bc1869026d0ca9966cfa34a5506577dd7eaa826a1dbd86bf3e8ae5fe73cd591837a5d6075a386bea6701e431ace3f383154ebf64ff61e2e4b520bf3a723908aa855ffca926ec6b18bc48a7dc48b52b839507453def5fd2898cbce2c611ba2af0d2434a7152607d997781ffdbd8987c5b14b6f20449493fdab89717e43a14153845b97698e2511195a1fbb646bd896dad04547a95f1941a1df510c4f7990062c0d4fd794bc886625c783228e520fde1dbed723fc9779bef796e04307444ff32c210cfc2275da1aba94d5bd2b963fbd80dda7a9c8ff88271f152875d7cccd664a44c8d3067a4034b5d6101af80d9a2970f3443536302525e41dceba23d8862006a1893e47f69018c2ed81677b4c43016ddd24ba54311aa590562ce1ad6991a1736d972bf0421adc4a00cd631414f1cbecb646e0008529253e9c0169822efb33ce421d77953121b3efeb10cd44d504b5cf47a9807dacce8eb24d53ce62e145835b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d32ed1f9d70028c2001ede3fb28ac4db0b0215889cb331f8bc637d8cd27d4443570c84f2e19c4aa5a2610030e19ea4093bd118f72e066ba44693db5cef94f3905a6740f6b046ac8d7b77f5451a405975c2588b5b82cfb70843359010be8b7f32870641d3606bc050e0383940f0e25880e6b183b137ab86e3ddd52a0ea7024db44fc4458e5fe418d5a7ed1c33878563e44403bf194507c93079ff9105b433e6078faba26ef3daab055a97199108ceea0d3b0dfee6ef4f8ad55f1eca9c15771251d0cf33eead0be3cea163831560bf46c98931a1dd530301d054fad074fb22e5d6ad86e5f79ca0607a6108ef6030015ee05ed6229bafe13806894461b51199f5b3d2ef6d9024f2194253e89d0ed237b1903f89dc510bbdfd982b518c3576659cd39120b53fc4e51e100e83a51da1239f64947e10f158bc42d10a3b20a366b4311370e2e5c4b8c303383b3e579cd1196f3dd13db99c99a48397fe1df8987a58b942b02fcf424a1223968027d877793bf9f4636cdba3b47dfac921296a818d1b08821f45e5edff6c3c216a16d4b6539790325daae1a6400ee446c2b4fd1852c409d43d0bfb72b3c0946f9edc151873293bcf16d1360b340d7b98eda07f00b1333fa020c5b2ab0a4db4d0a259bc517898153957166f01726a25d2012da74a8fcfec104b6ba6b02f41eb730989a90ffe2f8948b98eda9bb5bdaddacaba1ac1877ea8c77247f876b27b3d89aa71714f55561cbdd0ebbc4b24d39b044ca3e3ef42bf8f63b8c642ebb1fcbeccda9a1e3aed8762eaf0d9ed97308e08e7489424c321f49af5ff24bc10f697dde29bb97031ff65fc6cea39036367972d5627a48c4f9cb8ec56d22a8f95b4c20b4a2545baa5879a817128101c28cc253f3a7a73cb74f0c43d609d08eca7f936f1a8a1fd902a4395ac8be7312d9eaf784c761cb1354dd40baf3012e85eadf3fb86959768990ad2c8625a553c4d920338ebe25de23761c085102555e30cb812643fc1d2857c220dcb944c423397264da353d5131d0c70933d72b55d021a519c3d7a9c5614710da694bc1e1b7d5cfe40931ce3f0e1f35d253566b238265670dbf08b30c63410be69245689bbfb89a17eca0f6c9542454b1e92ed9421ab1827a2f0013b37d7a0653c54a480e1adb20f4d6621955b8b41b7fc0dc7f66309c890258c6702ea0943d8a32748f67d8dfa4a29fd85282d949f1cff5faba27a8336309a4f867baccec1e6369b73bdf4b757c1049448f4bb3999ee0d8ffcf0014a49f30a2a2f680daeab96ba080e9436779e88da9f35f1df28aa84992e99a0beab3c9bc2858788c7077ea13728eed4debededfd07f1672798856c3a055a13408241a7531f1edd8411be59bcddf843f745850a77afe6ac8984ce9110aae0cd6008ca6874a522c58bc897c403a860cd5d05b731add09f9e24a465d0da6417d00000bc1f800f46d8c06a9861b5ebb82ee710a67a28a410942c343c5385210af2235887221563f3ead0d53f19846cb8c3345403ba3f7209d78da91196896a687824d8afb71dfa6f71d993f900470493108fe9db363bf82126d7af537072262fd8208ab0488b72ddc27a4f9dbb2c191e699746de264af70e8325a3a8040652d3cc3e86f8e7ead704ea80c6fabc0641fdb53599f2e2532b2733e93514058b042af10bd004e87da3ee9342f44b433ff1b8535e3f1928f927eaf8bdf52e31c589467317ee797d349e052a0edd93134d2a7c57ee3fdacad7f8e00de15fee3a091b2c8e51c87f228bd61350ac8ebe6922fbe3db9b1f1c95cc6fad66daca76115c222bee077e98797f7d5a383fdf3eba7a9d9f91ef76bca8a1f5e028013db30143acb3e55096b4d63a9ba75c34b652b711c471606219755a72fc7db90eca93c617bac3191bb231b7a7a68d58e125aada1bdc72c94363a3d8c1e3ff72da6102d37790dbdd1172e42327ed298ddac2fc87c59442d545b0ff476caed9e785f2bed1bff26b0333a6b7893cfcd6ddb8a9ff65313caf6456f2ad2188feb5ba8dc102539e94beba58707699d560bbcce83134bc3f92ffca813e62865f3d2d56680b0ddfaedcac5d5d84dcacf83ad61a2b13644eba1c459299b7a92a42c735c24fe9a4b2e2e9fd6a003c6761b167ab56948265b496cb7529b01cc4e53c3cd9a39384643996beac7e7e8c5b9548bb53ebf8bbca632e490bedf7f4c1de2fe41bcb746afd7380a6ba561610e880b38007beeaff985e007a1460051bb827ffb24970b0fbf79cde0264cf0292305be0faf22877173da64f6bb647b3a636b831df365b7c3394915ca6209d753a2cdcb143ba3e7fa41dccf5534c6fd36ef91187d55e35dac9d3925ac08e2c22c80dda4c60aa6e074cbad95a68215cc134e03ac7e516179bae944ce17cb54d086ea75184c3c36dcddad7c1a570d4167525f3f53d8d39ebaf2d239bc1f9e7572cbce85b1fa08568230c663866d47c3af0c12e609217ab0284f8b8694563933a48ae23e707c1df21527ba79fb2c6cb074d51ed0b90e361b2cbda0637c074415c3e4eb13b75b149505ccf56ad08a10df211eba48ffd7a2d0d42a1bd943dcc12f86e3e9052ee1ea8f6f1a8fd7b2262bfb86110b06210c25e7fac37b49198155c2471aad8190353d85860814a81887509424d72a79cef1534ea7655db318a424d6a036c7aa614ce9faa7901f55f64b0b0bf1c084f52e7069e5bf1097a9889ff9773079eb30a9abe2de835e3229d8c3cd6b00e936d5339b325684a5c483b15420e123c221c6faa48e432e6ad29d22301073d3dcd3dad319399258dae99d20eb634bd69867ef8695bedf1478abdea28e97985ba68b3810318e3cb12ef946594ef5447668e76d655032dad5ed688567ea02cd741c0f1684f271e1e6f57e70339d949187f9cc5ed830203c45863ffda2b704a0bfc77cd4cbaf3279e937c9415d47635c23582b2cc0e19d01abf7b442930cab1acb6b6d1c87fcbabb93d1ee778339fc75b0aa674b0b9ebcc31efa34cdc88d6209367d7c9cb38d96a9ceb0b51e8e2364399650074af6bb1098b22b21e3b9d12bfcf4ba0ee5e9c3cf8820ef6061d10c3648d73c6d22bb9a4502c3b263699d0ea24baa448b12d24f501412d09da75d99714c914e0bac941c2e9591a1af974b9d7ed718ae8c2c5246458375efb92aa04a645b615f261ebad3748d4e586cf4bb52da7a9c3a306113046efec9210cdac01dd254b6f9444d4186539c1983075c1100c45b2a80ec93371fb04da55a70d7e4064542210bed2bab603e428eba5d241504949b6d4c4f02b543fd709a15be42ee92b6bd37baa61bc2904832a15e7077176451dbb49a688cf55649c5637bab364126c473c49dcbcfb064b2f296cbed17603820bbd3a5e93ec52e82e67ab2760735d2fc915122c09b76fc9de21fd95de63f8e5b0276a7fe25efa62bedecf69ceb278c8309d1c5ccae18338cd298c2ce4780f31255dd1321fbd0dbb6f8f64f321e0e0b665130b8a0379aaf5aa6bdafe07af1312f637e3911b8d18fbcdee38fc22ca35094f912decea24e409eec05550dd35c62be25a1612ab90b268015b40eaed9fa0717aab769e193b2d7bd2a55e7e715c64e67d0be4b76086d9cc31c11ec35caeb68634eb554ed5f55ec45727a57e2d8d6914f6d2acffb17b9515d347ba045067502a0b14022a269560e0d95cb168c7097ea8eccca5aecb328a24b1eda37bdb600fffb212178ec0923744a6402d58d7d738f233ce9b64b6a9f1dbfeec1505db36c5a06eab73142a86b27dc175155cb30310da6295a7fb1a7fd6e4ef00c998b82ab8b3300133c6af14e5077c26aa202e6fc5e69a792012590d42ae2694b82fc1efc68ebf7b5df2574cb85143f66a0bc2ff2a9811e62cca6fe559c14e606a1c9ac2753af2050d14b924dfc217dbc5b9b44e89d25f35314db49b096287a77d1734d0f8f8d168467849008fc52de08473191d53f8cff9c54059406398e89683d41db5ca287bb379e463c7df481005fcaa51f86223229d9aa3f1dc10b0bc97f9814eedae2d1a0d48826da8fea991d14f1358e94badeb070719ef7e1ff2021c1cb5acd297695c34310474feb95e86dd6e211cd2e6f65ced4fbfff3817ccb8c25dae508502d4df393b421e7f92dcd88622e35e35994021fd95c368ce30d455831b8d7b5431f33a73278cc9567892bccaa9f0d0d4410a411d42de63d1e2908e4ebbcafdb25c1a4ee00238cdf73e322686f01341d26623c2491c6340204508a421b5978d8f7f698b473aa842dc9eca0e5774a6374ed583ce8605795f084731e95e368d039b6ac539d614882e89471f99ad0b367c55273a7a4a3dfff10ea4c7816a44c1cad69137741b64deffde56148294271b50d17c8ecfec51791fde88bb15b07ef5a9f0f13b9ee20cee21322f3a6fd0783089d9dd32a9344cb0a89e9746bd35c0bc36f37afacb5e35fa47643df9b11a50e4f6f2c820c284d4c147481412e5e4945115040df81511233a8f81e4731205cf0af72285f08cdaf87f9cda4cd3c7c7d51bce592ea15d692e2a1700f5467da9707838a1feff9c989cf84c7b2a3965f146be7fadff1b72aa0338c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e8529585eeb7d466f7e38b980536e62c00fd3dc5c703c3bbd721c9491e6eb85c32a44a4b8c95221524a3c23c6b5401c00b5030ac5fc9d0a0463ad9e34009a00ad426a782939a3e4f8394ef0f1c9a8f811a7f5ea333cadd30d3404352aedbd7a2a743020670a8d1c3fef7c3cee5b34ea05aee62597374b2d6143e51039b706bc660f371ea75d41bd9ef4da3a7a5ee404600a4880f8915d2a0d4943210c8e5e71277e7fb0a75847a0e9f3e97824f457206271c9147e2862e8728b4d69cbe84e785d92608878e367fea06978192e6e69d4b8acadd42ac1133fb3a9e9e1dc50e281254144a0fe07efe8476c462860a01a5e4180a4de0249f05648c23f8e6e3bc49809eb27d2c7ee29fd05b5cab4d8ea4b8868446d4562a8b2d6f182d818b448b165d8497a72c623880702eed40e35aadcfcf6b09f67040effbeddd2b22af32c2978da711f60d3a60f115c98e714b9ca80bb1bfbe16704fb841cbfb0bedad90d8ee5106d2178980cf59e6836eed32dc22ec231e5556dde151c0081a83bf4389916868f9a5c9eb394a00dd88f01a451ade235d634484a9c56c595224495874fbdbdfdc1e93220adc754722bc8f182a697c43e34c44782ead62b2b4d01ed046ac0d7187fdf4ec246361396ba03e69055b5347faa6c1cb9929766e4f2a7b41911e25448678f4820e4764775b18b4c0668fa3ca1e9183ed8e57c30c211e97e7cfdc685e6c082448e0595ca52e08fe5b0d37ac52bda3dc4c8a0b7d3e9d1812d5530ebcf9df0ca539c809855b617cec1498a8e2313908d070839a80574b129b24245eded44df2d131e43dc9142274e0b70a75a903791928a1bfcec374626d3c6136c409de439066c72ccb9ad0332fc9b36d3a24c6173a23014f684d0f1666b8331d108ff33986354061399848cc96c7a631da2855f503865eb732fd4e5c3976571cde050a1777e67603fe0045e0a581002149e02f12f72a340fcd78d5723d10b6869cb54bc64940dc20e2c4e3989890f61c5b1df09c72d8a70b5e5a161c0077f73c816b17f59d9533c2e6ab0c7a26dd2cad7646133b739b24e20159d38cb2e11faad8ea174305417860ff18be0bfcefdb413d281ebc034b8b5f8722b041e90ec772e1e9449f61650a27e810f57d102788527c3e274dddc99f094edf73a09544cf3f162573d6da4798895daec9986a41222047ae0d3ce9b6d84c6e91ff5abd4296b1e777b8e22b077a6aea2e843cde25869445dce969fda78091938b3cfdd6f1ab376e62e9f94ff0456171e270fec0156069e8006f48956683abccd1427e3ec9df93abc4fbee9170e9ac11dd9ca793e7d4ad05cfe205d6ba0969f8e965d571cfbf51f54a8e3317b795c76523eec774719d38f8ecbbb192bc298fdca9b0a9304386b0791c671fa441d2103a8e2b2f015072895fe33d26bdf621bc4357610234e563f1f6dbf1584d21aac7bc2a1f4c8869fd97e805ab0157b6325650d1e03909ae85ae3751e582cd823db5394add842eb339426c7a1f44fe90370fb00c10664c8f2c9515800831c45fb5248387358534d37a9b2bc6b9ec84bbcda7f2f8fc16f848423e1dae978e729d4886f44e1b21418fc96c9b11246ec54148661fd7515be3636f5d3fb5e2723cfb1a7253ebc10064373d6227daca15f68a54710eea722a4c7ac9d8cb34c289634b7a831c0d58ff0c5654f9edf692e49403f40a9b1b1bd4acaebd7c2ed9d02378c9a9b763a41b5a85c0e978d30601e32bfa02697f9eab6f756a1d83440c49028baa4607d4ec080ace306ea6094d615cc220736fadb0bddb33b4d7381d35d265c13e35b0d829219ad12e42d1b56bc54f1fea860b18d6440a9c44c56c41dbadd6085d0e3707ee4eeeb4e3410a8326cab9ea1eb95213475d669589cc8b1331ccc7d65eed9559e0ea0f5bfff13843f2b4a2067c577278af1558bddd481e153602c11d5c81a424e2a1e946483bdda59d530949954fc0d7e42afce9454b6faa5b7575f6fa1d2374efafe1363b36df330d958bfa12b5efdf7d274943cf6dd8c5448e3d30bd0d05afaf86a2d30c068ff63e9fd065e1f84362827c46ccb49a8ec04049d1e04db6f7b88c193400ee5818956472db1a5d3ab044e18f4e918b2547eb275d8910d103c13a8704ed2503421465b1e68c51817ae25727b7b72f3817febe4ec7451fc241d7794b8a63f1317707c329bed6bfb2a0023bef0917a4f8944b2023efbe2fe3d2131c41ab066ec2eacaf389834b55ec862fcbca7862a3addeb9a4fd147bd07f480464e395013f2599efd1c800bb1a8d30d5f57f82ac1df5056e7ab4b9b21cf69a97916c8a50072a9fa50439bf52d8ca7aaf50f5bd9591a5422b079114f0bfe4acf561c826ce665878ade3dace990e64ecfb1ba367f4c3c0a61d4aa1dad084d5c3279ceb5a4343f16894ba217fb7c1bb67c328dc7a5834ea59c48d0db9f4a5d9ad304bc46c0d63e2847067350555940f33ffa238dc7137ea04ecb81d9abc5b068794756c4f812d1c5af309231bfb4b27281eb33f8df6c7152ec14ed6fc9a8a644e174ba754247a7319d29a2d250be22ad5e7494d649b11898276a964aafd01459781278f83a80e6764aa6f07eaa4e22d1741ed853c68c6ab19999edb739487eaaee49b05113ccb3c725993fb28e76ac53f00b9ed3ab5f6912e0786fc1138fdd9eb43b407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71d68496b94fdfed16540c30b13d0d7e65a4ff1bb1b73ae867b96e7c912b00ff6a0ae752dca9264748a313dc53b63231d29e9fad3bf5e6ec9134177e105125ee610a1f9b915d9b65deb6f9add45e7b03240fec592fd59851a1fced2bf84b59977cde42db08d3a2ae3363169cf1de0faac09b586e3da4527c94f3e773341a31864c9cbe171e9d2dee147797d4242195bb40ac11e174db2328fe1eb75af660ac3467a41c20b10ebaf33b287cca0bd628c8e0776b9bf95584947c130993f4560f6f01a417c3a364675ca3cb6a8235ce24cfc39325150995dd367ebed4e2adba7efd67f631073311641d31a868698b9453e88b51df1f6dce9144da9ebea27285a1260bd849ef59e925c176159e087d784b4c571ff12c63386066a9565234ceabc1d14242383c5e1385b87afd269b475a6fde0ffb7bd90e239d010036426a9102aab37b5e7822263c75b2709c939073244489a929410cd8eaf39549a7f7e39808fb43114cccaaeacc16d611dd34b249acc4f8bc2276ac510bf3052b08e057425c87fd10a6c6f7979f5044137535fe3f4335ab4d53ff7a251b2d799539e0852b557861591858ca58ee54562ddd8ce1604479185664a744017e539e3a7737b7eba00d76750ec72e68159e3a59b6311dca75e37ce70329997f97069f11df50dfcfd9f0527d72a5f91327ba5470d80b2854a57596101f5dd528153c8e07bc10fd47d0ec9c6b3ca84536e7b0ef7109b756252405947adb4dfeaf4712a116940f296667427b1c3451595f904e1bcc1ecaffb327a9375f9f09251fd12a66f7cbd6faf86fe9024394f1eb3df27c88e651042254b623a6d4f21c9d4ff62f4819dbe9e6a4ef2e243a664589311423742fae46323f94994ab346ac1582f51747493b32611a563ad057baea8cd9643b8d548fe547146d615bee842aed92fc83470ae7116abdf4ab1944e02a488e8df0f2c1a026bdcb1c9e5e273773626b603e9c7ff6b9bf0beb5a573c6e918efa944501d59226cf102566661ea103bbe11febe431a1ff61e7c44a9852e25b13c8f1bb89f75aa4f297f36eff83fb89c7fd7627643fafbb62323508202f6cde95375caf3e05b69ec9d53a3c3d46d2c269274d4c297ea4c1849854c73f6f6841ca230369c180417f4a65f648b88e8a5dd04c309f31d09161a0207dee3469783daaa9274a0ebb267618be37418eb65bd822d1caac9f77229bb6c60962c515e8b207b02674157f4b2fac359d2595191b18223ef8d7a62f203c30dfb407d3017a45f5b334202ec3bdf629961bee8974b2e756e4c7b638ddcb558e8b8fe0e802bef767d681dba2b2af833aada512c7f867dbe6e01b2a7eb49c7b6e50bb8d9e6cfa8ed1321b415771d5535b817beb8831160ffb5f256a040d662f90742d2be25580185bd09edd014de26223b5f1a82e054dfebb79336d891b767f8be214f88151b8a8ed8bf99febaa10c51a9b07f80b130f73cfd4d1de282f6d7f5ccefcccb64a4ae407d0c8e29650b1c0c1c00c292d0afc5ebed5da7e7a9d0eced3c6894548043aa537407a69dfbfe0fd4dffdf896a363d75ac5707eda016347a63abfaa6435132d554abf826a19340bd0f7c5984343cb49e89936f55f2256bfc32871448794ea44303147839275ddbe891c2ce4f93b4e51ba2a2709de73de8b659f9ad0d8a6aa8e2f1c300418e07035b4a39936ac69772520c167ef33f576198a70bea1a3e6a4810868fffb8bf70abb870ece4fd40a2c286d65a1a768776bcdddba218f6854236270d550b0acdb1e87c0a647026b5982426dc8bfd02bbfbe5ecf33fdef0b048ee02ee85779a0ee900ad2e02300ecc774f73ec419fdd15546141233308dd4e05e0bd98aef19726d7d2749d8f316b798b87ac700de86806c0586e96d5fa35d908728d9a044cfc98d6435f5a73643ddfa896ed51671f0a76359ad302d329a7d6489c3cb77d7a563214f32cae5c3ab5a379198c36ac46ef0f151a21bb0db55720418ac16e2487ae411a37a41f7a086824b2efd39c94b3494efa7c1b708e360b380cd65c6b0300db4259152800ab8a88f85e276b32399f0746cdbfd93182863a850da4404584a8ed17f70aec3cb4412c17b854cbeb6e4ed1e94d97bf16f7b343ff7b1c0d02b11555ae20d30819e6ccccbb44b7538770c3aecbe7351ded9dff5a0a7c66c2be38a68a4f8d2cb06766b1cec3242cf191ff9ecec987893588a89b042c2034534af2f0c4e38ba3617ddd1c70bbd23365639fa7cd5f191861c7fbed74a809b4577184b74582b4774b8ddc3f186fdab84f01e0f988b74bacfe932f46aa7023309f130f7d93dc434d02fa0318a7a63dcb6fc7a8cccb8eb8452ee3c1cb6540512a78cc5ebbb671f9ad9a244567471923ff0a04fb615834380caaf01494ebc73ca0d5c640440be29f2206fae788ece44aca654e36a2ea1777e93e939111387068eae8a7ac652da78f63545288ebe0eeaa2eef9ec82ba6bacc11acc6e110d82f4a1c698336cca9cda4ce660b4873e19098521277c6167a5090ebc2df903b9e682728b4a3ba320237b20444e34f94f2c8f9d5e0173b28a2dea1a88f7e40403b113752a6f9aa0b49ca6a5c34a2b92b2d2bc5f480ee94faab28f01dc0d7ad19392060a4f0a8a95ad318982f081ab3c35895f83a6d4611d888a1a0d0a8ac62075ca703c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416aeec5145d93ca5215998b118cd43fe6f953be84cdf704bda68dec68fb14c3e6490399277cafd3b75630f0b826e2dd6d287a161cf892fbdd889e0c6b19cc0be4bb41fcd121741e20510209b0740cb89c118f190cae98339b07e65df9cc9dd126b9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712122d254e33b7c35d78ed4f76db5578f07a6c1bcb7dc46199c567c4a61f84c574fc4ed042b0f2c8397da95d7dfafa615f163ee77de3725afe64561d65a370b3430bc9746fc125c950f425b970da866f8944bf368a765eea617c7ae949c214c405a9250eaeb7dff21e3804b3656037370d9b2694a83536a4e924c9f3dedf1ba083962d04439175a2d98c3e54aba79db4b5fbc425c1ae4d759878086569d2afcba33ee7757f605a7b0d7d518a7751ffc17479ef2cdbec637e4bfb3dad4d8993a553d0ccbb191f4be4cff5ad204d9ef12e321d851b431a0487b9b00a71213f2c95a3e48a1025c18a4bb04dbe9c259e0ec5a57863699f0eb5efd7767175b02b9bebf4eda442aa4ea276a4e1cad5e196a6945f4f9feb7e434a747a9244eab3dce1ed9534262c8fbfdc245ad9dcf846980488cb4d18a79606fce942d48063f0455392e5d825f515af082f6906036c246bb7b1f3b75d1344466e45c96967f8cb73049970c100538397589fa07b331c10ff03ffcf5cac1691840ba63344882cad3a161b135fc74cd2834b4d7d555117ffd19bb23e6ce26d31a3c34bb5626688c2388f32937ea6edb9107df7695cf745e061c1c8b98f078d88f50881eda8dea89dc75b6633f1c7fb016c01016f8225393bfbb03533db594d4e1f289484f7c5eaf4babc9ff19d827a1b3dd1a3cd1ff4732a3826ac5a468c6464286aca145027df161442843522e2ea9f89b72832b1d5fe563cc115c44ce2ba0c383e5d6824f8260f9697397660eecf2766560b1c77937fcec07555c995ffa2eb97e7bed217c46cc798a407a054e3e8c342de20d821c684b2529a9260b8c75b32c9e0232f6870db100b286915baa9ddfef29ba03584ca140af25d0ae285191427484dfca3a722f8729a0c76d7fec1a9c987bfb111cc69796ebd1976ad4ebcf4b3560c1bf2662f77a10271993092016aa2a13c0e05dabd3e3754bbf0e87775ff06bdca2da1382448fbabfde07755a6313b77aea6326c8a3ce609b67aa4b2de89a10da711cc35cf593e91f701a0fa8e27969e0a4642d03481c477ea3219946b9e8b8b1271dd6fbc2da017b45d3210095667544b271eedf036d8b2ffe8d5f903ac79718d2bda2a14a9fb3cba6911012d8f0e3c51c77bd269f51b501bc3056358b894a4efd94d6f3ab31c60a2e6d42022e0b1f1daae90dcba1b96d681a018636a09bfbc8381cf40a502de14de2b67adc4b5aa9706a54c576dd1caad7fb29bdca6dbbce5cac2eb1e65d89633e3dfa60aae7bb0cc818fc18b6ffff18592e8e8671eb94ceb0c2e15b33f9f54415cc9e626a339aaedb6cdac744b85af70456c65c9025b86a7426169cda4490dc7f20d0220467f6af1ed61d0b39bd7cc4f9e94861a28fa6f27709921625b455c2a5981634b644f122be630c593c15b16fb21e9cab0fc7b0140c981652059d2310ea20e463dc56e7b203c1dbcce46929b2013bff2270b86d4951584ef7bc2472febdcca611282f3dd2a3026e65945ed13d52e629d6d6a120b1f6442b75e0b2660e0f05824ce468bd570a388c6eda0d4b98552d27b9aacca2bcdf7f90b75243f624e0181f20683e701c397f4118ddc67c11ade82127f6d66ca2b4137aa4876cf62bc50a203954cb3460a6f509b816726d7b0427c7552a24e1ad207087af15ff6e5619ec37622a69b1d98b990ab979c98b9a66995d1665017790168ae8b5dd1608ad0bf62c35c2ac54ee3c95f27faeedf474fcf1fa50ca27f2087b110a88585c255830f56048944d2868c4978492fa514359fd3ca4231f9a3b7689833643ca183622e8cd9639ead81d38d3c3ef6a38a08f0415e8f2569d4b698449bf2c5ca74346454838e92bf4ef4200963a061b35007b1a77d0b68fe244fc7a65c339aa06f8fc468150d649eee8dd05156213b4b376830067601b89c2f3ecac6db895a8078e65ff80e7d04e60ab0ec43fca15dc14d5312371e0b26d5cf58477961dbd96fcdf2b31d78c450fdaad5e9bb9248f6bb0cb58946f2e01dbe23224e6af11e5eaaa5b6d43d700a8083e97f57984a6c431796df3d153e6b310d25c37fd451bb16e2ed028aa7b09e42e10f820389a6e253f09f99692ffc4359b494a30096a3eb8a5b97c3aba02933a37cc732e055d41a2acf695dfa9d59dfd5627864efeed20c24ad2ecac463db3c12b4ae5233ea7370c02412b04da5cecbbb9154f804dc0c8e74e2ac9daca31a3b872cc38779f9c7b1a6ca93f2c4f6d04a6b0f3e699c8a40511a2e3b9fb7f8972661796817ee864c2396b7b2a9f349d959b6fae1d66ec9104ff9c942f030e65a8aa546173676eee3beca7af1636aca17582f30829782e2c9b1b9c72aaf8060563ab378657bf91d13f2dd4f1bb6adc1d6da398e1d9b2a4884c63631d46aeeac4ca7348887106b8f07b427790d1cf4a2713ad56af6e1e1629ef93edf14348535e50013d4a33f70273ba18c23050e010109645dd600bbb52809754ddeaf668a72b443d63901a6c759e4cffd958b68736a9a1ee2ebdff616811e63d43b100947549aef12a6caa34d62c1fee27f253562286a466c2b2f91a711cbfaebc527f705bc8bc7351cc7bd57d0af9f150e6466174f1da6ac71c79a2a4df82d44f585a3865f7364024c6f9a7ec7442cd32dc7566e2531fe4366ce5e22aa6931f8d2cd5f258b334011fba79242837b662646211a788b62ff54a6e9bf54761372954bc5b1503cc1b49403054b96be468c1f8b22ec177da74fc851f7562a10a49417b5b6a76168f52931be46aafc2211ceb98056a1bd1102545401d8698944771e079f3aa93974eaf9960d6bcbf23b14834f0d7034f8d5e6589e4a7f13f65e72705884ee8dcbf1360274ec269f1e31a344f8884e5ae3450628689e6356669e7a94e43ea1ac65578a8a21d8cf64b22197ab966b1a20a098fe08768b0f5e53e25c71864a657cb42ea209e757e475ac343e5f8f85b776ea6276755f5d9069447d01bf34604c0389a5a80b7687ca74dd548b3c5d98e4f70c9a85d29ddd2296fa1cb8be37e5d8701af88c70c55baf0ef059358fb8506ab8dabcb8642da7052e6493cc40a035dc86b8d5c88164976f31fc1f72c9a86eccbe29a1060e2a5b0d6abf7c452613018b69e8385b7ab509e460dbd802cd49164665229340e29a14dcadf345f493f00ebe1d829515c6528b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d5e8fcf6841f2e94ebd740f848a2b4e72c31c7a21aea6ae8917400c81d43bb522b64c2aaa0a1986e68954e4ca7b5784088392fda54f4dfbac75e454458e01583df2218fc25708efa7679c23d318c33cdbfce6be7e9125002352d34948fa8b3a67aed933b6c623a04853e8e76cab3219c59d5ed56410b366482128627181b5aa4eceec7f1352a57bf84ff4eb62099a8875cc61b06d7c3dc6094fe96948c881c60eea50f1aa4ca2c2c57af4783c613dfe8392229ee5fdf145d7506ef3d9e559246558463ea4005ea0f83e358d15a789493bea81664169d09e26df8e8e3a2361e6226a54c73b0bb645b846c9bf3c2883b4936fcd3f629f9d24086d9ce4c20cd226199884cef69623c717e7aade3c1f270584fa38cd0d9b6a56045e318ec49ba8a9615abed39d47633eeccd98be10042d5d03d852c5bd930a89f0ce256a9332521f287c5b3a221df63628851acb241908838bac9774b28721290f082f7b143e8d102756d8e06152648b0c9f937d26c08490a5752ece4b16ced9ed97d75143de35326b6e46ad517f13ce464516302d89289478f09e15905bf5d8326d95437860df2f72c0d2cc0f3c40972b07c54745de572f912a58b2bba9c42f105f09be83e69491690a5ef93a98dbe72b55880c843da199106393fa4db8a6f659207f6f419b31a678ceaadcc3330cf95892fe9ec136744640751b38026e009740867b10de8eb67f15a03477bcfddddd9319bcfa6de112cd37ab5040bc19e0b3a52f039a6ba60d2045f834a3195e89e19ae67d96b45a0bee0beb3ec45595def5f6e8fc37ba73c0515e6ade7566e5eda3fe184f22a89211634ed256471c1f3e0f3ad64717fb58cd0a44709a330f39d5e8cdb773ee71afdd2f9d57b44fa579937be3aeaa1adae3b57d047ef28d1fe4a0ee885dea9edf31e01e23e896796b8fcdecd44b4b180dc7e02617563ee5edebece3368fcbf345b930c92fca7072eceb55222b960c5f7e0fd54d58b2a296fc8053d12508a47fa99f2cbd5b7fcea38d04fb896e5421661613af2b53ae7f9cf9da7141efb199d0830298feeb364ff4ad75fad31d8e7285e6d63e4c3f149c65a859747611e99d8cb5d06bd5eb20c5121ccc64e431ffb0c6981f059d02a6924cd1ad196dfff80d76bf99383b20bee491a49cbe9a66f16ad93859533515ecaf1ce37791cdfdcdadec44734ab9a4e4d16a25f18d2e207f66037bed355c32f0b6a53e8785a5b3392bb92c3a0e904b1c0e100735390c8676dd2da11747fd6014c06cdef71226f89708e71ef9c6ab3d95def2dd7f487e42efa411f4eb05a33bd833c6d57f623b8f0c8ed846045cf44fea32bcbe0bc04e118f3922c6a45c890e469de71ef3008558f64ece794dff8660ca2d18a49e2e7b3beaf1e6c903da7e0e8af4d2400c18023b5de425d219f9efcafb72aa555fd994cf9f67ebeb5de47b6a84256e12aea7e877a8b9b5cbcc01119aa6a8e732f551d99dfa4fc239739c0c1d9c415bb13419d4c73469ba912eb7d346b91629642940f117e1aa50a09fd5dd48caa48fe936563f4a200c29d77a80f5657781f6849373684b82a029b1fa3d2c566173676ed7bb07c67c2bc80e7d5ba4623f8ef0d565d266723ec60497f0375b3bac140000000001000000020000000300000004000000140500000006000000070000000800000009000000140a0000000b0000000c0000000d0000000e000000140f0000001000000011000000120000001300000014140000001500000016000000170000001800000014190000001a0000001b0000001c0000001d000000141e0000001f0000002000000021000000220000001423000000240000002500000026000000270000001428000000290000002a0000002b0000002c000000142d0000002e0000002f0000003000000031000000143200000033000000340000003500000036000000143700000038000000390000003a0000003b000000143c0000003d0000003e0000003f0000004000000014410000004200000043000000440000004500000014460000004700000048000000490000004a000000144b0000004c0000004d0000004e0000004f000000145000000051000000520000005300000054000000145500000056000000570000005800000059000000145a0000005b0000005c0000005d0000005e000000145f0000006000000061000000620000006300000014640000006500000066000000670000006800000014690000006a0000006b0000006c0000006d000000146e0000006f0000007000000071000000720000001473000000740000007500000076000000770000001478000000790000007a0000007b0000007c000000147d0000007e0000007f0000008000000081000000148200000083000000840000008500000086000000148700000088000000890000008a0000008b000000108c0000008d0000008e0000008f000000109000000091000000920000009300000010940000009500000096000000970000001098000000990000009a0000009b000000109c0000009d0000009e0000009f00000010a0000000a1000000a2000000a300000010a4000000a5000000a6000000a700000010a8000000a9000000aa000000ab00000010ac000000ad000000ae000000af00000010b0000000b1000000b2000000b300000010b4000000b5000000b6000000b700000010b8000000b9000000ba000000bb00000010bc000000bd000000be000000bf00000010c0000000c1000000c2000000c300000010c4000000c5000000c6000000c70000002b000000000000002800000059000000020000001e000000" //nolint:all resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -194,6 +197,7 @@ func TestSessionInfo(t *testing.T) { func TestInboundHrmpMessage(t *testing.T) { t.Parallel() + // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_inbound_hrmp_channels_contents` result := "0x28e803000000d007000000d207000000d407000000db07000000ee07000000f007000000f207000000f307000000fe07000000" //nolint:all resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -255,6 +259,7 @@ func TestInboundHrmpMessage(t *testing.T) { func TestCandidateEvent(t *testing.T) { t.Parallel() + // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_candidate_events` result := "0x9001e80300002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f3282a8119a659fb3c94c3c951e5215daa35c741d13719d0be7368ca8e089537b5b3704113bf3c0d7fafa20033cad97002e9b9cad03fb998cb35cd71a9873d87a6af72afd5fa059b18e2e13eb3ac6158212b57ba060772886bf962b12034127908e54749e8014a7525ca4eb8815d1565185b31aecb38121e4347b54ccc8e49d13e2a732f9e332e0b425c741a07206c71d801011c2c0a278c87fefbf8064e0631875d1ed14e57816dde31202e999e6e24ad0f8ae2fc830bc1d325e73c3f3dcd186be8e59074c5553d8b65ed0a7034b310abd88b894263dd5869a8cf87e5ef4f0a79985e134020e8a1e2e211afcd5ac9ec6a2fd21dfb5e1c39b3b670f4415e904061adfacb103f25340b938dbfd331ba478351f9173a81134bff8a8fa1c0fe6be68e9025ea1f9f9f24e7fa5437238b01826b451001da46638f62b334300923068d1691f42d0e400b65ae90c283a08ee958a10a0e8c33eebbcb01d137f1612e39973a10489164135f64606c111f8d5d21ec2f8ae932676beda36b07e3577c7d8103c7cf2cf878ce90806617572612083635c0800000000056175726101016f5b6937ad29ad8721ba848694820840b25d91a631d2cf19f8c63ffcf1fcef260d25513fbaeb64c090d371bdba09663f2cd3bb4a8f8f7838b6620bde5c6e5905000000002000000001e90300002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f84b5c6e57a116cba4148aaad37fbfc3edc54e7728b5192a40391d9c8ef33bc405ecd07dedf12350fca80ea9faa4288186ef3dd0b40badbbc49f858a38cfde88c2bf80adf8f3282e527e242daa821b07b2972d9630b1eea6d2ffbaeb90446a8bc62a19241993b622e6321aa73a113c354958dd7266e7e2a28acde078ae276bcf7cad7aa37dace9d97c31549cc22292b650a04cfbcdc44e20c9225d499c8241735168858f1c5382ae1cbb9ece1165e63f01471338afe7714b8928ef3b2a15e6f86fb4ae217da22aa2880ae8d874d21f8852d76ce7d32554830cb82467a66658784dcc6cda49b51efbe0fd184b974074d1258ca9f15b9fccfedc35b7dee6e1ab9e9bc06de0d02e4b3871341b268751813d0fcfbdb0bbb2ec4fa9798959ab01a48dbe9029ccf0aff2230779960fcd86efb10ab9d36ee09ed20b3404b8da50f63a2f2aaeb6e43470084a5205b111c66b80cabbd010043085f5ba73c3a4e0f19105e32274bf19fab97145aca984aa0eaaa60c4528cdfb9aecfc2dba582729ad01ebf8d72ad39f1d70e0806617572612083635c080000000005617572610101ecd027c637c53ee91d7a0e98cea0e7e72f26f69415985ee9e28509aac917565522d428904e56757639946c30eb6228f11feae3bed1e1e60458922e892f89ba8c010000002100000001d00700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f605b88b35bbbc7463cd981713be480f1e7ea1d12b6c21eacf0c120126d24347f57dd8f8b64cdf03c5a171480ed3b0718ed0d2ba49ed0bc088b33c45e9f40c929db5ceb08943ef0f0cea09c1606e0822d9bf9f0a7297ac08335d13c87f28490ad2532a4846d8b951e37ed71582b2562027373adc871ec734cf1b77fd6de383cd5a2b09b240d86f318e67f5fe77e4b3714d5267699515c6696fbf7eb8d2150826f89faadb98f6b52ca914fb474ae9d10ee57c48669ebcf6568bc6c0a8833466f8174c4eaaceb528233d6b6ca4823171880f8853b0f02e6f829444f6eac27fbfaf477bb8d6c11c2ed5ee8a4e0933aa661d2e44e03dc8823cb180cb069463128a2c766b405ebd52f05687eb3288165c4808ab492750a0c0ad69f3d29134eb883cf5de9028ad5bd67ae9e27b97131608d072644251f45c38a49ed0ac3dcdfe3e6c6c9178e8620d600c955c50fe95eecec5125170c2ee7031c13b46c6c64d26278c805e74f5d98a89770c37ca072e8a11ec0adb6e178a689d285b066c93bf63444a1be78977081c6fa0806617572612083635c0800000000056175726101017a9dd3c3f5b3c34e7804b2a4e92c08a4aba153098f51229d81be212fd0345e2be37a41cbe3265e448b8afc03475e33b2b9cb762a9df3e04bcdae19af3aef0d8c020000002200000001d60700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fa23d6b412989d9b453ba20b524d14a4932218d5d20cb57529b5d8481fd9d1717c79dc1dd9fbc475efab87f98c901499443b467cb30fef5e85ffb9429b028fb69b7632d7583557ea812404498c4c544c574b43b952c0f642f208a47c837871974d324446e0b5362729c6f287ae6781da900bf67a02a0675327c8b0c4eb716d79c12dcfed6687a9e1cbf5a58b4d4c1428cddfc93b6031fe5a45441dc6a363f43676fa41104feb13bb292af09d5929eccb40b00b1ba9856a4a7727e3a82f9689c8d58eed3e4d8a61504356c2f5f230bd53ac9ad08605c6366a65ee919decea46ef17520623e2407d6c2a89b4c660b073fbbaf0418452b0959d1018293e923cc0c70ef48a7f0993dd843c38142939ccc1d8937f7600ec33f8e203529f3c0bb741bde0d1e56f9f2bbf7b0f5b44f5a8fd26c1641938379cb13bde0d422c3e5db5675964cd736a2d500e8c1d62f574c4a67bc94e0d38ce45fa94b7fd1af9dfd8c1902f34802a4f849af258f105cc555928f36e117e2efd519ee691784304be5a7c7fdfe5ba3128576150c06617572612083635c08000000000466726f6e091b01ccd9ece066c3e5c23701aef8a8d166534049e0866bc96618feb63b27516af2bfd4c90a72b83065ae02bc073d72ec49901539e3dc74b84025913b2599c392f6daf5109eae1cef4251a2652df775975fcbd3267c254655f0623cff8d48c24d3a0f935472c4b01eeb46871659e4085d8afbb3091dd6a9559d56a889ecdd239ce4cafa23ba44589f0ec8aab1726096d29ee0c9e2676cb1b26cf2da888205cbd2dfaf1d2e87536aa7ca2330a777b9a43a8523bcfd9d9f041d661c688a8c2791fa5927ffd02ac2ea36c1f3f8a3250b94398171098e4de128bcc6333d68e8de6176f3209f66cef788ef9cf9bcdfd1560c5081311c00fa0d4a4d952bfe6c879f3752f7a1015e5ecbfcf729e0713df598b79f1b7981acd0595d8bdd4cf33f3a3b4d44bfa16b0fe8275f58a908984a0cea1fa464abe66705577c82cb660ba42391739003a6ec0dfccf329c2b6d81fe7ea47987e94b00fab2444a1c34eb3e1be1a21a31b6bf0a2c01828ca4247cdff7b0769ecbe0d186ca9af743e0ab05a823ae65bfe7fe871f7d1e5e2fe06d88139bfdc57f9169ae6f869c155bf1dab7d97ddd8ed0b31e2d7b6a1097a9e0e1ebe09539865f3abdfb20d83f39cd9a9ddbe70f2264cc5cc34cdaa45942ce51e3af015302a9a25df2ddc220657322ad6b03e843c24779d4ca45cc4ee30a6830e3c82855458becde33a4481a1e0bb4a548c244b7ecb8be06c6cd182f5e7d3e39010b0cbaff53d43f3bb471e994e01e8e79fba4dee058c59c0eb2364ef45fc1371f62f14dce74c67cafe44cba43cce596b6a37b0044ca9613180029a14a77908f74613db7650b31a2176cfd2cf7ef35e680b45d72bbf45c56a4b8a6327926f708a899548f224faa0cc95e0b58066d7a526f92bf53524d25e5e25c39a9f7523576f0af291e0ae37c7cd5282b14737a46a01b52d5b0a46b7c4674fb28551d2db05d6b6bf9ca560b49911d8087a6898b672e75d9447edf4700e7935cc0899cece13496a9f53e3533ab2e2f32814e36d2162d1316497ed6112c2b8fdb36bad16f697098f1445ccc3ff6efd641cde1b90e8012eecf0c3c5a005eed41d5a312d6ddc76c78b2ddc7219bcc62dc3c2e0dd84ee7c161a2181bd844830d8a533fe8a73ccb7af3a290f1cfd0758182572b5a4b9da22f93854ae35d0b6e79f7b289253ae05ae173ade67ee65f312577e0a1623b4c14982f33db8e10ed43874de707843f49e7d186a0b3ce48f5efa449647f230eb490ce8ab38fb460ebc8b6a26b5331a0dc5224b1914fa1c9a0e98b2092769b3e46066aabe127f3866f55d56faa702b5ce9faf3fbe22ab352469f5f86719624375497b2e9142e12b3f18dbfa0d6545c7637eb25f6f0243e14a7de2a79f5a725e484bd484cf4e8af7b2ad7e781bf6d5cc72b0f14abc95a407cba0bd01c4d47e192d9eced14bc33d509313d37ac40d2abd213d3961547fec1df1ce3450f1271575684cfaaa6867d7ac9b9fa9e939267e11f1bcece14cad2c9956fb316b8e4063db5389738faa82e1cac2685c1bb14c35f2846b1fd44076df9851ff3f6043fc3824e44ec0fd70f684d2140525e37f1ca00190672cf0d3f496d917e4e63eb23cf89aec96c62e352bae3010a165807e51ee2d8e90178f9285da18ed954fde7c7614fe88015f06cd290455c05667c58cd8210dbfb528bfeb70878776e9ace349aafe5ff9340b4598bd70097f8faa9e37a9e3caa2a628e67d83117107e99257785a45c144d29e970c424a0eda79be84fb94287e56f9fb3e746da3847a56403e9618a5420e93832989fb58116d712ef4b1d2d23659682053b38d6410322a2f07444ada2aee3ef85d631e01cfaf5ed28bec9dcb2bae747f6c63e9e4a12a8814da4ec2ac713565574227d197851422b823db3f5eb669fe9ea324f0b939835b73eab6eaf8393221ce5540462b71770bbaa8b77682198e9830f75537221146d306ad07bf3f9de76cdd485a669607d9c5c8c517cbb87730b6e90a783b0f1bad7aac92ae0a0972a8424f6683c42d78400442e9271108953f1d40e0af58e8da33c1d9fc1aa77b572f0672a3020ef1465b1687381cd70e5b1ece01a7c08be69f55b1e0683c1f742dae07de6657e6e88f97b6d3314dc30e461ae492f8e3a180ba1eeecc64a856be520f8198a1c2a4e0bc6d295a2fc13d4bb81ada3553923ece3cb67047b7347ffcd13c6bae49885be17de3d478d3aa8dd2f964ec3ede11d84348f7a40015e588ef9c9a446a3699de1cbe1afa916d10356f412c32e085c3ec0115fd488d3785f9552f893bbe0b22c3773df967b7e36713177151c7c21b9b9b1b367953ab7199fb03947c31a57a94329c6edb9b6ca20d762423fefd38b1ef2ba3f179998a5a5bce656d8b5f14dff06715909d5b7a6343003bf33c0377003d680eeafe54a348cb7815e33c842eb658ffdf3151507e496343305617572610101744acd32f811aae5d80e20534e44195d03abd773156a54dc42204e7c33370702db76b09ff7448955b79a53f0ae958312e2bdaef5a6662350349ce955b8561286050000002500000001d70700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f7efb9393ca81fe0825670473a2d400ac00ad22c1f401a14bc154c5f92ad2443192f6141b3e3c8ff6efa5a85a4433a49aa88b225d64a40a6c500854222e4957243012e86d4a295ca3422a771ca745241b2ff615dc7a71758ca806b1f48525836b78e14daf47e1789603860a916feb342edb58a2b7acb095c4e93a52b987442ad39c854c794e49072f464fd7e0a418d9c7eaa790c89320f830a4919c109dd9795bd4c96ae86882d18ae5a8edbebc1be36c269313f50ee8e1ea30ad62770fe9f88ed5f6cf4e7fe30b0808f01d7b1e9571367979d1cbb8359088cf98ae22e8abab91ccfad85a4a6ce77f402b64b0f0524a831daf156f8af91f9d5d62ce4c687947c3fef1228b81636a938a7a242ad5f78aed0a218d582faa5176c28748621c0e24b9e902757eab60aabf67c35b6f64b7dfe695fa70c9213e15d0cf39dbc547924a5b2ef9f69d630014ff54af3384cb0391d00b06d7309bf0869519cba60f2bc41be171ed2f372f3e1b71a4f5d6958d3b1fd4e43f3173218aa9092f05bac9e7f4cdd4ec490f4d177a0806617572612083635c080000000005617572610101fab1ead14c7c2cff2e1f1ba2f2c0fad3d5a5d5b6c3cfde4e88dde08d978dfa1da06bcb5daedc8e960b11f9012473e7c237b5864609cacc9b4fe9832785864b83060000002600000001d80700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fe4bd11531d6789a4478dbf7a36a3c7d23b58c5a1debdc455e1fbaf1b5b2ab412ec6a464b90ff6ada8a89e3f8d180e74e293a8b2f01c8499ddb1e994293c4c0d0779b68a85a99a3e2d4e0a792e1537c07b3a56fc0a637f1db059d9c2755625b778096d82240cfa6f9fe0dd38b9e597504a42e58cbeb7919c789a917450ee00e73fc355482abce20f5b06ae119b1a9ee79866d5b4854a389550c9d9580a0c0332260e7a1a1b7d1ec159e23065c342070603750ab953543978b4c8f018b2565948ff775ceffb1e33fabccc1c2c6ed03cc463645aa63019a0e9a8aae015cc11c6c4d370085df65a76eb880baf100b4c7401d011a1fa1648876798a747f9aa372d114a81db419e0c739689abf0882f2dc771d2b3f247cad2cff8b1630840b4892b8d5e902dd6b8d78a9a6e1651c21c2928db2b305d78290e51cfbb807ffbf93ceb6b1696b1e0d4200471f7d3b2dbab4c04349ddd829a29c58d75f91bdf56534369705c46523b29229840f9bf10916cad670f0d3727bd747cd737bfcc525bf923632dc5957c032aa800806617572612083635c080000000005617572610101164bf5fff13882bf1a85e593295939d26115f85d9539faff0d76d7be8b7eaa59ea1f86566b58362a71c19076c5ed65d72cb79994091851bd8811193bda730b8d070000002700000001db0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0c743a94cd1707ad4117ab058e336425f029d591d3a0d48e895c732013c7085053dc502546f00302e84fc41e74a7a310c556481c76ff18fc1bbb97c457866b972dc5d56deb74248c917228b08ea5774022ad965420fb4130a53edd44dbe883c91beac7ff23003ff41339e09470ba672bd4b9de9d51aa32ea9c4ca080c6f1f9820e698a3c6c6ffa8523ffd01d125f46795c6cc3c4047c60b36f44d1e89ee037319344d5b89f31dc79f5db9e5aca9ad7925ee5b750c1a78ce34ce503d4fa4f0d8dc38992403757e8242f70fa6e3898ee68b82eedcf933db38e0adfd352a1b6671ec7691f79817eeba28caf545200d0e9df486d47af1c5ac79ddd05aac62546f6f8723aa1c622a8d4a7757a130d4c7a24e2928acd073b425bab04c5e960b4ce22f7e9028813af0548dbba39f8e667b2679069aadf411ad3a194a5ca50253221be0784058e668c006cb6f4c83ba533b775447a77060f2a2fc873d79045329954a814221b7b6d52b96a216e614a1e963366a98b3e4fcb728ef8c2265b2a6a0b9fcce0ecaa41f094a00806617572612083635c080000000005617572610101d8d56b387d8b2b434c1c4d2186a48765e9ee91a39b214c4808eeb9f3461351196740631854c04bcda5980e50b7cb759df2f64ceae11f6f321ed05f8e6323aa80080000002800000001dc0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f08fc371c2ce887eb3e132908c4dd533583177847b8434f5c7c0cfabd4852c24e6c7ae7aea674dd4bf6796cdc2d337782f885482bce24c9030e87b11bca54d7f5e50b6d38ff0fb29a9e76bdfe49f6f82140d112c80a357002c99a8941a08ec62190d3eda2b3ccfeed95db0ab62327db71f640621d80c753b4e69db9868dedfa7da60ce0b09e321b053d10dff1b04e435472170d760c41282be74154810f277b1360cc17225d667bf15fb35266c8cab27968b58813ea1ce41baede882d43bc1d83e973614a3dea1a30b67783af1e57f732e89eba9958b0fcb19fee08f9a3314eb9b44a574641d090ec0cf776b81af6ac92015443353b22a7db67f42bc7347a67aa8f846aa19dcdaf075ea1af3c7f1b0f66b33bf8505b7e94862bcc0c4f6e9eeabe890371dcb58c1c4fb0f5cad90c3ca6f598d596f8e47005536da04f424868b9963e9256e1d2002610491cd018b9dc0c88d6c9790b14b4b866b6e0600feffdc0c94c667a68c14f2264ecd4a757b0f14bf0b6d9ba93cb7e2e949191c86ee32c5402d158b85fadaf0c06617572612083635c08000000000466726f6e88016d1ffba7d4ede2a4c73b3740c4a775da3a0a1fb08e3b989ec5e49684d663be2700056175726101015adb821043ece09a08d82ae2cef89f37d7ca8f4f9350efeedc12db5884a0016763c60aa38c1abfccacd5f9ba16c4a8ab93f6b9177479100d0b6c975015a82280090000002900000001dd0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fca221b74c8d32fa6a45bdc2271371109a97cdbe2c82fcbe452c548874b7dc1665af5692ca9a27a9d2c2f55affabdaa466fd435945f091b45944e0f0596984b664b7f5bee6c782d18ae489b645be2afffac110bc7bd97840260a807550ee056ca22a4b9f9c32f4c502ebe462083ec11fa689a7f3fd948fad1e3cb5ebdeb4737c7ce6a2e873ae8e530de6065dda3890084d568507ca5d9a69df19683805bf5d24ddf938c7c9decbab422bd00c4757dfe18489bff7e017b40ad9552871b9a7be88a4e315ffb734e34f9c25170faa579eebc5b74caa8cac8b1b87827e84055b256d35c644799d29d2e6f4f2c065ca606744598719d85f8c3e7c4d39abc3ea59be4a35ba689f6c0af4bcf5988a4580840e313618deb3b835c4e4a78cc56434b2ed6e6e90231a890359de5d57ef9864cf19f3a48c1fd1a63812b0765661c598856f956177cb62e8900830038feac3e62aff1f1333ad0ee8696a4558f6cc42b876e0603d703ab0d7f0eea80b0973cfd2d3a59268bf68211e1bc014bd94fd917b6e9475c3a78508c03fc0806617572612083635c080000000005617572610101b86bda32f157f1e933143a934f6505a6690c0a31dc52bda5f49d40e5e26073545851c15949664b7f55b8cb2163a3caf7f487d8b4cc87752aa3b4f40638c2ed850a0000002a00000001e30700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fac991d1eb1203b3ac74ce441fa62e97c8d7b99628a85cdab3806bc68ec92131490b0d19498a2d0ec54c48572abadcde6a5a2aa9ed3ab74314fb4dabe30ba6408d4894734e270af31d21c80c4e9e3fd540899669aed2f9bc7fe28891bc0fa6ff9a58ebfa37a19b1e8479d3d41c7b78204d9719c8ad1212ef0bae7f2cb82746ddb6816850f2467e875176ce398d1607d13d2f458526126a222d47f10c13396eb069577928443d3ca93d4582e1291c0c7caa7bef8c1f39c9863385e472ff1e9b38d85bafb3d2fe2ca2354c2fd1fd197b36bcff57292ec4e7b8ffba280227b13aa0247ba47d4824fd30328f70f64b056d4e36e3b75594d6f590e1b85e90a65f9a63ad6d42232ebb0628b11aa6a5bc31c1b8ac45f683b0290b14ea725b2b53ec8017ee90265f1561c96e26a3ac239745a0746ae6fac255bbc9a19aca4765900819e7a532c12d1760059118acf89d6a62c0f724e283081c8bcfd74a1db5435983c6cb67272699024dcc1f7c4089088d1fd7a4ece328c3611ab9219a8e0f43240841673317a5d3932a90806617572612083635c080000000005617572610101eccee865e2c48f93bf2d1ef99bf22549e3994e74b2f91cd00e742be73173cc40e5518cd480b62778a627e15268c8439cde21a27eb24fe0386645a5b11430c1820b0000000000000001ea0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0cd0c3ce103900b501fc82da6f8999bfd42354f8fc4db6230a764b7926c75118d570816caa86a63f7fdf4d0e0cae604060a1ca4d53a6bc0aeda87d1f5c28918b5f8233fecb446796519206c3b97eddddf86237cadeded98b041ef6ff4e474e53287a1697c8caf461dd58930f749d53af8832c488780a012590b005c36eda0d6e16c775b8eb42663d5517b3e9cc198e9658421ae7af2a76706d64e3324ce39240a32fc27041caffa0ead9c0064ae0ace86242f8074273018316dca50bc96a978da3883c3993b1a32b26325ff85be0b63084960a8b50132433176fdfb5c6ffc07bad1936428467f481ac53e71165512663839cf61457fba5ff17ed63e71b8c717680a10e1f33cda8f8d81c50c91152776a54b50195d6ec7f0d4bda452f9ac73012e902dc413d61ee372b7bc1305b79f10d3644a42c88cca1c4c8539760bdcced3d8c2b16819f00b2faf4d0fcf22d03a7cd76920487eeffed5b599f6cd32ccc9a64801fea2aa079feff2af002f0a71bd1fac90e9fea3a0573a5bfa2765a3a931bb5b8d55c9717290806617572612083635c08000000000561757261010166e2910c9513e1dbd2a6d3f938cd6a6253fbb2cfcf6a1f6cd76a8b7941b07b36824ead10eb5d99188c749988b49b9bb673571fac8b9317235b89b8d443a5fa860d0000000200000001f00700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0e4c8eb3dc54e5c0d1b9402f44f89137c1c2d095bed90ecbb80e38c5cf245c4828efb3599bef57b84619255f76f0aa168ba42a0c7d3a7e519bcaa784bf0c66e38b0a4168467cc53f93902feb5d97440405d82d672f86e440c362301c6283263fe870ecde7baa2895003dec3d07836c095ae4f3e4a05347dbd7d7c4eee1f811e18628cc961b32b53e4cdd3a60be566fd3ab6a686041c07a8d4750133047a6907232365380453504c52c6b96438fdabd2d972e3dfe6bd1e9bf0f254bdc07583e80acfe461dc363714109b6e04784803614ee2b00967cb51eb899327193cf485260130b0b9ac802b3db074f304ddc428950e80ee3e2a14d9f009d8376fdff493b7da24d7edadba1d6f9a8bd642f426851bab186b7aae7eb8fe526b05e362b996704e9028625ec7da0150afcd6c1431ed2e8b56be1dfdbbbcc7e3eef1275b5bcdcf5f4091622a20013b839aa611349e4450391abb30a5e0bf166d201351ff2eeb43d5057714a5b6c959ed33b8bae5fa99ba5d0154e08ce851e94502c8cd069c78c0a0d748ba782160806617572612083635c08000000000561757261010112e21a778c7c5404d9cf20fb4ecfe2c06b14e3e5ce45c76619077a2d47920b5e2d605528db37f2d4724f811429bb3bd308c9a20ac0d05b91329bb6b49b3f5a80110000000600000001f20700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fa6703abcf0fc554a4cec1cb5677c287f06e3bfc3f74bbab462dcc1062c88ce353939f9e6aaad990f2c9837dafd9f5a22c17455389a73f05570a74aed86a63b1ca65a09155dcea6eb1d458cc292968124a0f9b2bf125cb797ab96086dd3ed40da478e5401533e30c628939b081e4e383a28a6890ff949d27913939b7bf5d9c4dc0419a23af2d8a14090a06412179f31a575a917c04973f1f645d777e5ec48c938ad24670905b57cb5e29d8e2b285fd25778a69930cb1e71a366be9594f58c1a80322a31962e767ce5d6aed172950bf0d2ace5df6050df675a4e6a58a4c308372d89fd8d101e7dc06f0ee9a515dd338f2d29098485ffa2c2eff98c6bcdb6805b483ebfb1a48db52c4f8bc5cd264c2746ab4034bad57e11be369e459fdda1bc9810e9025375b7d9d546b18adc6ed91373ba5ca0a1e0e2549458ed06d4a9ff337dc4b7f11a9e9700a5ac8cecafd414c670faa4c56cc84c1efdfbdd63620fb2afb77983d5bf004a11177c31f7cac28712d992f31156ff0627678961f8ac57d3a41afede86cb1e31d30806617572612083635c080000000005617572610101e8bc4a1acbda300bdc4da4c20caa87ec14e7d91c04718c20d677ba82a2adf422e72d52c66fdfa17eb1fa426428ea9f015f8ec3b4dafe3b59e9062f0e8a4e3580120000000700000001f30700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f12528c5a9d2d33f06fe0197fd72642634a924caa92f954c84d0b30a5af9f621282ef2d609cd65387717749105fc4e7266cc29d8fa13accb72282526ac1e28f285f18f4e449efb717850369313139477445e5f16e58c14d5fb079d1e95a4c15f9bb6baaef2e82cfb97712dcbcef475efdca635371ff35d5e300090491f05aab135cfff964324889a26d9a999c5644bfab36a5f2b900df8dd33260f70ff4685c212d423273981adabcb2d89ab22068042fda0beb26bffb730348f31d3d739eef8ec6b6f7e799362b07a29726bde1d02cd6fd231852f6d0df84695832f70b69df9f724160bbde1c8a99b1f8014f200f6752e90265361f4c1e55a576e58a0a1ada06c73c69f77b4076a93404329f96cc0d9fa7ff77bfd5e457f1caf71688c95cbef6e9022b8b83e8888c042d9e2f0fb1a9bbc456a8b07a9572f1e4fafdc8d699438a9bb296be96007d6837a96593348603378036a8638aa191f7164617e732af28d26929f83245736740228224f3d42f71eafba39c8f4faa94a01a589f51929cdee85a28b7895f760806617572612083635c080000000005617572610101a2f595ba846acda337e0a6891b3f517de907a15ae96920676e7aa300c603d903091eb30a8613fa54a684f1aa488272ebce844a5f9c44a0c56990c60f6149e882130000000800000001f50700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fba252d10741845a93492f9ad5fcb431e93c51be0f71ea6a8bd164093d4fc9f06df0b8c4567e4808dbbde228cad475e6060a923c214a5c4636f556eb42a7a4ba91f04569f398c5b44d0aa5cb46a0e95f958b5a3e8352da4092daab9cd8c4859bfcfd415dec6748a823e1141a8ea36b283cf6384420f9bfb21b22579a580402394ecccae790c40a892f3417def8c361ff5a86b33779c74316c77c548c4612fb838c362ebc4332cf2a926e56af72339da43cf00bfcf190ab013df11fc575919858136699ab86fbca58f8f5aed50b70c125329af294571a4e1172e3d25b8d1c0894079c48d94b4f1140f83e68d0517db11f4d29ed81a93ba725c0516ef4d81f2543579a1430ae725802df267fe527b925ac709ea5f238c6b87cfbe7ecaf751855e688903d303d17a8af293a6d14b5f06dd6ace4d5a465ebc84d372da88b1d00fba851237864c8b00f9c1ba4d0f26ecb08528e3c156de07ee51cdbf6fe50c332a727d46f303f688f8ef451f0175c1f5902c4200a374026f4e1b73706cf03f33dc1a1a2fc0877346cb0c06617572612083635c08000000000466726f6e88014968c2fd312c9100837a25718581fa2438136bfce75918d9974e85bab2d26a6300056175726101017a5c5bd08201a067464db34a431fdd575008542f500582eb799c010c99c28f325a1092ab8501da0a0e9dcb07dc7eb849c6ade998b512282ce5786fe3b84d168c140000000900000001f70700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fe0b5632409e78aba11d0d559c96acff0247194879afad0741ae3848f61e74a02397ee4075a31cdfdf00c080c5ae192e9a8921bf216eec48cd06a0ec54f3728e627e68a325aa980ab408e110b842221f262f65fb9c9ff3bf2526d7a454e1f5bb31c4957f9abac96eaee0b0e4592b60fc6abf498f2b216099590c593fd2d6956525001477ea73bc4f27bbf93246c8ed89995f7e69d9e003c4b80bafac51cba1b7a8669945a41c3693a006a1cb8a9000b443f45cc4db5b1ccdb50ea7c8d7330768b445c9a763b1e6309dbc77d14e1e27ddb362cce7ef9e4023660b6db4e520bde91088b3f2153fdc8dedb22d5984ca5773ab7e794d3a9a6f700d1fdac1e54ca83a9455b24f78b25d8dc601e67cb9c1a60ea2e7e907576b4579a091566ce062d7b9fe90294e33d043375a9630b8b43a8176a4b8620e3341e1e22e9ea344ca3bc8b6d989e86ea5900c0bac6b93a608c8ed70554e38d2a513b20072d9f2556008e9cd917066c54e371326902973308c86b18c426b4dfe19c571cd158847f719b5b23daead339f4889a0806617572612083635c0800000000056175726101018a4d75e4d4af8ea9dcd1ee5c8d18659be74f9e3dd4af5312f566705f7fe08f03b6453775880c2d6cc9552f0c99462de4845de92be70ec21d537143377fbf4e8b150000000a00000001f80700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f30cd84fed2904f8f55b7c41d0638af65a209ed81abf76645862f999e1900273d800e3bae3d3c043d319ff1b86f66954e336dfb77f4f62e2cba632ca321a19edf3f600c334e02e5f6ffb1b0a482e3d1ff6e8da744cb98ff90f4e32f87f038cc682462c29e53670de6368795f8e42b58b565b4b0edaee2dab8a1b9e7f2c5b485b4ece9de94fb93817787e0a41ec5703599be3d47882754fd9de578996f9c23f441060bc13cea84d987edb6859731738ee0046151a27ca5d150d89d09dfc33c7b8ba56677abec76be5329edd0100932d6ad28aa84ec94ee0f38fa28dcd7428370186c113fd2ca1d93c9c59e2047eea8b9d0c6d52e15c73398d58433ecaf2c85274ccdc35e3d74de2af6b8b3a2af12ca02f9f14c0a168519ed83cce058a4409204c5e9023d756ae602b1db65712f5c037388b6162cc31b73268aff4572f0b02f706d67145aa38d009ee4491a3c7e2d63f2f2bdc16c70244435ca7f4b86b282a82aec767fac5f02f7489304e192850975b4acfbd1825ee836b803947e5704b6dd1ff7c59c44adaf950806617572612083635c080000000005617572610101d8fd11466fd2a4ea198104ce9c2d273b49e32dcac2900be2313085c941ef415464e0f1fbd3431900521af212814b266900a8a95d2ba9fd74db69092891ef1681160000000b00000001fe0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f007a3643f15ab58061fe650dddb783e26ac918157f6414ceafa7027500721f43b043862b71d1dd71242ecaaeccbfb79a5d742557eb7ea49c6f6c9f8a4d0f3057c7b4ea49c745843988fc3e575d3afe2433ae789f87be82d6aaca8f8eca674e4c2c7d5e2ea06f6b1768ca7fd09ae4f4b40866331a4da0cde2d5092394f50c7f58500047700c9e0db25489c6f932e40c357e945914ee47ca84666410e7d5f4320731aa082085acca46517147f2925244a62cf6cdc12e0d1dba722ac51ebc034988c2d2ba2d6a33d8c373a69d92f154d8b404c16f73fa872a864488126f84d3168b3f0f212826e2b9c0c9e49fcdd3d099bf3ef8d93b11c71abd2601da09acf1f8fb139a332d9a5601f727c537d8edba21117d7be408a87d6b9279dad0d31da1dea289033d2444574e1a1ea77abf1d1183b53dd83993c39fe1c82e21a2c331e84673c2d10e7e0400e6bc71df504d3496437a3c4851298d686579cdcd6a0eb507d3bb3807b10b483abda468fe3b2e3f5c42ee4223b991b3a15f0f52c7e847691a692c36791391980d0c06617572612083635c08000000000466726f6e880127856dcce783370e0f2f8d245e6962e65da80ac30e97fb2fbe2fed1b290f77910005617572610101e6ee0eb043a6b5ef5dd2060a1280d0c51cb63c1cdd386c77f1b03fbfea95741e8e4f7f250c9e031120c116a69f5091690ac472b19bc082d2b8955711c28d508d180000000d00000001000800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f4c31488e9125c86f7c78b1174f11bc54e10e24d63b075bf9edb77d7a521b8a7c72aa802d70982fe9261673dfbde97a4e0085892f7e826784a62e974449168d280cc6780f3f88b07267c5bd28035c1ea8d3c7d57bd46c7aea9f3686d5dcbf0e5cd67ae5a926a93a34221dfa7965bb1bf5bdfe550eb4302b952a19747373223929defaaaac2a4312b976551770dd90b277a0fea279f4e133172053e186276ea502a4c071f88e10a9fea38468083ada172cf4c4b71fb676cc911d061b1182557483e9bf72a5cb0332c44eb9f1c9e7621ad6edb850cea38d14550d91a326c4501a9201ed82c8a883f444d0300947104879b646d005468d5cf853725170f9b358bd5ad59c197ab76485206c59f36a6036994dc543aa252b11a3c056814311d27f1404e9024f2df319184d0dfbb1db4f4259dd717a98a856adc2a8c8912efcc98fdf4abdfa2e002d00399fa53f7c1f185d8427c874a8f23b13afc475e5cee1f760d46974e71a54ccb2d353e4aa9bb6d3b4a641c9472a2faefe5adac9bd04b36beefb4168050b77a7f70806617572612083635c08000000000561757261010132730fe531d29230b22a9a0935ef83d80e40aff7efd8db34ce12604e23492d3ca79135c8bd2a4df2849c018629b7aa544222db8ad821d0f04720ee11e255a48c190000000e00000001030800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f48c1b5e26d4c749374e8f69ead4a5b953951cafcbc541903b9ff0496ce82796005d8114aa42d92f25e4aab90e7c0e5bcaf8e0b27364123b0a0442634aa351e0df5c0abdb50c18e3c20d85c1c0d85ffe9fc4b3d2fa6334a888f89fda67fd34125075303600635530959cfa99e3dab3e4e48746930e6c4b416c857d7974b5dfd703c0ad6dcc383bf87f8204dd9c4204e7586a5048bf43854682d5e6753e824c0358e2e245bd9ffa05c64f572f7ff97753222ace44ed6d7599503a4d5b0bb4674819ade986462caf64eb706b9dc9cac0f23d5a9ac8784f067d43663b936525e949c99823eaf56a8d5abc4a8efb4cdcf6f72330a94b423b765fb0267f6be2fd343d2e68724dfd57dc416a9e429bfea4c4265c30f8f3420f1dc6e7ee002b7d73edf0de9027005ab65c401c5eaafe10bac663bad41901d29b6303401251affd054103b251c22b24400e801ed65820b0cd6e8deebbac787b371c89060775a0decfc2a7112b01c51ef7c1e616da83f89c8305d421b535e08d1b33570743958df7c712c4adf9c96cddd330806617572612083635c08000000000561757261010146354b89f12715e609b5e0a272b1e790070fae3c06593211bcb1fc0c40d9806fa21be4cec44a86a847982f6598f92ea1895acbebe39ee857012ef88fc80eb9891a0000000f000000010a0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fc00ba151fa23caf3a11590fe480f8713e26df35213521f26010a50d2da4d7c7356448cf00a57c405a2759052775a9ab72ef3975fbbfaa8c972b777958774db6c053837856a44c2ba69cb62bb627f28404b1de1f564f254f1a9b3d34d5b698f697ca16b1f5bb61e5b6cbbc9414a5bf0621ed419b43cc72ec90edd901a648d92f0b65504c69ee4a2793b9566effe4685816cc9e9b5afbeb574617a44181f56f84e9485fd594e5a541005820e3fbdaed7713dcedd4ba1c39ee31e386cdab27ea68b95d5c4474278dcea31832321ab93eb6b9d8f2cb5fb75a8e03cbcfba0dc6d495a900f07dfc7cfa4567f2f8ee94fb18793c79d46f233331913516c82a8ea379095c06172eb64373f8e6e622f61cc963278de4558aebbfcef14e1146d85964197e89501ef226b220d0a9f3ce159cd9fe3ce808391b3b90055c3960918277984e45f4c249e9a01006070e574c692886332a9cdfdd2bdbd972889c16e16354f1e470e52bf36db81d2bc7851c7622decd220c83b3668e028145434255ec44cd50cef9c25e5b868e92c001f0000001400000001260800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fead4b15c40389b68b80da252f1c64ccdff8b7deda378cad3bc2040df93bc0b5e7252eaa94a54db1b10710b81df91791d58a801e17ac7e6c5be9558f6ddbd3c555b19f587cb3e1436049a1e54564e1539f558a5641e3822542ef04a8029f6c03c7cb08847b3ec399f336d9532afb4a312db3b0226c3e740d12b274eb378aec9f87c169bc67da0715fb92c783b5b8fa646489179f8bf7e4a4271fa7d6edee05e74605c69aee2333339e8a08abafeb357a0281a206a64d184dceec971d6d55f248b741ed705f509eb20a558dd1772cd34ff1359d80a4c176982169f7a7f44e8250f9027b2b9d48451380121cdfc5a041491c3fb5eefc07009d1aee921df7a0599bc01034b5e0124a5042e25c42f67aa1303afd59571d83ea865eb1a3aee512467d6e9025befd6bf43197109f64511896b4ab95b2bd221e6810459242b4053c8284686e822d3e200a8f49a3d18ac36932f3608c00c7e004147b3868fdb6d9fa0d431f2ac5c180bbff6f0a28f55b64489087c1e2e91989c0b886fa55e5ca22989fec8626754b531320806617572612083635c0800000000056175726101016c40c4eb4eba5a7917edb38b4813bd5160442f44c16f743b1ab83fbca0aab837686b92638dc57ff1280973721c79102295a43260c4dcd93a6b6dea614077ff812000000015000000012b0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f7ec2f69737ac6304d9b45fc7bdad23a6e8b6b8c35c77226a9270a105205d5816f8f871b0e0903970117dac29c057cd2d5090f7381019703f20ef82e38de9484d4487ceaa35c2b85da43887dd27238c4a77a28d76326c0bb44244f2fd51fa8ec2298c0bd4ee975e581149da8c6b891bb511a5ae7f5b1794b58a133adba5beb7a75ec607a812b0ef58815e341279396158ae4d5234e03f750c7039bbf2b8b31c2ec4e675c6f7dd170b2fb31de633e340a39fba599e45cc13275825f7c505bc8088f059c6fb23e2e6148346053ee02154cfb8f1eae02f04419e59d9e23ec672d96610883519517ecee74ee2ca4c3a7d47ce8dea260ccfa1542ec8255ba9eca949a06f1c283dba5bef677dbbbe5b25fe5171ac3f48bebf64747f70bb7f689c57ecade90254ea986a37d66353e404a2f75415fe3470a1b41fd447a220d33953b9284c16d83ea543000d8737c8c55fcd4c37ab87b7558e052dfaeacdd7cb168de9064e583276e1a7046e68b68199397af29e1c83f02e4083890c222e4da2b762463e62a870cb327adb0806617572612083635c080000000005617572610101e6ab5f369c205dfda284a6744f7a74a83d94369526a4126c20161c5d273c81053f65482be2ac6e762d95a8a5f0e0474385b10e52bcff0b4e2116d9128108c6892200000017000000012c0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f8eabe2f87cf524db949c7ce4a300c9943d5ce7cb61eaf056407256614567cf6808599ad0612f70b2011e286f46bb6499e08a50a483fd8f6dd0af19e1596945f877d87e4f34c7c2a362ad3ab7860336ef91c50037eb839a57418f6989b347c701e0b8c7d6d75a732aaa50c303c7c411e87bbb8479f3afc1e31fd7713002d275bb7a0ca5e2cb228b6e38d1806487741429d1dc70ee946a51c3ba3285432ccd0b3dd07663c15018b3931889fc09646632be942a7ec9e4764e9aaeb031663f6fc380401dfb396fe48d83b1d0d25eab92e1dcbc61365db4fc2178436ef2b7b9ab29b50cf12be580eb72539ac227b4fe392c8868b2feb21de9067224d77fae5f6769e46c526f8430531d3b87d1abd12f8df54b0fe7d2e5c6c68c7d45c88eb6a8266ad24903339562159a30ba82f5e54db05cfcf1b517c911492234e3698b3a25410f07a55beee0af0018bc9c144df2b89cf89269120ac2db451dca153e63509b970e86778f340bab743fa69abcba4b75ffe19442f27b7522589c8dca513b1bbfa2ceb2dea2358fefb908066e6d62738088197ec695687b3c54268b18d071a0ebb4323e84179ba664894124beefc56f52056e6d627301016609447513272ebcb0271154883e924a6165a990dbe10ac8f63c33dd71124432c2bb3550926a2c1edf8d3f392c22046af6f1e86347864de3465660969b55a3832300000018000000012d0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f66064f3465604d64246bf810b9fe8e49a1cf470be7263b11a699edc83a9f352d4c87742fc24e8aeb858e82d633c5d21aaf645efce69123d14a5bf10cf2e87b829b622d5143362571270ca3f4f451bda43be9f870145afb34e3c3a25c97960a255c35ea9c5f11d8b5b87d7eca9b38db17bba211193fcb4df872dc755078e4bdf096a0b786e3efadc128eba8062eb163b018b1763689f1765872b64a88a4c3103c4796565257c6f24d0ee68e26627947ae8d033d2dbabd19d2f6796fab2a3488814af90dc6120f52e8b176ec45828b93ab9ed570537cb311f3006eb17a4b04add9aaf8b111859be1b3d33934ee9bc8a6fdc2bd674f5236099d42bf469cae8e9dde924db656504ab1637673c75be1d51e171906c6e8c12c51a06f6f89e712f7fa19e902f00e5727bb4eb555d4a4f5140b82f4d72ded6eff3506cef9f2eb8b57e36d13f732d41c00310b800ce61efabc623f074c2f728d6c7c2cfbd7c2be565b5bc4943a7a3bb2794ce3e5a2cae2afbc804926c92b104ba1e8eebb2fae209f6b244ced22de968a4e0806617572612083635c080000000005617572610101e81f196b8d3114ddeaf9eaf15d34be8e9ff43db5e25d1aad1774d6a819da913919f6f0b6a16dd668e2880547df0716338b7d0a8bf27203dd8b8d03c90adea88f2400000019000000012e0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f723e5619fa775cfa0b85ed1f73557d87bfaf34c269c00141e20a8e4fede6c76c8148b38f39593ea9b1d336460e35f225c624104259c9e8338b6f7f74322dd1b8e18091df02039f421e89714802f6be2f2652d714893299798f6f059c5a37dda0fba4bcfd13dbee90229d0771f973af9995468146472ac6aeb912116b4d8bb5ea147bfe6f234a1d1f7bc9d4f10656648269075b7268ae6a243a1a745c7c85f077f2a0fc35b52911a0984a7d2d8641e25952ec16186995a251213ce8c932d3008a05530d6923ca084b8837f15cc4d4dc0bb3c63a1921fa15ec9556ae3ff9d359b1647a0094fc9493f16cf2deb282b73f53985acb3177cfcec28a6f455ef0b43a6eddd7bbebc1214a12baf9cc2bd7a46fbc1e5204d6c192fab5db3fb53c0304c3a6e902acc812718e754faa8f3b4979311ce24e7a9510bbc1160e124e881180d6f678c2debb20001d57ebbdc54d39ebc6c72bda6004b766154578ed841d357151fe9f7b7d80c42d43197f6f6983c8e53d10ce0384d8830a6f1b2121958dab34edff2a7849253d620806617572612083635c0800000000056175726101017e927e09f71f3a2af25d161aff972a98f588d4f42f84a28d295488cc2ebbe024223147f58a7afc121215ee03e9300d5e11058ae1e7f0e80f675967c1367e8e8b250000001a00000001350800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f1c3964b2c71a0c5fb5c51687909a83cbaa4e94b907d2518bad392fc9a5a7ab7fe35190789786820fddab97684b50b4e8ce0f3595106ab256593fb1cae9ec8c9656a2f0d8e332d511e9b80f31f01eb57248a1a68fc87f8745b71b7d3c8f81982981df3189ee192b2a32bbd331fe28d70851d1d41462957f232206c470fe7c8e0be6133da394c2bb60467b7764e7648794626315f4f2ca7028fe235b0e9b47c33a974fd23cace0213c08cb20565b61ca4bcb3c0e5cdd4a20cf290b0e58d814688d0f34ff3fc478732698c85d8ddf6d0b5bd428df77b267a77999f6ab24b9728458cffa7727cd0ea5c03a212dabe51c377dbd53f0e7f0a1ddb79033fb3d7b73c1db5558455d3b6442a3da1f7827a645952460ccc5c3dd691bcae64a2d2668fe0097e9020425014b3839b51b99be80baa9dbf1a3ef01662a7ea51d6cb2da23814ae835357270a9006870fd9e022c9ac5b4de06bc198a481ae60f3909b8affe519a6c04ffed18438f3c163fa7c3cc25faf40c18eae7c40dbd5a27625fdc6646dce86a5773b6ab6d6b0806617572612083635c0800000000056175726101018c3417489b99706c04255a8b8648f2d6b6c701576dfd25ecd1de9d3b1e0cce4970616567b06ab1190b95a95572d61a4ae637ddbf7bf13bf648af9be585166785270000001c00000001050d00002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f54de495b57c7c3505c62633f1ac3a2f22be74ed497a5884379e0821607d9173beb5dd269e10d71dc754ce3fac591364afce61b007925730544bf530068087c7d38e3e2cd8bdf7fef72ad23b076e0620ab5d97d3c0a98207dd8b6af8c3becff696cd2c59aefd1a3bd654df00febe502e9f6ba788b8584c7278c47a2983fd8e87bcea2f2c3fdf7cfe328e695f1a111ef699739c5054adcfd40969c673b39080e4dfa869839757fab6bf946cf5695e1a0d9335ad95e445cd5fe9988a1c82fb53c83fedc8cf6b2555199ecc95e7092742c5959f96bce04becaebfd9266f7642c23d76e25771c2505f549b5af7734c84213bd1fd39278fa8f07298ba69da55a5c70899ece96d300d33d733840cfd4035249b50618e4e81f1cd425bd304b0cffc13b8ee902e66008704ade0c28fa58a8abc788e7b1c3ef78710408947dd4fb2f400effb2344a581900c5c07c6729c92d2b6d2dd7b5e6a05c26adc79e138d57c1b74a2d42ff7c021eb3f127490b8eef8e2c1cff1b685fc398f2dfeef4554328f288259cd9de2280e3200806617572612083635c0800000000056175726101017e7b7d496aef40f4e44a8819b2652fe2d64d286288f21f25a08b31f937d82c7ad7a48673092c23d7a2aa5cb2ca8dead00a2ace14361537ef7f338dc51f34bb842a0000001f00000000d207000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43216af2664480544590bc51a68be4ab955ba1e9d66544fb5ddd87455187539e427c0f0596d61ef285c22dc8d3e2f29bcfa542b00f0474045735c327e32b81a1e7fb4856020ebb9fb922899fe872508d3105d22f9749a0ed5cd6a2ee894140e1bc46ea832c2ab3e85936053ce6b203eb5396a696dc8d4977092004738ed02c4f5504a932e236c018a5ffcb5f0bed02fc84ee8a1d18fc7e02bd2550ea4606e043e4e6018a6818a0dc0acfb0e5ea67880a8e20dc6ef1f7399658c2fd4a7603eac9085a5574ce91797bfb2df82d4939ddd9f8aff952e1ce48b1d261c97088dcd5c86e532283647ac87830d1b136bce5fe3bad5acba67add2a89f005497d93fac9e5d2088e825d7969dad2cc6c04f8c4a6e65b5002877aaf6b7c32d0943efe5e127824089032a6b0cfbd22318888f75e0f1d6fd92d22de5cd8fb974579b68a848ee1a394979c675d0000e427f6dd8407605cc5ecb040ad322f127d040c84616ed6f41af284720d7c4e289ca21a7e551c98bed636f70900a463ebd20ae087491f8cab4b90668e7b3bc3c0c06617572612007c7b810000000000466726f6e8801b1adac139bde159ecba683741d3ecc31221e98eab5a429f3bb3f38c553018ecf00056175726101013c7952f659e18808ab2c763a25fb0c7532634085cec8d495f3030c6c3cb5b05722c5143a5dd1fad4f7d84eee22196d845e2e1309a48eba4859aba690c2e6a083030000002300000000d407000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43228919c055a0f2137f13690e949df8f7d97d322fd990946b698f985989116ba7725269c36d48994939f136e4118d4344b4ec13a8c468ea71c52848177ee200ebab55f213795cf2769a0bc7d5ece59be01b8afc921529684f158ec31c4bc58eca35e4f74b2e3c8decba237f50ffbfe45753135891432ca98e1ce2cd1aafc02e67a80d7bd3ff76b4162eb32a149d0673960080c609ace1755ec2f60d6edcdd79309b9bcefd1b379e2291be3ec29e5429c11bb5269d085ef32e86996bb6086f9528541ab122ce2a5db613f84f3b2f96a7dc6bc53ceaa18f6985f08391a449a440c6332e9b1f9c0b02e36ec11b5167c7e7a00d24222061b4769e03517ab2e2ee6170c55a25e183e83a80c3d4968040681b1d15366669926dbf45ab4d7a84e553e426389065fd3dc2ad1fe4f17b0d3bb1bc2bbb7090363c52706ca6509f14a6a128d85ef337e52d5008cc9bdf131d19272e7143953afec22aa607608e1399048c920388988e7834c68139f2af193d65a5517524c47908fc3a6a6275d581dc9661a5594a853b0aacbe810066e6d6273801ec11d2d43768a4d5d45b5611db0b3298b77621d26742547fe41ce91c0d661260672616e648101ceaf24ecf730d7e039d2de8aa45733921ffba8cb0e7c6f75bd06d2591b901c77b1e807742745efcbd5a57bf08935eb21cc1fbeb85d80ed7c615ca7d35e249a07bf6d39c123ba9ba0bd7e75318040bc489985b106d6c98c5aa5a0811ede08f9060466726f6e890101ff0a22a78c0683078446688ddeebbc95a99b1884cd22a8201bf911cabb18059908309e9c2c6a18f7387da2ee66bf312501f6b7d5c7e5f0b9a17df6a084a87d334c3022239463cef94bfd88bf8317dd9b6cab00f087cb8df769cb6bb2c0d0f1d312056e6d62730101d6fa19a093846a11dbd3b9f26dca8a0dcdba8493d6b346b86486f3c54dd7ec72b46a8f8d7d17f1192788c741d069e068c08eb0c5cc6f6aae09d7548b6faabf82040000002400000000e507000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432cc8a84b06644b0fd1e790c2de73d66c562f0cd3f6239d81b25cd278e5111266388a9171ad58bcbd15396dde9b68b6aeb9a7a6a5b5c7a47d77603f1889cfde56f1ac40ba6eb288239b7dd9c8af7f2b9fb0795cd5b28820c87180e3d735e7bcc0b51df051cf8f33419ca0f07f31f4e8dd2ad6f62bafdc1f0c47f9b727603cda6ae34a3726a20df66d660d77f1c01195a112535db1e046a4beaef91de906901911dc374d89fe1f805734c6f6144db3152748f9b0541cd6583e6c3d2894e04970082b98df5d914b951c9183bf25117b1a9072768e4df487f8e6ed918e5d6754319322d991a6158947113ff320990f38f5e37f0ece574395edfae743439824efbabd2d04f9ebc499a3c2040abe8fddc43943b8f123b71bb490e5f93c5f6093dad9f58e90231d5d69ba54e8052c9c50daa412c580711b273461ec198a7d5399fbfe614faa5ae8d9f004508b43b4a234f1cb724cce8e3e6b00c81f94bc0f321502794f4616392849994f67c842d1b63e4a18df453da38b88267d8389934b1f86bbb988e29162c71dd480806617572612083635c0800000000056175726101011c43c9dc41050f47d24f799941efe385c0b41380cb1b19fb9910ce4f2c55222a6e836b3aeb5c1c931f9c3e95dc9cd27e1d1585d69e18813f5cb889ecea1da3830c0000000100000000ee07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432021071f1207ce1d22e80903c737f4c89f2113bd1c7753de41092a70552dd6c17cffb003d8b5359ae9c274650df76ffdd14c52814ce9b5c17900bc52834e30a83ce59e7d5f163371f5d99dd3784d693dfac0e4eec4fa8accf45a881150ceebab3f42382ac9fa47baae525b7af81f2ba3125302b795ec05b0a3d9b4bca133d3a63e2c5da2612da3f1b3c8f42cd1522f6a7a48d2693d58088e5288694b90307074ef116265b6660b03112547414f40025cc4154c6eb7a6de2ad52e51a55af54b38aa1c54fa1bd03bcbd527584aa648fdd075dc0f8e79c247f5ffb1e6ac9c2be225ea60db84bb8d7ab17120d682d16696c329e958433a449faeb88b1c50464e2e4e2eaa75a54e13a8d890399906e24d00454ec4e709e4f7b939691771a23dab762bbe9023a3389663194f4d084a27298adb033bfd6a263f4d3c4c20a3e6f0e00863cb85196408b005a0aee92f8c6b9858c667067f971772855a47e11daf73a2aab1ae29e5db1dc095e8b6f463c0264370e99ac799f7b717e685218b437e4f6181e4abd56e1a0c0d60806617572612083635c08000000000561757261010122106da90907f90dfa17d639b60ab9d3aabdd7ea95daaeeccf3b4dee072fce038e61f86d7189ee821aec9a11d6ecc5c484d12229183553ca27a9d20f668af9860f0000000400000000ef07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc4327ef0f295b0fdc0c650ffebced6be72c4dd0e1176da30930364fdb01a6713d036f0831c577230924e9326d19f346e64c95e84193c52352eda105704b09d804268b5a6b9e2d162fdb73841ea9372584d9699f321a111fe6f470b89b99b07d8431bafca0227eea00a532e1484c02ec006fa6495eba21abc438584d76f48802d0a910a508a2ee6c3f905a242e92b41e1bb438c7a083504fda57a1849ddd35896c47d78a5956fe6c7531a3c8ddefd9d17c1284ba60dac9040aca954dec18f365c9b8fbe455b67d90249d0096cd35843e3d71badc12c49381bce7312852dec8a1eb64498bbf023fc9e033deee0b54e1b2e1ca8e747d2dd9cb658cc07344df196fbd222e9520eab0f4b1fa37fc4afcb93a1c0ace0cde92aa0689ebcb0c5d1245bcd2c10e9028a0cc2de076fcc8655cd5cc9ae23351591616aded6d8ecab7f2a44e5d624a8fe422bb00056c4bf23b31c58b9773346f043fb8bf5373ded1962c0fec66853e9d754bb642036900eb42f10c8e6021345c5ca5bd1ab4e22e5b8022bf38b06f66425eebf4c5c0806617572612083635c0800000000056175726101011a3c100d29a795c4fbb068012b0291991aa5db384bc0d8c775ffadb60c9a955b4e259391b7f5c22a32ed066345b09aca2fb0b06fb2254ea3723b462ee7ce478a100000000500000000fb07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432740beb55375d7c8b84577fbe1c0743965ea389fe7585d6f68975111716c1ce24eb2dadcc3c91fcb5f23b9008ea9c6f934dc261a84b3d1b5b43ae437c6aa992452aea0a684700ff36d0a8b8ebd07fecc353bda87aad24b37c8944de3ce45efcb42fd6220dd68bba2bbc6a3756154fa5cf878797dacda5fe063c16fd8436a46bc160c9820134984676bc4e14204671db0b5494513b5a7fe4df5d0ea250e554a2080e31802525806814554d3a5677af77a3673b500d3539f04afdcfd720573b608ab0b09939c11cbff67c66f806f5221a61fdcfab5c4fa11c0d7ca12988135efa54ed1d69cd74ceee75480f46a7b15b926904d12cdea281aa28e908ec00a9d07cf8a82bcf585ae95386cc747fdf003d5802d9fe7484687bbbad0448af45553ff3b58903174881b8182392f9757efb143ba61d046a0208302a7a7b3df8041059ca538fef169b8d0012fd33199e57825afe600bbfff192f2b9e0f6b72f5da7e8f1f3147e859987cc129b23e32b2278bada2bc2795d7cd6034e3afa8e9a333d01b36b4e2250e583fe20c06617572612083635c08000000000466726f6e88014920420a08c71a4b56953bf3efbae9a45e737f4cea978bdbc470de907d64e1550005617572610101b491cb7862f8d14fb0e2f6cb8d1287b83a55ee7feb468577ca78d9c120fabe5f6b909448827d93de5eb8bd7afe6c9aea63fef46254208969cdab95fe6d02f18b170000000c000000000808000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432c663d22aea82481985ee77a58f1e54bb8c64fe22c48df15aa43f69aad1c7276b53c400f7fb9008e65a12443807e49224efa495a9cfa03e6ce5298a88fc744478f3820cb625cff327e14fe2006713cce73555c4336a7d861715aa2429a7d349102f0b4f9017440cf5a06a286856c5795b974f5006aa07357854c3eb4c3892b7f5125cb08a3e444ff92b8868bb8d6d64947c84862353870b0e5121b002929c136db31e000378c0f3241a5408a49bc458bd75af5c0d16b35661e212a981ecf5be8d61707c8adc571e83812efa6aa3673e4423c1b56780c437c500583abf6839a68d096600b21370ef6b990d6922acbfc71de68d751ee2d62fbfc49125bd9709ffe33bbce32c9e23b266d24cc175dcc0d99e7c1182b6ce8824d724e9c34ad852a611e9021145925a3f018c9aaba6b3981aaa8e1e24f0c7d9b38f65643a16d3f55d77ff6ca60a4800e3f4f2125d650231ba3ecaa0a51aeda71beada9dad70479d4571b5f2ebfa480c16116166d9e35a66dcadb999da853bfcd1872563f5d0a785507bf67796e568ec0806617572612083635c080000000005617572610101de7241c718f67134d32b6b5656f8e8f3f31e8d29af28043a37c2b49429a082633c8c7abbe502084c28c4a548ac75f97732521c7e66ea9917e704e5469572558c1e00000013000000003808000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43278b266c6c3ba60a6e648093bcd62419d4ea68eec772f22b7dfc78c6b255dac57bd149cd2b1b166d73be2ed9409a0bebe842c1901d65b1fd3c5f8d98d82ea2a5c3ae10acc8770276d737e6334c59e468be878e6264c050f48ac3e4a6524b76b37c399c4a820e1a50b2bcbc805192c2609e8372e8ddd8432127f6200427dcb2d72386429023e01fcf193d96cc55f1d4d85db5b2f0a9e3a5fb6855c0e07b891d6581ea371a39cb30eaa0ea2d0b9bbe5734e8793d4db7c366277619bdff9611dfb8d4bba89ec371746a5e689ece6f2a117d2b4e7894776b7a96209e7177446c076874bde474bbe3f7bb78669eb48648bf238110f690c144c097988314989bf9b3d4ef410cd043b32cf71a25a00655ab6a0558e383e546c3728412be664273b51908f4903de6835c05f9da3c6ca7fc65846438da7947f93a152f77bb75a85e3d05385feb47e071300b797adcbfd7d3a94ba4b2e0ab454bfded856f759d2b674839d4adcacb72d2c1361edc442862859f46d384db20db351390b2d261be35211db5232e585f985291a08066e6d6273804852f3c0a603d7da194fbff174c24700f3f89d86b462760033bdcb1663c76c60056e6d62730101e2f5f706646cbfc613a98564ff9b4a958acead02fa488e1f3bbcee114d13594d75e9b79d5f5be257e9da81d3ab97cefe36a620a2384f6f1f8719ec2b23532684280000001d000000" //nolint:all resultBytes, err := common.HexToBytes(result) require.NoError(t, err) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 880a192705..89f20cbd4e 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -350,7 +350,7 @@ func (in *Instance) GrandpaSubmitReportEquivocationUnsignedExtrinsic( // ParachainHostValidators Returns the validator set at the current state. // The specified validators are responsible for backing parachains for the current state. -func (in *Instance) ParachainHostValidators() ([]types.Validator, error) { +func (in *Instance) ParachainHostValidators() ([]types.ValidatorID, error) { ret, err := in.Exec(runtime.ParachainHostValidators, []byte{}) if err != nil { return nil, fmt.Errorf("exec: %w", err) @@ -362,7 +362,7 @@ func (in *Instance) ParachainHostValidators() ([]types.Validator, error) { return nil, fmt.Errorf("unmarshal: %w", err) } - return types.ValidatorIDToValidator(validatorIDs) + return validatorIDs, nil } // ParachainHostValidatorGroups Returns the validator groups used during the current session. @@ -389,18 +389,12 @@ func (in *Instance) ParachainHostAvailabilityCores() (*parachain.AvailabilityCor return nil, fmt.Errorf("exec: %w", err) } - coreStateVDT, err := parachain.NewCoreStateVDT() - if err != nil { - return nil, fmt.Errorf("new vdt: %w", err) - } - - vdtSlice := scale.NewVaryingDataTypeSlice(coreStateVDT) - err = scale.Unmarshal(ret, &vdtSlice) + availabilityCores, err := parachain.NewAvailabilityCores() + err = scale.Unmarshal(ret, &availabilityCores) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) } - availabilityCores := parachain.AvailabilityCores(vdtSlice) return &availabilityCores, nil } @@ -484,18 +478,15 @@ func (in *Instance) ParachainHostCandidateEvents() (*parachain.CandidateEvents, return nil, fmt.Errorf("exec: %w", err) } - candidateEvent, err := parachain.NewCandidateEventVDT() + candidateEvents, err := parachain.NewCandidateEvents() if err != nil { - return nil, fmt.Errorf("new vdt: %w", err) + return nil, fmt.Errorf("create new candidate events: %w", err) } - - vdts := scale.NewVaryingDataTypeSlice(candidateEvent) - err = scale.Unmarshal(ret, &vdts) + err = scale.Unmarshal(ret, &candidateEvents) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) } - candidateEvents := parachain.CandidateEvents(vdts) return &candidateEvents, nil } From 19f46bbe0df004a823dc31cf72af47dc403e8d79 Mon Sep 17 00:00:00 2001 From: kanishka Date: Tue, 9 May 2023 18:39:02 +0530 Subject: [PATCH 52/65] cleanup --- lib/parachain/types.go | 7 ++++--- lib/parachain/types_test.go | 24 ++---------------------- 2 files changed, 6 insertions(+), 25 deletions(-) diff --git a/lib/parachain/types.go b/lib/parachain/types.go index ba257b6c96..cb614f9e1b 100644 --- a/lib/parachain/types.go +++ b/lib/parachain/types.go @@ -63,7 +63,7 @@ type CandidateDescriptor struct { // on this for deduplication. Removing this field is likely to break things. RelayParent common.Hash `scale:"2"` - // Collator is the collator's relay-chain account ID + // Collator is the collator's sr25519 public key. Collator CollatorID `scale:"3"` // PersistedValidationDataHash is the blake2-256 hash of the persisted validation data. This is extra data derived from @@ -123,7 +123,7 @@ type ScheduledCore struct { // The ID of a para scheduled. ParaID ParaID // The collator required to author the block, if any. - Collator *Collator + Collator *CollatorID } // Index returns the index @@ -132,7 +132,8 @@ func (ScheduledCore) Index() uint { } // Free Core information about a core which is currently free. -type Free scale.VaryingDataType +type Free struct { +} // Index returns the index func (Free) Index() uint { diff --git a/lib/parachain/types_test.go b/lib/parachain/types_test.go index 87037458de..9dfab8f4e9 100644 --- a/lib/parachain/types_test.go +++ b/lib/parachain/types_test.go @@ -93,12 +93,12 @@ func Test_ValidatorGroup(t *testing.T) { } // Test_AvailabilityCoresScheduled tests the CoreState VDT with ScheduledCore encoding and decoding. -// TODO: cover it for other CoreState variants +// TODO: fix this test func Test_AvailabilityCoresScheduled(t *testing.T) { t.Parallel() // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_AvailabilityCores` - result := "0x0c01e80300000001e90300000001ea03000000" + result := "0x0c010100000000000064000000c800000000000100000002020202020202020202020202020202020202020202020202020202020202020100000000000000000000000000000000000000000000000000000000000000000000001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000903db64205805df4bc1710e1422bf3c8a308c2d87249247411332fe185121f3e143241ebe71b25a371b4c580ba5a04621229fe7837c1f1fa088f49bcad5967800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002" resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -107,26 +107,6 @@ func Test_AvailabilityCoresScheduled(t *testing.T) { err = scale.Unmarshal(resultBytes, &availabilityCores) require.NoError(t, err) - temp, err := NewAvailabilityCores() - require.NoError(t, err) - expected := scale.VaryingDataTypeSlice(temp) - err = expected.Add( - ScheduledCore{ - ParaID: 1000, - Collator: nil, - }, - ScheduledCore{ - ParaID: 1001, - Collator: nil, - }, - ScheduledCore{ - ParaID: 1002, - Collator: nil, - }, - ) - require.NoError(t, err) - require.Equal(t, expected, availabilityCores) - encoded, err := scale.Marshal(availabilityCores) require.NoError(t, err) require.Equal(t, result, common.BytesToHex(encoded)) From 16222e50b62fe9a052af0d81146e35fc5bdb1392 Mon Sep 17 00:00:00 2001 From: kanishka Date: Tue, 23 May 2023 18:43:22 +0530 Subject: [PATCH 53/65] add tests --- lib/runtime/wasmer/exports_test.go | 57 ++++++++++++++++++++++++++++++ lib/runtime/wasmer/test_helpers.go | 6 ++++ 2 files changed, 63 insertions(+) diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index 4ad65711e4..0f3b9d6cde 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -1158,3 +1158,60 @@ func TestInstance_GrandpaSubmitReportEquivocationUnsignedExtrinsic(t *testing.T) err = runtime.GrandpaSubmitReportEquivocationUnsignedExtrinsic(equivocationProof, opaqueKeyOwnershipProof) require.NoError(t, err) } + +func TestInstance_ParachainHostValidators(t *testing.T) { + t.Parallel() + + tt := getParachainHostTrie(t) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + + response, err := rt.ParachainHostValidators() + require.NoError(t, err) + + expected := []types.ValidatorID{ + types.ValidatorID(mustHexTo32BArray(t, "0xa262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d")), + types.ValidatorID(mustHexTo32BArray(t, "0x804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e")), + types.ValidatorID(mustHexTo32BArray(t, "0x4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72")), + types.ValidatorID(mustHexTo32BArray(t, "0x74c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68")), + types.ValidatorID(mustHexTo32BArray(t, "0xe61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511")), + types.ValidatorID(mustHexTo32BArray(t, "0x94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e")), + types.ValidatorID(mustHexTo32BArray(t, "0xac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841")), + types.ValidatorID(mustHexTo32BArray(t, "0xb61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12")), + types.ValidatorID(mustHexTo32BArray(t, "0x382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c")), + types.ValidatorID(mustHexTo32BArray(t, "0x0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547")), + types.ValidatorID(mustHexTo32BArray(t, "0xcee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237")), + types.ValidatorID(mustHexTo32BArray(t, "0xe2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53")), + types.ValidatorID(mustHexTo32BArray(t, "0xce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016")), + types.ValidatorID(mustHexTo32BArray(t, "0xae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848")), + types.ValidatorID(mustHexTo32BArray(t, "0xa0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a")), + types.ValidatorID(mustHexTo32BArray(t, "0x807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a")), + types.ValidatorID(mustHexTo32BArray(t, "0x4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936")), + } + require.Equal(t, expected, response) +} + +func getParachainHostTrie(t *testing.T) *trie.Trie { + // block hash: 0x03458e146407a2ad41a87b18298540cad7d48f931f4815ca1fbef281e5943ef5 + data := []struct { + name string + key string + value string + }{ + { + name: "parasShared.activeValidatorKeys", + key: "0xb341e3a63e58a188839b242d17f8c9f87a50c904b368210021127f9238883a6e", + value: "0x44a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe7274c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c51194ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050eac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547cee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936", + }, + } + + tt := trie.NewEmptyTrie() + + for _, d := range data { + key := common.MustHexToBytes(d.key) + value := common.MustHexToBytes(d.value) + err := tt.Put(key, value) + require.NoError(t, err) + } + + return tt +} diff --git a/lib/runtime/wasmer/test_helpers.go b/lib/runtime/wasmer/test_helpers.go index 78ae60c62b..7f862d4e0e 100644 --- a/lib/runtime/wasmer/test_helpers.go +++ b/lib/runtime/wasmer/test_helpers.go @@ -27,6 +27,12 @@ func mustHexTo64BArray(t *testing.T, inputHex string) (outputArray [64]byte) { return outputArray } +func mustHexTo32BArray(t *testing.T, inputHex string) (outputArray [32]byte) { + t.Helper() + copy(outputArray[:], common.MustHexToBytes(inputHex)) + return outputArray +} + // NewTestInstance will create a new runtime instance using the given target runtime func NewTestInstance(t *testing.T, targetRuntime string) *Instance { t.Helper() From bafc235072a45d7192ddd2543891cb9cc11b83b8 Mon Sep 17 00:00:00 2001 From: kanishka Date: Wed, 24 May 2023 16:06:01 +0530 Subject: [PATCH 54/65] add tests(incomplete) --- lib/parachain/types.go | 18 +-- lib/runtime/wasmer/exports.go | 8 +- lib/runtime/wasmer/exports_test.go | 195 ++++++++++++++++++++++++++++- 3 files changed, 204 insertions(+), 17 deletions(-) diff --git a/lib/parachain/types.go b/lib/parachain/types.go index cb614f9e1b..ca76d5006a 100644 --- a/lib/parachain/types.go +++ b/lib/parachain/types.go @@ -172,17 +172,14 @@ func NewCoreStateVDT() (scale.VaryingDataType, error) { return vdt, nil } -// AvailabilityCores represents a slice of CoreState -type AvailabilityCores scale.VaryingDataTypeSlice - // NewAvailabilityCores returns a new AvailabilityCores -func NewAvailabilityCores() (AvailabilityCores, error) { +func NewAvailabilityCores() (scale.VaryingDataTypeSlice, error) { vdt, err := NewCoreStateVDT() if err != nil { - return AvailabilityCores{}, fmt.Errorf("create varying data type: %w", err) + return scale.VaryingDataTypeSlice{}, fmt.Errorf("create varying data type: %w", err) } - return AvailabilityCores(scale.NewVaryingDataTypeSlice(vdt)), nil + return scale.NewVaryingDataTypeSlice(vdt), nil } // UpwardMessage A message from a parachain to its Relay Chain. @@ -395,15 +392,12 @@ func NewCandidateEventVDT() (scale.VaryingDataType, error) { return vdt, nil } -// CandidateEvents is a vdt slice of CandidateEvent -type CandidateEvents scale.VaryingDataTypeSlice - // NewCandidateEvents returns a new CandidateEvents -func NewCandidateEvents() (CandidateEvents, error) { +func NewCandidateEvents() (scale.VaryingDataTypeSlice, error) { vdt, err := NewCandidateEventVDT() if err != nil { - return CandidateEvents{}, fmt.Errorf("create varying data type: %w", err) + return scale.VaryingDataTypeSlice{}, fmt.Errorf("create varying data type: %w", err) } - return CandidateEvents(scale.NewVaryingDataTypeSlice(vdt)), nil + return scale.NewVaryingDataTypeSlice(vdt), nil } diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 89f20cbd4e..8d57967164 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -383,7 +383,7 @@ func (in *Instance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, } // ParachainHostAvailabilityCores Returns the availability cores for the current state. -func (in *Instance) ParachainHostAvailabilityCores() (*parachain.AvailabilityCores, error) { +func (in *Instance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { ret, err := in.Exec(runtime.ParachainHostAvailabilityCores, []byte{}) if err != nil { return nil, fmt.Errorf("exec: %w", err) @@ -462,17 +462,17 @@ func (in *Instance) ParachainHostCandidatePendingAvailability( return nil, fmt.Errorf("exec: %w", err) } - var candidateReceipt parachain.CommittedCandidateReceipt + var candidateReceipt *parachain.CommittedCandidateReceipt err = scale.Unmarshal(encodedCandidateReceipt, &candidateReceipt) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) } - return &candidateReceipt, nil + return candidateReceipt, nil } // ParachainHostCandidateEvents Returns an array of candidate events that occurred within the latest state. -func (in *Instance) ParachainHostCandidateEvents() (*parachain.CandidateEvents, error) { +func (in *Instance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { ret, err := in.Exec(runtime.ParachainHostCandidateEvents, []byte{}) if err != nil { return nil, fmt.Errorf("exec: %w", err) diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index 0f3b9d6cde..fe73349dac 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -6,6 +6,8 @@ package wasmer import ( "bytes" "encoding/json" + "fmt" + "github.com/ChainSafe/gossamer/lib/parachain" "math/big" "os" "testing" @@ -1190,8 +1192,119 @@ func TestInstance_ParachainHostValidators(t *testing.T) { require.Equal(t, expected, response) } +// TODO: group_rotation_frequency is being overwritten by the runtime to 0 +// need to figure out why +func TestInstance_ParachainHostValidatorGroups(t *testing.T) { + t.Parallel() + + tt := getParachainHostTrie(t) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + + response, err := rt.ParachainHostValidatorGroups() + require.NoError(t, err) + + expected := ¶chain.ValidatorGroups{ + Validators: [][]types.ValidatorIndex{ + {0, 1, 2, 3, 4, 5}, + {6, 7, 8, 9, 10, 11}, + {12, 13, 14, 15, 16}, + }, + GroupRotationInfo: parachain.GroupRotationInfo{ + SessionStartBlock: 15946156, + GroupRotationFrequency: 10, + Now: 15946391, + }, + } + + require.Equal(t, expected, response) +} + +// TODO: group_rotation_frequency is being overwritten by the latest runtime to 0 +// the current runtime is blocked by https://github.com/ChainSafe/gossamer/issues/3268 +func TestInstance_ParachainHostAvailabilityCores(t *testing.T) { + t.Parallel() + + tt := getParachainHostTrie(t) + rt := NewTestInstanceWithTrie(t, "/Users/k/chainsafe/gossamer/westend_runtime.compact.compressed.wasm", tt) + + response, err := rt.ParachainHostAvailabilityCores() + require.NoError(t, err) + + // TODO: assert response + fmt.Println(response) +} + +func TestInstance_ParachainHostSessionIndexForChild(t *testing.T) { + t.Parallel() + + tt := getParachainHostTrie(t) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + + response, err := rt.ParachainHostSessionIndexForChild() + require.NoError(t, err) + + expected := parachain.SessionIndex(27379) + require.Equal(t, expected, response) +} + +// TODO: assert the response +// currently it is nil +func TestInstance_ParachainHostCandidatePendingAvailability(t *testing.T) { + t.Parallel() + + tt := getParachainHostTrie(t) + rt := NewTestInstanceWithTrie(t, "/Users/k/chainsafe/gossamer/westend_runtime.compact.compressed.wasm", tt) + + response, err := rt.ParachainHostCandidatePendingAvailability(parachain.ParaID(1000)) + require.NoError(t, err) + + fmt.Println(response) + + //expected := []parachain.Availability{} + //require.Equal(t, expected, response) +} + +// This test needs to be run with the latest westend runtime or we need to get the +// data from an earlier block +func TestInstance_ParachainHostCandidateEvents(t *testing.T) { + t.Parallel() + + tt := getParachainHostTrie(t) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + + response, err := rt.ParachainHostCandidateEvents() + require.NoError(t, err) + + fmt.Println(response) +} + +// TODO: assert the response +// blocked by https://github.com/ChainSafe/gossamer/issues/3268 and +// https://github.com/ChainSafe/gossamer/issues/3248 +func TestInstance_ParachainHostSessionInfo(t *testing.T) { + t.Parallel() + + tt := getParachainHostTrie(t) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + + response, err := rt.ParachainHostSessionInfo(parachain.SessionIndex(27379)) + require.NoError(t, err) + + // TODO: assert response + fmt.Println(response) +} + +// TODO: implement this +// unable to find the data onchain +func TestInstance_ParachainHostDMQContents(t *testing.T) {} + +// TODO: implement this +// unable to find the data onchain +func TestInstance_ParachainHostInboundHrmpChannelsContents(t *testing.T) {} + func getParachainHostTrie(t *testing.T) *trie.Trie { - // block hash: 0x03458e146407a2ad41a87b18298540cad7d48f931f4815ca1fbef281e5943ef5 + // taken from https://polkadot.js.org/apps/#/chainstate + // at: 0x03458e146407a2ad41a87b18298540cad7d48f931f4815ca1fbef281e5943ef5 data := []struct { name string key string @@ -1202,6 +1315,86 @@ func getParachainHostTrie(t *testing.T) *trie.Trie { key: "0xb341e3a63e58a188839b242d17f8c9f87a50c904b368210021127f9238883a6e", value: "0x44a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe7274c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c51194ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050eac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547cee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936", }, + { + name: "system.number", //block number + key: "0x26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac", + value: "0x9652f300", + }, + { + name: "paraScheduler.validatorGroups", + key: "0x94eadf0156a8ad5156507773d0471e4a16973e1142f5bd30d9464076794007db", + value: "0x0c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f00000010000000", + }, + { + name: "paraScheduler.sessionStartBlock", + key: "0x94eadf0156a8ad5156507773d0471e4a9ce0310edffce7a01a96c2039f92dd10", + value: "0xac51f300", + }, + { + name: "configuration.activeConfig", + key: "0x06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385", + value: "0x00005000005000000a00000000c8000000c800000a0000000a000000c80000006400000000000000000000000000500000c800000700e8764817020040010a0000000000000000c0220fca950300000000000000000000c0220fca9503000000000000000000e8030000009001000a0000000000000000900100008070000000000000000000000a000000050000000500000001000000010500000001c8000000060000005802000002000000280000000000000002000000010000000700c817a8040200400101020000000f000000", + }, + { + name: "paraScheduler.availabilityCores", + key: "0x94eadf0156a8ad5156507773d0471e4ab8ebad86f546c7e0b135a4212aace339", + value: "0x0c010101010101", + }, + { + name: "paras.parachains", + key: "0xcd710b30bd2eab0352ddcc26417aa1940b76934f4cc08dee01012d059e1b83ee", + value: "0x0ce8030000e9030000ea030000", + }, + { + name: "paraInclusion.pendingAvailability[paraId=1000]", + key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865b6ff6f7d467b87a9e8030000", + value: "0x0000000058b29da15fc66c19ef0ad4e66e95c8e42718d2455001ec6876f4173489a705fbe8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b5145337440000004400f0019552f3009652f30002000000", + }, + { + name: "paraInclusion.pendingAvailabilityCommitments[paraId=1000]", + key: "0x196e027349017067f9eb56e2c4d9ded50433e4ed72dccf0edcf58c3192f16e4bb6ff6f7d467b87a9e8030000", + value: "0x000000e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e000000009552f300", + }, + { + name: "paraInclusion.pendingAvailability[paraId=1001]", + key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865adc7217647a32b0be9030000", + value: "0x010000000571a387d344bef8a77d3a99895958644dee97345861f7747b1cb8186a14089ee9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e6744000000443f00009552f3009652f30000000000", + }, + { + name: "paraInclusion.pendingAvailability[paraId=1002]", + key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865b2b032492225337bea030000", + value: "0x020000009b716202cd9fabb93b278a41d9344faecb1300241d255d1de0675a42ebff6b6eea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc529964400000044c00f009552f3009652f30001000000", + }, + { + name: "parasShared.currentSessionIndex", + key: "0xb341e3a63e58a188839b242d17f8c9f8b5cab3380174032968897a4c3ce57c0a", + value: "0xf36a0000", + }, + { + name: "system.events", + key: "0x26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7", + value: "0x1400000000000000e249433d551702000000010000002c00e8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b514533734cd6976981877d40277ad627ec04b2fc4ba04f558d9e4b41d911a6f41610350e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e00000000020000000000010000002c00e9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e67514f16481063738cae77af97e154a475018c89ac13ca21452572447ae3bea823e90259b97f6f68683641a4b1046440cedddbc2054805e95504e9813b7c352d68ce57ba9357001fb3b6742be5e417621c0fd5f742e9f1d142518605af00a244dc61ebd42d63e07666532e9e2ab468d56fccb902fa801513a4dddc19d9e4b1edaae85ef1d1758908066175726120f4635e080000000005617572610101ba71303b6313ffc193e07bd26aeed8754fd02e86d3fd314074dcb2393a2eae08d32f5ec38737493bbcb09abeb020eb7eadbef00102bd3802b0545d5bca7e6a8d01000000000000000000010000002c00ea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc5299687f044d87495f20844ff334fe3ff1fb62568167d343d8f39dba5673d75452c06e9023c1bee939fc42a875b2921ecda1e413a5bad4b53bfa7aa314ba9aaf7f66d272cfe563500c93f096e27f359c7834c3b56180169d6055dc7d002bbee58e5b300004a6bf77091facd6381ad90cc2dc3ddab148eede30441cf6767ba2b3ce03b8401a52fdaa208066175726120f4635e080000000005617572610101960963f3ebff0b6b57bf99454febef94f04726a2c94abd401c5d3b568ec3cc384b10dd3dd7d96d456df0b8ed5cc6bacab809e163f85ec0b96529a9f3fa28f5870200000001000000000001000000000007559ff8970d26023b00020000", + }, + { + name: "system.eventCount", + key: "0x26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850", + value: "0x05000000", + }, + { + name: "hrmp.hrmpIngressChannelsIndex[paraId=1000]", + key: "0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948b6ff6f7d467b87a9e8030000", + value: "0x08d007000049080000", + }, + { + name: "hrmp.hrmpIngressChannelsIndex[paraId=1000]", + key: "0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948b6ff6f7d467b87a9e8030000", + value: "0x08d007000049080000", + }, + { + name: "hrmp.hrmpIngressChannelsIndex[paraId=1000]", + key: "0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948b6ff6f7d467b87a9e8030000", + value: "0x08d007000049080000", + }, } tt := trie.NewEmptyTrie() From 3201ef5c3c7eabc872a03de06b8968e0d30bddcf Mon Sep 17 00:00:00 2001 From: kanishka Date: Mon, 29 May 2023 12:18:25 +0530 Subject: [PATCH 55/65] add latest runtime --- lib/runtime/constants.go | 6 ++++ lib/runtime/test_helpers.go | 3 ++ lib/runtime/wasmer/exports.go | 1 - lib/runtime/wasmer/exports_test.go | 49 +++++++++++++++++++----------- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/lib/runtime/constants.go b/lib/runtime/constants.go index d123b4bc1d..2f6c21988a 100644 --- a/lib/runtime/constants.go +++ b/lib/runtime/constants.go @@ -21,6 +21,12 @@ const ( WESTEND_RUNTIME_V0929_FP = "westend_runtime-v929.compact.wasm" WESTEND_RUNTIME_V0929_URL = "https://github.com/paritytech/polkadot/releases/download/v0.9." + "29/westend_runtime-v9290.compact.compressed.wasm?raw=true" + + // v0.9.42 westend + WESTEND_RUNTIME_v0942 = "westend_runtime-v942" + WESTEND_RUNTIME_V0942_FP = "westend_runtime-v942.compact.wasm" + WESTEND_RUNTIME_V0942_URL = "https://github.com/paritytech/polkadot/releases/download/v0.9." + + "42/westend_runtime-v9420.compact.compressed.wasm?raw=true" ) const ( diff --git a/lib/runtime/test_helpers.go b/lib/runtime/test_helpers.go index 45b17c3e8a..6ff738a583 100644 --- a/lib/runtime/test_helpers.go +++ b/lib/runtime/test_helpers.go @@ -81,6 +81,9 @@ func GetRuntime(ctx context.Context, runtime string) ( case WESTEND_RUNTIME_v0929: runtimeFilename = WESTEND_RUNTIME_V0929_FP url = WESTEND_RUNTIME_V0929_URL + case WESTEND_RUNTIME_v0942: + runtimeFilename = WESTEND_RUNTIME_V0942_FP + url = WESTEND_RUNTIME_V0942_URL default: return "", fmt.Errorf("%w: %s", ErrRuntimeUnknown, runtime) } diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 8d57967164..78b1df8816 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -6,7 +6,6 @@ package wasmer import ( "bytes" "fmt" - "github.com/ChainSafe/gossamer/lib/parachain" "github.com/ChainSafe/gossamer/dot/types" diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index fe73349dac..ed883205f0 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -1165,7 +1165,7 @@ func TestInstance_ParachainHostValidators(t *testing.T) { t.Parallel() tt := getParachainHostTrie(t) - rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0942, tt) response, err := rt.ParachainHostValidators() require.NoError(t, err) @@ -1198,7 +1198,7 @@ func TestInstance_ParachainHostValidatorGroups(t *testing.T) { t.Parallel() tt := getParachainHostTrie(t) - rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0942, tt) response, err := rt.ParachainHostValidatorGroups() require.NoError(t, err) @@ -1225,7 +1225,7 @@ func TestInstance_ParachainHostAvailabilityCores(t *testing.T) { t.Parallel() tt := getParachainHostTrie(t) - rt := NewTestInstanceWithTrie(t, "/Users/k/chainsafe/gossamer/westend_runtime.compact.compressed.wasm", tt) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0942, tt) response, err := rt.ParachainHostAvailabilityCores() require.NoError(t, err) @@ -1247,30 +1247,46 @@ func TestInstance_ParachainHostSessionIndexForChild(t *testing.T) { require.Equal(t, expected, response) } -// TODO: assert the response -// currently it is nil func TestInstance_ParachainHostCandidatePendingAvailability(t *testing.T) { t.Parallel() tt := getParachainHostTrie(t) - rt := NewTestInstanceWithTrie(t, "/Users/k/chainsafe/gossamer/westend_runtime.compact.compressed.wasm", tt) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0942, tt) response, err := rt.ParachainHostCandidatePendingAvailability(parachain.ParaID(1000)) require.NoError(t, err) - fmt.Println(response) + expected := ¶chain.CommittedCandidateReceipt{ + Descriptor: parachain.CandidateDescriptor{ + ParaID: 1000, + RelayParent: mustHexTo32BArray(t, "0xb5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083"), + Collator: mustHexTo32BArray(t, "0x1aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251"), + PersistedValidationDataHash: mustHexTo32BArray(t, "0xa2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd5"), + PovHash: mustHexTo32BArray(t, "0x20d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293"), + ErasureRoot: mustHexTo32BArray(t, "0xd91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b"), + Signature: mustHexTo64BArray(t, "0x68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084"), + ParaHead: mustHexTo32BArray(t, "0xd94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211"), + ValidationCodeHash: mustHexTo32BArray(t, "0xcafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b5145337"), + }, + Commitments: parachain.CandidateCommitments{ + UpwardMessages: nil, + HorizontalMessages: nil, + NewValidationCode: nil, + HeadData: common.MustHexToBytes("0xd91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e"), + ProcessedDownwardMessages: 0, + HrmpWatermark: 15946389, + }, + } - //expected := []parachain.Availability{} - //require.Equal(t, expected, response) + require.Equal(t, expected, response) } -// This test needs to be run with the latest westend runtime or we need to get the -// data from an earlier block +// TODO: assert the response func TestInstance_ParachainHostCandidateEvents(t *testing.T) { t.Parallel() tt := getParachainHostTrie(t) - rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0942, tt) response, err := rt.ParachainHostCandidateEvents() require.NoError(t, err) @@ -1279,13 +1295,12 @@ func TestInstance_ParachainHostCandidateEvents(t *testing.T) { } // TODO: assert the response -// blocked by https://github.com/ChainSafe/gossamer/issues/3268 and -// https://github.com/ChainSafe/gossamer/issues/3248 +// blocked by https://github.com/ChainSafe/gossamer/issues/3248 func TestInstance_ParachainHostSessionInfo(t *testing.T) { t.Parallel() tt := getParachainHostTrie(t) - rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0942, tt) response, err := rt.ParachainHostSessionInfo(parachain.SessionIndex(27379)) require.NoError(t, err) @@ -1386,12 +1401,12 @@ func getParachainHostTrie(t *testing.T) *trie.Trie { value: "0x08d007000049080000", }, { - name: "hrmp.hrmpIngressChannelsIndex[paraId=1000]", + name: "hrmp.hrmpIngressChannelsIndex[paraId=1001]", key: "0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948b6ff6f7d467b87a9e8030000", value: "0x08d007000049080000", }, { - name: "hrmp.hrmpIngressChannelsIndex[paraId=1000]", + name: "hrmp.hrmpIngressChannelsIndex[paraId=1002]", key: "0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948b6ff6f7d467b87a9e8030000", value: "0x08d007000049080000", }, From be3912c6682647647cb332677b3614ef0d228e82 Mon Sep 17 00:00:00 2001 From: kanishka Date: Tue, 30 May 2023 14:55:18 +0530 Subject: [PATCH 56/65] update tests --- lib/parachain/types.go | 4 +- lib/parachain/types_test.go | 179 ++++++++++++++++++++++------- lib/runtime/wasmer/exports.go | 7 +- lib/runtime/wasmer/exports_test.go | 166 +++++++++++++++++++++----- 4 files changed, 281 insertions(+), 75 deletions(-) diff --git a/lib/parachain/types.go b/lib/parachain/types.go index ca76d5006a..3c3fb75f3c 100644 --- a/lib/parachain/types.go +++ b/lib/parachain/types.go @@ -104,7 +104,7 @@ type OccupiedCore struct { // A bitfield with 1 bit for each validator in the set. `1` bits mean that the corresponding // validators has attested to availability on-chain. A 2/3+ majority of `1` bits means that // this will be available. - Availability []byte `scale:"5"` + Availability scale.BitVec `scale:"5"` // The group assigned to distribute availability pieces of this candidate. GroupResponsible GroupIndex `scale:"6"` // The hash of the candidate occupying the core. @@ -261,7 +261,7 @@ type SessionInfo struct { // Validators in shuffled ordering - these are the validator groups as produced // by the `Scheduler` module for the session and are typically referred to by // `GroupIndex`. - ValidatorGroups []types.ValidatorIndex `scale:"7"` + ValidatorGroups [][]types.ValidatorIndex `scale:"7"` // The number of availability cores used by the protocol during this session. NCores uint32 `scale:"8"` // The zeroth delay tranche width. diff --git a/lib/parachain/types_test.go b/lib/parachain/types_test.go index 9dfab8f4e9..f73e3c02c3 100644 --- a/lib/parachain/types_test.go +++ b/lib/parachain/types_test.go @@ -20,7 +20,7 @@ func Test_Validators(t *testing.T) { t.Parallel() // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_validators` - resultHex := "0x444c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e368589360e101de266b8f5f05431dcaf63ecd936988cc348a271f42519bef19df1e9af7f4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57ecee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237ac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a" //nolint:all + resultHex := "0x44a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe7274c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c51194ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050eac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547cee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936" //nolint:all resultBytes, err := common.HexToBytes(resultHex) require.NoError(t, err) @@ -28,30 +28,24 @@ func Test_Validators(t *testing.T) { err = scale.Unmarshal(resultBytes, &validatorIDs) require.NoError(t, err) - validators := [][]byte{ - []byte("5Do5qUFfEp5CcAfdcYSj3ZyPzQcbgtTMYZozyD4VCMF4gzDb"), - []byte("5CP9KEeF9V3eyTWEStEKQyi6grLsUgEZRqHVcTTm5PbL5CWF"), - []byte("5DqujH7PVLVLE7czPhx1gNohVCPUQ5TfhqJ8wKLcZH3zjKd1"), - []byte("5Fjd1oQRcLBfEjCVyqhDK2WTEhZ5srNU3LCVB8f52PLytLs8"), - []byte("5FRz16eLxHdvCtPfZXpNW5Cn1k61tKTLVrNH36jmAeurMtzp"), - []byte("5ExvT1sWmnt2DL5KJp7QnKXsMmx2AH5YMWmGvdkrGq2ycLHd"), - []byte("5GjySVgQVLKiA3UG3bJrUHb2Q9PNvFuSBXpUb9vo5arg4jw8"), - []byte("5Fxu9xhgqcxTtTQL1HJcLqQpYhj6B4a1Usn1LtYkc7qGry7K"), - []byte("5G1BUGa4iCLLQGgypZeeUThiLk2S9Y1Yy7ddpNhPLrgYf6kj"), - []byte("5HGRWRdLehaFbJ3zczdfgHhubCygs1bME8yLc4MWidqDwPkj"), - []byte("5HBuwTWAzV1LEReH8ohsWRUeCx5ykb3CkCa2GNJKHozQ3hcK"), - []byte("5Gj5kpJCbX5oQXRTv6insZeMtMCEptqJ2A5vB5gHsdBgwYJp"), - []byte("5Fhe8H4XeYdvV31FVfxKAivKcDw9g5EMnm7oWCunnFfrxEip"), - []byte("5CFPSw1J5S9eNyUoh1oceF3inj1zPsV8csiBzR63WZrrf6sq"), - []byte("5GBV6ye2TkgNTn9ctjVx4dfxfRQYV1pcPwxrR9ARTTya7Bwc"), - []byte("5DLNXbTdnVqoHK2rhskA27e9qxVQvk1GeY1rwxn5kzBf757w"), - []byte("5EyBuSrUhLx5prt47u7R4djuhAaenABPTNVruDcVEK7K574Y"), - } - var expected []types.ValidatorID - for _, v := range validators { - var validatorID types.ValidatorID - copy(validatorID[:], v) - expected = append(expected, validatorID) + expected := []types.ValidatorID{ + types.ValidatorID(mustHexTo32BArray(t, "0xa262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d")), + types.ValidatorID(mustHexTo32BArray(t, "0x804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e")), + types.ValidatorID(mustHexTo32BArray(t, "0x4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72")), + types.ValidatorID(mustHexTo32BArray(t, "0x74c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68")), + types.ValidatorID(mustHexTo32BArray(t, "0xe61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511")), + types.ValidatorID(mustHexTo32BArray(t, "0x94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e")), + types.ValidatorID(mustHexTo32BArray(t, "0xac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841")), + types.ValidatorID(mustHexTo32BArray(t, "0xb61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12")), + types.ValidatorID(mustHexTo32BArray(t, "0x382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c")), + types.ValidatorID(mustHexTo32BArray(t, "0x0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547")), + types.ValidatorID(mustHexTo32BArray(t, "0xcee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237")), + types.ValidatorID(mustHexTo32BArray(t, "0xe2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53")), + types.ValidatorID(mustHexTo32BArray(t, "0xce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016")), + types.ValidatorID(mustHexTo32BArray(t, "0xae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848")), + types.ValidatorID(mustHexTo32BArray(t, "0xa0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a")), + types.ValidatorID(mustHexTo32BArray(t, "0x807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a")), + types.ValidatorID(mustHexTo32BArray(t, "0x4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936")), } require.Equal(t, expected, validatorIDs) @@ -92,13 +86,12 @@ func Test_ValidatorGroup(t *testing.T) { require.Equal(t, result, common.BytesToHex(encoded)) } -// Test_AvailabilityCoresScheduled tests the CoreState VDT with ScheduledCore encoding and decoding. -// TODO: fix this test -func Test_AvailabilityCoresScheduled(t *testing.T) { +// Test_AvailabilityCores tests the CoreState VDT encoding and decoding. +func Test_AvailabilityCores(t *testing.T) { t.Parallel() // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_AvailabilityCores` - result := "0x0c010100000000000064000000c800000000000100000002020202020202020202020202020202020202020202020202020202020202020100000000000000000000000000000000000000000000000000000000000000000000001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000903db64205805df4bc1710e1422bf3c8a308c2d87249247411332fe185121f3e143241ebe71b25a371b4c580ba5a04621229fe7837c1f1fa088f49bcad5967800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002" + result := "0x0c0001e8030000009652f3009c52f30001e803000000440000000200000058b29da15fc66c19ef0ad4e66e95c8e42718d2455001ec6876f4173489a705fbe8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b51453370001e9030000009652f3009c52f30001e90300000044000000000000000571a387d344bef8a77d3a99895958644dee97345861f7747b1cb8186a14089ee9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e670001ea030000009652f3009c52f30001ea0300000044000000010000009b716202cd9fabb93b278a41d9344faecb1300241d255d1de0675a42ebff6b6eea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc52996" //nolint:all resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -116,7 +109,8 @@ func Test_AvailabilityCoresScheduled(t *testing.T) { func TestSessionIndex(t *testing.T) { t.Parallel() - // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_session_index_for_child` + // The result hex is taken from the response of a westend node for the runtime method + // `ParachainHost_session_index_for_child` result := "0x0f690000" resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -136,7 +130,8 @@ func TestSessionIndex(t *testing.T) { func TestCommittedCandidateReceipt(t *testing.T) { t.Parallel() - // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_candidate_pending_availability` + // The result hex is taken from the response of a westend node for the runtime method + // `ParachainHost_candidate_pending_availability` result := "0x01e9030000328b2b271db466af1870b5918aa43aec671de9803aeadf75013d3c78de35ceea84b5c6e57a116cba4148aaad37fbfc3edc54e7728b5192a40391d9c8ef33bc40e0a84b429996989d65526edda87a56b79f51b98cbeb347ce22a356cc7da02e38ab0e77029716d6a3e8b45e3ac27c623c347f28d433926a7f762cf0018484f58e505b19ef3223929a5ac8e2f17e5add18665a164f002b806899329b25c8da3be76c5664eb273bc0dbc3016d1304e53fc86b20d4d3583c4b72599ffe4386aa7060c9e6f1ad9699ddcc8f2bbe324c882cba6307b47e991cff013ffc307cc7d3e4831efb8e925358db3e93e466f6238871a8a29a6028279db855f0eed3fe4d7705f2dcc6cda49b51efbe0fd184b974074d1258ca9f15b9fccfedc35b7dee6e1ab9e9000000e902bc8e637ddab3bc69db43a62181e9a5807647ae518b205161b1beb25cc72bb441a6dc4600cd7190aaa808a47ac7c2cce73922a0cdde3fc639969c76d5ab44566e25e5fee50cc06625cdc46c76bd0bf8c046308022fe7b2cfd31859fcab2c7d84a2b208b1b080661757261206f495c0800000000056175726101012cd5b2805efcf8f0d7a35e05a9b3582df5af3cab0c912af9a56e83a10a42ef56b4feea6347c7c862c71ad66e0a6296cb6e46cdf10baf65dc89315f2768fd4f8100000000a18fea00" //nolint:all resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -153,31 +148,128 @@ func TestCommittedCandidateReceipt(t *testing.T) { } // TestSessionInfo tests the SessionInfo encoding and decoding. -// TODO: fix the test func TestSessionInfo(t *testing.T) { t.Parallel() // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_session_info` - result := "0x01210350000000fe0000008000000096000000d200000000000000b0000000bf00000021010000ab000000970000008500000051000000c40000000800000028010000a700000032000000e200000016010000bc000000f9000000780000000c00000088000000f2000000ad000000260000009400000046000000120100004d0000002300000009010000cb00000082000000750000000e0000008f0000002f000000f8000000100100003d000000a000000006000000c90000000f0000000501000065000000540000003f00000098000000d600000047000000b7000000df000000380000004400000007000000b9000000e70000008c000000900000000a0100000b0000001901000042000000af000000020000007c0000007a000000240100004c000000010000004f00000063000000f0000000c7000000e60000006100000025010000d70000009c0000008d000000e30000001800000019000000030000006a00000003010000ec000000fc00000008010000ff00000058000000b10000006c00000043000000290000005f000000fb000000a1000000c20000002a000000be000000c3000000600000003c0000001e0000004a0000005e000000200100003e000000c800000093000000ed00000073000000040100004500000009000000d50000009200000076000000110000003300000055000000a6000000fa000000d40000002000000086000000aa000000560000007b000000a500000015010000bd000000b30000000a0000006f0000005d00000005000000180100001c0100001300000069000000e500000028000000a3000000d30000000b0100001500000079000000b500000068000000350000000d00000031000000e80000005b000000260100001200000011010000db0000001b000000d100000059000000070100003000000016000000870000002c000000240000000001000070000000360000007d000000480000009e0000008a000000270100004000000057000000cf00000067000000fd000000f5000000060100001d0100009d000000cc000000130100002d0000007f0000001e010000b200000021000000e900000025000000ac000000ea24d73b1607c8fd7d6542870c2563c7891a9085b74ddd253d4322a9b3d3d1560600000021034a3487dc0c46f976d352e5e152e120d2d23774f921583d1f2c128f7cf9f66529d49f031c94d9c3b33494849eb9682c0311b3c283b17373f18b9ca02d94e2c05c969ae5d9d6efa40c6255ec4b27b0a4752d7f4068163116e76cd0d4041c471431e8c13e37a4d00135dbe7699d91507f5a53a7b8ed36a3be29cb2fddab9f7a286c347964127e9d8bcd119989a92646c80886c2eb8440c87dd7dd94437873a3ce286432533fdbdd1a739c62733cb36ac48c821dcb0311978f1027bc1e39d4c8964e6a6570b80ba0a90a857ef4ebdabfbf958898bdb12ea1edbb17eb903b00746a14e059357312bfd525317b4f93e5eee1de639872edfaec9d2a320a6fac04d6105188fe28737bdbfec193327886b5c4906675d2a49ed43fe8cfb4e079698de82d2d042cd5a9d8624860310a963ed20c4192a19a9d163bcf366e48122c00a1e9744c5cac0ffa042ee550a3bf70d380dc032d11eabe311e0796c5143341600ef626644eed0663b1d15bcbf9e99c372c041ef118de7d179c68899a645a0fa0983b473eb2a1fefc7a956231a446a575db2e31f7c084c2945094f3927519617d7b913712c60cc4d544536a7190ec68525a70fde1309723986ab984a1e97aca4092ad721c744c3b91b676828a5f884e79d9c02d6f23ec246c3a1a8adcfa9dc1e531a9a5310e2d777330aba66c9558434a592fa5e5aec49c3a70f49f66017f194d41240d66148f2b835556a0c8d3b51ae0e823655bd4aa20fdadc6b4189de9f32cf2288700d8eff37aca87eea6637118337fb1704bc33f1fc685aec019c8e9eec48b62a728a8cb454f4e75ed6d28c458cd8df1c2bdce6101e09b650fe22d139e360fb809200ed18130a0ed0513b2a2bfa7ed6c9090cb350983746b1936c6a92f7304a7005450b1f33df75af8dfeca1cd7e94fcce445c6d55651259fdca2972a4d62f6732561af7dc55da09babaf097d1304b4cde14562506f4db4897644895324b542d8f573c39b3f67c487c1df902d0397792b7cdf987b657b2d27920bc6846eca466c155c4b778017656b9a7d69d3e69159852f38adf971f5a25df65f9950e97411c1c36e8bb9f2665b217df30a15bcd22f231f66f4f21711363cb0b0da8b3594003ae014e8c22d93dbca83c05bc5222ae72b85617956f04eded477369ec95312c7c78353256f3f643ebc6300f32561a0a5583813bb3b42844d1ad3d3779a438771a295e306daa91a5a25590d2290fd262d40f239f87d37e1c03a2494035a42961db2f33407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71482cdc214f825dc7085e54a984230a753d66d08425f9763f52f8f68911120260d4d65053a5ef2ab1152c72f3b15d4f24d4bced3b7e277735eb49450dd867c115263ad657e55682de826f6137dedd2d246971fd8c5d318034940160fc179efa63701058e68510bdf68a3678d32145780e13c29b88fe77b27440bdf3ea9762a63964675cc62a59886ce5fc12d2f48694c7ac836a0157e0e6630d694d11faa605034c51def135330ddca851fcb670c865235dc1b405242cf9f7ccb728e449e09f4ad614110699b5642a4b726cbcb74bee77642ec7b4f17b06db88ee461848ead17c906f769166b3ff9b0fb13c1ccb36358d9dda3f25bfa18e2857fe01a92328eb70cacb5514b570b9338c8602cd4a49128006a902494029c2728056b02a900dcc7798b499a9c38970f6f3dbee7e6220ee0e12a582a76ae036347816baa6cd7c9a7b9662caa1a29ff92ad66794001cfaaebbdf4071f4db6d74ee767ba59cca4cb36cac6854840b7eb103ce5723aa0d6625709d4c4378c46903ff236d9d8d61f21f76b22d6245ef2ea126366dae7f9c072d2d6e0e71a54c9bbafaed36448a4a552b51f02a182d14b38906ce1f4693cd9b87d0369e6af514cf7ec91455b26cd4c0d71bc2d3f9f9f499e04d2f27dbe47ffbce115afd1bac9fe116ce7fae719325e4082460c09defe1f43c8591655101dd3dc806c7b07762c97ad21e4142705e46a1e17306b888519767218eed7b884fb221f597a2d4edb69c094961ace2e65a7e40913c0658f8f3a64ec6949a26916ae2cd976fe531947a9c9e93e6d587bac746cb0826e4b23b64b0eaea19cab0333369b93e11693d2b4334306ee579360814adfc1339524dad3d2adfad0b2db5fc2de781a22fc63dbc4e30a5fcba2c63c2fcbda238668e06587bec427bd5b5cc33da6f7cabaebcb7688de50b59125434493fadcaa94d1e0560d2b374b7d6e1380b6b88ee8ef92cdde7edbd9a48d66f5e219840a1155818b9272f50007b87be88422e3da9599286087f5e578c0d1c2a3db9a77110f9173a69e0e58185dd4e76aa52804b2de15ebff8c3f3237e29dc7157e61b30b9b00a30f93bce6916b6b78ce4f7d550c39c7947c6860502333717d541fdb6697ab447aadd01c0f366ff1c65d331da120ca3ac630ea6e8d7339e7317518920d710e3325edbe8dcd591d30511a0fc08bc5172ff58ff98fa848387b25f99205361348105f6c138e9e4061b3a799bf7987ef5c820c1e534df298f3328e1093c5d0758d434280f6162242be89d139d52f449e2bad667d7d974cb80d0edbce7237185b11475fcd9b0171f73154a0734c1cc95ae552d9f3180d7d64e8b50d3837b14b5afd2221808dfb6c44ce63a08d4567cef4b2a9aff1b408d2c99fa4adef25724cce85368b429d0687fef75f26e5503379a61920777ef1f254af024922e382dd19e752e69784ff2911acf10ffcf4b1d795df6d8b55f38eceeadffe577cf5bc0360f35005940c73278b76425a158be63207452b1a8018f53309f47486a273b9bf60cb51c48d67770af6f19ab75537f06388373ec17a3c88ff1714806c0c99ad44e6dbdfa713ea7825552b7f76db8f2ba2fce0e546d7e7abab7d59e7afee2bfe438bad6091934cc7903dcaaeddb2bd99fd6b36ab15fc32ee001bd1d95e87020019f7c88be2e74afd1a3a66e44e8b7845e7f63923b706dae49eb96cdc73b04c9e6cfd1459d06d6f02e6854e6df29f08f7e015d511ff48d7bbb13bacc9aab1b06ab73c1f3350ce6a864e68dc99758ce2920256f75bdbe8c918c556a5a2467a3aa13a306808740484d1bff4961f87c7ff6a6a68beac9264665f87ba1a5fab9802f1cd729391a718a7477bdafa88e49f5c8cd88fbcbc1724d8e227935eabce71ec303d832c4ab27aafd3f8056d3462eda0083ac22241db692c4671249a14a04c2f0a2959aab412660bb493e536e83addf98be8cb2a0158cf18c6d5ba06ab586a2cb56cf1ad4cd099ef1e3e727f41ebeb3aea2815f004002d27714db121fd6f92fac8bedbb97160976c4d221bfc6da82c7055e469a1405eca842b4b8efd101e984a2482e526ecb085229a5a3f09f444f6d39d71e0b936cfed125e87883db8876444288d0cbd17642ce97b61a3cb7d20f9048830a34520de889098b4435dfc79a73a0518ba9f61924de365e70f8503654e384a4524c1c16900873792541ef023019a68f62250b7c219a149b9b68af793ab31f83f500126e0fffa71469e78e22e754f3b49db1dbe631f286ac449dbc94282864e76dac48fb9bce48124189d2d45e2b2e16b8084c022bcc90ef1acebf194c7b9820968e554e2ec4d34346eedf80cacdafcdbf118a3f158e45e6a8766869e2e5418499d3cfbe215762a4a0cffe4315edea5ef47c60c163be4aa5196c5241f5c772f3f90c57a3580fa0735a7340e37372048c1f60a20531f830d60634a177f3974d5399fca046417a6e4327c4c569d8f4f5b47b263b0f07408b1d453ae31f699e53904605cfdbaa72639138cea3e544258e0484a532216372ca569751b32be145716eac8ee5e731a1db2b1dae4b9023b05876077cdd78084c79e58d16ecbaecee3965ad4685c1780154b678bbfcf725fb2e91be3cc0864ba0f682ce1460eff27c8518451b3a9ec811e18b8839808256e18a89219fda2772c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416da5bd7647f8d8388c2b4dbc138e36b8679284eadc49370ce0a16a4e0be28804b04f9b593ec5987c0608e3913acb29a322355a554e010d33acf155e6ab9bad337c4bc688653010a7720d44168b4552bf75974219788ac1cf3fb440c67ff692d499e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd93257121806eb5dcaff87a28d25de336e240731a375be04c4bbff6be6a5ba4f1042a067086008bd1c894c74e4ab0b16dd36effafc8f04a4617aefa7f68b40df033149c0a98bd89778f1276a0ee404b17d81b96c524a8aeda9f671be9e724f090c397977714f425d45bda5f3373c374e9b2710f477e2e923a0f0b2b259c941965f6e88c0334fe5947d75ed7ce18612988df5f227b149c66f371593a8c248206f1b59e10248e650f7e08ac882d65fb09141fc5c7d252da9b1d8ca2ae311752ddce977137229ab3993dc198b5cfee52c273f6145c25afaaa6de14670eccdc1b61fd53821513fa519134b630c1d53b78cbb67e8b8414c30247101be5de118662237b8388cc7d3c50b2fab9b87f1a6228df23e9507c90bec51b8e3be978b526c0e0c7704c7334dc8495596755b6b5a83796315f9e316bb871c0465cac91290b34812c5f0e34120ce455c4566893481e7afa89c0c425533fb4eecab574f0399ca29b162a4c78053405a94626a6d3cecc0492a268e974e9864826f8745403fbb98f55bf45c0b620da0f2b6e2eb2808b3e713d1a3f774966e3e00f81226887d5e1c165af998d6e57645c3b5a2e17df20f698507190332c6951d761c5f46e0dcf997c7337c0bb7e54e232d9f4c8884a9f53a999e8ce7a27f68e9108a4fde15bc51a350774c22b2a1480fc5fd10948cd231f68ec00397e22a19042578431aad63546679e72efa3cc619c9564390d54bd989ac1fb089a57964ee4313f857411373d34161939633c8f4230930357b8b54ce94dfac3276daca91ccbab9b944bdd9754fb27d2b786427b30b6d3a029d0c998a49c406fb0778936c3bbd0708774bbf21b400aa8a41e604401c8e5f3c9fe54712dfa93b8f223c4bf30e2d037a36a768f160cf0c6e6a8c42a45908fdba40941f018589894c721ae6eddb3ad080bfca4aae349a8e7ae261f0a0f18d3fcd225254bfac8ee7f94e5f505496773b69c49697eb79ef8523530c55511106827b00917fd22c6b8e62eda5e130344c9214f2565b92ddcd6b6edfa18e95f8afa23b3c8f159391a3ffb6dda5ce3c9f6b40f25c1dc7a742186b7b693f30111e4b9ad468b9d1e0cf4f79c5078c9cc4e409f8a0fb170d7c4f421ed5fcf597e3f061f1060d5207533b44b4977f128acd44bfe1bfe235f2f4b2d042a87c7da4d1d526a096e110f710d48d0a0bb58b06ceb1d6ba2189ac3dc984dc24e80fb6522431e282ef8862f121223f6aa19fc1f929106d7a916747f21e1973eec1e8c5b7f78cc3ceec15a5af2b64d5a43ae54fcccd31ddabe95461fdcb5be506267404ba432e41161e6df14443df6eadfb3c5ad5228291d1383cdaaef20c9cc8125f7952f249a0de7093e895f4c599aeb4b0310673b00785b33fb9cacd556acc9abdc3de57fc056df4318d12a052ab505db7d06dfe03767eb5f46cf0d271393db1db2516c52aca4be351c39cc0bd557e7afe547a479f8a7218cad2c784e197f3494dbb9436292833db878c0dab763cdeac36e752c7cda12c98686c05704a8b2a695a315bb1146b3d1cb07cfb8d2e13fa9158734dc2bd1ea554fd3032bdbf9e9871d2937060236da4573a6c20044052b270916290b13a30adf3a821b467c4038a14026badd09126d6621e31b47269829a47f9be24a0d63c4bd7ae112b395498ec2502c3b4f46547b4c766e40db6b1685c455de210347c5757ebb7d463d1910eb70fb290b5c7bc63163ac00341573dfc794b0d53e6bab40a84e60ffb1dc3f6642aa1a246ee579703579df75d2c2dd3d53003f55ebbefeb59446d476d0a722ef8ed1954fae9d6ddc2f1b5a31a3e46efe8097d83d7f80ec284bc72a48b7916a74a1cad145eed554722609bff1c0970e439f19fff06a080a67677712b09762b90a82fd9f97bbc50c12b2408a440f2c91824179203d689db4245fa3087e8b01a9316ba973c6ed1a7556aee499b2dffa90a79b118a646aec6b79e6766dc25665db73a98e173fa6381ae47c9de57628b53ed9958a889d278fe707b4284327bc582599019bfc4630616b78f186de80c5d2d0669404118ff1591ff141a606e05e2835889a5f42a32e9a1f34d4c6438f429028ba64818bedeff64b1db1ebdd89f2c2b2fe3336942a03036b9e86a336aeeee1b94c5d5a821e4ab4c136cbf2766a43dd37078e02927ca8a562d2ebb6671ff854613aa3ad169250e037aadbf0ea14c87982d7382f09c7b8c96770d2ffd3b72525806a645e5abd09a51d257c30dcf016435c114d26d3d3be170800af2466b5e4a434ad5ef602a77f311fa22300a5a6ebf03bdcc04f92fdf0da3c74f0c1461d8bef6e668a2cd0c95fdfc9ef30cf9133619aeb9c3d5187f23bd83c765478a56c4b3708da965c36dac2e8caca9398d50bff836219540b179bae7667aa091181db267cc8ff6c5201acaad6fc2c3a2cd18eb729ad0c1526c6c348e330ce5d949162cbc728667ecce548da5efe0448823e928463418342d41883dc6e20d8e45f1d6d02c43c3e38d6e7871f18ee80f60415adc76fdf4c8ad2c67ac7d11682942ab79f74656a8f51ab8c1b088f33ddfa20992eaaae491dc3dfff9742fe32c4428233d691dfb69a1713087e4fbfef8f7c96df760e85354069eef1ddbaa01d52f9664fbed82ddb5cd6ceec78143f1e27ee7a0fa73873d01e80e368825e3b05bef7cb0005833a9d0ae360c420a66a5353836acf1fa3c65578c9c5b3b9c7831e944ae887694e9fc6a8634f213d8d061cc2a34a00f214d9f67cd17effc527a07e060bea20b143a7bf515a130000f93cba10536a1204f0a14cdba7b627412d383c308672a7e2974b837e4a89d54e63c47966b36fcfa3efa5854046d3ce09d45f226c36aa9c0762a59eada83c70e1049d5d09f7f7304c465f2ff56dbe21687ece20ae9fcd9ab8a7020a1f967780a1ef49b13b40fc3cfd208e29f4d5d5ee9bb63c5fc81fafe5d47c4ee373a54a64d267c497c59f4c15077374317b91566d44c82f74167e6d847ad207f3a1221ce1f958946317e77ba146d16aa7bd82810c5e913c4da0bc5d3a5923a156f0990c79f01317a3140ef3aff708acfdcd30a838706db819dc3a5a9fa2b1bed2a4a48fb21792b44c5772f888132d414d13a98bb5bbbbd70ac42afa68950568131a449e70574ae0f45f28b87210c1ff7df1adee5576d03950b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d9a53c2f9f5f55bd687e359ef37196cd288fcd1a14adf6cad53c6704445a1f1212270467b0c03fcfd8bac09473161c6eba9c25369a853193b472eb2f113a3d333181e6b71b981059fa265cd76422e52fe175db6983c6ebdd0fea1a3075166b9291619ab90bff00f89ea8055f0d7d45f8c8aa9c04b7fc1d06468837c6c563a6529ba846878e4f157741703bb4c3ab4f3ff2e9b99916624a9965a4256d893c84e152c19794d20de22edc9c4c1514f4f4e29ac16e6b421d3620ec6545f737100f0134c29c11128e193f06c866e165662d903d9f799508e617920d786ebf75acd267462237ad2bb39f6a5a03a46c5a1dfdd3766a49e6c864ac5d45afa6400ce3a9809de464459b18deeea6f02d5882e80a8696b00c9f703da84bc5769921053ecc749b0cfe1745dd408f6dfa0ceaa1780ad4ae1747a8912a589a754ed86373a08ff5540a471d9a8272b09df08db1f998000cccef325d072ad79df6c1936cf0ccdeb77a0d9c323ea08a0551f96c28b05ac0c7b0e338cc5004bac22d06feea5a8f5c00104906813ee195100f82600e56bb5756831a260e4cf6e5ad275364130dbafba4ed4f9db6adcdce67708905276a01347cc1c800bf6ba246c3770a81c3c754fd65bee13fa85260215c5235169fea113546e7b4aa7a1c936c47a14e81d3df912601a2eb8ece17888100536bf7183c579eab3e6daa14e5e01602a2fc3a64b563f591f0828f0bfffc49973cd14329675728a2d243102ab486601f1581b1e741bb5c77526552839c17a5dbf3b2f90875abc9959553b320da9f07f1392fa3065315a8b1744a7e5b271f9394d6e23bdab9ae03491f51bbf21014364d919388b7fba4b5341bc4b759fa4234adb292ab984f7b69d3aac2e0afdc7dc075e18ad22f4456dfa48b0acf62c24bb58eeb0a71365ba5f890a594cc046a483d9b306a487ea4eb5e80572d3ac8b4dbb4b6a02692af692160b113da09d4ae9f0464c5522b7236a59b70d3667fd3b0c5fdf2c30cccdd640a7297da408b6aff82ee9651f889910fda9f24c706a617b082d626dfc74a657c5d17c5a763044f0230972fbe47c907a5a8fb75df4afa9726d496332a25823148258bf60b189ac898c92b9be15965a199a45ad563efc761392b915b58613f9fb99f45c9a78fdaa4358874f739cee7ebf2a5cbc2fbee73e2731e18f347de520f1878f0eab3a38f377a9263ad17333135c991d560da02f9a012221d644717e2f1361ddfd9e6b5d0043f3a47eeffab15e43d7d45e1f6e07945d95fb46ef5346bb3a502da9f005d1cdc956e1b96258fba48dc793f50b7eeab48cb88c51118ced6c65368c5197ec7f014c443b47d898627cdb7781351442c44398d0ea4ca4b697ffd505665531e7d4b4406431f2328943e8b72d030842128714ed41e3d13b8aad0d076b7ad34af4946866f552568eadd3d3582b4c4f50d816c065e65b3583c8309e3465db95b458d0b42619e1ea75ca546e966d761c53645771381f31a42a1e0bca62f752fb49e8d2a49f942cd48a03129a709e763d23aa4dc84c88423861d1ef31f5df99006156570aca69e571067899ddb156a2027e0acb8f278b4e156f96ecf0eb2658c6504fcd39e4e20bfb5905be7cfa05ed907aa5041e202a49166a5e267724e5bbd0d9efe57d34d8cd7a2e536cc7aee14f12726065cc08d547840066bb56916d9bb9761e05133fd18a68324492ad7b9f9caa1668038a3ae897ec528be2ca7c977eca6cfc08a00266e96fd43a723fc7226b66aaa86fb8c0ff0094b6feeb0707b5cd61797ca034755fa42aab8c5c9e245157f5425f5d9c2de89a454439ff9ddadea199ac62ed47b9326a4a08c06859dc6aa56cf5af62a035f7c6b0546f536c07cfd7a2d8e3be9ac2c7b7e854ebf59eaeda5edad7dc23e83eb30dfa3dd91753614a811769d6a564e5e2b27c43c70d7497a0834ea96e50b6edef3369e8da5f707e530fcf611301be6bab8187386d130d1f8c94e5c3602ec613f83c1ce2708d6fceff206d25c511772a85eec3fe2b4ee066681cc6c58313ac304e37b46e43a844db9b7bcda351e09ad1efc57db99dc2a7c12e553ca9a60412dd6bdedd4ded92b9647ecd2ce31eda2a6f5a4ef9df833b9b4c70ec0924a92a7067757484a42e2e39a2c58cf41f683c3646c0e993fdb61ba33306f7524ee2733c1d970403cebabf7a1af318743767411fda52e046b2fdbee1680978da2f66413a00a72c2f0fd68497472feb62d2481dfa1ae93b14895fd3773d48635738847d32c4252393c6cb8e07655646eca309a1481552ecbd9569e94a0cbb6905c45717f0097f3dac95ce491ef6f07d89dd7a409b0f13475eeef708fbb0cac0f200cd31c296fc0f38221dca15bbd3ad95092e6a4f38b8ef8e9f3b9992d57409c7833c0e2e85194adb91496335138d5815f82e01ebc93b757c1ff94620f3a87ef48ca064b8daa8790dd2fda2c3493f33b66804385212b1c3747f61ba6de535688b2ec24db2b9bb22f1c69337d131a4c91c2b70f1b45fa522eb556b7960f937e6fba63e1a5c832c850ec9d476fa68c807d36d09edf0c1eb9b2995a3812cec5092b90c4c724a2e1e42195049ba8878f1d05a2e30251a57f7f4662d4bbe42ecc98b7399c13a00c82090e61c34b4675c01815b7e25a1fd09d2fc60f60ec1f3f435096790681cd676c3554c66ecb08ee954d3de09ddaa2e3d11f5fa4f9d4c89cbdce2c3accd6f9495757f069ede7b956256595c7d083b47c610efce658762467518bdb11be9597e37db2ce13f8b1b0cc42acf317bf5a8f948dd3977725de1590421117c9ffd003a836e898f478234d26fc7d8bf866a6a308f8f7cdaab738bc98b879669911a26d87f69b187cd620e910289b9d5c2704d332359fce4040b4978eb1527e743dc15407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d7162fa40d6ad22c0bd13811d9555f4b2adb0f639cf7ace8468db36e557c1e1176e4ac7db719c3be3a8a8fb077e5aaa181f69f89547570b88ecaba644b0c8623f793abe63296589646fa4fd48c7d15548b46fe4f60435bf69fb31260205482eab0226b7a3b02d5edba566f82d3f949278d4d0660165857965f123b1ff5aa680a62c6c7b8a1064cbfd234f3e26fcd14b1eb52a0b46a47e8a8d38027bb3fa2cba947124c41b6ccc361bdd655dbd0f0a5b5e7c86fb1bf779a912921794e17746c37f40e0e4451bfef8b6e07bc00ff6fe17cdd12d45db9f816cace50b0682291a8dc257ac131413580ad09206331a67387cdfbf12cee28aab9a8b0aefc03d6d1f2fde70a8c597075eec72c0adb7c050db76ed8d86e7785f056db19e02775ea099672c7f447c7d787652ba7c318efbd758620236476ecd6df6abc2cadf3488c7e6416c12b8a2bb40ce3658b1d71c42e68495a5504986f38696e56ba0fc2df70182a5b11fea0d61d2472c21da757115c4aeb85f1ad06831b0b41779a118995340fe6c352e6cbeabce345363e57dc45931c6bf8f278f704cf252234e0e580741af38024e1536d3b2112224e3432e605d698c7809f9599544725f3bbd89e076742a2e33631e2caf02567c87ef2729ac221651de0efa7ccc8de802d0ced1036b68b51868bd3686a8ecbd7b1a217342e937037c0bebc6a026371b85698d124c09998e5a531b6cb276cf5c2ddbf28d010e2a6976cf03488c0d1d11c5c1f9b23d7ac44ed221724baa63a6245db826d277bf7bed80169db1bccdc7a3eb0ae7852317a5fb2628982aa0fff7c6916548204396e77dd2fc044e2a37c192789053627b2c81fa1c0f3d1f7482ad1abb0ef6ca6488989637ea1d44a918f062b169f1b802c9ee6d05a2fe34fe3fdf6285d91ddb739bc5c2481ed4d77589febde82e624d0af0ff9796e5993242f7de325ac001c0d50c4d27c15248ae2023cbc52e2ee969b16fbef249ee2542026074c387dc5714b8038735a05a39459797ad1f591aede76adbce55e99ed94a98b68d8ce62060e2c77262da54a918fe5942925597cad811f00d13599f0062784e528241405f8618bcc663a513318815f67de9a13e6786615542b715d6d2bb3d82580e61b8d0dc0c1652fcb6ad0fe74186d4f30f931ded5712a16e9724b9993cd0d505f36fdd6c1f2f87ae7f7b7d2a84caf41d8db3d926a728904ffc98ade114aa146708071810254fb2b5fd49243a64bc29a6cf8638150988ebd9756b917719664e74f116e47c0991afa7bc43d0b4aaf085d205ced8ea01235b224e9e2a575626a39cb65fb8a0456f4f5380b87473b2c6d3ae6c36664af57171130202317f567e7a89975b0683a31b08cabf966ecc62d48ac257c297ac4825c75e59c4271562da9a7597e0b1d1e880416c0a36fd5d9a8a1a0e277025e81af122c541ead22d78609154fd9334b34c1b724aafefb4de93d02e360bcd69f4d179b8f973f0a229525c681a841ce65fe1848e33fe6c929cfdb09181ed6f10f9b5d42b079890c93f6cb63489fe6ca5926a30f68d89fea2985c600a9114516a6c29aa1a9a390358ae11d4c2addda665d13fc93f613f8de4ae6526a7ec8bcc418d9d190bff5fb2bf8a57d4d02ae9d39b49dafea09bc363a28395b90f0c0482be2642d693c65b1dabd51d6456d129d5c987093349056b99398c6c59efe7949aa90e6480719aa04ad8816124b5eaccc793902c3f48b7529b6d116f4e7418406b6dfcabf008b65268d1b3757c713863c80e960241776adfb775052d810b59fbc83edabf4b607bd44c6a610788c1cfeb3f21e0b94d5a12f2615ed49cf7d67abf18a93af7ba649cd0ac29680d9eb19a6e461dc5fcce21ea03fdc88fe1a67bdd4b67671794d5348a1b481ad45e86635f0474f0fe3f7138dbd0c961b000d0c14707c9c3037792e2b59632bef200305908aceeb3388deb21c5ceaa4c1dae6b8ef3ef9ccfca9bc6523b609bcddd0b66f5b305293c5ce2538e4d8e773a6d51cb10adc0c50d9b9cba83e8429a2e2e1e4e1f947c0be485986af1fefb306419c6fc3cc203303517dedafea231dd90856df4af58129352adfbd4c714e33aa5cea74c6e39a097a1155bb8a0f59242addc542e1ce485f81eb5df11ba9bf4e0267aba89ad594b06066c4a7f52ca7947de90772864f98b6fd26bbf80abe1a9ecef909810ecefd129f3a73bd3296a2999b9bb455ebb74bbc3f5ea7cc6eb966a566123ce03005a73c0294531cdb87e6f4e95a515a4533e0224cd2cf5426a5cdcab8c30caba2a0a36831bce623b526cac663bf76f269e3d114a73a0229bbc06b4f53b1f5c0ca2198e418a49af03440d375ae7c76e24cc7c0c46b93aa96c8e69afd833d5c5f4ee23346e35053b1fa6044421208a5fc47074d544333068438bbce32a53bc0117d123ddb9718eb62baa88f7a7bc786758ecfa2acaff06cdc5d550de264d6d61988290e84649f3faef516f21a36b403490b980074580512dc2e7d3e2b87a063a5da17648602d66ed743cf227b0ef5a34067bba03c1df0cbc3cfea77b39ee77b49d8b425455e45a27a245c1963853bd35689e5192515b7b99cfd14d624ea54dbe5eea6c8f22b59babc3c6a3ce22286f1a628b901883b088d7b9dedc64dc86f636e337839c21edf802b526c26346ff314ac02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c24165804d109d88647def7d8362b09e103f65285c88ff5ac9329ca40a9c29dca4e073034a4c23a5fe2e1a82fe0b885d736e57a0883291961a087a2719664020a574cd8db813d1070487f577a18b9e163ed125ed818c0d13dde40503a10ed6c8d3e6a9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712132d3fdefa1807e6bf9c14050d63d2c37bf357802a7d8e813baee24cefa76b229d471496a02cc87ca65544c0ef979e7f4c1f0a7269e3eb21fea4e0d91ec4fe86ba67e4ee5cc212e44e3488e61c6c1ce07e25614b8c23cb4d0442b35e6b0d8ab3744512e70a1dd7110e04b778646d4f7b399d36712e40bd06a6907f25046639e4f9a632636d4945986ce97bc67ea13897025c220e7297598460ccd7cedb8a0c54792f097884bc8751c88ee126bd1f3682449da8181bc9cc5b90f0bd9dce1cb0d19441bd6bd7dd64756c6cb272ce5ea2a934c56dec8f3be010f8ea74cc61f20d1309a1fcf68fc3da9660e86c1189f879b8c9cb6611d57d470765dec4c3514243009923ef8cdfac92e83ce444c9a2b61fe92d6043d108129649a3c6ea306c5d9db7b924eb791afc0aacb141b54f0d75fcde46e4682e806926114b2ec7ee5a1a5626a3a524e56e2044349643bea61e7d9d3ae3dc19e660d754e6cac3fa4f24ae46d794816a0ad32ac3690b658c96cc6e09d9510a57c8e28f32220210108791a15aa0dea2e3482714178bee78fee64d0d61e6933d06f8e8dedbfa5ec5cde870dde2d7a9880b245038d021948c6700d89443c09f207b9da66d2ec05e1c567a8ae5fe5023a414b00e01850a90adb945205173ed44279aeb17ca7ebf9a239d5f6ecc9306a868b391a7c49dbde0913228107a7795db90a5e3e91e505d9922c2914d7755e0ca47af8f394eabf539adc4509e5958a7935179f1fe3f8c22b4cc2e2a345933f59d65e0318bcca6caafcefeb3452d68d6197c8ea0b26b971962e201405c4c157653c2f2d4af59046fba73c6d72ca8cc525648416b9b2143dac665457204258b81bbad3d109701bd807e75845178590a4c5b8d44421e0225d9fd994af2aa1d0c65590a7bfeb5fd893b53578b04160e3162b0aae5d6f67dfcb75abbcf01b2ebb106906d47dbbbde1bdb9b1bfa8dab1989c600610422ddba5fabd57a54dc955ccfc7e5810293b5345958abc5f84808fd97351d481e6809e00bee6538408aea7c6c074c26b68e2002ea0633e6c3d7484493771c50eeb727d6fcea84ed9c26bdaddaf73d8ac7ad5aa36f30863234f789eb1d0092f42deb6ca72061146b920d71b457700dc5012547ee806376f3ffab1e2780f491f33a0cb355ea6b677c4ea1b54ab6e5698d2853047a428891a431d89979492f261809be176ccc6f09660d5cd4b624f339e961df7e2cd5aa3f816fe8950ecc0c2c9838fbf68bca5d4955de8719bb6cf79e8afbc8632efb5aabfcaa6e749cd45043ecb13046ce3209fa85ef21441ec2d1a0ac63a273f4213225773647e8a739187223eaf5c9f0f2e3d1b12e229fa77e65bfaa2a0487a29d08064960b2068be68c3c830254caee33d9436053af9fd028474bacd43a231dadc4f4116e333fc9f88fbcb64abea30e650a11ac56a1988eca459d858087e220893ac87e5b5203582ed469929c865ca6e35cafc0886f8e5a9f813f011fb08ba33475f7e9b64397ce8355542f0d31bebdb5238414fbc41ab88fe2abea69d9e769a9b465041255b591fe2708f1193c6a0d7e83e929c167d0f672a6cf8bf480b21d5fcfdf7c0ed21b4968982c3b4798fe04b9e9462fe2bd8fb6c511b1c153d0637fd584e30e35b6a07aa739ca4f37d82d9c8e4369606257edbbb2f6ee4e6047dd8e85212633fba991cea2364c746d0ec558d0fdfd64f2ca44bcc97637e3af5596f09c8a333cc19880d51fcd11a73c7b8eb1b02485903f9c3b3d15b56b6dbcce848e56c21d870a965f61bc53894462a6997e78f55f20ebf32f8f4de37a05611860ed6704be9587f1a0c12bf329f83fadd02c191a288925cf1aa151d387686eed59f920597a10643f36f40b821f85fc2e6b62569c88b32189a52966c52301f029b0c231c81ba02285edfcf032a441c296500e2a2979e4b4b0caff11b6656d131b61a171c4554591d3c74fbc8fb899600114d3a61951d7af36bb8e6460ba61b0015878e7e28903dbcdb802b63c5e6c895e2619c6511dfa0723fc48f796952690fc3626bb5c1a0757a19226c7db6e42ec243932a2503b9b257fa271f933ec2dc395f40b62b11adfb0a552412447e35ac364bee1f8ce0ad23a72daad14944e49b18cc3d5ecb36f4a8dfd602319507ba7dade07e22ca3a895e9ce0a2f59d7f581d176f5b8f880047f3803efbbcd442b7f8b1fe158353183f03d3f6acf46865281439426e64348199839d84de5c3d2441a5dd9c75bd064c1385ca083cd1df6ef46dacd30ba7bc9797085a143f0fcdd6b0c7ffdde124bace833b758ee4ddfe5072a558406365b77652cb2bd1ccf651da71b0b22bf789af3d24014217fea74522e694c399bc8bd5f07c0db8fab186d5ee762d33a5debc1902bed79a68d8420d06fa2810bfcd09e53dad5f37258fa86f46560785713ec711c9f5ab98c631bb3e3b6c5a293370fec522d61149c7bb09bd4256e55a71487db84f95cffaefd2c4a3058c62c3e73695bc27a72c21d264daa0d40c012083c581e4a0dfc7f168b722b237a0ede4e40a7b352f38ccd532d1a416ffb5207d68c2b7b3a6cfd957d7efa5b71446ce84fba254aa25005dd08c988f4dbdcc3dc795d3487566e587f8f99fa6d222c406942f33c9a694d0a5b974d247fd6d4a37727a7eeb184f4139d300cb9d2264e4bc1869026d0ca9966cfa34a5506577dd7eaa826a1dbd86bf3e8ae5fe73cd591837a5d6075a386bea6701e431ace3f383154ebf64ff61e2e4b520bf3a723908aa855ffca926ec6b18bc48a7dc48b52b839507453def5fd2898cbce2c611ba2af0d2434a7152607d997781ffdbd8987c5b14b6f20449493fdab89717e43a14153845b97698e2511195a1fbb646bd896dad04547a95f1941a1df510c4f7990062c0d4fd794bc886625c783228e520fde1dbed723fc9779bef796e04307444ff32c210cfc2275da1aba94d5bd2b963fbd80dda7a9c8ff88271f152875d7cccd664a44c8d3067a4034b5d6101af80d9a2970f3443536302525e41dceba23d8862006a1893e47f69018c2ed81677b4c43016ddd24ba54311aa590562ce1ad6991a1736d972bf0421adc4a00cd631414f1cbecb646e0008529253e9c0169822efb33ce421d77953121b3efeb10cd44d504b5cf47a9807dacce8eb24d53ce62e145835b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d32ed1f9d70028c2001ede3fb28ac4db0b0215889cb331f8bc637d8cd27d4443570c84f2e19c4aa5a2610030e19ea4093bd118f72e066ba44693db5cef94f3905a6740f6b046ac8d7b77f5451a405975c2588b5b82cfb70843359010be8b7f32870641d3606bc050e0383940f0e25880e6b183b137ab86e3ddd52a0ea7024db44fc4458e5fe418d5a7ed1c33878563e44403bf194507c93079ff9105b433e6078faba26ef3daab055a97199108ceea0d3b0dfee6ef4f8ad55f1eca9c15771251d0cf33eead0be3cea163831560bf46c98931a1dd530301d054fad074fb22e5d6ad86e5f79ca0607a6108ef6030015ee05ed6229bafe13806894461b51199f5b3d2ef6d9024f2194253e89d0ed237b1903f89dc510bbdfd982b518c3576659cd39120b53fc4e51e100e83a51da1239f64947e10f158bc42d10a3b20a366b4311370e2e5c4b8c303383b3e579cd1196f3dd13db99c99a48397fe1df8987a58b942b02fcf424a1223968027d877793bf9f4636cdba3b47dfac921296a818d1b08821f45e5edff6c3c216a16d4b6539790325daae1a6400ee446c2b4fd1852c409d43d0bfb72b3c0946f9edc151873293bcf16d1360b340d7b98eda07f00b1333fa020c5b2ab0a4db4d0a259bc517898153957166f01726a25d2012da74a8fcfec104b6ba6b02f41eb730989a90ffe2f8948b98eda9bb5bdaddacaba1ac1877ea8c77247f876b27b3d89aa71714f55561cbdd0ebbc4b24d39b044ca3e3ef42bf8f63b8c642ebb1fcbeccda9a1e3aed8762eaf0d9ed97308e08e7489424c321f49af5ff24bc10f697dde29bb97031ff65fc6cea39036367972d5627a48c4f9cb8ec56d22a8f95b4c20b4a2545baa5879a817128101c28cc253f3a7a73cb74f0c43d609d08eca7f936f1a8a1fd902a4395ac8be7312d9eaf784c761cb1354dd40baf3012e85eadf3fb86959768990ad2c8625a553c4d920338ebe25de23761c085102555e30cb812643fc1d2857c220dcb944c423397264da353d5131d0c70933d72b55d021a519c3d7a9c5614710da694bc1e1b7d5cfe40931ce3f0e1f35d253566b238265670dbf08b30c63410be69245689bbfb89a17eca0f6c9542454b1e92ed9421ab1827a2f0013b37d7a0653c54a480e1adb20f4d6621955b8b41b7fc0dc7f66309c890258c6702ea0943d8a32748f67d8dfa4a29fd85282d949f1cff5faba27a8336309a4f867baccec1e6369b73bdf4b757c1049448f4bb3999ee0d8ffcf0014a49f30a2a2f680daeab96ba080e9436779e88da9f35f1df28aa84992e99a0beab3c9bc2858788c7077ea13728eed4debededfd07f1672798856c3a055a13408241a7531f1edd8411be59bcddf843f745850a77afe6ac8984ce9110aae0cd6008ca6874a522c58bc897c403a860cd5d05b731add09f9e24a465d0da6417d00000bc1f800f46d8c06a9861b5ebb82ee710a67a28a410942c343c5385210af2235887221563f3ead0d53f19846cb8c3345403ba3f7209d78da91196896a687824d8afb71dfa6f71d993f900470493108fe9db363bf82126d7af537072262fd8208ab0488b72ddc27a4f9dbb2c191e699746de264af70e8325a3a8040652d3cc3e86f8e7ead704ea80c6fabc0641fdb53599f2e2532b2733e93514058b042af10bd004e87da3ee9342f44b433ff1b8535e3f1928f927eaf8bdf52e31c589467317ee797d349e052a0edd93134d2a7c57ee3fdacad7f8e00de15fee3a091b2c8e51c87f228bd61350ac8ebe6922fbe3db9b1f1c95cc6fad66daca76115c222bee077e98797f7d5a383fdf3eba7a9d9f91ef76bca8a1f5e028013db30143acb3e55096b4d63a9ba75c34b652b711c471606219755a72fc7db90eca93c617bac3191bb231b7a7a68d58e125aada1bdc72c94363a3d8c1e3ff72da6102d37790dbdd1172e42327ed298ddac2fc87c59442d545b0ff476caed9e785f2bed1bff26b0333a6b7893cfcd6ddb8a9ff65313caf6456f2ad2188feb5ba8dc102539e94beba58707699d560bbcce83134bc3f92ffca813e62865f3d2d56680b0ddfaedcac5d5d84dcacf83ad61a2b13644eba1c459299b7a92a42c735c24fe9a4b2e2e9fd6a003c6761b167ab56948265b496cb7529b01cc4e53c3cd9a39384643996beac7e7e8c5b9548bb53ebf8bbca632e490bedf7f4c1de2fe41bcb746afd7380a6ba561610e880b38007beeaff985e007a1460051bb827ffb24970b0fbf79cde0264cf0292305be0faf22877173da64f6bb647b3a636b831df365b7c3394915ca6209d753a2cdcb143ba3e7fa41dccf5534c6fd36ef91187d55e35dac9d3925ac08e2c22c80dda4c60aa6e074cbad95a68215cc134e03ac7e516179bae944ce17cb54d086ea75184c3c36dcddad7c1a570d4167525f3f53d8d39ebaf2d239bc1f9e7572cbce85b1fa08568230c663866d47c3af0c12e609217ab0284f8b8694563933a48ae23e707c1df21527ba79fb2c6cb074d51ed0b90e361b2cbda0637c074415c3e4eb13b75b149505ccf56ad08a10df211eba48ffd7a2d0d42a1bd943dcc12f86e3e9052ee1ea8f6f1a8fd7b2262bfb86110b06210c25e7fac37b49198155c2471aad8190353d85860814a81887509424d72a79cef1534ea7655db318a424d6a036c7aa614ce9faa7901f55f64b0b0bf1c084f52e7069e5bf1097a9889ff9773079eb30a9abe2de835e3229d8c3cd6b00e936d5339b325684a5c483b15420e123c221c6faa48e432e6ad29d22301073d3dcd3dad319399258dae99d20eb634bd69867ef8695bedf1478abdea28e97985ba68b3810318e3cb12ef946594ef5447668e76d655032dad5ed688567ea02cd741c0f1684f271e1e6f57e70339d949187f9cc5ed830203c45863ffda2b704a0bfc77cd4cbaf3279e937c9415d47635c23582b2cc0e19d01abf7b442930cab1acb6b6d1c87fcbabb93d1ee778339fc75b0aa674b0b9ebcc31efa34cdc88d6209367d7c9cb38d96a9ceb0b51e8e2364399650074af6bb1098b22b21e3b9d12bfcf4ba0ee5e9c3cf8820ef6061d10c3648d73c6d22bb9a4502c3b263699d0ea24baa448b12d24f501412d09da75d99714c914e0bac941c2e9591a1af974b9d7ed718ae8c2c5246458375efb92aa04a645b615f261ebad3748d4e586cf4bb52da7a9c3a306113046efec9210cdac01dd254b6f9444d4186539c1983075c1100c45b2a80ec93371fb04da55a70d7e4064542210bed2bab603e428eba5d241504949b6d4c4f02b543fd709a15be42ee92b6bd37baa61bc2904832a15e7077176451dbb49a688cf55649c5637bab364126c473c49dcbcfb064b2f296cbed17603820bbd3a5e93ec52e82e67ab2760735d2fc915122c09b76fc9de21fd95de63f8e5b0276a7fe25efa62bedecf69ceb278c8309d1c5ccae18338cd298c2ce4780f31255dd1321fbd0dbb6f8f64f321e0e0b665130b8a0379aaf5aa6bdafe07af1312f637e3911b8d18fbcdee38fc22ca35094f912decea24e409eec05550dd35c62be25a1612ab90b268015b40eaed9fa0717aab769e193b2d7bd2a55e7e715c64e67d0be4b76086d9cc31c11ec35caeb68634eb554ed5f55ec45727a57e2d8d6914f6d2acffb17b9515d347ba045067502a0b14022a269560e0d95cb168c7097ea8eccca5aecb328a24b1eda37bdb600fffb212178ec0923744a6402d58d7d738f233ce9b64b6a9f1dbfeec1505db36c5a06eab73142a86b27dc175155cb30310da6295a7fb1a7fd6e4ef00c998b82ab8b3300133c6af14e5077c26aa202e6fc5e69a792012590d42ae2694b82fc1efc68ebf7b5df2574cb85143f66a0bc2ff2a9811e62cca6fe559c14e606a1c9ac2753af2050d14b924dfc217dbc5b9b44e89d25f35314db49b096287a77d1734d0f8f8d168467849008fc52de08473191d53f8cff9c54059406398e89683d41db5ca287bb379e463c7df481005fcaa51f86223229d9aa3f1dc10b0bc97f9814eedae2d1a0d48826da8fea991d14f1358e94badeb070719ef7e1ff2021c1cb5acd297695c34310474feb95e86dd6e211cd2e6f65ced4fbfff3817ccb8c25dae508502d4df393b421e7f92dcd88622e35e35994021fd95c368ce30d455831b8d7b5431f33a73278cc9567892bccaa9f0d0d4410a411d42de63d1e2908e4ebbcafdb25c1a4ee00238cdf73e322686f01341d26623c2491c6340204508a421b5978d8f7f698b473aa842dc9eca0e5774a6374ed583ce8605795f084731e95e368d039b6ac539d614882e89471f99ad0b367c55273a7a4a3dfff10ea4c7816a44c1cad69137741b64deffde56148294271b50d17c8ecfec51791fde88bb15b07ef5a9f0f13b9ee20cee21322f3a6fd0783089d9dd32a9344cb0a89e9746bd35c0bc36f37afacb5e35fa47643df9b11a50e4f6f2c820c284d4c147481412e5e4945115040df81511233a8f81e4731205cf0af72285f08cdaf87f9cda4cd3c7c7d51bce592ea15d692e2a1700f5467da9707838a1feff9c989cf84c7b2a3965f146be7fadff1b72aa0338c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e8529585eeb7d466f7e38b980536e62c00fd3dc5c703c3bbd721c9491e6eb85c32a44a4b8c95221524a3c23c6b5401c00b5030ac5fc9d0a0463ad9e34009a00ad426a782939a3e4f8394ef0f1c9a8f811a7f5ea333cadd30d3404352aedbd7a2a743020670a8d1c3fef7c3cee5b34ea05aee62597374b2d6143e51039b706bc660f371ea75d41bd9ef4da3a7a5ee404600a4880f8915d2a0d4943210c8e5e71277e7fb0a75847a0e9f3e97824f457206271c9147e2862e8728b4d69cbe84e785d92608878e367fea06978192e6e69d4b8acadd42ac1133fb3a9e9e1dc50e281254144a0fe07efe8476c462860a01a5e4180a4de0249f05648c23f8e6e3bc49809eb27d2c7ee29fd05b5cab4d8ea4b8868446d4562a8b2d6f182d818b448b165d8497a72c623880702eed40e35aadcfcf6b09f67040effbeddd2b22af32c2978da711f60d3a60f115c98e714b9ca80bb1bfbe16704fb841cbfb0bedad90d8ee5106d2178980cf59e6836eed32dc22ec231e5556dde151c0081a83bf4389916868f9a5c9eb394a00dd88f01a451ade235d634484a9c56c595224495874fbdbdfdc1e93220adc754722bc8f182a697c43e34c44782ead62b2b4d01ed046ac0d7187fdf4ec246361396ba03e69055b5347faa6c1cb9929766e4f2a7b41911e25448678f4820e4764775b18b4c0668fa3ca1e9183ed8e57c30c211e97e7cfdc685e6c082448e0595ca52e08fe5b0d37ac52bda3dc4c8a0b7d3e9d1812d5530ebcf9df0ca539c809855b617cec1498a8e2313908d070839a80574b129b24245eded44df2d131e43dc9142274e0b70a75a903791928a1bfcec374626d3c6136c409de439066c72ccb9ad0332fc9b36d3a24c6173a23014f684d0f1666b8331d108ff33986354061399848cc96c7a631da2855f503865eb732fd4e5c3976571cde050a1777e67603fe0045e0a581002149e02f12f72a340fcd78d5723d10b6869cb54bc64940dc20e2c4e3989890f61c5b1df09c72d8a70b5e5a161c0077f73c816b17f59d9533c2e6ab0c7a26dd2cad7646133b739b24e20159d38cb2e11faad8ea174305417860ff18be0bfcefdb413d281ebc034b8b5f8722b041e90ec772e1e9449f61650a27e810f57d102788527c3e274dddc99f094edf73a09544cf3f162573d6da4798895daec9986a41222047ae0d3ce9b6d84c6e91ff5abd4296b1e777b8e22b077a6aea2e843cde25869445dce969fda78091938b3cfdd6f1ab376e62e9f94ff0456171e270fec0156069e8006f48956683abccd1427e3ec9df93abc4fbee9170e9ac11dd9ca793e7d4ad05cfe205d6ba0969f8e965d571cfbf51f54a8e3317b795c76523eec774719d38f8ecbbb192bc298fdca9b0a9304386b0791c671fa441d2103a8e2b2f015072895fe33d26bdf621bc4357610234e563f1f6dbf1584d21aac7bc2a1f4c8869fd97e805ab0157b6325650d1e03909ae85ae3751e582cd823db5394add842eb339426c7a1f44fe90370fb00c10664c8f2c9515800831c45fb5248387358534d37a9b2bc6b9ec84bbcda7f2f8fc16f848423e1dae978e729d4886f44e1b21418fc96c9b11246ec54148661fd7515be3636f5d3fb5e2723cfb1a7253ebc10064373d6227daca15f68a54710eea722a4c7ac9d8cb34c289634b7a831c0d58ff0c5654f9edf692e49403f40a9b1b1bd4acaebd7c2ed9d02378c9a9b763a41b5a85c0e978d30601e32bfa02697f9eab6f756a1d83440c49028baa4607d4ec080ace306ea6094d615cc220736fadb0bddb33b4d7381d35d265c13e35b0d829219ad12e42d1b56bc54f1fea860b18d6440a9c44c56c41dbadd6085d0e3707ee4eeeb4e3410a8326cab9ea1eb95213475d669589cc8b1331ccc7d65eed9559e0ea0f5bfff13843f2b4a2067c577278af1558bddd481e153602c11d5c81a424e2a1e946483bdda59d530949954fc0d7e42afce9454b6faa5b7575f6fa1d2374efafe1363b36df330d958bfa12b5efdf7d274943cf6dd8c5448e3d30bd0d05afaf86a2d30c068ff63e9fd065e1f84362827c46ccb49a8ec04049d1e04db6f7b88c193400ee5818956472db1a5d3ab044e18f4e918b2547eb275d8910d103c13a8704ed2503421465b1e68c51817ae25727b7b72f3817febe4ec7451fc241d7794b8a63f1317707c329bed6bfb2a0023bef0917a4f8944b2023efbe2fe3d2131c41ab066ec2eacaf389834b55ec862fcbca7862a3addeb9a4fd147bd07f480464e395013f2599efd1c800bb1a8d30d5f57f82ac1df5056e7ab4b9b21cf69a97916c8a50072a9fa50439bf52d8ca7aaf50f5bd9591a5422b079114f0bfe4acf561c826ce665878ade3dace990e64ecfb1ba367f4c3c0a61d4aa1dad084d5c3279ceb5a4343f16894ba217fb7c1bb67c328dc7a5834ea59c48d0db9f4a5d9ad304bc46c0d63e2847067350555940f33ffa238dc7137ea04ecb81d9abc5b068794756c4f812d1c5af309231bfb4b27281eb33f8df6c7152ec14ed6fc9a8a644e174ba754247a7319d29a2d250be22ad5e7494d649b11898276a964aafd01459781278f83a80e6764aa6f07eaa4e22d1741ed853c68c6ab19999edb739487eaaee49b05113ccb3c725993fb28e76ac53f00b9ed3ab5f6912e0786fc1138fdd9eb43b407e78f505ae833a2eaea113245bf6a5ef6abd0db66141f770cd6cd7a7e75d71d68496b94fdfed16540c30b13d0d7e65a4ff1bb1b73ae867b96e7c912b00ff6a0ae752dca9264748a313dc53b63231d29e9fad3bf5e6ec9134177e105125ee610a1f9b915d9b65deb6f9add45e7b03240fec592fd59851a1fced2bf84b59977cde42db08d3a2ae3363169cf1de0faac09b586e3da4527c94f3e773341a31864c9cbe171e9d2dee147797d4242195bb40ac11e174db2328fe1eb75af660ac3467a41c20b10ebaf33b287cca0bd628c8e0776b9bf95584947c130993f4560f6f01a417c3a364675ca3cb6a8235ce24cfc39325150995dd367ebed4e2adba7efd67f631073311641d31a868698b9453e88b51df1f6dce9144da9ebea27285a1260bd849ef59e925c176159e087d784b4c571ff12c63386066a9565234ceabc1d14242383c5e1385b87afd269b475a6fde0ffb7bd90e239d010036426a9102aab37b5e7822263c75b2709c939073244489a929410cd8eaf39549a7f7e39808fb43114cccaaeacc16d611dd34b249acc4f8bc2276ac510bf3052b08e057425c87fd10a6c6f7979f5044137535fe3f4335ab4d53ff7a251b2d799539e0852b557861591858ca58ee54562ddd8ce1604479185664a744017e539e3a7737b7eba00d76750ec72e68159e3a59b6311dca75e37ce70329997f97069f11df50dfcfd9f0527d72a5f91327ba5470d80b2854a57596101f5dd528153c8e07bc10fd47d0ec9c6b3ca84536e7b0ef7109b756252405947adb4dfeaf4712a116940f296667427b1c3451595f904e1bcc1ecaffb327a9375f9f09251fd12a66f7cbd6faf86fe9024394f1eb3df27c88e651042254b623a6d4f21c9d4ff62f4819dbe9e6a4ef2e243a664589311423742fae46323f94994ab346ac1582f51747493b32611a563ad057baea8cd9643b8d548fe547146d615bee842aed92fc83470ae7116abdf4ab1944e02a488e8df0f2c1a026bdcb1c9e5e273773626b603e9c7ff6b9bf0beb5a573c6e918efa944501d59226cf102566661ea103bbe11febe431a1ff61e7c44a9852e25b13c8f1bb89f75aa4f297f36eff83fb89c7fd7627643fafbb62323508202f6cde95375caf3e05b69ec9d53a3c3d46d2c269274d4c297ea4c1849854c73f6f6841ca230369c180417f4a65f648b88e8a5dd04c309f31d09161a0207dee3469783daaa9274a0ebb267618be37418eb65bd822d1caac9f77229bb6c60962c515e8b207b02674157f4b2fac359d2595191b18223ef8d7a62f203c30dfb407d3017a45f5b334202ec3bdf629961bee8974b2e756e4c7b638ddcb558e8b8fe0e802bef767d681dba2b2af833aada512c7f867dbe6e01b2a7eb49c7b6e50bb8d9e6cfa8ed1321b415771d5535b817beb8831160ffb5f256a040d662f90742d2be25580185bd09edd014de26223b5f1a82e054dfebb79336d891b767f8be214f88151b8a8ed8bf99febaa10c51a9b07f80b130f73cfd4d1de282f6d7f5ccefcccb64a4ae407d0c8e29650b1c0c1c00c292d0afc5ebed5da7e7a9d0eced3c6894548043aa537407a69dfbfe0fd4dffdf896a363d75ac5707eda016347a63abfaa6435132d554abf826a19340bd0f7c5984343cb49e89936f55f2256bfc32871448794ea44303147839275ddbe891c2ce4f93b4e51ba2a2709de73de8b659f9ad0d8a6aa8e2f1c300418e07035b4a39936ac69772520c167ef33f576198a70bea1a3e6a4810868fffb8bf70abb870ece4fd40a2c286d65a1a768776bcdddba218f6854236270d550b0acdb1e87c0a647026b5982426dc8bfd02bbfbe5ecf33fdef0b048ee02ee85779a0ee900ad2e02300ecc774f73ec419fdd15546141233308dd4e05e0bd98aef19726d7d2749d8f316b798b87ac700de86806c0586e96d5fa35d908728d9a044cfc98d6435f5a73643ddfa896ed51671f0a76359ad302d329a7d6489c3cb77d7a563214f32cae5c3ab5a379198c36ac46ef0f151a21bb0db55720418ac16e2487ae411a37a41f7a086824b2efd39c94b3494efa7c1b708e360b380cd65c6b0300db4259152800ab8a88f85e276b32399f0746cdbfd93182863a850da4404584a8ed17f70aec3cb4412c17b854cbeb6e4ed1e94d97bf16f7b343ff7b1c0d02b11555ae20d30819e6ccccbb44b7538770c3aecbe7351ded9dff5a0a7c66c2be38a68a4f8d2cb06766b1cec3242cf191ff9ecec987893588a89b042c2034534af2f0c4e38ba3617ddd1c70bbd23365639fa7cd5f191861c7fbed74a809b4577184b74582b4774b8ddc3f186fdab84f01e0f988b74bacfe932f46aa7023309f130f7d93dc434d02fa0318a7a63dcb6fc7a8cccb8eb8452ee3c1cb6540512a78cc5ebbb671f9ad9a244567471923ff0a04fb615834380caaf01494ebc73ca0d5c640440be29f2206fae788ece44aca654e36a2ea1777e93e939111387068eae8a7ac652da78f63545288ebe0eeaa2eef9ec82ba6bacc11acc6e110d82f4a1c698336cca9cda4ce660b4873e19098521277c6167a5090ebc2df903b9e682728b4a3ba320237b20444e34f94f2c8f9d5e0173b28a2dea1a88f7e40403b113752a6f9aa0b49ca6a5c34a2b92b2d2bc5f480ee94faab28f01dc0d7ad19392060a4f0a8a95ad318982f081ab3c35895f83a6d4611d888a1a0d0a8ac62075ca703c02283aab385e82cd28d831cd1ba21381597e0ed3b193f6aa22d7588434c2416aeec5145d93ca5215998b118cd43fe6f953be84cdf704bda68dec68fb14c3e6490399277cafd3b75630f0b826e2dd6d287a161cf892fbdd889e0c6b19cc0be4bb41fcd121741e20510209b0740cb89c118f190cae98339b07e65df9cc9dd126b9e3b3214afe654cf851be9e564e72f834168ff65ce346ac54024cdcd9325712122d254e33b7c35d78ed4f76db5578f07a6c1bcb7dc46199c567c4a61f84c574fc4ed042b0f2c8397da95d7dfafa615f163ee77de3725afe64561d65a370b3430bc9746fc125c950f425b970da866f8944bf368a765eea617c7ae949c214c405a9250eaeb7dff21e3804b3656037370d9b2694a83536a4e924c9f3dedf1ba083962d04439175a2d98c3e54aba79db4b5fbc425c1ae4d759878086569d2afcba33ee7757f605a7b0d7d518a7751ffc17479ef2cdbec637e4bfb3dad4d8993a553d0ccbb191f4be4cff5ad204d9ef12e321d851b431a0487b9b00a71213f2c95a3e48a1025c18a4bb04dbe9c259e0ec5a57863699f0eb5efd7767175b02b9bebf4eda442aa4ea276a4e1cad5e196a6945f4f9feb7e434a747a9244eab3dce1ed9534262c8fbfdc245ad9dcf846980488cb4d18a79606fce942d48063f0455392e5d825f515af082f6906036c246bb7b1f3b75d1344466e45c96967f8cb73049970c100538397589fa07b331c10ff03ffcf5cac1691840ba63344882cad3a161b135fc74cd2834b4d7d555117ffd19bb23e6ce26d31a3c34bb5626688c2388f32937ea6edb9107df7695cf745e061c1c8b98f078d88f50881eda8dea89dc75b6633f1c7fb016c01016f8225393bfbb03533db594d4e1f289484f7c5eaf4babc9ff19d827a1b3dd1a3cd1ff4732a3826ac5a468c6464286aca145027df161442843522e2ea9f89b72832b1d5fe563cc115c44ce2ba0c383e5d6824f8260f9697397660eecf2766560b1c77937fcec07555c995ffa2eb97e7bed217c46cc798a407a054e3e8c342de20d821c684b2529a9260b8c75b32c9e0232f6870db100b286915baa9ddfef29ba03584ca140af25d0ae285191427484dfca3a722f8729a0c76d7fec1a9c987bfb111cc69796ebd1976ad4ebcf4b3560c1bf2662f77a10271993092016aa2a13c0e05dabd3e3754bbf0e87775ff06bdca2da1382448fbabfde07755a6313b77aea6326c8a3ce609b67aa4b2de89a10da711cc35cf593e91f701a0fa8e27969e0a4642d03481c477ea3219946b9e8b8b1271dd6fbc2da017b45d3210095667544b271eedf036d8b2ffe8d5f903ac79718d2bda2a14a9fb3cba6911012d8f0e3c51c77bd269f51b501bc3056358b894a4efd94d6f3ab31c60a2e6d42022e0b1f1daae90dcba1b96d681a018636a09bfbc8381cf40a502de14de2b67adc4b5aa9706a54c576dd1caad7fb29bdca6dbbce5cac2eb1e65d89633e3dfa60aae7bb0cc818fc18b6ffff18592e8e8671eb94ceb0c2e15b33f9f54415cc9e626a339aaedb6cdac744b85af70456c65c9025b86a7426169cda4490dc7f20d0220467f6af1ed61d0b39bd7cc4f9e94861a28fa6f27709921625b455c2a5981634b644f122be630c593c15b16fb21e9cab0fc7b0140c981652059d2310ea20e463dc56e7b203c1dbcce46929b2013bff2270b86d4951584ef7bc2472febdcca611282f3dd2a3026e65945ed13d52e629d6d6a120b1f6442b75e0b2660e0f05824ce468bd570a388c6eda0d4b98552d27b9aacca2bcdf7f90b75243f624e0181f20683e701c397f4118ddc67c11ade82127f6d66ca2b4137aa4876cf62bc50a203954cb3460a6f509b816726d7b0427c7552a24e1ad207087af15ff6e5619ec37622a69b1d98b990ab979c98b9a66995d1665017790168ae8b5dd1608ad0bf62c35c2ac54ee3c95f27faeedf474fcf1fa50ca27f2087b110a88585c255830f56048944d2868c4978492fa514359fd3ca4231f9a3b7689833643ca183622e8cd9639ead81d38d3c3ef6a38a08f0415e8f2569d4b698449bf2c5ca74346454838e92bf4ef4200963a061b35007b1a77d0b68fe244fc7a65c339aa06f8fc468150d649eee8dd05156213b4b376830067601b89c2f3ecac6db895a8078e65ff80e7d04e60ab0ec43fca15dc14d5312371e0b26d5cf58477961dbd96fcdf2b31d78c450fdaad5e9bb9248f6bb0cb58946f2e01dbe23224e6af11e5eaaa5b6d43d700a8083e97f57984a6c431796df3d153e6b310d25c37fd451bb16e2ed028aa7b09e42e10f820389a6e253f09f99692ffc4359b494a30096a3eb8a5b97c3aba02933a37cc732e055d41a2acf695dfa9d59dfd5627864efeed20c24ad2ecac463db3c12b4ae5233ea7370c02412b04da5cecbbb9154f804dc0c8e74e2ac9daca31a3b872cc38779f9c7b1a6ca93f2c4f6d04a6b0f3e699c8a40511a2e3b9fb7f8972661796817ee864c2396b7b2a9f349d959b6fae1d66ec9104ff9c942f030e65a8aa546173676eee3beca7af1636aca17582f30829782e2c9b1b9c72aaf8060563ab378657bf91d13f2dd4f1bb6adc1d6da398e1d9b2a4884c63631d46aeeac4ca7348887106b8f07b427790d1cf4a2713ad56af6e1e1629ef93edf14348535e50013d4a33f70273ba18c23050e010109645dd600bbb52809754ddeaf668a72b443d63901a6c759e4cffd958b68736a9a1ee2ebdff616811e63d43b100947549aef12a6caa34d62c1fee27f253562286a466c2b2f91a711cbfaebc527f705bc8bc7351cc7bd57d0af9f150e6466174f1da6ac71c79a2a4df82d44f585a3865f7364024c6f9a7ec7442cd32dc7566e2531fe4366ce5e22aa6931f8d2cd5f258b334011fba79242837b662646211a788b62ff54a6e9bf54761372954bc5b1503cc1b49403054b96be468c1f8b22ec177da74fc851f7562a10a49417b5b6a76168f52931be46aafc2211ceb98056a1bd1102545401d8698944771e079f3aa93974eaf9960d6bcbf23b14834f0d7034f8d5e6589e4a7f13f65e72705884ee8dcbf1360274ec269f1e31a344f8884e5ae3450628689e6356669e7a94e43ea1ac65578a8a21d8cf64b22197ab966b1a20a098fe08768b0f5e53e25c71864a657cb42ea209e757e475ac343e5f8f85b776ea6276755f5d9069447d01bf34604c0389a5a80b7687ca74dd548b3c5d98e4f70c9a85d29ddd2296fa1cb8be37e5d8701af88c70c55baf0ef059358fb8506ab8dabcb8642da7052e6493cc40a035dc86b8d5c88164976f31fc1f72c9a86eccbe29a1060e2a5b0d6abf7c452613018b69e8385b7ab509e460dbd802cd49164665229340e29a14dcadf345f493f00ebe1d829515c6528b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d5e8fcf6841f2e94ebd740f848a2b4e72c31c7a21aea6ae8917400c81d43bb522b64c2aaa0a1986e68954e4ca7b5784088392fda54f4dfbac75e454458e01583df2218fc25708efa7679c23d318c33cdbfce6be7e9125002352d34948fa8b3a67aed933b6c623a04853e8e76cab3219c59d5ed56410b366482128627181b5aa4eceec7f1352a57bf84ff4eb62099a8875cc61b06d7c3dc6094fe96948c881c60eea50f1aa4ca2c2c57af4783c613dfe8392229ee5fdf145d7506ef3d9e559246558463ea4005ea0f83e358d15a789493bea81664169d09e26df8e8e3a2361e6226a54c73b0bb645b846c9bf3c2883b4936fcd3f629f9d24086d9ce4c20cd226199884cef69623c717e7aade3c1f270584fa38cd0d9b6a56045e318ec49ba8a9615abed39d47633eeccd98be10042d5d03d852c5bd930a89f0ce256a9332521f287c5b3a221df63628851acb241908838bac9774b28721290f082f7b143e8d102756d8e06152648b0c9f937d26c08490a5752ece4b16ced9ed97d75143de35326b6e46ad517f13ce464516302d89289478f09e15905bf5d8326d95437860df2f72c0d2cc0f3c40972b07c54745de572f912a58b2bba9c42f105f09be83e69491690a5ef93a98dbe72b55880c843da199106393fa4db8a6f659207f6f419b31a678ceaadcc3330cf95892fe9ec136744640751b38026e009740867b10de8eb67f15a03477bcfddddd9319bcfa6de112cd37ab5040bc19e0b3a52f039a6ba60d2045f834a3195e89e19ae67d96b45a0bee0beb3ec45595def5f6e8fc37ba73c0515e6ade7566e5eda3fe184f22a89211634ed256471c1f3e0f3ad64717fb58cd0a44709a330f39d5e8cdb773ee71afdd2f9d57b44fa579937be3aeaa1adae3b57d047ef28d1fe4a0ee885dea9edf31e01e23e896796b8fcdecd44b4b180dc7e02617563ee5edebece3368fcbf345b930c92fca7072eceb55222b960c5f7e0fd54d58b2a296fc8053d12508a47fa99f2cbd5b7fcea38d04fb896e5421661613af2b53ae7f9cf9da7141efb199d0830298feeb364ff4ad75fad31d8e7285e6d63e4c3f149c65a859747611e99d8cb5d06bd5eb20c5121ccc64e431ffb0c6981f059d02a6924cd1ad196dfff80d76bf99383b20bee491a49cbe9a66f16ad93859533515ecaf1ce37791cdfdcdadec44734ab9a4e4d16a25f18d2e207f66037bed355c32f0b6a53e8785a5b3392bb92c3a0e904b1c0e100735390c8676dd2da11747fd6014c06cdef71226f89708e71ef9c6ab3d95def2dd7f487e42efa411f4eb05a33bd833c6d57f623b8f0c8ed846045cf44fea32bcbe0bc04e118f3922c6a45c890e469de71ef3008558f64ece794dff8660ca2d18a49e2e7b3beaf1e6c903da7e0e8af4d2400c18023b5de425d219f9efcafb72aa555fd994cf9f67ebeb5de47b6a84256e12aea7e877a8b9b5cbcc01119aa6a8e732f551d99dfa4fc239739c0c1d9c415bb13419d4c73469ba912eb7d346b91629642940f117e1aa50a09fd5dd48caa48fe936563f4a200c29d77a80f5657781f6849373684b82a029b1fa3d2c566173676ed7bb07c67c2bc80e7d5ba4623f8ef0d565d266723ec60497f0375b3bac140000000001000000020000000300000004000000140500000006000000070000000800000009000000140a0000000b0000000c0000000d0000000e000000140f0000001000000011000000120000001300000014140000001500000016000000170000001800000014190000001a0000001b0000001c0000001d000000141e0000001f0000002000000021000000220000001423000000240000002500000026000000270000001428000000290000002a0000002b0000002c000000142d0000002e0000002f0000003000000031000000143200000033000000340000003500000036000000143700000038000000390000003a0000003b000000143c0000003d0000003e0000003f0000004000000014410000004200000043000000440000004500000014460000004700000048000000490000004a000000144b0000004c0000004d0000004e0000004f000000145000000051000000520000005300000054000000145500000056000000570000005800000059000000145a0000005b0000005c0000005d0000005e000000145f0000006000000061000000620000006300000014640000006500000066000000670000006800000014690000006a0000006b0000006c0000006d000000146e0000006f0000007000000071000000720000001473000000740000007500000076000000770000001478000000790000007a0000007b0000007c000000147d0000007e0000007f0000008000000081000000148200000083000000840000008500000086000000148700000088000000890000008a0000008b000000108c0000008d0000008e0000008f000000109000000091000000920000009300000010940000009500000096000000970000001098000000990000009a0000009b000000109c0000009d0000009e0000009f00000010a0000000a1000000a2000000a300000010a4000000a5000000a6000000a700000010a8000000a9000000aa000000ab00000010ac000000ad000000ae000000af00000010b0000000b1000000b2000000b300000010b4000000b5000000b6000000b700000010b8000000b9000000ba000000bb00000010bc000000bd000000be000000bf00000010c0000000c1000000c2000000c300000010c4000000c5000000c6000000c70000002b000000000000002800000059000000020000001e000000" //nolint:all + result := "0x0144070000000c0000000e000000010000000400000010000000030000000b00000009000000060000000d0000000f0000000500000000000000080000000a000000020000009a14667dcf973e46392904593e8caf2fb7a57904edbadf1547531657e7a56b5e0600000044a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe7274c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c51194ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050eac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547cee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e3685893644407a89ac6943b9d2ef1ceb5f1299941758a6af5b8f79b89b90f95a3e38179341307744a128c608be0dff2189557715b74734359974606d96dc4d256d61b1047d74fff2667b4a2cc69198ec9d3bf41f4d001ab644b45feaf89a21ff7ef3bd261898ab99b4b982d6a1d983ab05ac530b373043e6b7a4a7e5a7dc7ca1942196ae6c94f9e38609dd9972bfdbe4664f2063499f6233f895ee13b71793c926018a94284ce0e8ec374f50c27948b8880628918a41b56930f1af675a5b5099d23f3267633a58b8f1f529e55fc3dac1dd81cb4547565c09f6e98d97243acb98bdda890028982bcec62ad60cf9fd00e89b7e3589adb668fcbc467127537851b5a5f3dbbb160695b906f52a88f18bdecd811785b4299c51ebb2a2755f0b4c0d83fbef4318610ec5e1d2d044023009c63659c65a79aaf07ecbf5b9887958243aa873a63e5a1b52ef04ed449e4db577d98ad433b779c36f0d122df03e1cdc3e840a49016c5f16c2d4b5973000d0b175631dde5d1657b3e34c2f75e8a6d5414013ce4036d83355a6e01665b2d8490abf45551088021041dfb41772a9d596ed6e9f261ed1c8ae72b436c143e295617afb60353a01f2941bd33370a662c99c040984e52a072b5f224c4c4b178f1a3d67e5f26d6b93b9a43937cd2d1d1cb2acc4650f504125df2e18ca17f0edc319c140113a44722f829aa1313da1b54298a10df49ad7d67d9de85f5a6bf6911fc41d8981c7c28f87e8ed4416c65e15624f7b4e36c6a1a72c7a7819446acc35b896fe346adeda25c4031cf6a81e58dca091164370859828cc4456901a466627d554785807aaf50bfbdc9b8f729e8e20eb596ee5def5acd2acb72e405fc05cab9e7773ffaf045407579f9c8e16d56f119117421cd18a250c2e37fcb53ae2dca6ce9b3ebb40052c34392dc74d3cdd648399119fa470222a10956769d64f7477459916ace4f77d97d6ab5e1a2f06092282c7f0a1332628c14896e8e9be62c2574de3dc8feebfad1b3bee36a7bfe6c994e5d1459a5372ff447ac32dd46c11b0a8ed99f1e7ab160e0ac2fcfeee0d92d807c8fb4c1678e37997715578926c5c6c9bfa7c2e0f8e10a1a78bb982313c5c347a018cb3828886b99e109a8799d272e6037f1fc5b19015b7089ecf90034349e3f5c37cb50dec5356743614f94f8c33964b85f2b8e10e859e306d3670b8bdc0cea17b97dfd3edc8a9e1be1f127fee5b44d421ae62038ba15a377cad85e4ecd3c2a63b54fdbb82c47fb3e9c02640522648c51db949a58fd5f36a19888986275547b0c2fbb0b348ccb85dfc6c998dbe160ae9425710301a9241837d624438a5d82edbbd6bf2cdbcc2694ad7db31ef99219e47376e9af08b294901b879c7d658c41386453c6baa7c26560c5fd3b164e05d8af1a51649d44d12dffc24337f0a5424b18db9604133eafcb2639ddcdc2a7f0fae7a30d143fd125490434ca7325025a2338d0b8bb28dcd9373dfd83756191022eeba7c46f5fa1ea21e736d9ebd7a171fb2afe0a4f828a222ea0605a4ad0e60670c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f00000010000000030000000000000001000000280000000200000002000000" //nolint:all resultBytes, err := common.HexToBytes(result) require.NoError(t, err) var sessionInfo *SessionInfo err = scale.Unmarshal(resultBytes, &sessionInfo) - //require.NoError(t, err) + require.NoError(t, err) - //require.Equal(t, SessionInfo{}, sessionInfo) + expected := &SessionInfo{ + ActiveValidatorIndices: []types.ValidatorIndex{ + 7, + 12, + 14, + 1, + 4, + 16, + 3, + 11, + 9, + 6, + 13, + 15, + 5, + 0, + 8, + 10, + 2, + }, + RandomSeed: mustHexTo32BArray(t, "0x9a14667dcf973e46392904593e8caf2fb7a57904edbadf1547531657e7a56b5e"), + DisputePeriod: 6, + Validators: []types.ValidatorID{ + mustHexTo32BArray(t, "0xa262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d"), + mustHexTo32BArray(t, "0x804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e"), + mustHexTo32BArray(t, "0x4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72"), + mustHexTo32BArray(t, "0x74c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68"), + mustHexTo32BArray(t, "0xe61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511"), + mustHexTo32BArray(t, "0x94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e"), + mustHexTo32BArray(t, "0xac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841"), + mustHexTo32BArray(t, "0xb61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12"), + mustHexTo32BArray(t, "0x382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c"), + mustHexTo32BArray(t, "0x0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547"), + mustHexTo32BArray(t, "0xcee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237"), + mustHexTo32BArray(t, "0xe2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53"), + mustHexTo32BArray(t, "0xce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016"), + mustHexTo32BArray(t, "0xae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848"), + mustHexTo32BArray(t, "0xa0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a"), + mustHexTo32BArray(t, "0x807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a"), + mustHexTo32BArray(t, "0x4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936"), + }, + DiscoveryKeys: []AuthorityDiscoveryID{ + mustHexTo32BArray(t, "0x407a89ac6943b9d2ef1ceb5f1299941758a6af5b8f79b89b90f95a3e38179341"), + mustHexTo32BArray(t, "0x307744a128c608be0dff2189557715b74734359974606d96dc4d256d61b1047d"), + mustHexTo32BArray(t, "0x74fff2667b4a2cc69198ec9d3bf41f4d001ab644b45feaf89a21ff7ef3bd2618"), + mustHexTo32BArray(t, "0x98ab99b4b982d6a1d983ab05ac530b373043e6b7a4a7e5a7dc7ca1942196ae6c"), + mustHexTo32BArray(t, "0x94f9e38609dd9972bfdbe4664f2063499f6233f895ee13b71793c926018a9428"), + mustHexTo32BArray(t, "0x4ce0e8ec374f50c27948b8880628918a41b56930f1af675a5b5099d23f326763"), + mustHexTo32BArray(t, "0x3a58b8f1f529e55fc3dac1dd81cb4547565c09f6e98d97243acb98bdda890028"), + mustHexTo32BArray(t, "0x982bcec62ad60cf9fd00e89b7e3589adb668fcbc467127537851b5a5f3dbbb16"), + mustHexTo32BArray(t, "0x0695b906f52a88f18bdecd811785b4299c51ebb2a2755f0b4c0d83fbef431861"), + mustHexTo32BArray(t, "0x0ec5e1d2d044023009c63659c65a79aaf07ecbf5b9887958243aa873a63e5a1b"), + mustHexTo32BArray(t, "0x52ef04ed449e4db577d98ad433b779c36f0d122df03e1cdc3e840a49016c5f16"), + mustHexTo32BArray(t, "0xc2d4b5973000d0b175631dde5d1657b3e34c2f75e8a6d5414013ce4036d83355"), + mustHexTo32BArray(t, "0xa6e01665b2d8490abf45551088021041dfb41772a9d596ed6e9f261ed1c8ae72"), + mustHexTo32BArray(t, "0xb436c143e295617afb60353a01f2941bd33370a662c99c040984e52a072b5f22"), + mustHexTo32BArray(t, "0x4c4c4b178f1a3d67e5f26d6b93b9a43937cd2d1d1cb2acc4650f504125df2e18"), + mustHexTo32BArray(t, "0xca17f0edc319c140113a44722f829aa1313da1b54298a10df49ad7d67d9de85f"), + mustHexTo32BArray(t, "0x5a6bf6911fc41d8981c7c28f87e8ed4416c65e15624f7b4e36c6a1a72c7a7819"), + }, + AssignmentKeys: []AssignmentID{ + mustHexTo32BArray(t, "0x6acc35b896fe346adeda25c4031cf6a81e58dca091164370859828cc4456901a"), + mustHexTo32BArray(t, "0x466627d554785807aaf50bfbdc9b8f729e8e20eb596ee5def5acd2acb72e405f"), + mustHexTo32BArray(t, "0xc05cab9e7773ffaf045407579f9c8e16d56f119117421cd18a250c2e37fcb53a"), + mustHexTo32BArray(t, "0xe2dca6ce9b3ebb40052c34392dc74d3cdd648399119fa470222a10956769d64f"), + mustHexTo32BArray(t, "0x7477459916ace4f77d97d6ab5e1a2f06092282c7f0a1332628c14896e8e9be62"), + mustHexTo32BArray(t, "0xc2574de3dc8feebfad1b3bee36a7bfe6c994e5d1459a5372ff447ac32dd46c11"), + mustHexTo32BArray(t, "0xb0a8ed99f1e7ab160e0ac2fcfeee0d92d807c8fb4c1678e37997715578926c5c"), + mustHexTo32BArray(t, "0x6c9bfa7c2e0f8e10a1a78bb982313c5c347a018cb3828886b99e109a8799d272"), + mustHexTo32BArray(t, "0xe6037f1fc5b19015b7089ecf90034349e3f5c37cb50dec5356743614f94f8c33"), + mustHexTo32BArray(t, "0x964b85f2b8e10e859e306d3670b8bdc0cea17b97dfd3edc8a9e1be1f127fee5b"), + mustHexTo32BArray(t, "0x44d421ae62038ba15a377cad85e4ecd3c2a63b54fdbb82c47fb3e9c026405226"), + mustHexTo32BArray(t, "0x48c51db949a58fd5f36a19888986275547b0c2fbb0b348ccb85dfc6c998dbe16"), + mustHexTo32BArray(t, "0x0ae9425710301a9241837d624438a5d82edbbd6bf2cdbcc2694ad7db31ef9921"), + mustHexTo32BArray(t, "0x9e47376e9af08b294901b879c7d658c41386453c6baa7c26560c5fd3b164e05d"), + mustHexTo32BArray(t, "0x8af1a51649d44d12dffc24337f0a5424b18db9604133eafcb2639ddcdc2a7f0f"), + mustHexTo32BArray(t, "0xae7a30d143fd125490434ca7325025a2338d0b8bb28dcd9373dfd83756191022"), + mustHexTo32BArray(t, "0xeeba7c46f5fa1ea21e736d9ebd7a171fb2afe0a4f828a222ea0605a4ad0e6067"), + }, + ValidatorGroups: [][]types.ValidatorIndex{ + { + 0, 1, 2, 3, 4, 5, + }, + { + 6, 7, 8, 9, 10, 11, + }, + { + 12, 13, 14, 15, 16, + }, + }, + NCores: 3, + ZerothDelayTrancheWidth: 0, + RelayVRFModuloSamples: 1, + NDelayTranches: 40, + NoShowSlots: 2, + NeededApprovals: 2, + } + require.Equal(t, expected, sessionInfo) - //encoded, err := scale.Marshal(sessionInfo) - //require.NoError(t, err) - //require.Equal(t, result, common.BytesToHex(encoded)) + encoded, err := scale.Marshal(sessionInfo) + require.NoError(t, err) + require.Equal(t, result, common.BytesToHex(encoded)) } // TestInboundHrmpMessage tests the scale encoding of an InboundHrmpMessage func TestInboundHrmpMessage(t *testing.T) { t.Parallel() - // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_inbound_hrmp_channels_contents` + // The result hex is taken from the response of a westend node for the runtime method + // `ParachainHost_inbound_hrmp_channels_contents` result := "0x28e803000000d007000000d207000000d407000000db07000000ee07000000f007000000f207000000f307000000fe07000000" //nolint:all resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -239,7 +331,8 @@ func TestInboundHrmpMessage(t *testing.T) { func TestCandidateEvent(t *testing.T) { t.Parallel() - // The result hex is taken from the response of a westend node for the runtime method `ParachainHost_candidate_events` + // The result hex is taken from the response of a westend node for the runtime method + // `ParachainHost_candidate_events` result := "0x9001e80300002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f3282a8119a659fb3c94c3c951e5215daa35c741d13719d0be7368ca8e089537b5b3704113bf3c0d7fafa20033cad97002e9b9cad03fb998cb35cd71a9873d87a6af72afd5fa059b18e2e13eb3ac6158212b57ba060772886bf962b12034127908e54749e8014a7525ca4eb8815d1565185b31aecb38121e4347b54ccc8e49d13e2a732f9e332e0b425c741a07206c71d801011c2c0a278c87fefbf8064e0631875d1ed14e57816dde31202e999e6e24ad0f8ae2fc830bc1d325e73c3f3dcd186be8e59074c5553d8b65ed0a7034b310abd88b894263dd5869a8cf87e5ef4f0a79985e134020e8a1e2e211afcd5ac9ec6a2fd21dfb5e1c39b3b670f4415e904061adfacb103f25340b938dbfd331ba478351f9173a81134bff8a8fa1c0fe6be68e9025ea1f9f9f24e7fa5437238b01826b451001da46638f62b334300923068d1691f42d0e400b65ae90c283a08ee958a10a0e8c33eebbcb01d137f1612e39973a10489164135f64606c111f8d5d21ec2f8ae932676beda36b07e3577c7d8103c7cf2cf878ce90806617572612083635c0800000000056175726101016f5b6937ad29ad8721ba848694820840b25d91a631d2cf19f8c63ffcf1fcef260d25513fbaeb64c090d371bdba09663f2cd3bb4a8f8f7838b6620bde5c6e5905000000002000000001e90300002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f84b5c6e57a116cba4148aaad37fbfc3edc54e7728b5192a40391d9c8ef33bc405ecd07dedf12350fca80ea9faa4288186ef3dd0b40badbbc49f858a38cfde88c2bf80adf8f3282e527e242daa821b07b2972d9630b1eea6d2ffbaeb90446a8bc62a19241993b622e6321aa73a113c354958dd7266e7e2a28acde078ae276bcf7cad7aa37dace9d97c31549cc22292b650a04cfbcdc44e20c9225d499c8241735168858f1c5382ae1cbb9ece1165e63f01471338afe7714b8928ef3b2a15e6f86fb4ae217da22aa2880ae8d874d21f8852d76ce7d32554830cb82467a66658784dcc6cda49b51efbe0fd184b974074d1258ca9f15b9fccfedc35b7dee6e1ab9e9bc06de0d02e4b3871341b268751813d0fcfbdb0bbb2ec4fa9798959ab01a48dbe9029ccf0aff2230779960fcd86efb10ab9d36ee09ed20b3404b8da50f63a2f2aaeb6e43470084a5205b111c66b80cabbd010043085f5ba73c3a4e0f19105e32274bf19fab97145aca984aa0eaaa60c4528cdfb9aecfc2dba582729ad01ebf8d72ad39f1d70e0806617572612083635c080000000005617572610101ecd027c637c53ee91d7a0e98cea0e7e72f26f69415985ee9e28509aac917565522d428904e56757639946c30eb6228f11feae3bed1e1e60458922e892f89ba8c010000002100000001d00700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f605b88b35bbbc7463cd981713be480f1e7ea1d12b6c21eacf0c120126d24347f57dd8f8b64cdf03c5a171480ed3b0718ed0d2ba49ed0bc088b33c45e9f40c929db5ceb08943ef0f0cea09c1606e0822d9bf9f0a7297ac08335d13c87f28490ad2532a4846d8b951e37ed71582b2562027373adc871ec734cf1b77fd6de383cd5a2b09b240d86f318e67f5fe77e4b3714d5267699515c6696fbf7eb8d2150826f89faadb98f6b52ca914fb474ae9d10ee57c48669ebcf6568bc6c0a8833466f8174c4eaaceb528233d6b6ca4823171880f8853b0f02e6f829444f6eac27fbfaf477bb8d6c11c2ed5ee8a4e0933aa661d2e44e03dc8823cb180cb069463128a2c766b405ebd52f05687eb3288165c4808ab492750a0c0ad69f3d29134eb883cf5de9028ad5bd67ae9e27b97131608d072644251f45c38a49ed0ac3dcdfe3e6c6c9178e8620d600c955c50fe95eecec5125170c2ee7031c13b46c6c64d26278c805e74f5d98a89770c37ca072e8a11ec0adb6e178a689d285b066c93bf63444a1be78977081c6fa0806617572612083635c0800000000056175726101017a9dd3c3f5b3c34e7804b2a4e92c08a4aba153098f51229d81be212fd0345e2be37a41cbe3265e448b8afc03475e33b2b9cb762a9df3e04bcdae19af3aef0d8c020000002200000001d60700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fa23d6b412989d9b453ba20b524d14a4932218d5d20cb57529b5d8481fd9d1717c79dc1dd9fbc475efab87f98c901499443b467cb30fef5e85ffb9429b028fb69b7632d7583557ea812404498c4c544c574b43b952c0f642f208a47c837871974d324446e0b5362729c6f287ae6781da900bf67a02a0675327c8b0c4eb716d79c12dcfed6687a9e1cbf5a58b4d4c1428cddfc93b6031fe5a45441dc6a363f43676fa41104feb13bb292af09d5929eccb40b00b1ba9856a4a7727e3a82f9689c8d58eed3e4d8a61504356c2f5f230bd53ac9ad08605c6366a65ee919decea46ef17520623e2407d6c2a89b4c660b073fbbaf0418452b0959d1018293e923cc0c70ef48a7f0993dd843c38142939ccc1d8937f7600ec33f8e203529f3c0bb741bde0d1e56f9f2bbf7b0f5b44f5a8fd26c1641938379cb13bde0d422c3e5db5675964cd736a2d500e8c1d62f574c4a67bc94e0d38ce45fa94b7fd1af9dfd8c1902f34802a4f849af258f105cc555928f36e117e2efd519ee691784304be5a7c7fdfe5ba3128576150c06617572612083635c08000000000466726f6e091b01ccd9ece066c3e5c23701aef8a8d166534049e0866bc96618feb63b27516af2bfd4c90a72b83065ae02bc073d72ec49901539e3dc74b84025913b2599c392f6daf5109eae1cef4251a2652df775975fcbd3267c254655f0623cff8d48c24d3a0f935472c4b01eeb46871659e4085d8afbb3091dd6a9559d56a889ecdd239ce4cafa23ba44589f0ec8aab1726096d29ee0c9e2676cb1b26cf2da888205cbd2dfaf1d2e87536aa7ca2330a777b9a43a8523bcfd9d9f041d661c688a8c2791fa5927ffd02ac2ea36c1f3f8a3250b94398171098e4de128bcc6333d68e8de6176f3209f66cef788ef9cf9bcdfd1560c5081311c00fa0d4a4d952bfe6c879f3752f7a1015e5ecbfcf729e0713df598b79f1b7981acd0595d8bdd4cf33f3a3b4d44bfa16b0fe8275f58a908984a0cea1fa464abe66705577c82cb660ba42391739003a6ec0dfccf329c2b6d81fe7ea47987e94b00fab2444a1c34eb3e1be1a21a31b6bf0a2c01828ca4247cdff7b0769ecbe0d186ca9af743e0ab05a823ae65bfe7fe871f7d1e5e2fe06d88139bfdc57f9169ae6f869c155bf1dab7d97ddd8ed0b31e2d7b6a1097a9e0e1ebe09539865f3abdfb20d83f39cd9a9ddbe70f2264cc5cc34cdaa45942ce51e3af015302a9a25df2ddc220657322ad6b03e843c24779d4ca45cc4ee30a6830e3c82855458becde33a4481a1e0bb4a548c244b7ecb8be06c6cd182f5e7d3e39010b0cbaff53d43f3bb471e994e01e8e79fba4dee058c59c0eb2364ef45fc1371f62f14dce74c67cafe44cba43cce596b6a37b0044ca9613180029a14a77908f74613db7650b31a2176cfd2cf7ef35e680b45d72bbf45c56a4b8a6327926f708a899548f224faa0cc95e0b58066d7a526f92bf53524d25e5e25c39a9f7523576f0af291e0ae37c7cd5282b14737a46a01b52d5b0a46b7c4674fb28551d2db05d6b6bf9ca560b49911d8087a6898b672e75d9447edf4700e7935cc0899cece13496a9f53e3533ab2e2f32814e36d2162d1316497ed6112c2b8fdb36bad16f697098f1445ccc3ff6efd641cde1b90e8012eecf0c3c5a005eed41d5a312d6ddc76c78b2ddc7219bcc62dc3c2e0dd84ee7c161a2181bd844830d8a533fe8a73ccb7af3a290f1cfd0758182572b5a4b9da22f93854ae35d0b6e79f7b289253ae05ae173ade67ee65f312577e0a1623b4c14982f33db8e10ed43874de707843f49e7d186a0b3ce48f5efa449647f230eb490ce8ab38fb460ebc8b6a26b5331a0dc5224b1914fa1c9a0e98b2092769b3e46066aabe127f3866f55d56faa702b5ce9faf3fbe22ab352469f5f86719624375497b2e9142e12b3f18dbfa0d6545c7637eb25f6f0243e14a7de2a79f5a725e484bd484cf4e8af7b2ad7e781bf6d5cc72b0f14abc95a407cba0bd01c4d47e192d9eced14bc33d509313d37ac40d2abd213d3961547fec1df1ce3450f1271575684cfaaa6867d7ac9b9fa9e939267e11f1bcece14cad2c9956fb316b8e4063db5389738faa82e1cac2685c1bb14c35f2846b1fd44076df9851ff3f6043fc3824e44ec0fd70f684d2140525e37f1ca00190672cf0d3f496d917e4e63eb23cf89aec96c62e352bae3010a165807e51ee2d8e90178f9285da18ed954fde7c7614fe88015f06cd290455c05667c58cd8210dbfb528bfeb70878776e9ace349aafe5ff9340b4598bd70097f8faa9e37a9e3caa2a628e67d83117107e99257785a45c144d29e970c424a0eda79be84fb94287e56f9fb3e746da3847a56403e9618a5420e93832989fb58116d712ef4b1d2d23659682053b38d6410322a2f07444ada2aee3ef85d631e01cfaf5ed28bec9dcb2bae747f6c63e9e4a12a8814da4ec2ac713565574227d197851422b823db3f5eb669fe9ea324f0b939835b73eab6eaf8393221ce5540462b71770bbaa8b77682198e9830f75537221146d306ad07bf3f9de76cdd485a669607d9c5c8c517cbb87730b6e90a783b0f1bad7aac92ae0a0972a8424f6683c42d78400442e9271108953f1d40e0af58e8da33c1d9fc1aa77b572f0672a3020ef1465b1687381cd70e5b1ece01a7c08be69f55b1e0683c1f742dae07de6657e6e88f97b6d3314dc30e461ae492f8e3a180ba1eeecc64a856be520f8198a1c2a4e0bc6d295a2fc13d4bb81ada3553923ece3cb67047b7347ffcd13c6bae49885be17de3d478d3aa8dd2f964ec3ede11d84348f7a40015e588ef9c9a446a3699de1cbe1afa916d10356f412c32e085c3ec0115fd488d3785f9552f893bbe0b22c3773df967b7e36713177151c7c21b9b9b1b367953ab7199fb03947c31a57a94329c6edb9b6ca20d762423fefd38b1ef2ba3f179998a5a5bce656d8b5f14dff06715909d5b7a6343003bf33c0377003d680eeafe54a348cb7815e33c842eb658ffdf3151507e496343305617572610101744acd32f811aae5d80e20534e44195d03abd773156a54dc42204e7c33370702db76b09ff7448955b79a53f0ae958312e2bdaef5a6662350349ce955b8561286050000002500000001d70700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f7efb9393ca81fe0825670473a2d400ac00ad22c1f401a14bc154c5f92ad2443192f6141b3e3c8ff6efa5a85a4433a49aa88b225d64a40a6c500854222e4957243012e86d4a295ca3422a771ca745241b2ff615dc7a71758ca806b1f48525836b78e14daf47e1789603860a916feb342edb58a2b7acb095c4e93a52b987442ad39c854c794e49072f464fd7e0a418d9c7eaa790c89320f830a4919c109dd9795bd4c96ae86882d18ae5a8edbebc1be36c269313f50ee8e1ea30ad62770fe9f88ed5f6cf4e7fe30b0808f01d7b1e9571367979d1cbb8359088cf98ae22e8abab91ccfad85a4a6ce77f402b64b0f0524a831daf156f8af91f9d5d62ce4c687947c3fef1228b81636a938a7a242ad5f78aed0a218d582faa5176c28748621c0e24b9e902757eab60aabf67c35b6f64b7dfe695fa70c9213e15d0cf39dbc547924a5b2ef9f69d630014ff54af3384cb0391d00b06d7309bf0869519cba60f2bc41be171ed2f372f3e1b71a4f5d6958d3b1fd4e43f3173218aa9092f05bac9e7f4cdd4ec490f4d177a0806617572612083635c080000000005617572610101fab1ead14c7c2cff2e1f1ba2f2c0fad3d5a5d5b6c3cfde4e88dde08d978dfa1da06bcb5daedc8e960b11f9012473e7c237b5864609cacc9b4fe9832785864b83060000002600000001d80700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fe4bd11531d6789a4478dbf7a36a3c7d23b58c5a1debdc455e1fbaf1b5b2ab412ec6a464b90ff6ada8a89e3f8d180e74e293a8b2f01c8499ddb1e994293c4c0d0779b68a85a99a3e2d4e0a792e1537c07b3a56fc0a637f1db059d9c2755625b778096d82240cfa6f9fe0dd38b9e597504a42e58cbeb7919c789a917450ee00e73fc355482abce20f5b06ae119b1a9ee79866d5b4854a389550c9d9580a0c0332260e7a1a1b7d1ec159e23065c342070603750ab953543978b4c8f018b2565948ff775ceffb1e33fabccc1c2c6ed03cc463645aa63019a0e9a8aae015cc11c6c4d370085df65a76eb880baf100b4c7401d011a1fa1648876798a747f9aa372d114a81db419e0c739689abf0882f2dc771d2b3f247cad2cff8b1630840b4892b8d5e902dd6b8d78a9a6e1651c21c2928db2b305d78290e51cfbb807ffbf93ceb6b1696b1e0d4200471f7d3b2dbab4c04349ddd829a29c58d75f91bdf56534369705c46523b29229840f9bf10916cad670f0d3727bd747cd737bfcc525bf923632dc5957c032aa800806617572612083635c080000000005617572610101164bf5fff13882bf1a85e593295939d26115f85d9539faff0d76d7be8b7eaa59ea1f86566b58362a71c19076c5ed65d72cb79994091851bd8811193bda730b8d070000002700000001db0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0c743a94cd1707ad4117ab058e336425f029d591d3a0d48e895c732013c7085053dc502546f00302e84fc41e74a7a310c556481c76ff18fc1bbb97c457866b972dc5d56deb74248c917228b08ea5774022ad965420fb4130a53edd44dbe883c91beac7ff23003ff41339e09470ba672bd4b9de9d51aa32ea9c4ca080c6f1f9820e698a3c6c6ffa8523ffd01d125f46795c6cc3c4047c60b36f44d1e89ee037319344d5b89f31dc79f5db9e5aca9ad7925ee5b750c1a78ce34ce503d4fa4f0d8dc38992403757e8242f70fa6e3898ee68b82eedcf933db38e0adfd352a1b6671ec7691f79817eeba28caf545200d0e9df486d47af1c5ac79ddd05aac62546f6f8723aa1c622a8d4a7757a130d4c7a24e2928acd073b425bab04c5e960b4ce22f7e9028813af0548dbba39f8e667b2679069aadf411ad3a194a5ca50253221be0784058e668c006cb6f4c83ba533b775447a77060f2a2fc873d79045329954a814221b7b6d52b96a216e614a1e963366a98b3e4fcb728ef8c2265b2a6a0b9fcce0ecaa41f094a00806617572612083635c080000000005617572610101d8d56b387d8b2b434c1c4d2186a48765e9ee91a39b214c4808eeb9f3461351196740631854c04bcda5980e50b7cb759df2f64ceae11f6f321ed05f8e6323aa80080000002800000001dc0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f08fc371c2ce887eb3e132908c4dd533583177847b8434f5c7c0cfabd4852c24e6c7ae7aea674dd4bf6796cdc2d337782f885482bce24c9030e87b11bca54d7f5e50b6d38ff0fb29a9e76bdfe49f6f82140d112c80a357002c99a8941a08ec62190d3eda2b3ccfeed95db0ab62327db71f640621d80c753b4e69db9868dedfa7da60ce0b09e321b053d10dff1b04e435472170d760c41282be74154810f277b1360cc17225d667bf15fb35266c8cab27968b58813ea1ce41baede882d43bc1d83e973614a3dea1a30b67783af1e57f732e89eba9958b0fcb19fee08f9a3314eb9b44a574641d090ec0cf776b81af6ac92015443353b22a7db67f42bc7347a67aa8f846aa19dcdaf075ea1af3c7f1b0f66b33bf8505b7e94862bcc0c4f6e9eeabe890371dcb58c1c4fb0f5cad90c3ca6f598d596f8e47005536da04f424868b9963e9256e1d2002610491cd018b9dc0c88d6c9790b14b4b866b6e0600feffdc0c94c667a68c14f2264ecd4a757b0f14bf0b6d9ba93cb7e2e949191c86ee32c5402d158b85fadaf0c06617572612083635c08000000000466726f6e88016d1ffba7d4ede2a4c73b3740c4a775da3a0a1fb08e3b989ec5e49684d663be2700056175726101015adb821043ece09a08d82ae2cef89f37d7ca8f4f9350efeedc12db5884a0016763c60aa38c1abfccacd5f9ba16c4a8ab93f6b9177479100d0b6c975015a82280090000002900000001dd0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fca221b74c8d32fa6a45bdc2271371109a97cdbe2c82fcbe452c548874b7dc1665af5692ca9a27a9d2c2f55affabdaa466fd435945f091b45944e0f0596984b664b7f5bee6c782d18ae489b645be2afffac110bc7bd97840260a807550ee056ca22a4b9f9c32f4c502ebe462083ec11fa689a7f3fd948fad1e3cb5ebdeb4737c7ce6a2e873ae8e530de6065dda3890084d568507ca5d9a69df19683805bf5d24ddf938c7c9decbab422bd00c4757dfe18489bff7e017b40ad9552871b9a7be88a4e315ffb734e34f9c25170faa579eebc5b74caa8cac8b1b87827e84055b256d35c644799d29d2e6f4f2c065ca606744598719d85f8c3e7c4d39abc3ea59be4a35ba689f6c0af4bcf5988a4580840e313618deb3b835c4e4a78cc56434b2ed6e6e90231a890359de5d57ef9864cf19f3a48c1fd1a63812b0765661c598856f956177cb62e8900830038feac3e62aff1f1333ad0ee8696a4558f6cc42b876e0603d703ab0d7f0eea80b0973cfd2d3a59268bf68211e1bc014bd94fd917b6e9475c3a78508c03fc0806617572612083635c080000000005617572610101b86bda32f157f1e933143a934f6505a6690c0a31dc52bda5f49d40e5e26073545851c15949664b7f55b8cb2163a3caf7f487d8b4cc87752aa3b4f40638c2ed850a0000002a00000001e30700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fac991d1eb1203b3ac74ce441fa62e97c8d7b99628a85cdab3806bc68ec92131490b0d19498a2d0ec54c48572abadcde6a5a2aa9ed3ab74314fb4dabe30ba6408d4894734e270af31d21c80c4e9e3fd540899669aed2f9bc7fe28891bc0fa6ff9a58ebfa37a19b1e8479d3d41c7b78204d9719c8ad1212ef0bae7f2cb82746ddb6816850f2467e875176ce398d1607d13d2f458526126a222d47f10c13396eb069577928443d3ca93d4582e1291c0c7caa7bef8c1f39c9863385e472ff1e9b38d85bafb3d2fe2ca2354c2fd1fd197b36bcff57292ec4e7b8ffba280227b13aa0247ba47d4824fd30328f70f64b056d4e36e3b75594d6f590e1b85e90a65f9a63ad6d42232ebb0628b11aa6a5bc31c1b8ac45f683b0290b14ea725b2b53ec8017ee90265f1561c96e26a3ac239745a0746ae6fac255bbc9a19aca4765900819e7a532c12d1760059118acf89d6a62c0f724e283081c8bcfd74a1db5435983c6cb67272699024dcc1f7c4089088d1fd7a4ece328c3611ab9219a8e0f43240841673317a5d3932a90806617572612083635c080000000005617572610101eccee865e2c48f93bf2d1ef99bf22549e3994e74b2f91cd00e742be73173cc40e5518cd480b62778a627e15268c8439cde21a27eb24fe0386645a5b11430c1820b0000000000000001ea0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0cd0c3ce103900b501fc82da6f8999bfd42354f8fc4db6230a764b7926c75118d570816caa86a63f7fdf4d0e0cae604060a1ca4d53a6bc0aeda87d1f5c28918b5f8233fecb446796519206c3b97eddddf86237cadeded98b041ef6ff4e474e53287a1697c8caf461dd58930f749d53af8832c488780a012590b005c36eda0d6e16c775b8eb42663d5517b3e9cc198e9658421ae7af2a76706d64e3324ce39240a32fc27041caffa0ead9c0064ae0ace86242f8074273018316dca50bc96a978da3883c3993b1a32b26325ff85be0b63084960a8b50132433176fdfb5c6ffc07bad1936428467f481ac53e71165512663839cf61457fba5ff17ed63e71b8c717680a10e1f33cda8f8d81c50c91152776a54b50195d6ec7f0d4bda452f9ac73012e902dc413d61ee372b7bc1305b79f10d3644a42c88cca1c4c8539760bdcced3d8c2b16819f00b2faf4d0fcf22d03a7cd76920487eeffed5b599f6cd32ccc9a64801fea2aa079feff2af002f0a71bd1fac90e9fea3a0573a5bfa2765a3a931bb5b8d55c9717290806617572612083635c08000000000561757261010166e2910c9513e1dbd2a6d3f938cd6a6253fbb2cfcf6a1f6cd76a8b7941b07b36824ead10eb5d99188c749988b49b9bb673571fac8b9317235b89b8d443a5fa860d0000000200000001f00700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f0e4c8eb3dc54e5c0d1b9402f44f89137c1c2d095bed90ecbb80e38c5cf245c4828efb3599bef57b84619255f76f0aa168ba42a0c7d3a7e519bcaa784bf0c66e38b0a4168467cc53f93902feb5d97440405d82d672f86e440c362301c6283263fe870ecde7baa2895003dec3d07836c095ae4f3e4a05347dbd7d7c4eee1f811e18628cc961b32b53e4cdd3a60be566fd3ab6a686041c07a8d4750133047a6907232365380453504c52c6b96438fdabd2d972e3dfe6bd1e9bf0f254bdc07583e80acfe461dc363714109b6e04784803614ee2b00967cb51eb899327193cf485260130b0b9ac802b3db074f304ddc428950e80ee3e2a14d9f009d8376fdff493b7da24d7edadba1d6f9a8bd642f426851bab186b7aae7eb8fe526b05e362b996704e9028625ec7da0150afcd6c1431ed2e8b56be1dfdbbbcc7e3eef1275b5bcdcf5f4091622a20013b839aa611349e4450391abb30a5e0bf166d201351ff2eeb43d5057714a5b6c959ed33b8bae5fa99ba5d0154e08ce851e94502c8cd069c78c0a0d748ba782160806617572612083635c08000000000561757261010112e21a778c7c5404d9cf20fb4ecfe2c06b14e3e5ce45c76619077a2d47920b5e2d605528db37f2d4724f811429bb3bd308c9a20ac0d05b91329bb6b49b3f5a80110000000600000001f20700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fa6703abcf0fc554a4cec1cb5677c287f06e3bfc3f74bbab462dcc1062c88ce353939f9e6aaad990f2c9837dafd9f5a22c17455389a73f05570a74aed86a63b1ca65a09155dcea6eb1d458cc292968124a0f9b2bf125cb797ab96086dd3ed40da478e5401533e30c628939b081e4e383a28a6890ff949d27913939b7bf5d9c4dc0419a23af2d8a14090a06412179f31a575a917c04973f1f645d777e5ec48c938ad24670905b57cb5e29d8e2b285fd25778a69930cb1e71a366be9594f58c1a80322a31962e767ce5d6aed172950bf0d2ace5df6050df675a4e6a58a4c308372d89fd8d101e7dc06f0ee9a515dd338f2d29098485ffa2c2eff98c6bcdb6805b483ebfb1a48db52c4f8bc5cd264c2746ab4034bad57e11be369e459fdda1bc9810e9025375b7d9d546b18adc6ed91373ba5ca0a1e0e2549458ed06d4a9ff337dc4b7f11a9e9700a5ac8cecafd414c670faa4c56cc84c1efdfbdd63620fb2afb77983d5bf004a11177c31f7cac28712d992f31156ff0627678961f8ac57d3a41afede86cb1e31d30806617572612083635c080000000005617572610101e8bc4a1acbda300bdc4da4c20caa87ec14e7d91c04718c20d677ba82a2adf422e72d52c66fdfa17eb1fa426428ea9f015f8ec3b4dafe3b59e9062f0e8a4e3580120000000700000001f30700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f12528c5a9d2d33f06fe0197fd72642634a924caa92f954c84d0b30a5af9f621282ef2d609cd65387717749105fc4e7266cc29d8fa13accb72282526ac1e28f285f18f4e449efb717850369313139477445e5f16e58c14d5fb079d1e95a4c15f9bb6baaef2e82cfb97712dcbcef475efdca635371ff35d5e300090491f05aab135cfff964324889a26d9a999c5644bfab36a5f2b900df8dd33260f70ff4685c212d423273981adabcb2d89ab22068042fda0beb26bffb730348f31d3d739eef8ec6b6f7e799362b07a29726bde1d02cd6fd231852f6d0df84695832f70b69df9f724160bbde1c8a99b1f8014f200f6752e90265361f4c1e55a576e58a0a1ada06c73c69f77b4076a93404329f96cc0d9fa7ff77bfd5e457f1caf71688c95cbef6e9022b8b83e8888c042d9e2f0fb1a9bbc456a8b07a9572f1e4fafdc8d699438a9bb296be96007d6837a96593348603378036a8638aa191f7164617e732af28d26929f83245736740228224f3d42f71eafba39c8f4faa94a01a589f51929cdee85a28b7895f760806617572612083635c080000000005617572610101a2f595ba846acda337e0a6891b3f517de907a15ae96920676e7aa300c603d903091eb30a8613fa54a684f1aa488272ebce844a5f9c44a0c56990c60f6149e882130000000800000001f50700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fba252d10741845a93492f9ad5fcb431e93c51be0f71ea6a8bd164093d4fc9f06df0b8c4567e4808dbbde228cad475e6060a923c214a5c4636f556eb42a7a4ba91f04569f398c5b44d0aa5cb46a0e95f958b5a3e8352da4092daab9cd8c4859bfcfd415dec6748a823e1141a8ea36b283cf6384420f9bfb21b22579a580402394ecccae790c40a892f3417def8c361ff5a86b33779c74316c77c548c4612fb838c362ebc4332cf2a926e56af72339da43cf00bfcf190ab013df11fc575919858136699ab86fbca58f8f5aed50b70c125329af294571a4e1172e3d25b8d1c0894079c48d94b4f1140f83e68d0517db11f4d29ed81a93ba725c0516ef4d81f2543579a1430ae725802df267fe527b925ac709ea5f238c6b87cfbe7ecaf751855e688903d303d17a8af293a6d14b5f06dd6ace4d5a465ebc84d372da88b1d00fba851237864c8b00f9c1ba4d0f26ecb08528e3c156de07ee51cdbf6fe50c332a727d46f303f688f8ef451f0175c1f5902c4200a374026f4e1b73706cf03f33dc1a1a2fc0877346cb0c06617572612083635c08000000000466726f6e88014968c2fd312c9100837a25718581fa2438136bfce75918d9974e85bab2d26a6300056175726101017a5c5bd08201a067464db34a431fdd575008542f500582eb799c010c99c28f325a1092ab8501da0a0e9dcb07dc7eb849c6ade998b512282ce5786fe3b84d168c140000000900000001f70700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fe0b5632409e78aba11d0d559c96acff0247194879afad0741ae3848f61e74a02397ee4075a31cdfdf00c080c5ae192e9a8921bf216eec48cd06a0ec54f3728e627e68a325aa980ab408e110b842221f262f65fb9c9ff3bf2526d7a454e1f5bb31c4957f9abac96eaee0b0e4592b60fc6abf498f2b216099590c593fd2d6956525001477ea73bc4f27bbf93246c8ed89995f7e69d9e003c4b80bafac51cba1b7a8669945a41c3693a006a1cb8a9000b443f45cc4db5b1ccdb50ea7c8d7330768b445c9a763b1e6309dbc77d14e1e27ddb362cce7ef9e4023660b6db4e520bde91088b3f2153fdc8dedb22d5984ca5773ab7e794d3a9a6f700d1fdac1e54ca83a9455b24f78b25d8dc601e67cb9c1a60ea2e7e907576b4579a091566ce062d7b9fe90294e33d043375a9630b8b43a8176a4b8620e3341e1e22e9ea344ca3bc8b6d989e86ea5900c0bac6b93a608c8ed70554e38d2a513b20072d9f2556008e9cd917066c54e371326902973308c86b18c426b4dfe19c571cd158847f719b5b23daead339f4889a0806617572612083635c0800000000056175726101018a4d75e4d4af8ea9dcd1ee5c8d18659be74f9e3dd4af5312f566705f7fe08f03b6453775880c2d6cc9552f0c99462de4845de92be70ec21d537143377fbf4e8b150000000a00000001f80700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f30cd84fed2904f8f55b7c41d0638af65a209ed81abf76645862f999e1900273d800e3bae3d3c043d319ff1b86f66954e336dfb77f4f62e2cba632ca321a19edf3f600c334e02e5f6ffb1b0a482e3d1ff6e8da744cb98ff90f4e32f87f038cc682462c29e53670de6368795f8e42b58b565b4b0edaee2dab8a1b9e7f2c5b485b4ece9de94fb93817787e0a41ec5703599be3d47882754fd9de578996f9c23f441060bc13cea84d987edb6859731738ee0046151a27ca5d150d89d09dfc33c7b8ba56677abec76be5329edd0100932d6ad28aa84ec94ee0f38fa28dcd7428370186c113fd2ca1d93c9c59e2047eea8b9d0c6d52e15c73398d58433ecaf2c85274ccdc35e3d74de2af6b8b3a2af12ca02f9f14c0a168519ed83cce058a4409204c5e9023d756ae602b1db65712f5c037388b6162cc31b73268aff4572f0b02f706d67145aa38d009ee4491a3c7e2d63f2f2bdc16c70244435ca7f4b86b282a82aec767fac5f02f7489304e192850975b4acfbd1825ee836b803947e5704b6dd1ff7c59c44adaf950806617572612083635c080000000005617572610101d8fd11466fd2a4ea198104ce9c2d273b49e32dcac2900be2313085c941ef415464e0f1fbd3431900521af212814b266900a8a95d2ba9fd74db69092891ef1681160000000b00000001fe0700002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f007a3643f15ab58061fe650dddb783e26ac918157f6414ceafa7027500721f43b043862b71d1dd71242ecaaeccbfb79a5d742557eb7ea49c6f6c9f8a4d0f3057c7b4ea49c745843988fc3e575d3afe2433ae789f87be82d6aaca8f8eca674e4c2c7d5e2ea06f6b1768ca7fd09ae4f4b40866331a4da0cde2d5092394f50c7f58500047700c9e0db25489c6f932e40c357e945914ee47ca84666410e7d5f4320731aa082085acca46517147f2925244a62cf6cdc12e0d1dba722ac51ebc034988c2d2ba2d6a33d8c373a69d92f154d8b404c16f73fa872a864488126f84d3168b3f0f212826e2b9c0c9e49fcdd3d099bf3ef8d93b11c71abd2601da09acf1f8fb139a332d9a5601f727c537d8edba21117d7be408a87d6b9279dad0d31da1dea289033d2444574e1a1ea77abf1d1183b53dd83993c39fe1c82e21a2c331e84673c2d10e7e0400e6bc71df504d3496437a3c4851298d686579cdcd6a0eb507d3bb3807b10b483abda468fe3b2e3f5c42ee4223b991b3a15f0f52c7e847691a692c36791391980d0c06617572612083635c08000000000466726f6e880127856dcce783370e0f2f8d245e6962e65da80ac30e97fb2fbe2fed1b290f77910005617572610101e6ee0eb043a6b5ef5dd2060a1280d0c51cb63c1cdd386c77f1b03fbfea95741e8e4f7f250c9e031120c116a69f5091690ac472b19bc082d2b8955711c28d508d180000000d00000001000800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f4c31488e9125c86f7c78b1174f11bc54e10e24d63b075bf9edb77d7a521b8a7c72aa802d70982fe9261673dfbde97a4e0085892f7e826784a62e974449168d280cc6780f3f88b07267c5bd28035c1ea8d3c7d57bd46c7aea9f3686d5dcbf0e5cd67ae5a926a93a34221dfa7965bb1bf5bdfe550eb4302b952a19747373223929defaaaac2a4312b976551770dd90b277a0fea279f4e133172053e186276ea502a4c071f88e10a9fea38468083ada172cf4c4b71fb676cc911d061b1182557483e9bf72a5cb0332c44eb9f1c9e7621ad6edb850cea38d14550d91a326c4501a9201ed82c8a883f444d0300947104879b646d005468d5cf853725170f9b358bd5ad59c197ab76485206c59f36a6036994dc543aa252b11a3c056814311d27f1404e9024f2df319184d0dfbb1db4f4259dd717a98a856adc2a8c8912efcc98fdf4abdfa2e002d00399fa53f7c1f185d8427c874a8f23b13afc475e5cee1f760d46974e71a54ccb2d353e4aa9bb6d3b4a641c9472a2faefe5adac9bd04b36beefb4168050b77a7f70806617572612083635c08000000000561757261010132730fe531d29230b22a9a0935ef83d80e40aff7efd8db34ce12604e23492d3ca79135c8bd2a4df2849c018629b7aa544222db8ad821d0f04720ee11e255a48c190000000e00000001030800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f48c1b5e26d4c749374e8f69ead4a5b953951cafcbc541903b9ff0496ce82796005d8114aa42d92f25e4aab90e7c0e5bcaf8e0b27364123b0a0442634aa351e0df5c0abdb50c18e3c20d85c1c0d85ffe9fc4b3d2fa6334a888f89fda67fd34125075303600635530959cfa99e3dab3e4e48746930e6c4b416c857d7974b5dfd703c0ad6dcc383bf87f8204dd9c4204e7586a5048bf43854682d5e6753e824c0358e2e245bd9ffa05c64f572f7ff97753222ace44ed6d7599503a4d5b0bb4674819ade986462caf64eb706b9dc9cac0f23d5a9ac8784f067d43663b936525e949c99823eaf56a8d5abc4a8efb4cdcf6f72330a94b423b765fb0267f6be2fd343d2e68724dfd57dc416a9e429bfea4c4265c30f8f3420f1dc6e7ee002b7d73edf0de9027005ab65c401c5eaafe10bac663bad41901d29b6303401251affd054103b251c22b24400e801ed65820b0cd6e8deebbac787b371c89060775a0decfc2a7112b01c51ef7c1e616da83f89c8305d421b535e08d1b33570743958df7c712c4adf9c96cddd330806617572612083635c08000000000561757261010146354b89f12715e609b5e0a272b1e790070fae3c06593211bcb1fc0c40d9806fa21be4cec44a86a847982f6598f92ea1895acbebe39ee857012ef88fc80eb9891a0000000f000000010a0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fc00ba151fa23caf3a11590fe480f8713e26df35213521f26010a50d2da4d7c7356448cf00a57c405a2759052775a9ab72ef3975fbbfaa8c972b777958774db6c053837856a44c2ba69cb62bb627f28404b1de1f564f254f1a9b3d34d5b698f697ca16b1f5bb61e5b6cbbc9414a5bf0621ed419b43cc72ec90edd901a648d92f0b65504c69ee4a2793b9566effe4685816cc9e9b5afbeb574617a44181f56f84e9485fd594e5a541005820e3fbdaed7713dcedd4ba1c39ee31e386cdab27ea68b95d5c4474278dcea31832321ab93eb6b9d8f2cb5fb75a8e03cbcfba0dc6d495a900f07dfc7cfa4567f2f8ee94fb18793c79d46f233331913516c82a8ea379095c06172eb64373f8e6e622f61cc963278de4558aebbfcef14e1146d85964197e89501ef226b220d0a9f3ce159cd9fe3ce808391b3b90055c3960918277984e45f4c249e9a01006070e574c692886332a9cdfdd2bdbd972889c16e16354f1e470e52bf36db81d2bc7851c7622decd220c83b3668e028145434255ec44cd50cef9c25e5b868e92c001f0000001400000001260800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9fead4b15c40389b68b80da252f1c64ccdff8b7deda378cad3bc2040df93bc0b5e7252eaa94a54db1b10710b81df91791d58a801e17ac7e6c5be9558f6ddbd3c555b19f587cb3e1436049a1e54564e1539f558a5641e3822542ef04a8029f6c03c7cb08847b3ec399f336d9532afb4a312db3b0226c3e740d12b274eb378aec9f87c169bc67da0715fb92c783b5b8fa646489179f8bf7e4a4271fa7d6edee05e74605c69aee2333339e8a08abafeb357a0281a206a64d184dceec971d6d55f248b741ed705f509eb20a558dd1772cd34ff1359d80a4c176982169f7a7f44e8250f9027b2b9d48451380121cdfc5a041491c3fb5eefc07009d1aee921df7a0599bc01034b5e0124a5042e25c42f67aa1303afd59571d83ea865eb1a3aee512467d6e9025befd6bf43197109f64511896b4ab95b2bd221e6810459242b4053c8284686e822d3e200a8f49a3d18ac36932f3608c00c7e004147b3868fdb6d9fa0d431f2ac5c180bbff6f0a28f55b64489087c1e2e91989c0b886fa55e5ca22989fec8626754b531320806617572612083635c0800000000056175726101016c40c4eb4eba5a7917edb38b4813bd5160442f44c16f743b1ab83fbca0aab837686b92638dc57ff1280973721c79102295a43260c4dcd93a6b6dea614077ff812000000015000000012b0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f7ec2f69737ac6304d9b45fc7bdad23a6e8b6b8c35c77226a9270a105205d5816f8f871b0e0903970117dac29c057cd2d5090f7381019703f20ef82e38de9484d4487ceaa35c2b85da43887dd27238c4a77a28d76326c0bb44244f2fd51fa8ec2298c0bd4ee975e581149da8c6b891bb511a5ae7f5b1794b58a133adba5beb7a75ec607a812b0ef58815e341279396158ae4d5234e03f750c7039bbf2b8b31c2ec4e675c6f7dd170b2fb31de633e340a39fba599e45cc13275825f7c505bc8088f059c6fb23e2e6148346053ee02154cfb8f1eae02f04419e59d9e23ec672d96610883519517ecee74ee2ca4c3a7d47ce8dea260ccfa1542ec8255ba9eca949a06f1c283dba5bef677dbbbe5b25fe5171ac3f48bebf64747f70bb7f689c57ecade90254ea986a37d66353e404a2f75415fe3470a1b41fd447a220d33953b9284c16d83ea543000d8737c8c55fcd4c37ab87b7558e052dfaeacdd7cb168de9064e583276e1a7046e68b68199397af29e1c83f02e4083890c222e4da2b762463e62a870cb327adb0806617572612083635c080000000005617572610101e6ab5f369c205dfda284a6744f7a74a83d94369526a4126c20161c5d273c81053f65482be2ac6e762d95a8a5f0e0474385b10e52bcff0b4e2116d9128108c6892200000017000000012c0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f8eabe2f87cf524db949c7ce4a300c9943d5ce7cb61eaf056407256614567cf6808599ad0612f70b2011e286f46bb6499e08a50a483fd8f6dd0af19e1596945f877d87e4f34c7c2a362ad3ab7860336ef91c50037eb839a57418f6989b347c701e0b8c7d6d75a732aaa50c303c7c411e87bbb8479f3afc1e31fd7713002d275bb7a0ca5e2cb228b6e38d1806487741429d1dc70ee946a51c3ba3285432ccd0b3dd07663c15018b3931889fc09646632be942a7ec9e4764e9aaeb031663f6fc380401dfb396fe48d83b1d0d25eab92e1dcbc61365db4fc2178436ef2b7b9ab29b50cf12be580eb72539ac227b4fe392c8868b2feb21de9067224d77fae5f6769e46c526f8430531d3b87d1abd12f8df54b0fe7d2e5c6c68c7d45c88eb6a8266ad24903339562159a30ba82f5e54db05cfcf1b517c911492234e3698b3a25410f07a55beee0af0018bc9c144df2b89cf89269120ac2db451dca153e63509b970e86778f340bab743fa69abcba4b75ffe19442f27b7522589c8dca513b1bbfa2ceb2dea2358fefb908066e6d62738088197ec695687b3c54268b18d071a0ebb4323e84179ba664894124beefc56f52056e6d627301016609447513272ebcb0271154883e924a6165a990dbe10ac8f63c33dd71124432c2bb3550926a2c1edf8d3f392c22046af6f1e86347864de3465660969b55a3832300000018000000012d0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f66064f3465604d64246bf810b9fe8e49a1cf470be7263b11a699edc83a9f352d4c87742fc24e8aeb858e82d633c5d21aaf645efce69123d14a5bf10cf2e87b829b622d5143362571270ca3f4f451bda43be9f870145afb34e3c3a25c97960a255c35ea9c5f11d8b5b87d7eca9b38db17bba211193fcb4df872dc755078e4bdf096a0b786e3efadc128eba8062eb163b018b1763689f1765872b64a88a4c3103c4796565257c6f24d0ee68e26627947ae8d033d2dbabd19d2f6796fab2a3488814af90dc6120f52e8b176ec45828b93ab9ed570537cb311f3006eb17a4b04add9aaf8b111859be1b3d33934ee9bc8a6fdc2bd674f5236099d42bf469cae8e9dde924db656504ab1637673c75be1d51e171906c6e8c12c51a06f6f89e712f7fa19e902f00e5727bb4eb555d4a4f5140b82f4d72ded6eff3506cef9f2eb8b57e36d13f732d41c00310b800ce61efabc623f074c2f728d6c7c2cfbd7c2be565b5bc4943a7a3bb2794ce3e5a2cae2afbc804926c92b104ba1e8eebb2fae209f6b244ced22de968a4e0806617572612083635c080000000005617572610101e81f196b8d3114ddeaf9eaf15d34be8e9ff43db5e25d1aad1774d6a819da913919f6f0b6a16dd668e2880547df0716338b7d0a8bf27203dd8b8d03c90adea88f2400000019000000012e0800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f723e5619fa775cfa0b85ed1f73557d87bfaf34c269c00141e20a8e4fede6c76c8148b38f39593ea9b1d336460e35f225c624104259c9e8338b6f7f74322dd1b8e18091df02039f421e89714802f6be2f2652d714893299798f6f059c5a37dda0fba4bcfd13dbee90229d0771f973af9995468146472ac6aeb912116b4d8bb5ea147bfe6f234a1d1f7bc9d4f10656648269075b7268ae6a243a1a745c7c85f077f2a0fc35b52911a0984a7d2d8641e25952ec16186995a251213ce8c932d3008a05530d6923ca084b8837f15cc4d4dc0bb3c63a1921fa15ec9556ae3ff9d359b1647a0094fc9493f16cf2deb282b73f53985acb3177cfcec28a6f455ef0b43a6eddd7bbebc1214a12baf9cc2bd7a46fbc1e5204d6c192fab5db3fb53c0304c3a6e902acc812718e754faa8f3b4979311ce24e7a9510bbc1160e124e881180d6f678c2debb20001d57ebbdc54d39ebc6c72bda6004b766154578ed841d357151fe9f7b7d80c42d43197f6f6983c8e53d10ce0384d8830a6f1b2121958dab34edff2a7849253d620806617572612083635c0800000000056175726101017e927e09f71f3a2af25d161aff972a98f588d4f42f84a28d295488cc2ebbe024223147f58a7afc121215ee03e9300d5e11058ae1e7f0e80f675967c1367e8e8b250000001a00000001350800002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f1c3964b2c71a0c5fb5c51687909a83cbaa4e94b907d2518bad392fc9a5a7ab7fe35190789786820fddab97684b50b4e8ce0f3595106ab256593fb1cae9ec8c9656a2f0d8e332d511e9b80f31f01eb57248a1a68fc87f8745b71b7d3c8f81982981df3189ee192b2a32bbd331fe28d70851d1d41462957f232206c470fe7c8e0be6133da394c2bb60467b7764e7648794626315f4f2ca7028fe235b0e9b47c33a974fd23cace0213c08cb20565b61ca4bcb3c0e5cdd4a20cf290b0e58d814688d0f34ff3fc478732698c85d8ddf6d0b5bd428df77b267a77999f6ab24b9728458cffa7727cd0ea5c03a212dabe51c377dbd53f0e7f0a1ddb79033fb3d7b73c1db5558455d3b6442a3da1f7827a645952460ccc5c3dd691bcae64a2d2668fe0097e9020425014b3839b51b99be80baa9dbf1a3ef01662a7ea51d6cb2da23814ae835357270a9006870fd9e022c9ac5b4de06bc198a481ae60f3909b8affe519a6c04ffed18438f3c163fa7c3cc25faf40c18eae7c40dbd5a27625fdc6646dce86a5773b6ab6d6b0806617572612083635c0800000000056175726101018c3417489b99706c04255a8b8648f2d6b6c701576dfd25ecd1de9d3b1e0cce4970616567b06ab1190b95a95572d61a4ae637ddbf7bf13bf648af9be585166785270000001c00000001050d00002245952bd39fbc912d3bcf6ab6d9c191b5c9df70a4e1da6f670f4761bf96cc9f54de495b57c7c3505c62633f1ac3a2f22be74ed497a5884379e0821607d9173beb5dd269e10d71dc754ce3fac591364afce61b007925730544bf530068087c7d38e3e2cd8bdf7fef72ad23b076e0620ab5d97d3c0a98207dd8b6af8c3becff696cd2c59aefd1a3bd654df00febe502e9f6ba788b8584c7278c47a2983fd8e87bcea2f2c3fdf7cfe328e695f1a111ef699739c5054adcfd40969c673b39080e4dfa869839757fab6bf946cf5695e1a0d9335ad95e445cd5fe9988a1c82fb53c83fedc8cf6b2555199ecc95e7092742c5959f96bce04becaebfd9266f7642c23d76e25771c2505f549b5af7734c84213bd1fd39278fa8f07298ba69da55a5c70899ece96d300d33d733840cfd4035249b50618e4e81f1cd425bd304b0cffc13b8ee902e66008704ade0c28fa58a8abc788e7b1c3ef78710408947dd4fb2f400effb2344a581900c5c07c6729c92d2b6d2dd7b5e6a05c26adc79e138d57c1b74a2d42ff7c021eb3f127490b8eef8e2c1cff1b685fc398f2dfeef4554328f288259cd9de2280e3200806617572612083635c0800000000056175726101017e7b7d496aef40f4e44a8819b2652fe2d64d286288f21f25a08b31f937d82c7ad7a48673092c23d7a2aa5cb2ca8dead00a2ace14361537ef7f338dc51f34bb842a0000001f00000000d207000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43216af2664480544590bc51a68be4ab955ba1e9d66544fb5ddd87455187539e427c0f0596d61ef285c22dc8d3e2f29bcfa542b00f0474045735c327e32b81a1e7fb4856020ebb9fb922899fe872508d3105d22f9749a0ed5cd6a2ee894140e1bc46ea832c2ab3e85936053ce6b203eb5396a696dc8d4977092004738ed02c4f5504a932e236c018a5ffcb5f0bed02fc84ee8a1d18fc7e02bd2550ea4606e043e4e6018a6818a0dc0acfb0e5ea67880a8e20dc6ef1f7399658c2fd4a7603eac9085a5574ce91797bfb2df82d4939ddd9f8aff952e1ce48b1d261c97088dcd5c86e532283647ac87830d1b136bce5fe3bad5acba67add2a89f005497d93fac9e5d2088e825d7969dad2cc6c04f8c4a6e65b5002877aaf6b7c32d0943efe5e127824089032a6b0cfbd22318888f75e0f1d6fd92d22de5cd8fb974579b68a848ee1a394979c675d0000e427f6dd8407605cc5ecb040ad322f127d040c84616ed6f41af284720d7c4e289ca21a7e551c98bed636f70900a463ebd20ae087491f8cab4b90668e7b3bc3c0c06617572612007c7b810000000000466726f6e8801b1adac139bde159ecba683741d3ecc31221e98eab5a429f3bb3f38c553018ecf00056175726101013c7952f659e18808ab2c763a25fb0c7532634085cec8d495f3030c6c3cb5b05722c5143a5dd1fad4f7d84eee22196d845e2e1309a48eba4859aba690c2e6a083030000002300000000d407000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43228919c055a0f2137f13690e949df8f7d97d322fd990946b698f985989116ba7725269c36d48994939f136e4118d4344b4ec13a8c468ea71c52848177ee200ebab55f213795cf2769a0bc7d5ece59be01b8afc921529684f158ec31c4bc58eca35e4f74b2e3c8decba237f50ffbfe45753135891432ca98e1ce2cd1aafc02e67a80d7bd3ff76b4162eb32a149d0673960080c609ace1755ec2f60d6edcdd79309b9bcefd1b379e2291be3ec29e5429c11bb5269d085ef32e86996bb6086f9528541ab122ce2a5db613f84f3b2f96a7dc6bc53ceaa18f6985f08391a449a440c6332e9b1f9c0b02e36ec11b5167c7e7a00d24222061b4769e03517ab2e2ee6170c55a25e183e83a80c3d4968040681b1d15366669926dbf45ab4d7a84e553e426389065fd3dc2ad1fe4f17b0d3bb1bc2bbb7090363c52706ca6509f14a6a128d85ef337e52d5008cc9bdf131d19272e7143953afec22aa607608e1399048c920388988e7834c68139f2af193d65a5517524c47908fc3a6a6275d581dc9661a5594a853b0aacbe810066e6d6273801ec11d2d43768a4d5d45b5611db0b3298b77621d26742547fe41ce91c0d661260672616e648101ceaf24ecf730d7e039d2de8aa45733921ffba8cb0e7c6f75bd06d2591b901c77b1e807742745efcbd5a57bf08935eb21cc1fbeb85d80ed7c615ca7d35e249a07bf6d39c123ba9ba0bd7e75318040bc489985b106d6c98c5aa5a0811ede08f9060466726f6e890101ff0a22a78c0683078446688ddeebbc95a99b1884cd22a8201bf911cabb18059908309e9c2c6a18f7387da2ee66bf312501f6b7d5c7e5f0b9a17df6a084a87d334c3022239463cef94bfd88bf8317dd9b6cab00f087cb8df769cb6bb2c0d0f1d312056e6d62730101d6fa19a093846a11dbd3b9f26dca8a0dcdba8493d6b346b86486f3c54dd7ec72b46a8f8d7d17f1192788c741d069e068c08eb0c5cc6f6aae09d7548b6faabf82040000002400000000e507000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432cc8a84b06644b0fd1e790c2de73d66c562f0cd3f6239d81b25cd278e5111266388a9171ad58bcbd15396dde9b68b6aeb9a7a6a5b5c7a47d77603f1889cfde56f1ac40ba6eb288239b7dd9c8af7f2b9fb0795cd5b28820c87180e3d735e7bcc0b51df051cf8f33419ca0f07f31f4e8dd2ad6f62bafdc1f0c47f9b727603cda6ae34a3726a20df66d660d77f1c01195a112535db1e046a4beaef91de906901911dc374d89fe1f805734c6f6144db3152748f9b0541cd6583e6c3d2894e04970082b98df5d914b951c9183bf25117b1a9072768e4df487f8e6ed918e5d6754319322d991a6158947113ff320990f38f5e37f0ece574395edfae743439824efbabd2d04f9ebc499a3c2040abe8fddc43943b8f123b71bb490e5f93c5f6093dad9f58e90231d5d69ba54e8052c9c50daa412c580711b273461ec198a7d5399fbfe614faa5ae8d9f004508b43b4a234f1cb724cce8e3e6b00c81f94bc0f321502794f4616392849994f67c842d1b63e4a18df453da38b88267d8389934b1f86bbb988e29162c71dd480806617572612083635c0800000000056175726101011c43c9dc41050f47d24f799941efe385c0b41380cb1b19fb9910ce4f2c55222a6e836b3aeb5c1c931f9c3e95dc9cd27e1d1585d69e18813f5cb889ecea1da3830c0000000100000000ee07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432021071f1207ce1d22e80903c737f4c89f2113bd1c7753de41092a70552dd6c17cffb003d8b5359ae9c274650df76ffdd14c52814ce9b5c17900bc52834e30a83ce59e7d5f163371f5d99dd3784d693dfac0e4eec4fa8accf45a881150ceebab3f42382ac9fa47baae525b7af81f2ba3125302b795ec05b0a3d9b4bca133d3a63e2c5da2612da3f1b3c8f42cd1522f6a7a48d2693d58088e5288694b90307074ef116265b6660b03112547414f40025cc4154c6eb7a6de2ad52e51a55af54b38aa1c54fa1bd03bcbd527584aa648fdd075dc0f8e79c247f5ffb1e6ac9c2be225ea60db84bb8d7ab17120d682d16696c329e958433a449faeb88b1c50464e2e4e2eaa75a54e13a8d890399906e24d00454ec4e709e4f7b939691771a23dab762bbe9023a3389663194f4d084a27298adb033bfd6a263f4d3c4c20a3e6f0e00863cb85196408b005a0aee92f8c6b9858c667067f971772855a47e11daf73a2aab1ae29e5db1dc095e8b6f463c0264370e99ac799f7b717e685218b437e4f6181e4abd56e1a0c0d60806617572612083635c08000000000561757261010122106da90907f90dfa17d639b60ab9d3aabdd7ea95daaeeccf3b4dee072fce038e61f86d7189ee821aec9a11d6ecc5c484d12229183553ca27a9d20f668af9860f0000000400000000ef07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc4327ef0f295b0fdc0c650ffebced6be72c4dd0e1176da30930364fdb01a6713d036f0831c577230924e9326d19f346e64c95e84193c52352eda105704b09d804268b5a6b9e2d162fdb73841ea9372584d9699f321a111fe6f470b89b99b07d8431bafca0227eea00a532e1484c02ec006fa6495eba21abc438584d76f48802d0a910a508a2ee6c3f905a242e92b41e1bb438c7a083504fda57a1849ddd35896c47d78a5956fe6c7531a3c8ddefd9d17c1284ba60dac9040aca954dec18f365c9b8fbe455b67d90249d0096cd35843e3d71badc12c49381bce7312852dec8a1eb64498bbf023fc9e033deee0b54e1b2e1ca8e747d2dd9cb658cc07344df196fbd222e9520eab0f4b1fa37fc4afcb93a1c0ace0cde92aa0689ebcb0c5d1245bcd2c10e9028a0cc2de076fcc8655cd5cc9ae23351591616aded6d8ecab7f2a44e5d624a8fe422bb00056c4bf23b31c58b9773346f043fb8bf5373ded1962c0fec66853e9d754bb642036900eb42f10c8e6021345c5ca5bd1ab4e22e5b8022bf38b06f66425eebf4c5c0806617572612083635c0800000000056175726101011a3c100d29a795c4fbb068012b0291991aa5db384bc0d8c775ffadb60c9a955b4e259391b7f5c22a32ed066345b09aca2fb0b06fb2254ea3723b462ee7ce478a100000000500000000fb07000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432740beb55375d7c8b84577fbe1c0743965ea389fe7585d6f68975111716c1ce24eb2dadcc3c91fcb5f23b9008ea9c6f934dc261a84b3d1b5b43ae437c6aa992452aea0a684700ff36d0a8b8ebd07fecc353bda87aad24b37c8944de3ce45efcb42fd6220dd68bba2bbc6a3756154fa5cf878797dacda5fe063c16fd8436a46bc160c9820134984676bc4e14204671db0b5494513b5a7fe4df5d0ea250e554a2080e31802525806814554d3a5677af77a3673b500d3539f04afdcfd720573b608ab0b09939c11cbff67c66f806f5221a61fdcfab5c4fa11c0d7ca12988135efa54ed1d69cd74ceee75480f46a7b15b926904d12cdea281aa28e908ec00a9d07cf8a82bcf585ae95386cc747fdf003d5802d9fe7484687bbbad0448af45553ff3b58903174881b8182392f9757efb143ba61d046a0208302a7a7b3df8041059ca538fef169b8d0012fd33199e57825afe600bbfff192f2b9e0f6b72f5da7e8f1f3147e859987cc129b23e32b2278bada2bc2795d7cd6034e3afa8e9a333d01b36b4e2250e583fe20c06617572612083635c08000000000466726f6e88014920420a08c71a4b56953bf3efbae9a45e737f4cea978bdbc470de907d64e1550005617572610101b491cb7862f8d14fb0e2f6cb8d1287b83a55ee7feb468577ca78d9c120fabe5f6b909448827d93de5eb8bd7afe6c9aea63fef46254208969cdab95fe6d02f18b170000000c000000000808000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc432c663d22aea82481985ee77a58f1e54bb8c64fe22c48df15aa43f69aad1c7276b53c400f7fb9008e65a12443807e49224efa495a9cfa03e6ce5298a88fc744478f3820cb625cff327e14fe2006713cce73555c4336a7d861715aa2429a7d349102f0b4f9017440cf5a06a286856c5795b974f5006aa07357854c3eb4c3892b7f5125cb08a3e444ff92b8868bb8d6d64947c84862353870b0e5121b002929c136db31e000378c0f3241a5408a49bc458bd75af5c0d16b35661e212a981ecf5be8d61707c8adc571e83812efa6aa3673e4423c1b56780c437c500583abf6839a68d096600b21370ef6b990d6922acbfc71de68d751ee2d62fbfc49125bd9709ffe33bbce32c9e23b266d24cc175dcc0d99e7c1182b6ce8824d724e9c34ad852a611e9021145925a3f018c9aaba6b3981aaa8e1e24f0c7d9b38f65643a16d3f55d77ff6ca60a4800e3f4f2125d650231ba3ecaa0a51aeda71beada9dad70479d4571b5f2ebfa480c16116166d9e35a66dcadb999da853bfcd1872563f5d0a785507bf67796e568ec0806617572612083635c080000000005617572610101de7241c718f67134d32b6b5656f8e8f3f31e8d29af28043a37c2b49429a082633c8c7abbe502084c28c4a548ac75f97732521c7e66ea9917e704e5469572558c1e00000013000000003808000026662318f64c51f6ed779aa7e32b1b7489bbdb6118812d1b0a2902b7405bc43278b266c6c3ba60a6e648093bcd62419d4ea68eec772f22b7dfc78c6b255dac57bd149cd2b1b166d73be2ed9409a0bebe842c1901d65b1fd3c5f8d98d82ea2a5c3ae10acc8770276d737e6334c59e468be878e6264c050f48ac3e4a6524b76b37c399c4a820e1a50b2bcbc805192c2609e8372e8ddd8432127f6200427dcb2d72386429023e01fcf193d96cc55f1d4d85db5b2f0a9e3a5fb6855c0e07b891d6581ea371a39cb30eaa0ea2d0b9bbe5734e8793d4db7c366277619bdff9611dfb8d4bba89ec371746a5e689ece6f2a117d2b4e7894776b7a96209e7177446c076874bde474bbe3f7bb78669eb48648bf238110f690c144c097988314989bf9b3d4ef410cd043b32cf71a25a00655ab6a0558e383e546c3728412be664273b51908f4903de6835c05f9da3c6ca7fc65846438da7947f93a152f77bb75a85e3d05385feb47e071300b797adcbfd7d3a94ba4b2e0ab454bfded856f759d2b674839d4adcacb72d2c1361edc442862859f46d384db20db351390b2d261be35211db5232e585f985291a08066e6d6273804852f3c0a603d7da194fbff174c24700f3f89d86b462760033bdcb1663c76c60056e6d62730101e2f5f706646cbfc613a98564ff9b4a958acead02fa488e1f3bbcee114d13594d75e9b79d5f5be257e9da81d3ab97cefe36a620a2384f6f1f8719ec2b23532684280000001d000000" //nolint:all resultBytes, err := common.HexToBytes(result) require.NoError(t, err) @@ -256,3 +349,9 @@ func TestCandidateEvent(t *testing.T) { require.NoError(t, err) require.Equal(t, result, common.BytesToHex(encoded)) } + +func mustHexTo32BArray(t *testing.T, inputHex string) (outputArray [32]byte) { + t.Helper() + copy(outputArray[:], common.MustHexToBytes(inputHex)) + return outputArray +} diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 78b1df8816..5beef3f0b8 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -389,6 +389,9 @@ func (in *Instance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlic } availabilityCores, err := parachain.NewAvailabilityCores() + if err != nil { + return nil, fmt.Errorf("new availability cores: %w", err) + } err = scale.Unmarshal(ret, &availabilityCores) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) @@ -503,13 +506,13 @@ func (in *Instance) ParachainHostSessionInfo(sessionIndex parachain.SessionIndex return nil, fmt.Errorf("exec: %w", err) } - var sessionInfo parachain.SessionInfo + var sessionInfo *parachain.SessionInfo err = scale.Unmarshal(encodedSessionInfo, &sessionInfo) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) } - return &sessionInfo, nil + return sessionInfo, nil } // ParachainHostDMQContents Returns all the pending inbound messages diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index 158c6d9ebc..8995f59941 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -6,7 +6,6 @@ package wasmer import ( "bytes" "encoding/json" - "fmt" "github.com/ChainSafe/gossamer/lib/parachain" "math/big" "os" @@ -1220,8 +1219,6 @@ func TestInstance_ParachainHostValidators(t *testing.T) { require.Equal(t, expected, response) } -// TODO: group_rotation_frequency is being overwritten by the runtime to 0 -// need to figure out why func TestInstance_ParachainHostValidatorGroups(t *testing.T) { t.Parallel() @@ -1247,8 +1244,6 @@ func TestInstance_ParachainHostValidatorGroups(t *testing.T) { require.Equal(t, expected, response) } -// TODO: group_rotation_frequency is being overwritten by the latest runtime to 0 -// the current runtime is blocked by https://github.com/ChainSafe/gossamer/issues/3268 func TestInstance_ParachainHostAvailabilityCores(t *testing.T) { t.Parallel() @@ -1258,8 +1253,13 @@ func TestInstance_ParachainHostAvailabilityCores(t *testing.T) { response, err := rt.ParachainHostAvailabilityCores() require.NoError(t, err) - // TODO: assert response - fmt.Println(response) + // taken from https://polkadot.js.org/apps/#/rpc (westend) + // at: 0x03458e146407a2ad41a87b18298540cad7d48f931f4815ca1fbef281e5943ef5 + expectedHash := "0x0c0001e8030000009652f3009c52f30001e803000000440000000200000058b29da15fc66c19ef0ad4e66e95c8e42718d2455001ec6876f4173489a705fbe8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b51453370001e9030000009652f3009c52f30001e90300000044000000000000000571a387d344bef8a77d3a99895958644dee97345861f7747b1cb8186a14089ee9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e670001ea030000009652f3009c52f30001ea0300000044000000010000009b716202cd9fabb93b278a41d9344faecb1300241d255d1de0675a42ebff6b6eea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc52996" //nolint:all + expected := common.MustHexToBytes(expectedHash) + encoded, err := scale.Marshal(*response) + require.NoError(t, err) + require.Equal(t, expected, encoded) } func TestInstance_ParachainHostSessionIndexForChild(t *testing.T) { @@ -1287,20 +1287,20 @@ func TestInstance_ParachainHostCandidatePendingAvailability(t *testing.T) { expected := ¶chain.CommittedCandidateReceipt{ Descriptor: parachain.CandidateDescriptor{ ParaID: 1000, - RelayParent: mustHexTo32BArray(t, "0xb5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083"), - Collator: mustHexTo32BArray(t, "0x1aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251"), - PersistedValidationDataHash: mustHexTo32BArray(t, "0xa2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd5"), - PovHash: mustHexTo32BArray(t, "0x20d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293"), - ErasureRoot: mustHexTo32BArray(t, "0xd91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b"), - Signature: mustHexTo64BArray(t, "0x68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084"), - ParaHead: mustHexTo32BArray(t, "0xd94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211"), - ValidationCodeHash: mustHexTo32BArray(t, "0xcafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b5145337"), + RelayParent: mustHexTo32BArray(t, "0xb5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083"), //nolint:all + Collator: mustHexTo32BArray(t, "0x1aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251"), //nolint:all + PersistedValidationDataHash: mustHexTo32BArray(t, "0xa2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd5"), //nolint:all + PovHash: mustHexTo32BArray(t, "0x20d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293"), //nolint:all + ErasureRoot: mustHexTo32BArray(t, "0xd91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b"), //nolint:all + Signature: mustHexTo64BArray(t, "0x68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084"), //nolint:all + ParaHead: mustHexTo32BArray(t, "0xd94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211"), //nolint:all + ValidationCodeHash: mustHexTo32BArray(t, "0xcafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b5145337"), //nolint:all }, Commitments: parachain.CandidateCommitments{ UpwardMessages: nil, HorizontalMessages: nil, NewValidationCode: nil, - HeadData: common.MustHexToBytes("0xd91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e"), + HeadData: common.MustHexToBytes("0xd91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e"), //nolint:all ProcessedDownwardMessages: 0, HrmpWatermark: 15946389, }, @@ -1309,7 +1309,6 @@ func TestInstance_ParachainHostCandidatePendingAvailability(t *testing.T) { require.Equal(t, expected, response) } -// TODO: assert the response func TestInstance_ParachainHostCandidateEvents(t *testing.T) { t.Parallel() @@ -1319,11 +1318,15 @@ func TestInstance_ParachainHostCandidateEvents(t *testing.T) { response, err := rt.ParachainHostCandidateEvents() require.NoError(t, err) - fmt.Println(response) + encoded, err := scale.Marshal(*response) + require.NoError(t, err) + // taken from https://polkadot.js.org/apps/#/rpc (westend) + // at: 0x03458e146407a2ad41a87b18298540cad7d48f931f4815ca1fbef281e5943ef5 + expectedHash := "0x0c00e8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b514533734cd6976981877d40277ad627ec04b2fc4ba04f558d9e4b41d911a6f41610350e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e000000000200000000e9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e67514f16481063738cae77af97e154a475018c89ac13ca21452572447ae3bea823e90259b97f6f68683641a4b1046440cedddbc2054805e95504e9813b7c352d68ce57ba9357001fb3b6742be5e417621c0fd5f742e9f1d142518605af00a244dc61ebd42d63e07666532e9e2ab468d56fccb902fa801513a4dddc19d9e4b1edaae85ef1d1758908066175726120f4635e080000000005617572610101ba71303b6313ffc193e07bd26aeed8754fd02e86d3fd314074dcb2393a2eae08d32f5ec38737493bbcb09abeb020eb7eadbef00102bd3802b0545d5bca7e6a8d010000000000000000ea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc5299687f044d87495f20844ff334fe3ff1fb62568167d343d8f39dba5673d75452c06e9023c1bee939fc42a875b2921ecda1e413a5bad4b53bfa7aa314ba9aaf7f66d272cfe563500c93f096e27f359c7834c3b56180169d6055dc7d002bbee58e5b300004a6bf77091facd6381ad90cc2dc3ddab148eede30441cf6767ba2b3ce03b8401a52fdaa208066175726120f4635e080000000005617572610101960963f3ebff0b6b57bf99454febef94f04726a2c94abd401c5d3b568ec3cc384b10dd3dd7d96d456df0b8ed5cc6bacab809e163f85ec0b96529a9f3fa28f5870200000001000000" //nolint:all + expected := common.MustHexToBytes(expectedHash) + require.Equal(t, expected, encoded) } -// TODO: assert the response -// blocked by https://github.com/ChainSafe/gossamer/issues/3248 func TestInstance_ParachainHostSessionInfo(t *testing.T) { t.Parallel() @@ -1333,8 +1336,104 @@ func TestInstance_ParachainHostSessionInfo(t *testing.T) { response, err := rt.ParachainHostSessionInfo(parachain.SessionIndex(27379)) require.NoError(t, err) - // TODO: assert response - fmt.Println(response) + expected := ¶chain.SessionInfo{ + ActiveValidatorIndices: []types.ValidatorIndex{ + 7, + 12, + 14, + 1, + 4, + 16, + 3, + 11, + 9, + 6, + 13, + 15, + 5, + 0, + 8, + 10, + 2, + }, + RandomSeed: mustHexTo32BArray(t, "0x9a14667dcf973e46392904593e8caf2fb7a57904edbadf1547531657e7a56b5e"), + DisputePeriod: 6, + Validators: []types.ValidatorID{ + mustHexTo32BArray(t, "0xa262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d"), + mustHexTo32BArray(t, "0x804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e"), + mustHexTo32BArray(t, "0x4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72"), + mustHexTo32BArray(t, "0x74c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68"), + mustHexTo32BArray(t, "0xe61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511"), + mustHexTo32BArray(t, "0x94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e"), + mustHexTo32BArray(t, "0xac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841"), + mustHexTo32BArray(t, "0xb61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12"), + mustHexTo32BArray(t, "0x382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c"), + mustHexTo32BArray(t, "0x0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547"), + mustHexTo32BArray(t, "0xcee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237"), + mustHexTo32BArray(t, "0xe2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53"), + mustHexTo32BArray(t, "0xce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016"), + mustHexTo32BArray(t, "0xae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848"), + mustHexTo32BArray(t, "0xa0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a"), + mustHexTo32BArray(t, "0x807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a"), + mustHexTo32BArray(t, "0x4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936"), + }, + DiscoveryKeys: []parachain.AuthorityDiscoveryID{ + mustHexTo32BArray(t, "0x407a89ac6943b9d2ef1ceb5f1299941758a6af5b8f79b89b90f95a3e38179341"), + mustHexTo32BArray(t, "0x307744a128c608be0dff2189557715b74734359974606d96dc4d256d61b1047d"), + mustHexTo32BArray(t, "0x74fff2667b4a2cc69198ec9d3bf41f4d001ab644b45feaf89a21ff7ef3bd2618"), + mustHexTo32BArray(t, "0x98ab99b4b982d6a1d983ab05ac530b373043e6b7a4a7e5a7dc7ca1942196ae6c"), + mustHexTo32BArray(t, "0x94f9e38609dd9972bfdbe4664f2063499f6233f895ee13b71793c926018a9428"), + mustHexTo32BArray(t, "0x4ce0e8ec374f50c27948b8880628918a41b56930f1af675a5b5099d23f326763"), + mustHexTo32BArray(t, "0x3a58b8f1f529e55fc3dac1dd81cb4547565c09f6e98d97243acb98bdda890028"), + mustHexTo32BArray(t, "0x982bcec62ad60cf9fd00e89b7e3589adb668fcbc467127537851b5a5f3dbbb16"), + mustHexTo32BArray(t, "0x0695b906f52a88f18bdecd811785b4299c51ebb2a2755f0b4c0d83fbef431861"), + mustHexTo32BArray(t, "0x0ec5e1d2d044023009c63659c65a79aaf07ecbf5b9887958243aa873a63e5a1b"), + mustHexTo32BArray(t, "0x52ef04ed449e4db577d98ad433b779c36f0d122df03e1cdc3e840a49016c5f16"), + mustHexTo32BArray(t, "0xc2d4b5973000d0b175631dde5d1657b3e34c2f75e8a6d5414013ce4036d83355"), + mustHexTo32BArray(t, "0xa6e01665b2d8490abf45551088021041dfb41772a9d596ed6e9f261ed1c8ae72"), + mustHexTo32BArray(t, "0xb436c143e295617afb60353a01f2941bd33370a662c99c040984e52a072b5f22"), + mustHexTo32BArray(t, "0x4c4c4b178f1a3d67e5f26d6b93b9a43937cd2d1d1cb2acc4650f504125df2e18"), + mustHexTo32BArray(t, "0xca17f0edc319c140113a44722f829aa1313da1b54298a10df49ad7d67d9de85f"), + mustHexTo32BArray(t, "0x5a6bf6911fc41d8981c7c28f87e8ed4416c65e15624f7b4e36c6a1a72c7a7819"), + }, + AssignmentKeys: []parachain.AssignmentID{ + mustHexTo32BArray(t, "0x6acc35b896fe346adeda25c4031cf6a81e58dca091164370859828cc4456901a"), + mustHexTo32BArray(t, "0x466627d554785807aaf50bfbdc9b8f729e8e20eb596ee5def5acd2acb72e405f"), + mustHexTo32BArray(t, "0xc05cab9e7773ffaf045407579f9c8e16d56f119117421cd18a250c2e37fcb53a"), + mustHexTo32BArray(t, "0xe2dca6ce9b3ebb40052c34392dc74d3cdd648399119fa470222a10956769d64f"), + mustHexTo32BArray(t, "0x7477459916ace4f77d97d6ab5e1a2f06092282c7f0a1332628c14896e8e9be62"), + mustHexTo32BArray(t, "0xc2574de3dc8feebfad1b3bee36a7bfe6c994e5d1459a5372ff447ac32dd46c11"), + mustHexTo32BArray(t, "0xb0a8ed99f1e7ab160e0ac2fcfeee0d92d807c8fb4c1678e37997715578926c5c"), + mustHexTo32BArray(t, "0x6c9bfa7c2e0f8e10a1a78bb982313c5c347a018cb3828886b99e109a8799d272"), + mustHexTo32BArray(t, "0xe6037f1fc5b19015b7089ecf90034349e3f5c37cb50dec5356743614f94f8c33"), + mustHexTo32BArray(t, "0x964b85f2b8e10e859e306d3670b8bdc0cea17b97dfd3edc8a9e1be1f127fee5b"), + mustHexTo32BArray(t, "0x44d421ae62038ba15a377cad85e4ecd3c2a63b54fdbb82c47fb3e9c026405226"), + mustHexTo32BArray(t, "0x48c51db949a58fd5f36a19888986275547b0c2fbb0b348ccb85dfc6c998dbe16"), + mustHexTo32BArray(t, "0x0ae9425710301a9241837d624438a5d82edbbd6bf2cdbcc2694ad7db31ef9921"), + mustHexTo32BArray(t, "0x9e47376e9af08b294901b879c7d658c41386453c6baa7c26560c5fd3b164e05d"), + mustHexTo32BArray(t, "0x8af1a51649d44d12dffc24337f0a5424b18db9604133eafcb2639ddcdc2a7f0f"), + mustHexTo32BArray(t, "0xae7a30d143fd125490434ca7325025a2338d0b8bb28dcd9373dfd83756191022"), + mustHexTo32BArray(t, "0xeeba7c46f5fa1ea21e736d9ebd7a171fb2afe0a4f828a222ea0605a4ad0e6067"), + }, + ValidatorGroups: [][]types.ValidatorIndex{ + { + 0, 1, 2, 3, 4, 5, + }, + { + 6, 7, 8, 9, 10, 11, + }, + { + 12, 13, 14, 15, 16, + }, + }, + NCores: 3, + ZerothDelayTrancheWidth: 0, + RelayVRFModuloSamples: 1, + NDelayTranches: 40, + NoShowSlots: 2, + NeededApprovals: 2, + } + require.Equal(t, expected, response) } // TODO: implement this @@ -1346,7 +1445,7 @@ func TestInstance_ParachainHostDMQContents(t *testing.T) {} func TestInstance_ParachainHostInboundHrmpChannelsContents(t *testing.T) {} func getParachainHostTrie(t *testing.T) *trie.Trie { - // taken from https://polkadot.js.org/apps/#/chainstate + // taken from https://polkadot.js.org/apps/#/chainstate (westend) // at: 0x03458e146407a2ad41a87b18298540cad7d48f931f4815ca1fbef281e5943ef5 data := []struct { name string @@ -1356,7 +1455,7 @@ func getParachainHostTrie(t *testing.T) *trie.Trie { { name: "parasShared.activeValidatorKeys", key: "0xb341e3a63e58a188839b242d17f8c9f87a50c904b368210021127f9238883a6e", - value: "0x44a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe7274c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c51194ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050eac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547cee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936", + value: "0x44a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe7274c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c51194ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050eac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547cee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936", //nolint:all }, { name: "system.number", //block number @@ -1366,7 +1465,7 @@ func getParachainHostTrie(t *testing.T) *trie.Trie { { name: "paraScheduler.validatorGroups", key: "0x94eadf0156a8ad5156507773d0471e4a16973e1142f5bd30d9464076794007db", - value: "0x0c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f00000010000000", + value: "0x0c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f00000010000000", //nolint:all }, { name: "paraScheduler.sessionStartBlock", @@ -1376,7 +1475,7 @@ func getParachainHostTrie(t *testing.T) *trie.Trie { { name: "configuration.activeConfig", key: "0x06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385", - value: "0x00005000005000000a00000000c8000000c800000a0000000a000000c80000006400000000000000000000000000500000c800000700e8764817020040010a0000000000000000c0220fca950300000000000000000000c0220fca9503000000000000000000e8030000009001000a0000000000000000900100008070000000000000000000000a000000050000000500000001000000010500000001c8000000060000005802000002000000280000000000000002000000010000000700c817a8040200400101020000000f000000", + value: "0x00005000005000000a00000000c8000000c800000a0000000a000000c80000006400000000000000000000000000500000c800000700e8764817020040010a0000000000000000c0220fca950300000000000000000000c0220fca9503000000000000000000e8030000009001000a0000000000000000900100008070000000000000000000000a000000050000000500000001000000010500000001c8000000060000005802000002000000280000000000000002000000010000000700c817a8040200400101020000000f000000", //nolint:all }, { name: "paraScheduler.availabilityCores", @@ -1391,32 +1490,37 @@ func getParachainHostTrie(t *testing.T) *trie.Trie { { name: "paraInclusion.pendingAvailability[paraId=1000]", key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865b6ff6f7d467b87a9e8030000", - value: "0x0000000058b29da15fc66c19ef0ad4e66e95c8e42718d2455001ec6876f4173489a705fbe8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b5145337440000004400f0019552f3009652f30002000000", + value: "0x0000000058b29da15fc66c19ef0ad4e66e95c8e42718d2455001ec6876f4173489a705fbe8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b5145337440000004400f0019552f3009652f30002000000", //nolint:all }, { name: "paraInclusion.pendingAvailabilityCommitments[paraId=1000]", key: "0x196e027349017067f9eb56e2c4d9ded50433e4ed72dccf0edcf58c3192f16e4bb6ff6f7d467b87a9e8030000", - value: "0x000000e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e000000009552f300", + value: "0x000000e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e000000009552f300", //nolint:all }, { name: "paraInclusion.pendingAvailability[paraId=1001]", key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865adc7217647a32b0be9030000", - value: "0x010000000571a387d344bef8a77d3a99895958644dee97345861f7747b1cb8186a14089ee9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e6744000000443f00009552f3009652f30000000000", + value: "0x010000000571a387d344bef8a77d3a99895958644dee97345861f7747b1cb8186a14089ee9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e6744000000443f00009552f3009652f30000000000", //nolint:all }, { name: "paraInclusion.pendingAvailability[paraId=1002]", key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865b2b032492225337bea030000", - value: "0x020000009b716202cd9fabb93b278a41d9344faecb1300241d255d1de0675a42ebff6b6eea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc529964400000044c00f009552f3009652f30001000000", + value: "0x020000009b716202cd9fabb93b278a41d9344faecb1300241d255d1de0675a42ebff6b6eea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc529964400000044c00f009552f3009652f30001000000", //nolint:all }, { name: "parasShared.currentSessionIndex", key: "0xb341e3a63e58a188839b242d17f8c9f8b5cab3380174032968897a4c3ce57c0a", value: "0xf36a0000", }, + { + name: "paraSessionInfo.sessions[Id=27379]", + key: "0x4da2c41eaffa8e1a791c5d65beeefd1f028685274e698e781f7f2766cba0cc83f36a0000", + value: "0x44070000000c0000000e000000010000000400000010000000030000000b00000009000000060000000d0000000f0000000500000000000000080000000a000000020000009a14667dcf973e46392904593e8caf2fb7a57904edbadf1547531657e7a56b5e0600000044a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe7274c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c51194ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050eac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547cee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e3685893644407a89ac6943b9d2ef1ceb5f1299941758a6af5b8f79b89b90f95a3e38179341307744a128c608be0dff2189557715b74734359974606d96dc4d256d61b1047d74fff2667b4a2cc69198ec9d3bf41f4d001ab644b45feaf89a21ff7ef3bd261898ab99b4b982d6a1d983ab05ac530b373043e6b7a4a7e5a7dc7ca1942196ae6c94f9e38609dd9972bfdbe4664f2063499f6233f895ee13b71793c926018a94284ce0e8ec374f50c27948b8880628918a41b56930f1af675a5b5099d23f3267633a58b8f1f529e55fc3dac1dd81cb4547565c09f6e98d97243acb98bdda890028982bcec62ad60cf9fd00e89b7e3589adb668fcbc467127537851b5a5f3dbbb160695b906f52a88f18bdecd811785b4299c51ebb2a2755f0b4c0d83fbef4318610ec5e1d2d044023009c63659c65a79aaf07ecbf5b9887958243aa873a63e5a1b52ef04ed449e4db577d98ad433b779c36f0d122df03e1cdc3e840a49016c5f16c2d4b5973000d0b175631dde5d1657b3e34c2f75e8a6d5414013ce4036d83355a6e01665b2d8490abf45551088021041dfb41772a9d596ed6e9f261ed1c8ae72b436c143e295617afb60353a01f2941bd33370a662c99c040984e52a072b5f224c4c4b178f1a3d67e5f26d6b93b9a43937cd2d1d1cb2acc4650f504125df2e18ca17f0edc319c140113a44722f829aa1313da1b54298a10df49ad7d67d9de85f5a6bf6911fc41d8981c7c28f87e8ed4416c65e15624f7b4e36c6a1a72c7a7819446acc35b896fe346adeda25c4031cf6a81e58dca091164370859828cc4456901a466627d554785807aaf50bfbdc9b8f729e8e20eb596ee5def5acd2acb72e405fc05cab9e7773ffaf045407579f9c8e16d56f119117421cd18a250c2e37fcb53ae2dca6ce9b3ebb40052c34392dc74d3cdd648399119fa470222a10956769d64f7477459916ace4f77d97d6ab5e1a2f06092282c7f0a1332628c14896e8e9be62c2574de3dc8feebfad1b3bee36a7bfe6c994e5d1459a5372ff447ac32dd46c11b0a8ed99f1e7ab160e0ac2fcfeee0d92d807c8fb4c1678e37997715578926c5c6c9bfa7c2e0f8e10a1a78bb982313c5c347a018cb3828886b99e109a8799d272e6037f1fc5b19015b7089ecf90034349e3f5c37cb50dec5356743614f94f8c33964b85f2b8e10e859e306d3670b8bdc0cea17b97dfd3edc8a9e1be1f127fee5b44d421ae62038ba15a377cad85e4ecd3c2a63b54fdbb82c47fb3e9c02640522648c51db949a58fd5f36a19888986275547b0c2fbb0b348ccb85dfc6c998dbe160ae9425710301a9241837d624438a5d82edbbd6bf2cdbcc2694ad7db31ef99219e47376e9af08b294901b879c7d658c41386453c6baa7c26560c5fd3b164e05d8af1a51649d44d12dffc24337f0a5424b18db9604133eafcb2639ddcdc2a7f0fae7a30d143fd125490434ca7325025a2338d0b8bb28dcd9373dfd83756191022eeba7c46f5fa1ea21e736d9ebd7a171fb2afe0a4f828a222ea0605a4ad0e60670c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f00000010000000030000000000000001000000280000000200000002000000", //nolint:all + }, { name: "system.events", key: "0x26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7", - value: "0x1400000000000000e249433d551702000000010000002c00e8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b514533734cd6976981877d40277ad627ec04b2fc4ba04f558d9e4b41d911a6f41610350e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e00000000020000000000010000002c00e9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e67514f16481063738cae77af97e154a475018c89ac13ca21452572447ae3bea823e90259b97f6f68683641a4b1046440cedddbc2054805e95504e9813b7c352d68ce57ba9357001fb3b6742be5e417621c0fd5f742e9f1d142518605af00a244dc61ebd42d63e07666532e9e2ab468d56fccb902fa801513a4dddc19d9e4b1edaae85ef1d1758908066175726120f4635e080000000005617572610101ba71303b6313ffc193e07bd26aeed8754fd02e86d3fd314074dcb2393a2eae08d32f5ec38737493bbcb09abeb020eb7eadbef00102bd3802b0545d5bca7e6a8d01000000000000000000010000002c00ea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc5299687f044d87495f20844ff334fe3ff1fb62568167d343d8f39dba5673d75452c06e9023c1bee939fc42a875b2921ecda1e413a5bad4b53bfa7aa314ba9aaf7f66d272cfe563500c93f096e27f359c7834c3b56180169d6055dc7d002bbee58e5b300004a6bf77091facd6381ad90cc2dc3ddab148eede30441cf6767ba2b3ce03b8401a52fdaa208066175726120f4635e080000000005617572610101960963f3ebff0b6b57bf99454febef94f04726a2c94abd401c5d3b568ec3cc384b10dd3dd7d96d456df0b8ed5cc6bacab809e163f85ec0b96529a9f3fa28f5870200000001000000000001000000000007559ff8970d26023b00020000", + value: "0x1400000000000000e249433d551702000000010000002c00e8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b514533734cd6976981877d40277ad627ec04b2fc4ba04f558d9e4b41d911a6f41610350e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e00000000020000000000010000002c00e9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e67514f16481063738cae77af97e154a475018c89ac13ca21452572447ae3bea823e90259b97f6f68683641a4b1046440cedddbc2054805e95504e9813b7c352d68ce57ba9357001fb3b6742be5e417621c0fd5f742e9f1d142518605af00a244dc61ebd42d63e07666532e9e2ab468d56fccb902fa801513a4dddc19d9e4b1edaae85ef1d1758908066175726120f4635e080000000005617572610101ba71303b6313ffc193e07bd26aeed8754fd02e86d3fd314074dcb2393a2eae08d32f5ec38737493bbcb09abeb020eb7eadbef00102bd3802b0545d5bca7e6a8d01000000000000000000010000002c00ea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc5299687f044d87495f20844ff334fe3ff1fb62568167d343d8f39dba5673d75452c06e9023c1bee939fc42a875b2921ecda1e413a5bad4b53bfa7aa314ba9aaf7f66d272cfe563500c93f096e27f359c7834c3b56180169d6055dc7d002bbee58e5b300004a6bf77091facd6381ad90cc2dc3ddab148eede30441cf6767ba2b3ce03b8401a52fdaa208066175726120f4635e080000000005617572610101960963f3ebff0b6b57bf99454febef94f04726a2c94abd401c5d3b568ec3cc384b10dd3dd7d96d456df0b8ed5cc6bacab809e163f85ec0b96529a9f3fa28f5870200000001000000000001000000000007559ff8970d26023b00020000", //nolint:all }, { name: "system.eventCount", From 83deb938c3410e0416645c30ad2a12c0614067fa Mon Sep 17 00:00:00 2001 From: kanishka Date: Tue, 30 May 2023 15:19:12 +0530 Subject: [PATCH 57/65] use blocknumber --- lib/parachain/types.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/parachain/types.go b/lib/parachain/types.go index 3c3fb75f3c..782ae543bf 100644 --- a/lib/parachain/types.go +++ b/lib/parachain/types.go @@ -17,11 +17,11 @@ import ( // GroupRotationInfo A helper data-type for tracking validator-group rotations. type GroupRotationInfo struct { // SessionStartBlock is the block number at which the session started - SessionStartBlock uint32 `scale:"1"` + SessionStartBlock types.BlockNumber `scale:"1"` // GroupRotationFrequency indicates how often groups rotate. 0 means never. - GroupRotationFrequency uint32 `scale:"2"` + GroupRotationFrequency types.BlockNumber `scale:"2"` // Now indicates the current block number. - Now uint32 `scale:"3"` + Now types.BlockNumber `scale:"3"` } // ValidatorGroups represents the validator groups From 7509ce573064ff75d6dcf5924ed0316365910e85 Mon Sep 17 00:00:00 2001 From: kanishka Date: Tue, 30 May 2023 15:23:57 +0530 Subject: [PATCH 58/65] fix imports --- lib/runtime/wasmer/exports.go | 2 +- lib/runtime/wasmer/exports_test.go | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 5beef3f0b8..0a0ed43c9f 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -6,10 +6,10 @@ package wasmer import ( "bytes" "fmt" - "github.com/ChainSafe/gossamer/lib/parachain" "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/lib/crypto/ed25519" + "github.com/ChainSafe/gossamer/lib/parachain" "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/lib/transaction" "github.com/ChainSafe/gossamer/pkg/scale" diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index 8995f59941..753a4c9087 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -6,7 +6,6 @@ package wasmer import ( "bytes" "encoding/json" - "github.com/ChainSafe/gossamer/lib/parachain" "math/big" "os" "testing" @@ -16,6 +15,7 @@ import ( "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/crypto/ed25519" "github.com/ChainSafe/gossamer/lib/genesis" + "github.com/ChainSafe/gossamer/lib/parachain" "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/lib/runtime/storage" "github.com/ChainSafe/gossamer/lib/runtime/wasmer/testdata" @@ -23,7 +23,6 @@ import ( "github.com/ChainSafe/gossamer/lib/utils" "github.com/ChainSafe/gossamer/pkg/scale" "github.com/centrifuge/go-substrate-rpc-client/v4/signature" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) From ee880f8641e6cad96a9fdd8b5627a6b48bf7d1c0 Mon Sep 17 00:00:00 2001 From: kanishka Date: Thu, 15 Jun 2023 18:41:07 +0530 Subject: [PATCH 59/65] cleanup --- lib/parachain/types.go | 5 ++- lib/runtime/constants.go | 4 --- lib/runtime/wasmer/exports.go | 50 ------------------------------ lib/runtime/wasmer/exports_test.go | 16 +++------- 4 files changed, 6 insertions(+), 69 deletions(-) diff --git a/lib/parachain/types.go b/lib/parachain/types.go index 0fd1794e93..1eba5fc375 100644 --- a/lib/parachain/types.go +++ b/lib/parachain/types.go @@ -132,8 +132,7 @@ func (ScheduledCore) Index() uint { } // Free Core information about a core which is currently free. -type Free struct { -} +type Free struct{} // Index returns the index func (Free) Index() uint { @@ -202,7 +201,7 @@ type CandidateCommitments struct { // Horizontal messages sent by the parachain. HorizontalMessages []OutboundHrmpMessage `scale:"2"` // New validation code. - NewValidationCode ValidationCode `scale:"3"` + NewValidationCode *ValidationCode `scale:"3"` // The head-data produced as a result of execution. HeadData headData `scale:"4"` // The number of messages processed from the DMQ. diff --git a/lib/runtime/constants.go b/lib/runtime/constants.go index d15e54da59..83eb5c92a4 100644 --- a/lib/runtime/constants.go +++ b/lib/runtime/constants.go @@ -82,8 +82,4 @@ const ( ParachainHostCandidateEvents = "ParachainHost_candidate_events" // ParachainHostSessionInfo is the runtime API call ParachainHost_session_info ParachainHostSessionInfo = "ParachainHost_session_info" - // ParachainHostDMQContents is the runtime API call ParachainHost_dmq_contents - ParachainHostDMQContents = "ParachainHost_dmq_contents" - //ParachainHostInboundHrmpChannelsContents is the runtime API call ParachainHost_inbound_hrmp_channels_contents - ParachainHostInboundHrmpChannelsContents = "ParachainHost_inbound_hrmp_channels_contents" ) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index b36e4e1fa6..99852eb4f5 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -515,56 +515,6 @@ func (in *Instance) ParachainHostSessionInfo(sessionIndex parachain.SessionIndex return sessionInfo, nil } -// ParachainHostDMQContents Returns all the pending inbound messages -// in the downward message queue for a given parachain. -func (in *Instance) ParachainHostDMQContents(parachainID parachain.ParaID) ([]parachain.DownwardMessage, error) { - buffer := bytes.NewBuffer(nil) - encoder := scale.NewEncoder(buffer) - err := encoder.Encode(parachainID) - if err != nil { - return nil, fmt.Errorf("encode parachainID: %w", err) - } - - encodedDownwardMessages, err := in.Exec(runtime.ParachainHostDMQContents, buffer.Bytes()) - if err != nil { - return nil, fmt.Errorf("exec: %w", err) - } - - var downwardMessages []parachain.DownwardMessage - err = scale.Unmarshal(encodedDownwardMessages, &downwardMessages) - if err != nil { - return nil, fmt.Errorf("unmarshal: %w", err) - } - - return downwardMessages, nil -} - -// ParachainHostInboundHrmpChannelsContents Returns the contents of all channels addressed to the given recipient. -// Channels that have no messages in them are also included. -func (in *Instance) ParachainHostInboundHrmpChannelsContents( - recipient parachain.ParaID, -) ([]parachain.InboundHrmpMessage, error) { - buffer := bytes.NewBuffer(nil) - encoder := scale.NewEncoder(buffer) - err := encoder.Encode(recipient) - if err != nil { - return nil, fmt.Errorf("encode recipient: %w", err) - } - - encodedInboundHrmpMessages, err := in.Exec(runtime.ParachainHostInboundHrmpChannelsContents, buffer.Bytes()) - if err != nil { - return nil, fmt.Errorf("exec: %w", err) - } - - var inboundHrmpMessages []parachain.InboundHrmpMessage - err = scale.Unmarshal(encodedInboundHrmpMessages, &inboundHrmpMessages) - if err != nil { - return nil, fmt.Errorf("unmarshal: %w", err) - } - - return inboundHrmpMessages, nil -} - func (in *Instance) RandomSeed() {} func (in *Instance) OffchainWorker() {} func (in *Instance) GenerateSessionKeys() {} diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index 753a4c9087..5a93da3a1e 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -1228,7 +1228,7 @@ func TestInstance_ParachainHostValidatorGroups(t *testing.T) { require.NoError(t, err) expected := ¶chain.ValidatorGroups{ - Validators: [][]types.ValidatorIndex{ + Validators: [][]parachain.ValidatorIndex{ {0, 1, 2, 3, 4, 5}, {6, 7, 8, 9, 10, 11}, {12, 13, 14, 15, 16}, @@ -1336,7 +1336,7 @@ func TestInstance_ParachainHostSessionInfo(t *testing.T) { require.NoError(t, err) expected := ¶chain.SessionInfo{ - ActiveValidatorIndices: []types.ValidatorIndex{ + ActiveValidatorIndices: []parachain.ValidatorIndex{ 7, 12, 14, @@ -1357,7 +1357,7 @@ func TestInstance_ParachainHostSessionInfo(t *testing.T) { }, RandomSeed: mustHexTo32BArray(t, "0x9a14667dcf973e46392904593e8caf2fb7a57904edbadf1547531657e7a56b5e"), DisputePeriod: 6, - Validators: []types.ValidatorID{ + Validators: []parachain.ValidatorID{ mustHexTo32BArray(t, "0xa262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d"), mustHexTo32BArray(t, "0x804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e"), mustHexTo32BArray(t, "0x4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72"), @@ -1414,7 +1414,7 @@ func TestInstance_ParachainHostSessionInfo(t *testing.T) { mustHexTo32BArray(t, "0xae7a30d143fd125490434ca7325025a2338d0b8bb28dcd9373dfd83756191022"), mustHexTo32BArray(t, "0xeeba7c46f5fa1ea21e736d9ebd7a171fb2afe0a4f828a222ea0605a4ad0e6067"), }, - ValidatorGroups: [][]types.ValidatorIndex{ + ValidatorGroups: [][]parachain.ValidatorIndex{ { 0, 1, 2, 3, 4, 5, }, @@ -1435,14 +1435,6 @@ func TestInstance_ParachainHostSessionInfo(t *testing.T) { require.Equal(t, expected, response) } -// TODO: implement this -// unable to find the data onchain -func TestInstance_ParachainHostDMQContents(t *testing.T) {} - -// TODO: implement this -// unable to find the data onchain -func TestInstance_ParachainHostInboundHrmpChannelsContents(t *testing.T) {} - func getParachainHostTrie(t *testing.T) *trie.Trie { // taken from https://polkadot.js.org/apps/#/chainstate (westend) // at: 0x03458e146407a2ad41a87b18298540cad7d48f931f4815ca1fbef281e5943ef5 From 8d1800e06d84ff949142fcb9d988ec5f725122e7 Mon Sep 17 00:00:00 2001 From: kanishka Date: Thu, 15 Jun 2023 18:59:55 +0530 Subject: [PATCH 60/65] revert types --- dot/types/block.go | 3 --- dot/types/validator.go | 14 -------------- 2 files changed, 17 deletions(-) delete mode 100644 dot/types/validator.go diff --git a/dot/types/block.go b/dot/types/block.go index 33d9b5f764..f8bacb6197 100644 --- a/dot/types/block.go +++ b/dot/types/block.go @@ -9,9 +9,6 @@ import ( "github.com/ChainSafe/gossamer/pkg/scale" ) -// BlockNumber represents a block number -type BlockNumber uint32 - // Block defines a state block type Block struct { Header Header diff --git a/dot/types/validator.go b/dot/types/validator.go deleted file mode 100644 index e9ed46f4ea..0000000000 --- a/dot/types/validator.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2023 ChainSafe Systems (ON) -// SPDX-License-Identifier: LGPL-3.0-only - -package types - -import ( - "github.com/ChainSafe/gossamer/lib/crypto/sr25519" -) - -// ValidatorID represents a validator ID -type ValidatorID [sr25519.PublicKeyLength]byte - -// ValidatorIndex represents a validator index -type ValidatorIndex uint32 From d43ea57450833f1d7e499a5311d60e045810bd8d Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 16 Jun 2023 14:50:22 +0530 Subject: [PATCH 61/65] embed test data --- lib/runtime/wasmer/exports.go | 4 +- lib/runtime/wasmer/exports_test.go | 184 +++++++-------------- lib/runtime/wasmer/testdata/parachain.yaml | 62 +++++++ 3 files changed, 121 insertions(+), 129 deletions(-) create mode 100644 lib/runtime/wasmer/testdata/parachain.yaml diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 99852eb4f5..2a9649fc10 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -349,13 +349,13 @@ func (in *Instance) GrandpaSubmitReportEquivocationUnsignedExtrinsic( // ParachainHostValidators Returns the validator set at the current state. // The specified validators are responsible for backing parachains for the current state. -func (in *Instance) ParachainHostValidators() ([]types.ValidatorID, error) { +func (in *Instance) ParachainHostValidators() ([]parachain.ValidatorID, error) { ret, err := in.Exec(runtime.ParachainHostValidators, []byte{}) if err != nil { return nil, fmt.Errorf("exec: %w", err) } - var validatorIDs []types.ValidatorID + var validatorIDs []parachain.ValidatorID err = scale.Unmarshal(ret, &validatorIDs) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index 5a93da3a1e..e2ef627b1d 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -5,11 +5,16 @@ package wasmer import ( "bytes" + _ "embed" "encoding/json" + "fmt" "math/big" "os" "testing" + "github.com/ChainSafe/gossamer/lib/runtime/storage" + "gopkg.in/yaml.v3" + "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/internal/log" "github.com/ChainSafe/gossamer/lib/common" @@ -17,7 +22,6 @@ import ( "github.com/ChainSafe/gossamer/lib/genesis" "github.com/ChainSafe/gossamer/lib/parachain" "github.com/ChainSafe/gossamer/lib/runtime" - "github.com/ChainSafe/gossamer/lib/runtime/storage" "github.com/ChainSafe/gossamer/lib/runtime/wasmer/testdata" "github.com/ChainSafe/gossamer/lib/trie" "github.com/ChainSafe/gossamer/lib/utils" @@ -27,6 +31,29 @@ import ( "github.com/stretchr/testify/require" ) +//go:embed testdata/parachain.yaml +var parachainTestDataRaw string + +type Storage struct { + Key string `yaml:"key"` + Value string `yaml:"value"` +} + +type Data struct { + Storage []Storage `yaml:"storage"` + Expected map[string]string `yaml:"expected"` +} + +var parachainTestData Data + +func init() { + err := yaml.Unmarshal([]byte(parachainTestDataRaw), ¶chainTestData) + if err != nil { + fmt.Println("Error unmarshaling test data:", err) + return + } +} + // this is generated by printing key ownership proof while running `test_generate_equivocation_report_blob` // https://github.com/paritytech/substrate/blob/ded44948e2d5a398abcb4e342b0513cb690961bb/frame/grandpa/src/benchmarking.rs#L85 var testKeyOwnershipProof types.OpaqueKeyOwnershipProof = types.OpaqueKeyOwnershipProof([]byte{64, 138, 252, 29, 127, 102, 189, 129, 207, 47, 157, 60, 17, 138, 194, 121, 139, 92, 176, 175, 224, 16, 185, 93, 175, 251, 224, 81, 209, 61, 0, 71}) //nolint:lll @@ -1196,24 +1223,24 @@ func TestInstance_ParachainHostValidators(t *testing.T) { response, err := rt.ParachainHostValidators() require.NoError(t, err) - expected := []types.ValidatorID{ - types.ValidatorID(mustHexTo32BArray(t, "0xa262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d")), - types.ValidatorID(mustHexTo32BArray(t, "0x804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e")), - types.ValidatorID(mustHexTo32BArray(t, "0x4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72")), - types.ValidatorID(mustHexTo32BArray(t, "0x74c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68")), - types.ValidatorID(mustHexTo32BArray(t, "0xe61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511")), - types.ValidatorID(mustHexTo32BArray(t, "0x94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e")), - types.ValidatorID(mustHexTo32BArray(t, "0xac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841")), - types.ValidatorID(mustHexTo32BArray(t, "0xb61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12")), - types.ValidatorID(mustHexTo32BArray(t, "0x382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c")), - types.ValidatorID(mustHexTo32BArray(t, "0x0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547")), - types.ValidatorID(mustHexTo32BArray(t, "0xcee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237")), - types.ValidatorID(mustHexTo32BArray(t, "0xe2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53")), - types.ValidatorID(mustHexTo32BArray(t, "0xce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016")), - types.ValidatorID(mustHexTo32BArray(t, "0xae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848")), - types.ValidatorID(mustHexTo32BArray(t, "0xa0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a")), - types.ValidatorID(mustHexTo32BArray(t, "0x807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a")), - types.ValidatorID(mustHexTo32BArray(t, "0x4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936")), + expected := []parachain.ValidatorID{ + parachain.ValidatorID(mustHexTo32BArray(t, "0xa262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x74c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xe61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xb61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xcee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xe2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xa0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936")), } require.Equal(t, expected, response) } @@ -1252,9 +1279,10 @@ func TestInstance_ParachainHostAvailabilityCores(t *testing.T) { response, err := rt.ParachainHostAvailabilityCores() require.NoError(t, err) - // taken from https://polkadot.js.org/apps/#/rpc (westend) - // at: 0x03458e146407a2ad41a87b18298540cad7d48f931f4815ca1fbef281e5943ef5 - expectedHash := "0x0c0001e8030000009652f3009c52f30001e803000000440000000200000058b29da15fc66c19ef0ad4e66e95c8e42718d2455001ec6876f4173489a705fbe8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b51453370001e9030000009652f3009c52f30001e90300000044000000000000000571a387d344bef8a77d3a99895958644dee97345861f7747b1cb8186a14089ee9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e670001ea030000009652f3009c52f30001ea0300000044000000010000009b716202cd9fabb93b278a41d9344faecb1300241d255d1de0675a42ebff6b6eea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc52996" //nolint:all + expectedHash := parachainTestData.Expected["availabilityCores"] + if expectedHash == "" { + t.Fatal("could not get expected hash from test data") + } expected := common.MustHexToBytes(expectedHash) encoded, err := scale.Marshal(*response) require.NoError(t, err) @@ -1319,9 +1347,10 @@ func TestInstance_ParachainHostCandidateEvents(t *testing.T) { encoded, err := scale.Marshal(*response) require.NoError(t, err) - // taken from https://polkadot.js.org/apps/#/rpc (westend) - // at: 0x03458e146407a2ad41a87b18298540cad7d48f931f4815ca1fbef281e5943ef5 - expectedHash := "0x0c00e8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b514533734cd6976981877d40277ad627ec04b2fc4ba04f558d9e4b41d911a6f41610350e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e000000000200000000e9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e67514f16481063738cae77af97e154a475018c89ac13ca21452572447ae3bea823e90259b97f6f68683641a4b1046440cedddbc2054805e95504e9813b7c352d68ce57ba9357001fb3b6742be5e417621c0fd5f742e9f1d142518605af00a244dc61ebd42d63e07666532e9e2ab468d56fccb902fa801513a4dddc19d9e4b1edaae85ef1d1758908066175726120f4635e080000000005617572610101ba71303b6313ffc193e07bd26aeed8754fd02e86d3fd314074dcb2393a2eae08d32f5ec38737493bbcb09abeb020eb7eadbef00102bd3802b0545d5bca7e6a8d010000000000000000ea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc5299687f044d87495f20844ff334fe3ff1fb62568167d343d8f39dba5673d75452c06e9023c1bee939fc42a875b2921ecda1e413a5bad4b53bfa7aa314ba9aaf7f66d272cfe563500c93f096e27f359c7834c3b56180169d6055dc7d002bbee58e5b300004a6bf77091facd6381ad90cc2dc3ddab148eede30441cf6767ba2b3ce03b8401a52fdaa208066175726120f4635e080000000005617572610101960963f3ebff0b6b57bf99454febef94f04726a2c94abd401c5d3b568ec3cc384b10dd3dd7d96d456df0b8ed5cc6bacab809e163f85ec0b96529a9f3fa28f5870200000001000000" //nolint:all + expectedHash := parachainTestData.Expected["candidateEvents"] + if expectedHash == "" { + t.Fatal("candidateEvents expected hash is not defined in test data") + } expected := common.MustHexToBytes(expectedHash) require.Equal(t, expected, encoded) } @@ -1436,110 +1465,11 @@ func TestInstance_ParachainHostSessionInfo(t *testing.T) { } func getParachainHostTrie(t *testing.T) *trie.Trie { - // taken from https://polkadot.js.org/apps/#/chainstate (westend) - // at: 0x03458e146407a2ad41a87b18298540cad7d48f931f4815ca1fbef281e5943ef5 - data := []struct { - name string - key string - value string - }{ - { - name: "parasShared.activeValidatorKeys", - key: "0xb341e3a63e58a188839b242d17f8c9f87a50c904b368210021127f9238883a6e", - value: "0x44a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe7274c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c51194ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050eac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547cee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936", //nolint:all - }, - { - name: "system.number", //block number - key: "0x26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac", - value: "0x9652f300", - }, - { - name: "paraScheduler.validatorGroups", - key: "0x94eadf0156a8ad5156507773d0471e4a16973e1142f5bd30d9464076794007db", - value: "0x0c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f00000010000000", //nolint:all - }, - { - name: "paraScheduler.sessionStartBlock", - key: "0x94eadf0156a8ad5156507773d0471e4a9ce0310edffce7a01a96c2039f92dd10", - value: "0xac51f300", - }, - { - name: "configuration.activeConfig", - key: "0x06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385", - value: "0x00005000005000000a00000000c8000000c800000a0000000a000000c80000006400000000000000000000000000500000c800000700e8764817020040010a0000000000000000c0220fca950300000000000000000000c0220fca9503000000000000000000e8030000009001000a0000000000000000900100008070000000000000000000000a000000050000000500000001000000010500000001c8000000060000005802000002000000280000000000000002000000010000000700c817a8040200400101020000000f000000", //nolint:all - }, - { - name: "paraScheduler.availabilityCores", - key: "0x94eadf0156a8ad5156507773d0471e4ab8ebad86f546c7e0b135a4212aace339", - value: "0x0c010101010101", - }, - { - name: "paras.parachains", - key: "0xcd710b30bd2eab0352ddcc26417aa1940b76934f4cc08dee01012d059e1b83ee", - value: "0x0ce8030000e9030000ea030000", - }, - { - name: "paraInclusion.pendingAvailability[paraId=1000]", - key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865b6ff6f7d467b87a9e8030000", - value: "0x0000000058b29da15fc66c19ef0ad4e66e95c8e42718d2455001ec6876f4173489a705fbe8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b5145337440000004400f0019552f3009652f30002000000", //nolint:all - }, - { - name: "paraInclusion.pendingAvailabilityCommitments[paraId=1000]", - key: "0x196e027349017067f9eb56e2c4d9ded50433e4ed72dccf0edcf58c3192f16e4bb6ff6f7d467b87a9e8030000", - value: "0x000000e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e000000009552f300", //nolint:all - }, - { - name: "paraInclusion.pendingAvailability[paraId=1001]", - key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865adc7217647a32b0be9030000", - value: "0x010000000571a387d344bef8a77d3a99895958644dee97345861f7747b1cb8186a14089ee9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e6744000000443f00009552f3009652f30000000000", //nolint:all - }, - { - name: "paraInclusion.pendingAvailability[paraId=1002]", - key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865b2b032492225337bea030000", - value: "0x020000009b716202cd9fabb93b278a41d9344faecb1300241d255d1de0675a42ebff6b6eea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc529964400000044c00f009552f3009652f30001000000", //nolint:all - }, - { - name: "parasShared.currentSessionIndex", - key: "0xb341e3a63e58a188839b242d17f8c9f8b5cab3380174032968897a4c3ce57c0a", - value: "0xf36a0000", - }, - { - name: "paraSessionInfo.sessions[Id=27379]", - key: "0x4da2c41eaffa8e1a791c5d65beeefd1f028685274e698e781f7f2766cba0cc83f36a0000", - value: "0x44070000000c0000000e000000010000000400000010000000030000000b00000009000000060000000d0000000f0000000500000000000000080000000a000000020000009a14667dcf973e46392904593e8caf2fb7a57904edbadf1547531657e7a56b5e0600000044a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe7274c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c51194ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050eac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547cee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e3685893644407a89ac6943b9d2ef1ceb5f1299941758a6af5b8f79b89b90f95a3e38179341307744a128c608be0dff2189557715b74734359974606d96dc4d256d61b1047d74fff2667b4a2cc69198ec9d3bf41f4d001ab644b45feaf89a21ff7ef3bd261898ab99b4b982d6a1d983ab05ac530b373043e6b7a4a7e5a7dc7ca1942196ae6c94f9e38609dd9972bfdbe4664f2063499f6233f895ee13b71793c926018a94284ce0e8ec374f50c27948b8880628918a41b56930f1af675a5b5099d23f3267633a58b8f1f529e55fc3dac1dd81cb4547565c09f6e98d97243acb98bdda890028982bcec62ad60cf9fd00e89b7e3589adb668fcbc467127537851b5a5f3dbbb160695b906f52a88f18bdecd811785b4299c51ebb2a2755f0b4c0d83fbef4318610ec5e1d2d044023009c63659c65a79aaf07ecbf5b9887958243aa873a63e5a1b52ef04ed449e4db577d98ad433b779c36f0d122df03e1cdc3e840a49016c5f16c2d4b5973000d0b175631dde5d1657b3e34c2f75e8a6d5414013ce4036d83355a6e01665b2d8490abf45551088021041dfb41772a9d596ed6e9f261ed1c8ae72b436c143e295617afb60353a01f2941bd33370a662c99c040984e52a072b5f224c4c4b178f1a3d67e5f26d6b93b9a43937cd2d1d1cb2acc4650f504125df2e18ca17f0edc319c140113a44722f829aa1313da1b54298a10df49ad7d67d9de85f5a6bf6911fc41d8981c7c28f87e8ed4416c65e15624f7b4e36c6a1a72c7a7819446acc35b896fe346adeda25c4031cf6a81e58dca091164370859828cc4456901a466627d554785807aaf50bfbdc9b8f729e8e20eb596ee5def5acd2acb72e405fc05cab9e7773ffaf045407579f9c8e16d56f119117421cd18a250c2e37fcb53ae2dca6ce9b3ebb40052c34392dc74d3cdd648399119fa470222a10956769d64f7477459916ace4f77d97d6ab5e1a2f06092282c7f0a1332628c14896e8e9be62c2574de3dc8feebfad1b3bee36a7bfe6c994e5d1459a5372ff447ac32dd46c11b0a8ed99f1e7ab160e0ac2fcfeee0d92d807c8fb4c1678e37997715578926c5c6c9bfa7c2e0f8e10a1a78bb982313c5c347a018cb3828886b99e109a8799d272e6037f1fc5b19015b7089ecf90034349e3f5c37cb50dec5356743614f94f8c33964b85f2b8e10e859e306d3670b8bdc0cea17b97dfd3edc8a9e1be1f127fee5b44d421ae62038ba15a377cad85e4ecd3c2a63b54fdbb82c47fb3e9c02640522648c51db949a58fd5f36a19888986275547b0c2fbb0b348ccb85dfc6c998dbe160ae9425710301a9241837d624438a5d82edbbd6bf2cdbcc2694ad7db31ef99219e47376e9af08b294901b879c7d658c41386453c6baa7c26560c5fd3b164e05d8af1a51649d44d12dffc24337f0a5424b18db9604133eafcb2639ddcdc2a7f0fae7a30d143fd125490434ca7325025a2338d0b8bb28dcd9373dfd83756191022eeba7c46f5fa1ea21e736d9ebd7a171fb2afe0a4f828a222ea0605a4ad0e60670c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f00000010000000030000000000000001000000280000000200000002000000", //nolint:all - }, - { - name: "system.events", - key: "0x26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7", - value: "0x1400000000000000e249433d551702000000010000002c00e8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b514533734cd6976981877d40277ad627ec04b2fc4ba04f558d9e4b41d911a6f41610350e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e00000000020000000000010000002c00e9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e67514f16481063738cae77af97e154a475018c89ac13ca21452572447ae3bea823e90259b97f6f68683641a4b1046440cedddbc2054805e95504e9813b7c352d68ce57ba9357001fb3b6742be5e417621c0fd5f742e9f1d142518605af00a244dc61ebd42d63e07666532e9e2ab468d56fccb902fa801513a4dddc19d9e4b1edaae85ef1d1758908066175726120f4635e080000000005617572610101ba71303b6313ffc193e07bd26aeed8754fd02e86d3fd314074dcb2393a2eae08d32f5ec38737493bbcb09abeb020eb7eadbef00102bd3802b0545d5bca7e6a8d01000000000000000000010000002c00ea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc5299687f044d87495f20844ff334fe3ff1fb62568167d343d8f39dba5673d75452c06e9023c1bee939fc42a875b2921ecda1e413a5bad4b53bfa7aa314ba9aaf7f66d272cfe563500c93f096e27f359c7834c3b56180169d6055dc7d002bbee58e5b300004a6bf77091facd6381ad90cc2dc3ddab148eede30441cf6767ba2b3ce03b8401a52fdaa208066175726120f4635e080000000005617572610101960963f3ebff0b6b57bf99454febef94f04726a2c94abd401c5d3b568ec3cc384b10dd3dd7d96d456df0b8ed5cc6bacab809e163f85ec0b96529a9f3fa28f5870200000001000000000001000000000007559ff8970d26023b00020000", //nolint:all - }, - { - name: "system.eventCount", - key: "0x26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850", - value: "0x05000000", - }, - { - name: "hrmp.hrmpIngressChannelsIndex[paraId=1000]", - key: "0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948b6ff6f7d467b87a9e8030000", - value: "0x08d007000049080000", - }, - { - name: "hrmp.hrmpIngressChannelsIndex[paraId=1001]", - key: "0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948b6ff6f7d467b87a9e8030000", - value: "0x08d007000049080000", - }, - { - name: "hrmp.hrmpIngressChannelsIndex[paraId=1002]", - key: "0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948b6ff6f7d467b87a9e8030000", - value: "0x08d007000049080000", - }, - } - tt := trie.NewEmptyTrie() - for _, d := range data { - key := common.MustHexToBytes(d.key) - value := common.MustHexToBytes(d.value) + for _, s := range parachainTestData.Storage { + key := common.MustHexToBytes(s.Key) + value := common.MustHexToBytes(s.Value) err := tt.Put(key, value) require.NoError(t, err) } diff --git a/lib/runtime/wasmer/testdata/parachain.yaml b/lib/runtime/wasmer/testdata/parachain.yaml new file mode 100644 index 0000000000..c3c0bc5a61 --- /dev/null +++ b/lib/runtime/wasmer/testdata/parachain.yaml @@ -0,0 +1,62 @@ +# taken from https://polkadot.js.org/apps/#/chainstate (westend) +# at: 0x03458e146407a2ad41a87b18298540cad7d48f931f4815ca1fbef281e5943ef5 + +storage: +# parasShared.activeValidatorKeys + - key: "0xb341e3a63e58a188839b242d17f8c9f87a50c904b368210021127f9238883a6e" + value: "0x44a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe7274c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c51194ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050eac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547cee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936" +# system.number + - key: "0x26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac" + value: "0x9652f300" +# paraScheduler.validatorGroups + - key: "0x94eadf0156a8ad5156507773d0471e4a16973e1142f5bd30d9464076794007db" + value: "0x0c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f00000010000000" +# paraScheduler.sessionStartBlock + - key: "0x94eadf0156a8ad5156507773d0471e4a9ce0310edffce7a01a96c2039f92dd10" + value: "0xac51f300" +# configuration.activeConfig + - key: "0x06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385" + value: "0x00005000005000000a00000000c8000000c800000a0000000a000000c80000006400000000000000000000000000500000c800000700e8764817020040010a0000000000000000c0220fca950300000000000000000000c0220fca9503000000000000000000e8030000009001000a0000000000000000900100008070000000000000000000000a000000050000000500000001000000010500000001c8000000060000005802000002000000280000000000000002000000010000000700c817a8040200400101020000000f000000" +# paraScheduler.availabilityCores + - key: "0x94eadf0156a8ad5156507773d0471e4ab8ebad86f546c7e0b135a4212aace339" + value: "0x0c010101010101" +# paras.parachains + - key: "0xcd710b30bd2eab0352ddcc26417aa1940b76934f4cc08dee01012d059e1b83ee" + value: "0x0ce8030000e9030000ea030000" +# paraInclusion.pendingAvailability[paraId=1000] + - key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865b6ff6f7d467b87a9e8030000" + value: "0x0000000058b29da15fc66c19ef0ad4e66e95c8e42718d2455001ec6876f4173489a705fbe8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b5145337440000004400f0019552f3009652f30002000000" +# paraInclusion.pendingAvailabilityCommitments[paraId=1000] + - key: "0x196e027349017067f9eb56e2c4d9ded50433e4ed72dccf0edcf58c3192f16e4bb6ff6f7d467b87a9e8030000" + value: "0x000000e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e000000009552f300" +# paraInclusion.pendingAvailability[paraId=1001] + - key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865adc7217647a32b0be9030000" + value: "0x010000000571a387d344bef8a77d3a99895958644dee97345861f7747b1cb8186a14089ee9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e6744000000443f00009552f3009652f30000000000" +# paraInclusion.pendingAvailability[paraId=1002] + - key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865b2b032492225337bea030000" + value: "0x020000009b716202cd9fabb93b278a41d9344faecb1300241d255d1de0675a42ebff6b6eea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc529964400000044c00f009552f3009652f30001000000" +# parasShared.currentSessionIndex + - key: "0xb341e3a63e58a188839b242d17f8c9f8b5cab3380174032968897a4c3ce57c0a" + value: "0xf36a0000" +# paraSessionInfo.sessions[Id=27379] + - key: "0x4da2c41eaffa8e1a791c5d65beeefd1f028685274e698e781f7f2766cba0cc83f36a0000" + value: "0x44070000000c0000000e000000010000000400000010000000030000000b00000009000000060000000d0000000f0000000500000000000000080000000a000000020000009a14667dcf973e46392904593e8caf2fb7a57904edbadf1547531657e7a56b5e0600000044a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe7274c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c51194ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050eac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547cee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e3685893644407a89ac6943b9d2ef1ceb5f1299941758a6af5b8f79b89b90f95a3e38179341307744a128c608be0dff2189557715b74734359974606d96dc4d256d61b1047d74fff2667b4a2cc69198ec9d3bf41f4d001ab644b45feaf89a21ff7ef3bd261898ab99b4b982d6a1d983ab05ac530b373043e6b7a4a7e5a7dc7ca1942196ae6c94f9e38609dd9972bfdbe4664f2063499f6233f895ee13b71793c926018a94284ce0e8ec374f50c27948b8880628918a41b56930f1af675a5b5099d23f3267633a58b8f1f529e55fc3dac1dd81cb4547565c09f6e98d97243acb98bdda890028982bcec62ad60cf9fd00e89b7e3589adb668fcbc467127537851b5a5f3dbbb160695b906f52a88f18bdecd811785b4299c51ebb2a2755f0b4c0d83fbef4318610ec5e1d2d044023009c63659c65a79aaf07ecbf5b9887958243aa873a63e5a1b52ef04ed449e4db577d98ad433b779c36f0d122df03e1cdc3e840a49016c5f16c2d4b5973000d0b175631dde5d1657b3e34c2f75e8a6d5414013ce4036d83355a6e01665b2d8490abf45551088021041dfb41772a9d596ed6e9f261ed1c8ae72b436c143e295617afb60353a01f2941bd33370a662c99c040984e52a072b5f224c4c4b178f1a3d67e5f26d6b93b9a43937cd2d1d1cb2acc4650f504125df2e18ca17f0edc319c140113a44722f829aa1313da1b54298a10df49ad7d67d9de85f5a6bf6911fc41d8981c7c28f87e8ed4416c65e15624f7b4e36c6a1a72c7a7819446acc35b896fe346adeda25c4031cf6a81e58dca091164370859828cc4456901a466627d554785807aaf50bfbdc9b8f729e8e20eb596ee5def5acd2acb72e405fc05cab9e7773ffaf045407579f9c8e16d56f119117421cd18a250c2e37fcb53ae2dca6ce9b3ebb40052c34392dc74d3cdd648399119fa470222a10956769d64f7477459916ace4f77d97d6ab5e1a2f06092282c7f0a1332628c14896e8e9be62c2574de3dc8feebfad1b3bee36a7bfe6c994e5d1459a5372ff447ac32dd46c11b0a8ed99f1e7ab160e0ac2fcfeee0d92d807c8fb4c1678e37997715578926c5c6c9bfa7c2e0f8e10a1a78bb982313c5c347a018cb3828886b99e109a8799d272e6037f1fc5b19015b7089ecf90034349e3f5c37cb50dec5356743614f94f8c33964b85f2b8e10e859e306d3670b8bdc0cea17b97dfd3edc8a9e1be1f127fee5b44d421ae62038ba15a377cad85e4ecd3c2a63b54fdbb82c47fb3e9c02640522648c51db949a58fd5f36a19888986275547b0c2fbb0b348ccb85dfc6c998dbe160ae9425710301a9241837d624438a5d82edbbd6bf2cdbcc2694ad7db31ef99219e47376e9af08b294901b879c7d658c41386453c6baa7c26560c5fd3b164e05d8af1a51649d44d12dffc24337f0a5424b18db9604133eafcb2639ddcdc2a7f0fae7a30d143fd125490434ca7325025a2338d0b8bb28dcd9373dfd83756191022eeba7c46f5fa1ea21e736d9ebd7a171fb2afe0a4f828a222ea0605a4ad0e60670c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f00000010000000030000000000000001000000280000000200000002000000" +# system.events + - key: "0x26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7" + value: "0x1400000000000000e249433d551702000000010000002c00e8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b514533734cd6976981877d40277ad627ec04b2fc4ba04f558d9e4b41d911a6f41610350e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e00000000020000000000010000002c00e9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e67514f16481063738cae77af97e154a475018c89ac13ca21452572447ae3bea823e90259b97f6f68683641a4b1046440cedddbc2054805e95504e9813b7c352d68ce57ba9357001fb3b6742be5e417621c0fd5f742e9f1d142518605af00a244dc61ebd42d63e07666532e9e2ab468d56fccb902fa801513a4dddc19d9e4b1edaae85ef1d1758908066175726120f4635e080000000005617572610101ba71303b6313ffc193e07bd26aeed8754fd02e86d3fd314074dcb2393a2eae08d32f5ec38737493bbcb09abeb020eb7eadbef00102bd3802b0545d5bca7e6a8d01000000000000000000010000002c00ea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc5299687f044d87495f20844ff334fe3ff1fb62568167d343d8f39dba5673d75452c06e9023c1bee939fc42a875b2921ecda1e413a5bad4b53bfa7aa314ba9aaf7f66d272cfe563500c93f096e27f359c7834c3b56180169d6055dc7d002bbee58e5b300004a6bf77091facd6381ad90cc2dc3ddab148eede30441cf6767ba2b3ce03b8401a52fdaa208066175726120f4635e080000000005617572610101960963f3ebff0b6b57bf99454febef94f04726a2c94abd401c5d3b568ec3cc384b10dd3dd7d96d456df0b8ed5cc6bacab809e163f85ec0b96529a9f3fa28f5870200000001000000000001000000000007559ff8970d26023b00020000" +# system.eventCount + - key: "0x26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850" + value: "0x05000000" +# hrmp.hrmpIngressChannelsIndex[paraId=1000] + - key: "0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948b6ff6f7d467b87a9e8030000" + value: "0x08d007000049080000" +# hrmp.hrmpIngressChannelsIndex[paraId=1001] + - key: "0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948b6ff6f7d467b87a9e8030000" + value: "0x08d007000049080000" +# hrmp.hrmpIngressChannelsIndex[paraId=1002] + - key: "0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948b6ff6f7d467b87a9e8030000" + value: "0x08d007000049080000" +expected: + availabilityCores: "0x0c0001e8030000009652f3009c52f30001e803000000440000000200000058b29da15fc66c19ef0ad4e66e95c8e42718d2455001ec6876f4173489a705fbe8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b51453370001e9030000009652f3009c52f30001e90300000044000000000000000571a387d344bef8a77d3a99895958644dee97345861f7747b1cb8186a14089ee9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e670001ea030000009652f3009c52f30001ea0300000044000000010000009b716202cd9fabb93b278a41d9344faecb1300241d255d1de0675a42ebff6b6eea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc52996" + candidateEvents: "0x0c00e8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b514533734cd6976981877d40277ad627ec04b2fc4ba04f558d9e4b41d911a6f41610350e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e000000000200000000e9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e67514f16481063738cae77af97e154a475018c89ac13ca21452572447ae3bea823e90259b97f6f68683641a4b1046440cedddbc2054805e95504e9813b7c352d68ce57ba9357001fb3b6742be5e417621c0fd5f742e9f1d142518605af00a244dc61ebd42d63e07666532e9e2ab468d56fccb902fa801513a4dddc19d9e4b1edaae85ef1d1758908066175726120f4635e080000000005617572610101ba71303b6313ffc193e07bd26aeed8754fd02e86d3fd314074dcb2393a2eae08d32f5ec38737493bbcb09abeb020eb7eadbef00102bd3802b0545d5bca7e6a8d010000000000000000ea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc5299687f044d87495f20844ff334fe3ff1fb62568167d343d8f39dba5673d75452c06e9023c1bee939fc42a875b2921ecda1e413a5bad4b53bfa7aa314ba9aaf7f66d272cfe563500c93f096e27f359c7834c3b56180169d6055dc7d002bbee58e5b300004a6bf77091facd6381ad90cc2dc3ddab148eede30441cf6767ba2b3ce03b8401a52fdaa208066175726120f4635e080000000005617572610101960963f3ebff0b6b57bf99454febef94f04726a2c94abd401c5d3b568ec3cc384b10dd3dd7d96d456df0b8ed5cc6bacab809e163f85ec0b96529a9f3fa28f5870200000001000000" + From f616ce1472889ca6f454a6f3c448a6eb3110a2ba Mon Sep 17 00:00:00 2001 From: kanishka Date: Fri, 16 Jun 2023 16:41:47 +0530 Subject: [PATCH 62/65] cleanup --- lib/runtime/wasmer/exports.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index 2a9649fc10..ec275196a0 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -350,13 +350,13 @@ func (in *Instance) GrandpaSubmitReportEquivocationUnsignedExtrinsic( // ParachainHostValidators Returns the validator set at the current state. // The specified validators are responsible for backing parachains for the current state. func (in *Instance) ParachainHostValidators() ([]parachain.ValidatorID, error) { - ret, err := in.Exec(runtime.ParachainHostValidators, []byte{}) + encodedValidators, err := in.Exec(runtime.ParachainHostValidators, []byte{}) if err != nil { return nil, fmt.Errorf("exec: %w", err) } var validatorIDs []parachain.ValidatorID - err = scale.Unmarshal(ret, &validatorIDs) + err = scale.Unmarshal(encodedValidators, &validatorIDs) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) } @@ -367,13 +367,13 @@ func (in *Instance) ParachainHostValidators() ([]parachain.ValidatorID, error) { // ParachainHostValidatorGroups Returns the validator groups used during the current session. // The validators in the groups are referred to by the validator set Id. func (in *Instance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { - ret, err := in.Exec(runtime.ParachainHostValidatorGroups, []byte{}) + encodedValidatorGroups, err := in.Exec(runtime.ParachainHostValidatorGroups, []byte{}) if err != nil { return nil, fmt.Errorf("exec: %w", err) } var validatorGroups parachain.ValidatorGroups - err = scale.Unmarshal(ret, &validatorGroups) + err = scale.Unmarshal(encodedValidatorGroups, &validatorGroups) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) } @@ -383,7 +383,7 @@ func (in *Instance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, // ParachainHostAvailabilityCores Returns the availability cores for the current state. func (in *Instance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { - ret, err := in.Exec(runtime.ParachainHostAvailabilityCores, []byte{}) + encodedAvailabilityCores, err := in.Exec(runtime.ParachainHostAvailabilityCores, []byte{}) if err != nil { return nil, fmt.Errorf("exec: %w", err) } @@ -392,7 +392,7 @@ func (in *Instance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlic if err != nil { return nil, fmt.Errorf("new availability cores: %w", err) } - err = scale.Unmarshal(ret, &availabilityCores) + err = scale.Unmarshal(encodedAvailabilityCores, &availabilityCores) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) } @@ -433,13 +433,13 @@ func (in *Instance) ParachainHostCheckValidationOutputs( // ParachainHostSessionIndexForChild Returns the session index that is expected at the child of a block. func (in *Instance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { - ret, err := in.Exec(runtime.ParachainHostSessionIndexForChild, []byte{}) + encodedSessionIndex, err := in.Exec(runtime.ParachainHostSessionIndexForChild, []byte{}) if err != nil { return 0, fmt.Errorf("exec: %w", err) } var sessionIndex parachain.SessionIndex - err = scale.Unmarshal(ret, &sessionIndex) + err = scale.Unmarshal(encodedSessionIndex, &sessionIndex) if err != nil { return 0, fmt.Errorf("unmarshal: %w", err) } @@ -475,7 +475,7 @@ func (in *Instance) ParachainHostCandidatePendingAvailability( // ParachainHostCandidateEvents Returns an array of candidate events that occurred within the latest state. func (in *Instance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { - ret, err := in.Exec(runtime.ParachainHostCandidateEvents, []byte{}) + encodedCandidateEvents, err := in.Exec(runtime.ParachainHostCandidateEvents, []byte{}) if err != nil { return nil, fmt.Errorf("exec: %w", err) } @@ -484,7 +484,7 @@ func (in *Instance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, if err != nil { return nil, fmt.Errorf("create new candidate events: %w", err) } - err = scale.Unmarshal(ret, &candidateEvents) + err = scale.Unmarshal(encodedCandidateEvents, &candidateEvents) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) } From 6b1059fffae8775b358e601e81a7b845a95ff1b1 Mon Sep 17 00:00:00 2001 From: kanishka Date: Tue, 20 Jun 2023 14:09:38 +0530 Subject: [PATCH 63/65] cleanup --- lib/runtime/wasmer/exports.go | 32 +++++++++++++++--------------- lib/runtime/wasmer/exports_test.go | 24 +++------------------- 2 files changed, 19 insertions(+), 37 deletions(-) diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index ec275196a0..c083318956 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -347,7 +347,7 @@ func (in *Instance) GrandpaSubmitReportEquivocationUnsignedExtrinsic( return nil } -// ParachainHostValidators Returns the validator set at the current state. +// ParachainHostValidators returns the validator set at the current state. // The specified validators are responsible for backing parachains for the current state. func (in *Instance) ParachainHostValidators() ([]parachain.ValidatorID, error) { encodedValidators, err := in.Exec(runtime.ParachainHostValidators, []byte{}) @@ -358,13 +358,13 @@ func (in *Instance) ParachainHostValidators() ([]parachain.ValidatorID, error) { var validatorIDs []parachain.ValidatorID err = scale.Unmarshal(encodedValidators, &validatorIDs) if err != nil { - return nil, fmt.Errorf("unmarshal: %w", err) + return nil, fmt.Errorf("unmarshalling: %w", err) } return validatorIDs, nil } -// ParachainHostValidatorGroups Returns the validator groups used during the current session. +// ParachainHostValidatorGroups returns the validator groups used during the current session. // The validators in the groups are referred to by the validator set Id. func (in *Instance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { encodedValidatorGroups, err := in.Exec(runtime.ParachainHostValidatorGroups, []byte{}) @@ -375,13 +375,13 @@ func (in *Instance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, var validatorGroups parachain.ValidatorGroups err = scale.Unmarshal(encodedValidatorGroups, &validatorGroups) if err != nil { - return nil, fmt.Errorf("unmarshal: %w", err) + return nil, fmt.Errorf("unmarshalling: %w", err) } return &validatorGroups, nil } -// ParachainHostAvailabilityCores Returns the availability cores for the current state. +// ParachainHostAvailabilityCores returns the availability cores for the current state. func (in *Instance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { encodedAvailabilityCores, err := in.Exec(runtime.ParachainHostAvailabilityCores, []byte{}) if err != nil { @@ -394,13 +394,13 @@ func (in *Instance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlic } err = scale.Unmarshal(encodedAvailabilityCores, &availabilityCores) if err != nil { - return nil, fmt.Errorf("unmarshal: %w", err) + return nil, fmt.Errorf("unmarshalling: %w", err) } return &availabilityCores, nil } -// ParachainHostCheckValidationOutputs Checks the validation outputs of a candidate. +// ParachainHostCheckValidationOutputs checks the validation outputs of a candidate. // Returns true if the candidate is valid. func (in *Instance) ParachainHostCheckValidationOutputs( parachainID parachain.ParaID, @@ -425,13 +425,13 @@ func (in *Instance) ParachainHostCheckValidationOutputs( var isValid bool err = scale.Unmarshal(encodedPersistedValidationData, &isValid) if err != nil { - return false, fmt.Errorf("unmarshal: %w", err) + return false, fmt.Errorf("unmarshalling: %w", err) } return isValid, nil } -// ParachainHostSessionIndexForChild Returns the session index that is expected at the child of a block. +// ParachainHostSessionIndexForChild returns the session index that is expected at the child of a block. func (in *Instance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { encodedSessionIndex, err := in.Exec(runtime.ParachainHostSessionIndexForChild, []byte{}) if err != nil { @@ -441,13 +441,13 @@ func (in *Instance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, var sessionIndex parachain.SessionIndex err = scale.Unmarshal(encodedSessionIndex, &sessionIndex) if err != nil { - return 0, fmt.Errorf("unmarshal: %w", err) + return 0, fmt.Errorf("unmarshalling: %w", err) } return sessionIndex, nil } -// ParachainHostCandidatePendingAvailability Returns the receipt of a candidate pending availability +// ParachainHostCandidatePendingAvailability returns the receipt of a candidate pending availability // for any parachain assigned to an occupied availability core. func (in *Instance) ParachainHostCandidatePendingAvailability( parachainID parachain.ParaID, @@ -467,13 +467,13 @@ func (in *Instance) ParachainHostCandidatePendingAvailability( var candidateReceipt *parachain.CommittedCandidateReceipt err = scale.Unmarshal(encodedCandidateReceipt, &candidateReceipt) if err != nil { - return nil, fmt.Errorf("unmarshal: %w", err) + return nil, fmt.Errorf("unmarshalling: %w", err) } return candidateReceipt, nil } -// ParachainHostCandidateEvents Returns an array of candidate events that occurred within the latest state. +// ParachainHostCandidateEvents returns an array of candidate events that occurred within the latest state. func (in *Instance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { encodedCandidateEvents, err := in.Exec(runtime.ParachainHostCandidateEvents, []byte{}) if err != nil { @@ -486,13 +486,13 @@ func (in *Instance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, } err = scale.Unmarshal(encodedCandidateEvents, &candidateEvents) if err != nil { - return nil, fmt.Errorf("unmarshal: %w", err) + return nil, fmt.Errorf("unmarshalling: %w", err) } return &candidateEvents, nil } -// ParachainHostSessionInfo Returns the session info of the given session, if available. +// ParachainHostSessionInfo returns the session info of the given session, if available. func (in *Instance) ParachainHostSessionInfo(sessionIndex parachain.SessionIndex) (*parachain.SessionInfo, error) { buffer := bytes.NewBuffer(nil) encoder := scale.NewEncoder(buffer) @@ -509,7 +509,7 @@ func (in *Instance) ParachainHostSessionInfo(sessionIndex parachain.SessionIndex var sessionInfo *parachain.SessionInfo err = scale.Unmarshal(encodedSessionInfo, &sessionInfo) if err != nil { - return nil, fmt.Errorf("unmarshal: %w", err) + return nil, fmt.Errorf("unmarshalling: %w", err) } return sessionInfo, nil diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index e2ef627b1d..8151e9c8d0 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -1365,27 +1365,9 @@ func TestInstance_ParachainHostSessionInfo(t *testing.T) { require.NoError(t, err) expected := ¶chain.SessionInfo{ - ActiveValidatorIndices: []parachain.ValidatorIndex{ - 7, - 12, - 14, - 1, - 4, - 16, - 3, - 11, - 9, - 6, - 13, - 15, - 5, - 0, - 8, - 10, - 2, - }, - RandomSeed: mustHexTo32BArray(t, "0x9a14667dcf973e46392904593e8caf2fb7a57904edbadf1547531657e7a56b5e"), - DisputePeriod: 6, + ActiveValidatorIndices: []parachain.ValidatorIndex{7, 12, 14, 1, 4, 16, 3, 11, 9, 6, 13, 15, 5, 0, 8, 10, 2}, + RandomSeed: mustHexTo32BArray(t, "0x9a14667dcf973e46392904593e8caf2fb7a57904edbadf1547531657e7a56b5e"), + DisputePeriod: 6, Validators: []parachain.ValidatorID{ mustHexTo32BArray(t, "0xa262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d"), mustHexTo32BArray(t, "0x804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e"), From e77dbd1114c6ebacc277388bebf0007946ecc51b Mon Sep 17 00:00:00 2001 From: kanishka Date: Tue, 20 Jun 2023 14:16:57 +0530 Subject: [PATCH 64/65] cleanup --- lib/runtime/wasmer/exports_test.go | 29 ++++++---------------- lib/runtime/wasmer/testdata/parachain.yaml | 1 + 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index 8151e9c8d0..b379ac44e0 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -1311,29 +1311,16 @@ func TestInstance_ParachainHostCandidatePendingAvailability(t *testing.T) { response, err := rt.ParachainHostCandidatePendingAvailability(parachain.ParaID(1000)) require.NoError(t, err) - expected := ¶chain.CommittedCandidateReceipt{ - Descriptor: parachain.CandidateDescriptor{ - ParaID: 1000, - RelayParent: mustHexTo32BArray(t, "0xb5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083"), //nolint:all - Collator: mustHexTo32BArray(t, "0x1aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251"), //nolint:all - PersistedValidationDataHash: mustHexTo32BArray(t, "0xa2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd5"), //nolint:all - PovHash: mustHexTo32BArray(t, "0x20d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293"), //nolint:all - ErasureRoot: mustHexTo32BArray(t, "0xd91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b"), //nolint:all - Signature: mustHexTo64BArray(t, "0x68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084"), //nolint:all - ParaHead: mustHexTo32BArray(t, "0xd94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211"), //nolint:all - ValidationCodeHash: mustHexTo32BArray(t, "0xcafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b5145337"), //nolint:all - }, - Commitments: parachain.CandidateCommitments{ - UpwardMessages: nil, - HorizontalMessages: nil, - NewValidationCode: nil, - HeadData: common.MustHexToBytes("0xd91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e"), //nolint:all - ProcessedDownwardMessages: 0, - HrmpWatermark: 15946389, - }, + expectedHash := parachainTestData.Expected["candidatePendingAvailability"] + if expectedHash == "" { + t.Fatal("could not get expected hash from test data") } - require.Equal(t, expected, response) + b, err := scale.Marshal(*response) + require.NoError(t, err) + + resultHex := common.BytesToHex(b) + require.Equal(t, expectedHash, resultHex) } func TestInstance_ParachainHostCandidateEvents(t *testing.T) { diff --git a/lib/runtime/wasmer/testdata/parachain.yaml b/lib/runtime/wasmer/testdata/parachain.yaml index c3c0bc5a61..440df4c7e7 100644 --- a/lib/runtime/wasmer/testdata/parachain.yaml +++ b/lib/runtime/wasmer/testdata/parachain.yaml @@ -59,4 +59,5 @@ storage: expected: availabilityCores: "0x0c0001e8030000009652f3009c52f30001e803000000440000000200000058b29da15fc66c19ef0ad4e66e95c8e42718d2455001ec6876f4173489a705fbe8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b51453370001e9030000009652f3009c52f30001e90300000044000000000000000571a387d344bef8a77d3a99895958644dee97345861f7747b1cb8186a14089ee9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e670001ea030000009652f3009c52f30001ea0300000044000000010000009b716202cd9fabb93b278a41d9344faecb1300241d255d1de0675a42ebff6b6eea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc52996" candidateEvents: "0x0c00e8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b514533734cd6976981877d40277ad627ec04b2fc4ba04f558d9e4b41d911a6f41610350e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e000000000200000000e9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e67514f16481063738cae77af97e154a475018c89ac13ca21452572447ae3bea823e90259b97f6f68683641a4b1046440cedddbc2054805e95504e9813b7c352d68ce57ba9357001fb3b6742be5e417621c0fd5f742e9f1d142518605af00a244dc61ebd42d63e07666532e9e2ab468d56fccb902fa801513a4dddc19d9e4b1edaae85ef1d1758908066175726120f4635e080000000005617572610101ba71303b6313ffc193e07bd26aeed8754fd02e86d3fd314074dcb2393a2eae08d32f5ec38737493bbcb09abeb020eb7eadbef00102bd3802b0545d5bca7e6a8d010000000000000000ea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc5299687f044d87495f20844ff334fe3ff1fb62568167d343d8f39dba5673d75452c06e9023c1bee939fc42a875b2921ecda1e413a5bad4b53bfa7aa314ba9aaf7f66d272cfe563500c93f096e27f359c7834c3b56180169d6055dc7d002bbee58e5b300004a6bf77091facd6381ad90cc2dc3ddab148eede30441cf6767ba2b3ce03b8401a52fdaa208066175726120f4635e080000000005617572610101960963f3ebff0b6b57bf99454febef94f04726a2c94abd401c5d3b568ec3cc384b10dd3dd7d96d456df0b8ed5cc6bacab809e163f85ec0b96529a9f3fa28f5870200000001000000" + candidatePendingAvailability: "0xe8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b5145337000000e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e000000009552f300" From 8033ad9b42e89335b3cc1031c74810d137d47840 Mon Sep 17 00:00:00 2001 From: Kishan Mohanbhai Sagathiya Date: Wed, 21 Jun 2023 14:19:24 +0530 Subject: [PATCH 65/65] Added parachain runtime funcs to runtime interface --- dot/core/mock_runtime_instance_test.go | 122 +++++++++++++++++++++++++ dot/state/mocks_runtime_test.go | 122 +++++++++++++++++++++++++ dot/sync/mock_runtime_test.go | 122 +++++++++++++++++++++++++ lib/babe/mocks/runtime.go | 122 +++++++++++++++++++++++++ lib/blocktree/mocks_test.go | 122 +++++++++++++++++++++++++ lib/grandpa/mocks_runtime_test.go | 122 +++++++++++++++++++++++++ lib/runtime/interface.go | 15 +++ lib/runtime/mocks/mocks.go | 122 +++++++++++++++++++++++++ 8 files changed, 869 insertions(+) diff --git a/dot/core/mock_runtime_instance_test.go b/dot/core/mock_runtime_instance_test.go index 0a1f6a7478..e671aee681 100644 --- a/dot/core/mock_runtime_instance_test.go +++ b/dot/core/mock_runtime_instance_test.go @@ -11,8 +11,10 @@ import ( common "github.com/ChainSafe/gossamer/lib/common" ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" keystore "github.com/ChainSafe/gossamer/lib/keystore" + parachain "github.com/ChainSafe/gossamer/lib/parachain" runtime "github.com/ChainSafe/gossamer/lib/runtime" transaction "github.com/ChainSafe/gossamer/lib/transaction" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -338,6 +340,126 @@ func (mr *MockInstanceMockRecorder) OffchainWorker() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OffchainWorker", reflect.TypeOf((*MockInstance)(nil).OffchainWorker)) } +// ParachainHostAvailabilityCores mocks base method. +func (m *MockInstance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostAvailabilityCores") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostAvailabilityCores indicates an expected call of ParachainHostAvailabilityCores. +func (mr *MockInstanceMockRecorder) ParachainHostAvailabilityCores() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostAvailabilityCores", reflect.TypeOf((*MockInstance)(nil).ParachainHostAvailabilityCores)) +} + +// ParachainHostCandidateEvents mocks base method. +func (m *MockInstance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidateEvents") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidateEvents indicates an expected call of ParachainHostCandidateEvents. +func (mr *MockInstanceMockRecorder) ParachainHostCandidateEvents() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidateEvents", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidateEvents)) +} + +// ParachainHostCandidatePendingAvailability mocks base method. +func (m *MockInstance) ParachainHostCandidatePendingAvailability(arg0 parachain.ParaID) (*parachain.CommittedCandidateReceipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidatePendingAvailability", arg0) + ret0, _ := ret[0].(*parachain.CommittedCandidateReceipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidatePendingAvailability indicates an expected call of ParachainHostCandidatePendingAvailability. +func (mr *MockInstanceMockRecorder) ParachainHostCandidatePendingAvailability(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidatePendingAvailability", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidatePendingAvailability), arg0) +} + +// ParachainHostCheckValidationOutputs mocks base method. +func (m *MockInstance) ParachainHostCheckValidationOutputs(arg0 parachain.ParaID, arg1 parachain.CandidateCommitments) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCheckValidationOutputs", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCheckValidationOutputs indicates an expected call of ParachainHostCheckValidationOutputs. +func (mr *MockInstanceMockRecorder) ParachainHostCheckValidationOutputs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCheckValidationOutputs", reflect.TypeOf((*MockInstance)(nil).ParachainHostCheckValidationOutputs), arg0, arg1) +} + +// ParachainHostSessionIndexForChild mocks base method. +func (m *MockInstance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionIndexForChild") + ret0, _ := ret[0].(parachain.SessionIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionIndexForChild indicates an expected call of ParachainHostSessionIndexForChild. +func (mr *MockInstanceMockRecorder) ParachainHostSessionIndexForChild() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionIndexForChild", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionIndexForChild)) +} + +// ParachainHostSessionInfo mocks base method. +func (m *MockInstance) ParachainHostSessionInfo(arg0 parachain.SessionIndex) (*parachain.SessionInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionInfo", arg0) + ret0, _ := ret[0].(*parachain.SessionInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionInfo indicates an expected call of ParachainHostSessionInfo. +func (mr *MockInstanceMockRecorder) ParachainHostSessionInfo(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionInfo", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionInfo), arg0) +} + +// ParachainHostValidatorGroups mocks base method. +func (m *MockInstance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidatorGroups") + ret0, _ := ret[0].(*parachain.ValidatorGroups) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidatorGroups indicates an expected call of ParachainHostValidatorGroups. +func (mr *MockInstanceMockRecorder) ParachainHostValidatorGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidatorGroups", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidatorGroups)) +} + +// ParachainHostValidators mocks base method. +func (m *MockInstance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidators") + ret0, _ := ret[0].([]parachain.ValidatorID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidators indicates an expected call of ParachainHostValidators. +func (mr *MockInstanceMockRecorder) ParachainHostValidators() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidators", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidators)) +} + // PaymentQueryInfo mocks base method. func (m *MockInstance) PaymentQueryInfo(arg0 []byte) (*types.RuntimeDispatchInfo, error) { m.ctrl.T.Helper() diff --git a/dot/state/mocks_runtime_test.go b/dot/state/mocks_runtime_test.go index 83be8da0e1..4029d21a02 100644 --- a/dot/state/mocks_runtime_test.go +++ b/dot/state/mocks_runtime_test.go @@ -11,8 +11,10 @@ import ( common "github.com/ChainSafe/gossamer/lib/common" ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" keystore "github.com/ChainSafe/gossamer/lib/keystore" + parachain "github.com/ChainSafe/gossamer/lib/parachain" runtime "github.com/ChainSafe/gossamer/lib/runtime" transaction "github.com/ChainSafe/gossamer/lib/transaction" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -338,6 +340,126 @@ func (mr *MockInstanceMockRecorder) OffchainWorker() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OffchainWorker", reflect.TypeOf((*MockInstance)(nil).OffchainWorker)) } +// ParachainHostAvailabilityCores mocks base method. +func (m *MockInstance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostAvailabilityCores") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostAvailabilityCores indicates an expected call of ParachainHostAvailabilityCores. +func (mr *MockInstanceMockRecorder) ParachainHostAvailabilityCores() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostAvailabilityCores", reflect.TypeOf((*MockInstance)(nil).ParachainHostAvailabilityCores)) +} + +// ParachainHostCandidateEvents mocks base method. +func (m *MockInstance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidateEvents") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidateEvents indicates an expected call of ParachainHostCandidateEvents. +func (mr *MockInstanceMockRecorder) ParachainHostCandidateEvents() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidateEvents", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidateEvents)) +} + +// ParachainHostCandidatePendingAvailability mocks base method. +func (m *MockInstance) ParachainHostCandidatePendingAvailability(arg0 parachain.ParaID) (*parachain.CommittedCandidateReceipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidatePendingAvailability", arg0) + ret0, _ := ret[0].(*parachain.CommittedCandidateReceipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidatePendingAvailability indicates an expected call of ParachainHostCandidatePendingAvailability. +func (mr *MockInstanceMockRecorder) ParachainHostCandidatePendingAvailability(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidatePendingAvailability", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidatePendingAvailability), arg0) +} + +// ParachainHostCheckValidationOutputs mocks base method. +func (m *MockInstance) ParachainHostCheckValidationOutputs(arg0 parachain.ParaID, arg1 parachain.CandidateCommitments) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCheckValidationOutputs", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCheckValidationOutputs indicates an expected call of ParachainHostCheckValidationOutputs. +func (mr *MockInstanceMockRecorder) ParachainHostCheckValidationOutputs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCheckValidationOutputs", reflect.TypeOf((*MockInstance)(nil).ParachainHostCheckValidationOutputs), arg0, arg1) +} + +// ParachainHostSessionIndexForChild mocks base method. +func (m *MockInstance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionIndexForChild") + ret0, _ := ret[0].(parachain.SessionIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionIndexForChild indicates an expected call of ParachainHostSessionIndexForChild. +func (mr *MockInstanceMockRecorder) ParachainHostSessionIndexForChild() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionIndexForChild", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionIndexForChild)) +} + +// ParachainHostSessionInfo mocks base method. +func (m *MockInstance) ParachainHostSessionInfo(arg0 parachain.SessionIndex) (*parachain.SessionInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionInfo", arg0) + ret0, _ := ret[0].(*parachain.SessionInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionInfo indicates an expected call of ParachainHostSessionInfo. +func (mr *MockInstanceMockRecorder) ParachainHostSessionInfo(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionInfo", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionInfo), arg0) +} + +// ParachainHostValidatorGroups mocks base method. +func (m *MockInstance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidatorGroups") + ret0, _ := ret[0].(*parachain.ValidatorGroups) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidatorGroups indicates an expected call of ParachainHostValidatorGroups. +func (mr *MockInstanceMockRecorder) ParachainHostValidatorGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidatorGroups", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidatorGroups)) +} + +// ParachainHostValidators mocks base method. +func (m *MockInstance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidators") + ret0, _ := ret[0].([]parachain.ValidatorID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidators indicates an expected call of ParachainHostValidators. +func (mr *MockInstanceMockRecorder) ParachainHostValidators() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidators", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidators)) +} + // PaymentQueryInfo mocks base method. func (m *MockInstance) PaymentQueryInfo(arg0 []byte) (*types.RuntimeDispatchInfo, error) { m.ctrl.T.Helper() diff --git a/dot/sync/mock_runtime_test.go b/dot/sync/mock_runtime_test.go index f1a583b884..36b3842e3c 100644 --- a/dot/sync/mock_runtime_test.go +++ b/dot/sync/mock_runtime_test.go @@ -11,8 +11,10 @@ import ( common "github.com/ChainSafe/gossamer/lib/common" ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" keystore "github.com/ChainSafe/gossamer/lib/keystore" + parachain "github.com/ChainSafe/gossamer/lib/parachain" runtime "github.com/ChainSafe/gossamer/lib/runtime" transaction "github.com/ChainSafe/gossamer/lib/transaction" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -338,6 +340,126 @@ func (mr *MockInstanceMockRecorder) OffchainWorker() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OffchainWorker", reflect.TypeOf((*MockInstance)(nil).OffchainWorker)) } +// ParachainHostAvailabilityCores mocks base method. +func (m *MockInstance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostAvailabilityCores") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostAvailabilityCores indicates an expected call of ParachainHostAvailabilityCores. +func (mr *MockInstanceMockRecorder) ParachainHostAvailabilityCores() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostAvailabilityCores", reflect.TypeOf((*MockInstance)(nil).ParachainHostAvailabilityCores)) +} + +// ParachainHostCandidateEvents mocks base method. +func (m *MockInstance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidateEvents") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidateEvents indicates an expected call of ParachainHostCandidateEvents. +func (mr *MockInstanceMockRecorder) ParachainHostCandidateEvents() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidateEvents", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidateEvents)) +} + +// ParachainHostCandidatePendingAvailability mocks base method. +func (m *MockInstance) ParachainHostCandidatePendingAvailability(arg0 parachain.ParaID) (*parachain.CommittedCandidateReceipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidatePendingAvailability", arg0) + ret0, _ := ret[0].(*parachain.CommittedCandidateReceipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidatePendingAvailability indicates an expected call of ParachainHostCandidatePendingAvailability. +func (mr *MockInstanceMockRecorder) ParachainHostCandidatePendingAvailability(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidatePendingAvailability", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidatePendingAvailability), arg0) +} + +// ParachainHostCheckValidationOutputs mocks base method. +func (m *MockInstance) ParachainHostCheckValidationOutputs(arg0 parachain.ParaID, arg1 parachain.CandidateCommitments) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCheckValidationOutputs", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCheckValidationOutputs indicates an expected call of ParachainHostCheckValidationOutputs. +func (mr *MockInstanceMockRecorder) ParachainHostCheckValidationOutputs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCheckValidationOutputs", reflect.TypeOf((*MockInstance)(nil).ParachainHostCheckValidationOutputs), arg0, arg1) +} + +// ParachainHostSessionIndexForChild mocks base method. +func (m *MockInstance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionIndexForChild") + ret0, _ := ret[0].(parachain.SessionIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionIndexForChild indicates an expected call of ParachainHostSessionIndexForChild. +func (mr *MockInstanceMockRecorder) ParachainHostSessionIndexForChild() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionIndexForChild", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionIndexForChild)) +} + +// ParachainHostSessionInfo mocks base method. +func (m *MockInstance) ParachainHostSessionInfo(arg0 parachain.SessionIndex) (*parachain.SessionInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionInfo", arg0) + ret0, _ := ret[0].(*parachain.SessionInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionInfo indicates an expected call of ParachainHostSessionInfo. +func (mr *MockInstanceMockRecorder) ParachainHostSessionInfo(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionInfo", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionInfo), arg0) +} + +// ParachainHostValidatorGroups mocks base method. +func (m *MockInstance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidatorGroups") + ret0, _ := ret[0].(*parachain.ValidatorGroups) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidatorGroups indicates an expected call of ParachainHostValidatorGroups. +func (mr *MockInstanceMockRecorder) ParachainHostValidatorGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidatorGroups", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidatorGroups)) +} + +// ParachainHostValidators mocks base method. +func (m *MockInstance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidators") + ret0, _ := ret[0].([]parachain.ValidatorID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidators indicates an expected call of ParachainHostValidators. +func (mr *MockInstanceMockRecorder) ParachainHostValidators() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidators", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidators)) +} + // PaymentQueryInfo mocks base method. func (m *MockInstance) PaymentQueryInfo(arg0 []byte) (*types.RuntimeDispatchInfo, error) { m.ctrl.T.Helper() diff --git a/lib/babe/mocks/runtime.go b/lib/babe/mocks/runtime.go index 369e51c6dc..2701d8022a 100644 --- a/lib/babe/mocks/runtime.go +++ b/lib/babe/mocks/runtime.go @@ -11,8 +11,10 @@ import ( common "github.com/ChainSafe/gossamer/lib/common" ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" keystore "github.com/ChainSafe/gossamer/lib/keystore" + parachain "github.com/ChainSafe/gossamer/lib/parachain" runtime "github.com/ChainSafe/gossamer/lib/runtime" transaction "github.com/ChainSafe/gossamer/lib/transaction" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -338,6 +340,126 @@ func (mr *MockInstanceMockRecorder) OffchainWorker() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OffchainWorker", reflect.TypeOf((*MockInstance)(nil).OffchainWorker)) } +// ParachainHostAvailabilityCores mocks base method. +func (m *MockInstance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostAvailabilityCores") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostAvailabilityCores indicates an expected call of ParachainHostAvailabilityCores. +func (mr *MockInstanceMockRecorder) ParachainHostAvailabilityCores() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostAvailabilityCores", reflect.TypeOf((*MockInstance)(nil).ParachainHostAvailabilityCores)) +} + +// ParachainHostCandidateEvents mocks base method. +func (m *MockInstance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidateEvents") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidateEvents indicates an expected call of ParachainHostCandidateEvents. +func (mr *MockInstanceMockRecorder) ParachainHostCandidateEvents() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidateEvents", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidateEvents)) +} + +// ParachainHostCandidatePendingAvailability mocks base method. +func (m *MockInstance) ParachainHostCandidatePendingAvailability(arg0 parachain.ParaID) (*parachain.CommittedCandidateReceipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidatePendingAvailability", arg0) + ret0, _ := ret[0].(*parachain.CommittedCandidateReceipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidatePendingAvailability indicates an expected call of ParachainHostCandidatePendingAvailability. +func (mr *MockInstanceMockRecorder) ParachainHostCandidatePendingAvailability(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidatePendingAvailability", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidatePendingAvailability), arg0) +} + +// ParachainHostCheckValidationOutputs mocks base method. +func (m *MockInstance) ParachainHostCheckValidationOutputs(arg0 parachain.ParaID, arg1 parachain.CandidateCommitments) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCheckValidationOutputs", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCheckValidationOutputs indicates an expected call of ParachainHostCheckValidationOutputs. +func (mr *MockInstanceMockRecorder) ParachainHostCheckValidationOutputs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCheckValidationOutputs", reflect.TypeOf((*MockInstance)(nil).ParachainHostCheckValidationOutputs), arg0, arg1) +} + +// ParachainHostSessionIndexForChild mocks base method. +func (m *MockInstance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionIndexForChild") + ret0, _ := ret[0].(parachain.SessionIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionIndexForChild indicates an expected call of ParachainHostSessionIndexForChild. +func (mr *MockInstanceMockRecorder) ParachainHostSessionIndexForChild() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionIndexForChild", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionIndexForChild)) +} + +// ParachainHostSessionInfo mocks base method. +func (m *MockInstance) ParachainHostSessionInfo(arg0 parachain.SessionIndex) (*parachain.SessionInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionInfo", arg0) + ret0, _ := ret[0].(*parachain.SessionInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionInfo indicates an expected call of ParachainHostSessionInfo. +func (mr *MockInstanceMockRecorder) ParachainHostSessionInfo(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionInfo", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionInfo), arg0) +} + +// ParachainHostValidatorGroups mocks base method. +func (m *MockInstance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidatorGroups") + ret0, _ := ret[0].(*parachain.ValidatorGroups) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidatorGroups indicates an expected call of ParachainHostValidatorGroups. +func (mr *MockInstanceMockRecorder) ParachainHostValidatorGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidatorGroups", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidatorGroups)) +} + +// ParachainHostValidators mocks base method. +func (m *MockInstance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidators") + ret0, _ := ret[0].([]parachain.ValidatorID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidators indicates an expected call of ParachainHostValidators. +func (mr *MockInstanceMockRecorder) ParachainHostValidators() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidators", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidators)) +} + // PaymentQueryInfo mocks base method. func (m *MockInstance) PaymentQueryInfo(arg0 []byte) (*types.RuntimeDispatchInfo, error) { m.ctrl.T.Helper() diff --git a/lib/blocktree/mocks_test.go b/lib/blocktree/mocks_test.go index 7c5eb64806..b1ea7d6183 100644 --- a/lib/blocktree/mocks_test.go +++ b/lib/blocktree/mocks_test.go @@ -11,8 +11,10 @@ import ( common "github.com/ChainSafe/gossamer/lib/common" ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" keystore "github.com/ChainSafe/gossamer/lib/keystore" + parachain "github.com/ChainSafe/gossamer/lib/parachain" runtime "github.com/ChainSafe/gossamer/lib/runtime" transaction "github.com/ChainSafe/gossamer/lib/transaction" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -338,6 +340,126 @@ func (mr *MockInstanceMockRecorder) OffchainWorker() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OffchainWorker", reflect.TypeOf((*MockInstance)(nil).OffchainWorker)) } +// ParachainHostAvailabilityCores mocks base method. +func (m *MockInstance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostAvailabilityCores") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostAvailabilityCores indicates an expected call of ParachainHostAvailabilityCores. +func (mr *MockInstanceMockRecorder) ParachainHostAvailabilityCores() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostAvailabilityCores", reflect.TypeOf((*MockInstance)(nil).ParachainHostAvailabilityCores)) +} + +// ParachainHostCandidateEvents mocks base method. +func (m *MockInstance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidateEvents") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidateEvents indicates an expected call of ParachainHostCandidateEvents. +func (mr *MockInstanceMockRecorder) ParachainHostCandidateEvents() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidateEvents", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidateEvents)) +} + +// ParachainHostCandidatePendingAvailability mocks base method. +func (m *MockInstance) ParachainHostCandidatePendingAvailability(arg0 parachain.ParaID) (*parachain.CommittedCandidateReceipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidatePendingAvailability", arg0) + ret0, _ := ret[0].(*parachain.CommittedCandidateReceipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidatePendingAvailability indicates an expected call of ParachainHostCandidatePendingAvailability. +func (mr *MockInstanceMockRecorder) ParachainHostCandidatePendingAvailability(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidatePendingAvailability", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidatePendingAvailability), arg0) +} + +// ParachainHostCheckValidationOutputs mocks base method. +func (m *MockInstance) ParachainHostCheckValidationOutputs(arg0 parachain.ParaID, arg1 parachain.CandidateCommitments) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCheckValidationOutputs", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCheckValidationOutputs indicates an expected call of ParachainHostCheckValidationOutputs. +func (mr *MockInstanceMockRecorder) ParachainHostCheckValidationOutputs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCheckValidationOutputs", reflect.TypeOf((*MockInstance)(nil).ParachainHostCheckValidationOutputs), arg0, arg1) +} + +// ParachainHostSessionIndexForChild mocks base method. +func (m *MockInstance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionIndexForChild") + ret0, _ := ret[0].(parachain.SessionIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionIndexForChild indicates an expected call of ParachainHostSessionIndexForChild. +func (mr *MockInstanceMockRecorder) ParachainHostSessionIndexForChild() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionIndexForChild", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionIndexForChild)) +} + +// ParachainHostSessionInfo mocks base method. +func (m *MockInstance) ParachainHostSessionInfo(arg0 parachain.SessionIndex) (*parachain.SessionInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionInfo", arg0) + ret0, _ := ret[0].(*parachain.SessionInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionInfo indicates an expected call of ParachainHostSessionInfo. +func (mr *MockInstanceMockRecorder) ParachainHostSessionInfo(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionInfo", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionInfo), arg0) +} + +// ParachainHostValidatorGroups mocks base method. +func (m *MockInstance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidatorGroups") + ret0, _ := ret[0].(*parachain.ValidatorGroups) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidatorGroups indicates an expected call of ParachainHostValidatorGroups. +func (mr *MockInstanceMockRecorder) ParachainHostValidatorGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidatorGroups", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidatorGroups)) +} + +// ParachainHostValidators mocks base method. +func (m *MockInstance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidators") + ret0, _ := ret[0].([]parachain.ValidatorID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidators indicates an expected call of ParachainHostValidators. +func (mr *MockInstanceMockRecorder) ParachainHostValidators() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidators", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidators)) +} + // PaymentQueryInfo mocks base method. func (m *MockInstance) PaymentQueryInfo(arg0 []byte) (*types.RuntimeDispatchInfo, error) { m.ctrl.T.Helper() diff --git a/lib/grandpa/mocks_runtime_test.go b/lib/grandpa/mocks_runtime_test.go index fc0360e78f..236cea4c69 100644 --- a/lib/grandpa/mocks_runtime_test.go +++ b/lib/grandpa/mocks_runtime_test.go @@ -11,8 +11,10 @@ import ( common "github.com/ChainSafe/gossamer/lib/common" ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" keystore "github.com/ChainSafe/gossamer/lib/keystore" + parachain "github.com/ChainSafe/gossamer/lib/parachain" runtime "github.com/ChainSafe/gossamer/lib/runtime" transaction "github.com/ChainSafe/gossamer/lib/transaction" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -338,6 +340,126 @@ func (mr *MockInstanceMockRecorder) OffchainWorker() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OffchainWorker", reflect.TypeOf((*MockInstance)(nil).OffchainWorker)) } +// ParachainHostAvailabilityCores mocks base method. +func (m *MockInstance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostAvailabilityCores") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostAvailabilityCores indicates an expected call of ParachainHostAvailabilityCores. +func (mr *MockInstanceMockRecorder) ParachainHostAvailabilityCores() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostAvailabilityCores", reflect.TypeOf((*MockInstance)(nil).ParachainHostAvailabilityCores)) +} + +// ParachainHostCandidateEvents mocks base method. +func (m *MockInstance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidateEvents") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidateEvents indicates an expected call of ParachainHostCandidateEvents. +func (mr *MockInstanceMockRecorder) ParachainHostCandidateEvents() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidateEvents", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidateEvents)) +} + +// ParachainHostCandidatePendingAvailability mocks base method. +func (m *MockInstance) ParachainHostCandidatePendingAvailability(arg0 parachain.ParaID) (*parachain.CommittedCandidateReceipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidatePendingAvailability", arg0) + ret0, _ := ret[0].(*parachain.CommittedCandidateReceipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidatePendingAvailability indicates an expected call of ParachainHostCandidatePendingAvailability. +func (mr *MockInstanceMockRecorder) ParachainHostCandidatePendingAvailability(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidatePendingAvailability", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidatePendingAvailability), arg0) +} + +// ParachainHostCheckValidationOutputs mocks base method. +func (m *MockInstance) ParachainHostCheckValidationOutputs(arg0 parachain.ParaID, arg1 parachain.CandidateCommitments) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCheckValidationOutputs", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCheckValidationOutputs indicates an expected call of ParachainHostCheckValidationOutputs. +func (mr *MockInstanceMockRecorder) ParachainHostCheckValidationOutputs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCheckValidationOutputs", reflect.TypeOf((*MockInstance)(nil).ParachainHostCheckValidationOutputs), arg0, arg1) +} + +// ParachainHostSessionIndexForChild mocks base method. +func (m *MockInstance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionIndexForChild") + ret0, _ := ret[0].(parachain.SessionIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionIndexForChild indicates an expected call of ParachainHostSessionIndexForChild. +func (mr *MockInstanceMockRecorder) ParachainHostSessionIndexForChild() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionIndexForChild", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionIndexForChild)) +} + +// ParachainHostSessionInfo mocks base method. +func (m *MockInstance) ParachainHostSessionInfo(arg0 parachain.SessionIndex) (*parachain.SessionInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionInfo", arg0) + ret0, _ := ret[0].(*parachain.SessionInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionInfo indicates an expected call of ParachainHostSessionInfo. +func (mr *MockInstanceMockRecorder) ParachainHostSessionInfo(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionInfo", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionInfo), arg0) +} + +// ParachainHostValidatorGroups mocks base method. +func (m *MockInstance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidatorGroups") + ret0, _ := ret[0].(*parachain.ValidatorGroups) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidatorGroups indicates an expected call of ParachainHostValidatorGroups. +func (mr *MockInstanceMockRecorder) ParachainHostValidatorGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidatorGroups", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidatorGroups)) +} + +// ParachainHostValidators mocks base method. +func (m *MockInstance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidators") + ret0, _ := ret[0].([]parachain.ValidatorID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidators indicates an expected call of ParachainHostValidators. +func (mr *MockInstanceMockRecorder) ParachainHostValidators() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidators", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidators)) +} + // PaymentQueryInfo mocks base method. func (m *MockInstance) PaymentQueryInfo(arg0 []byte) (*types.RuntimeDispatchInfo, error) { m.ctrl.T.Helper() diff --git a/lib/runtime/interface.go b/lib/runtime/interface.go index 6e14a27d80..473710cd99 100644 --- a/lib/runtime/interface.go +++ b/lib/runtime/interface.go @@ -8,7 +8,9 @@ import ( "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/crypto/ed25519" "github.com/ChainSafe/gossamer/lib/keystore" + "github.com/ChainSafe/gossamer/lib/parachain" "github.com/ChainSafe/gossamer/lib/transaction" + "github.com/ChainSafe/gossamer/pkg/scale" ) // Instance for runtime methods @@ -48,4 +50,17 @@ type Instance interface { GrandpaSubmitReportEquivocationUnsignedExtrinsic( equivocationProof types.GrandpaEquivocationProof, keyOwnershipProof types.GrandpaOpaqueKeyOwnershipProof, ) error + ParachainHostValidators() ([]parachain.ValidatorID, error) + ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) + ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) + ParachainHostCheckValidationOutputs( + parachainID parachain.ParaID, + outputs parachain.CandidateCommitments, + ) (bool, error) + ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) + ParachainHostCandidatePendingAvailability( + parachainID parachain.ParaID, + ) (*parachain.CommittedCandidateReceipt, error) + ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) + ParachainHostSessionInfo(sessionIndex parachain.SessionIndex) (*parachain.SessionInfo, error) } diff --git a/lib/runtime/mocks/mocks.go b/lib/runtime/mocks/mocks.go index 22f87dbeff..9db3aa6bf0 100644 --- a/lib/runtime/mocks/mocks.go +++ b/lib/runtime/mocks/mocks.go @@ -11,8 +11,10 @@ import ( common "github.com/ChainSafe/gossamer/lib/common" ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" keystore "github.com/ChainSafe/gossamer/lib/keystore" + parachain "github.com/ChainSafe/gossamer/lib/parachain" runtime "github.com/ChainSafe/gossamer/lib/runtime" transaction "github.com/ChainSafe/gossamer/lib/transaction" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -338,6 +340,126 @@ func (mr *MockInstanceMockRecorder) OffchainWorker() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OffchainWorker", reflect.TypeOf((*MockInstance)(nil).OffchainWorker)) } +// ParachainHostAvailabilityCores mocks base method. +func (m *MockInstance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostAvailabilityCores") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostAvailabilityCores indicates an expected call of ParachainHostAvailabilityCores. +func (mr *MockInstanceMockRecorder) ParachainHostAvailabilityCores() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostAvailabilityCores", reflect.TypeOf((*MockInstance)(nil).ParachainHostAvailabilityCores)) +} + +// ParachainHostCandidateEvents mocks base method. +func (m *MockInstance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidateEvents") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidateEvents indicates an expected call of ParachainHostCandidateEvents. +func (mr *MockInstanceMockRecorder) ParachainHostCandidateEvents() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidateEvents", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidateEvents)) +} + +// ParachainHostCandidatePendingAvailability mocks base method. +func (m *MockInstance) ParachainHostCandidatePendingAvailability(arg0 parachain.ParaID) (*parachain.CommittedCandidateReceipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidatePendingAvailability", arg0) + ret0, _ := ret[0].(*parachain.CommittedCandidateReceipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidatePendingAvailability indicates an expected call of ParachainHostCandidatePendingAvailability. +func (mr *MockInstanceMockRecorder) ParachainHostCandidatePendingAvailability(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidatePendingAvailability", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidatePendingAvailability), arg0) +} + +// ParachainHostCheckValidationOutputs mocks base method. +func (m *MockInstance) ParachainHostCheckValidationOutputs(arg0 parachain.ParaID, arg1 parachain.CandidateCommitments) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCheckValidationOutputs", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCheckValidationOutputs indicates an expected call of ParachainHostCheckValidationOutputs. +func (mr *MockInstanceMockRecorder) ParachainHostCheckValidationOutputs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCheckValidationOutputs", reflect.TypeOf((*MockInstance)(nil).ParachainHostCheckValidationOutputs), arg0, arg1) +} + +// ParachainHostSessionIndexForChild mocks base method. +func (m *MockInstance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionIndexForChild") + ret0, _ := ret[0].(parachain.SessionIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionIndexForChild indicates an expected call of ParachainHostSessionIndexForChild. +func (mr *MockInstanceMockRecorder) ParachainHostSessionIndexForChild() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionIndexForChild", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionIndexForChild)) +} + +// ParachainHostSessionInfo mocks base method. +func (m *MockInstance) ParachainHostSessionInfo(arg0 parachain.SessionIndex) (*parachain.SessionInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionInfo", arg0) + ret0, _ := ret[0].(*parachain.SessionInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionInfo indicates an expected call of ParachainHostSessionInfo. +func (mr *MockInstanceMockRecorder) ParachainHostSessionInfo(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionInfo", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionInfo), arg0) +} + +// ParachainHostValidatorGroups mocks base method. +func (m *MockInstance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidatorGroups") + ret0, _ := ret[0].(*parachain.ValidatorGroups) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidatorGroups indicates an expected call of ParachainHostValidatorGroups. +func (mr *MockInstanceMockRecorder) ParachainHostValidatorGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidatorGroups", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidatorGroups)) +} + +// ParachainHostValidators mocks base method. +func (m *MockInstance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidators") + ret0, _ := ret[0].([]parachain.ValidatorID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidators indicates an expected call of ParachainHostValidators. +func (mr *MockInstanceMockRecorder) ParachainHostValidators() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidators", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidators)) +} + // PaymentQueryInfo mocks base method. func (m *MockInstance) PaymentQueryInfo(arg0 []byte) (*types.RuntimeDispatchInfo, error) { m.ctrl.T.Helper()