From e2b640762d366da7cf67ac415517a07e45ac56b2 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 17 Aug 2023 15:48:22 +0200 Subject: [PATCH 01/80] Start new attempt on Quint model of ICS --- .../core/quint_model/extraSpells.qnt | 62 ++++++++ tests/difference/core/quint_model/staking.qnt | 138 ++++++++++++++++++ 2 files changed, 200 insertions(+) create mode 100644 tests/difference/core/quint_model/extraSpells.qnt create mode 100644 tests/difference/core/quint_model/staking.qnt diff --git a/tests/difference/core/quint_model/extraSpells.qnt b/tests/difference/core/quint_model/extraSpells.qnt new file mode 100644 index 0000000000..bdc6fd0bf2 --- /dev/null +++ b/tests/difference/core/quint_model/extraSpells.qnt @@ -0,0 +1,62 @@ +module extraSpells { + + /// Removes a set of map entry. + /// + /// - @param __map a map to remove an entry from + /// - @param __keys a set of keys to remove from the map + /// - @returns a new map that contains all entries of __map + /// that do not have a key in __keys + pure def mapRemoveAll(__map: a -> b, __keys: Set[a]): a -> b = { + __map.keys().exclude(__keys).mapBy(__k => __map.get(__k)) + } + + run mapRemoveAllTest = + val m = Map(3 -> 4, 5 -> 6, 7 -> 8) + all { + assert(m.mapRemoveAll(Set(5, 7)) == Map(3 -> 4)), + assert(m.mapRemoveAll(Set(5, 99999)) == Map(3 -> 4, 7 -> 8)), + } + + pure def listSorted(__list: List[a], __lt: (a, a) => bool): List[a] = { + pure def __countSmaller(__j: int): int = { + pure val __jth = __list[__j] + __list.indices().filter(__i => + __lt(__list[__i], __jth) or (__list[__i] == __jth and __i < __j) + ) + .size() + } + + pure val __permutation = __list.indices().mapBy(__i => __countSmaller(__i)) + __list.foldl([], (__l, __i) => __l.append(__list[__permutation.get(__i)])) + } + + //// Returns a list of all elements of a set. + //// + //// - @param __set a set + //// - @returns a list of all elements of __set + pure def toList(__set: Set[a]): List[a] = { + __set.fold(List(), (__l, __e) => __l.append(__e)) + } + + //// Returns a set of the elements in the list. + //// + //// - @param __list a list + //// - @returns a set of the elements in __list + pure def toSet(__list: List[a]): Set[a] = { + __list.foldl(Set(), (__s, __e) => __s.union(Set(__e))) + } + + run toListAndSetTest = + all { + assert(Set(3, 2, 1).toList().toSet() == Set(1, 2, 3)), + assert(List(2,3,1).toSet() == Set(1, 2, 3)), + assert(List(2,3,1).toSet() == List(3,2,1).toSet()), + assert(toList(Set()) == List()), + assert(toSet(List()) == Set()) + } + + pure def add(__set: Set[a], elem: a): Set[a] = { + __set.union(Set(elem)) + } + +} \ No newline at end of file diff --git a/tests/difference/core/quint_model/staking.qnt b/tests/difference/core/quint_model/staking.qnt new file mode 100644 index 0000000000..bcb944cd41 --- /dev/null +++ b/tests/difference/core/quint_model/staking.qnt @@ -0,0 +1,138 @@ +module ccv { + import extraSpells.* from "./extraSpells" + + // Things that are not modelled: + // * Reward distribution + + // TYPE DEFINITIONS + type Chain = str + type Validator = { + identifier: str, + // for simplciity, voting power is equal to amount of tokens + votingPower: int + } + type Height = int + type Timestamp = int + + type Infraction = + { + validator: Validator, + infractionType: str, + // slash fraction in percent, i.e. 80 means 80% + slashFraction: int, + // the height at which the infraction was committed + infractionHeight: Height, + // the timestamp at which the infraction was committed + infractionTime: Timestamp, + // the chain on which the infraction was committed + originChain: Chain, + } + + type Block = + { + validatorSet: Set[Validator], + blockHeight: Height, + blockTime: Timestamp, + chain: Chain, + // Infrations comitted on this chain in this block. + comittedInfractions: Set[Infraction], + // Evidence received by this chain in this block. + receivedEvidence: Set[Infraction] // only used on the provider + } + + type Slash = + { + validator: Validator, + slashAmount: int, + slashHeight: Height, + slashTime: Timestamp, + chain: Chain, + infraction: Infraction + } + + + // MODEL PARAMETERS + const UnbondingPeriod: int + + // MODEL STATE + + // The singular provider chain. + var providerChain: Chain + + // The set of (possible) consumer chains that are being tracked. + var chains: Set[Chain] + + // Stores, for each chain, the list of blocks over its entire existence. + // Each height should occur at most once, and no height should be skipped. + // Blocks should be ordered by height in descending order. + var blockHistories: Chain -> List[Block] + + // Stores, for each chain, whether it is currently a consumer chain. + var consumerStatus: Chain -> bool + + var slashes: Set[Slash] + + // UTILITY FUNCTIONS + def getCurrentHeight(chain: Chain): Height = { + blockHistories.get(chain).head().blockHeight + } + + def getLatestBlock(chain: Chain): Block = { + blockHistories.get(chain).head() + } + + def isConsumer(chain: Chain): bool = { + consumerStatus.get(chain) + } + + def wasValidatorSetOnProvider(validatorSet: Set[Validator]): bool = { + blockHistories.get(providerChain).toSet().exists( + block => block.validatorSet == validatorSet + ) + } + + // PROPERTIES + + // Every validator set on any consumer chain MUST either be or + // have been a validator set on the provider chain. + val ValidatorSetReplication: bool = + chains.filter(chain => chain.isConsumer()).forall( + chain => chain.getLatestBlock().validatorSet.wasValidatorSetOnProvider() + ) + + // TODO: This is extremely convoluted, maybe coming later? + val BondBasedConsumerVotingPower: bool = + true + + // If a validator val commits an infraction, with a slashing fraction of sf, + // on a consumer chain cc at a block height hi, + // then any evidence of misbehavior that is received by cc at height he, + // such that ts(he) < ts(hi) + UnbondingPeriod, MUST results in exactly the amount of tokens + // sf*Token(Power(cc,hi,val)) to be slashed on the provider chain. + // Furthermore, val MUST NOT be slashed more than once for the same misbehavior. + val SlashableConsumerMisbehaviour: bool = + val latestProviderBlock = providerChain.getLatestBlock() + latestProviderBlock.receivedEvidence.forall( + // for each evidence the provider chain received + evidence => + // if the evidence is received before it is outdated + (evidence.infractionTime < latestProviderBlock.blockTime - UnbondingPeriod) + implies + // the provider needs to slash the validator + val expectedSlash = + { + validator: evidence.validator, + // the amount depends on the voting power during the infraction + slashAmount: evidence.validator.votingPower * evidence.slashFraction, + slashHeight: latestProviderBlock.blockHeight, + slashTime: latestProviderBlock.blockTime, + chain: providerChain, + infraction: evidence + } + slashes.exists(slash => slash == expectedSlash) + ) + + val ValidatorUpdateInclusion: bool = + true + +} \ No newline at end of file From 283dc0a01ac950c39a06b8f5e797f0ed6bf92ec3 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Wed, 23 Aug 2023 18:04:29 +0200 Subject: [PATCH 02/80] Advance quint model --- .../core/quint_model/extraSpells.qnt | 129 +++++++ tests/difference/core/quint_model/model.qnt | 327 ++++++++++++++++++ tests/difference/core/quint_model/staking.qnt | 138 -------- 3 files changed, 456 insertions(+), 138 deletions(-) create mode 100644 tests/difference/core/quint_model/model.qnt delete mode 100644 tests/difference/core/quint_model/staking.qnt diff --git a/tests/difference/core/quint_model/extraSpells.qnt b/tests/difference/core/quint_model/extraSpells.qnt index bdc6fd0bf2..a32a74ad8f 100644 --- a/tests/difference/core/quint_model/extraSpells.qnt +++ b/tests/difference/core/quint_model/extraSpells.qnt @@ -1,5 +1,134 @@ module extraSpells { + pure def prepend(__list: List[a], __elem: a): List[a] = { + List(__elem).concat(__list) + } + + run prependTest = all { + assert(List(2,3,4).prepend(1) == List(1,2,3,4)), + assert(List().prepend(1) == List(1)), + } + + /// An annotation for writing preconditions. + /// - @param __cond condition to check + /// - @returns true if and only if __cond evaluates to true + pure def require(__cond: bool): bool = __cond + + run requireTest = all { + assert(require(4 > 3)), + assert(not(require(false))), + } + + /// A convenience operator that returns a string error code, + /// if the condition does not hold true. + /// + /// - @param __cond condition to check + /// - @param __error a non-empty error message + /// - @returns "", when __cond holds true; otherwise __error + pure def requires(__cond: bool, __error: str): str = { + if (__cond) "" else __error + } + + run requiresTest = all { + assert(requires(4 > 3, "4 > 3") == ""), + assert(requires(4 < 3, "false: 4 < 3") == "false: 4 < 3"), + } + + + /// Compute the maximum of two integers. + /// + /// - @param __i first integer + /// - @param __j second integer + /// - @returns the maximum of __i and __j + pure def max(__i: int, __j: int): int = { + if (__i > __j) __i else __j + } + + run maxTest = all { + assert(max(3, 4) == 4), + assert(max(6, 3) == 6), + assert(max(10, 10) == 10), + assert(max(-3, -5) == -3), + assert(max(-5, -3) == -3), + } + + /// Compute the absolute value of an integer + /// + /// - @param __i : an integer whose absolute value we are interested in + /// - @returns |__i|, the absolute value of __i + pure def abs(__i: int): int = { + if (__i < 0) -__i else __i + } + + run absTest = all { + assert(abs(3) == 3), + assert(abs(-3) == 3), + assert(abs(0) == 0), + } + + /// Remove a set element. + /// + /// - @param __set a set to remove an element from + /// - @param __elem an element to remove + /// - @returns a new set that contains all elements of __set but __elem + pure def setRemove(__set: Set[a], __elem: a): Set[a] = { + __set.exclude(Set(__elem)) + } + + run setRemoveTest = all { + assert(Set(2, 4) == Set(2, 3, 4).setRemove(3)), + assert(Set() == Set().setRemove(3)), + } + + /// Test whether a key is present in a map + /// + /// - @param __map a map to query + /// - @param __key the key to look for + /// - @returns true if and only __map has an entry associated with __key + pure def has(__map: a -> b, __key: a): bool = { + __map.keys().contains(__key) + } + + run hasTest = all { + assert(Map(2 -> 3, 4 -> 5).has(2)), + assert(not(Map(2 -> 3, 4 -> 5).has(6))), + } + + /// Get the map value associated with a key, or the default, + /// if the key is not present. + /// + /// - @param __map the map to query + /// - @param __key the key to search for + /// - @returns the value associated with the key, if __key is + /// present in the map, and __default otherwise + pure def getOrElse(__map: a -> b, __key: a, __default: b): b = { + if (__map.has(__key)) { + __map.get(__key) + } else { + __default + } + } + + run getOrElseTest = all { + assert(Map(2 -> 3, 4 -> 5).getOrElse(2, 0) == 3), + assert(Map(2 -> 3, 4 -> 5).getOrElse(7, 11) == 11), + } + + /// Remove a map entry. + /// + /// - @param __map a map to remove an entry from + /// - @param __key the key of an entry to remove + /// - @returns a new map that contains all entries of __map + /// that do not have the key __key + pure def mapRemove(__map: a -> b, __key: a): a -> b = { + __map.keys().setRemove(__key).mapBy(__k => __map.get(__k)) + } + + run mapRemoveTest = all { + assert(Map(3 -> 4, 7 -> 8) == Map(3 -> 4, 5 -> 6, 7 -> 8).mapRemove(5)), + assert(Map() == Map().mapRemove(3)), + } + /// Removes a set of map entry. /// /// - @param __map a map to remove an entry from diff --git a/tests/difference/core/quint_model/model.qnt b/tests/difference/core/quint_model/model.qnt new file mode 100644 index 0000000000..6c78f6fb64 --- /dev/null +++ b/tests/difference/core/quint_model/model.qnt @@ -0,0 +1,327 @@ +module ccv { + import extraSpells.* from "./extraSpells" + + // Things that are not modelled: + // * Reward distribution + // * Starting/Stopping chains during execution + // * Slashes + + // TYPE DEFINITIONS + type Node = str + type Chain = str + type ValidatorSet = Node -> int + type Height = int + type Timestamp = int + + // --PACKETS + type VSCPacket = + { + // the identifier for this packet + id: int, + // the new validator set. in the implementation, this would be a list of validator updates + validatorSet: ValidatorSet + } + + type VSCMaturedPacket = + { + // the id of the VSCPacket that matured + id: int + } + + // MODEL PARAMETERS + // length of the unbonding period on each chain + const UnbondingPeriod: Chain -> int + + // set of identifiers of potential nodes + const Nodes: Set[Node] + + // the set of consumer chains + const ConsumerChains: Set[Chain] + + // The singular provider chain. + const ProviderChain: Chain + + pure val chains = ConsumerChains.union(Set(ProviderChain)) + + // the time until a packet times out + const PacketTimeout: int + + // the time until a consumer chain is dropped by the provider due to inactivity + const InactivityTimeout: int + + + // MODEL STATE + // --SHARED STATE + + // Stores, for each chain, the list of voting powers that corresponded to voting powers + // at blocks over its entire existence. + // Voting powers should be ordered by recency in descending order. + var votingPowerHistories: Chain -> List[ValidatorSet] + + // the current validator set on each chain. + // this will be included in the next block, but might not be final yet, + // e.g. there may be more modifications in the current block. + var runningValidatorSet: Chain -> ValidatorSet + + // the current timestamp for each chain + var curChainTimes: Chain -> Timestamp + + // stores, for each chain, its current status - + // unused, running, or stopped + var consumerStatus: Chain -> str + + // --CHANNELS + // Stores, for each consumer chain, the list of packets that have been sent to the provider chain + // and have not been received yet. + var outstandingPacketsToProvider: Chain -> List[VSCMaturedPacket] + + // Stores, for each consumer chain, the list of packets that have been sent to the consumer chain + // and have not been received yet. + var outstandingPacketsToConsumer: Chain -> List[VSCPacket] + + + // --CONSUMER STATE + // Stores the maturation times for VSCPackets received by consumers + var maturationTimes: Chain -> (VSCPacket -> Timestamp) + + // --PROVIDER STATE + // the set of VSCMaturedPackets received by the provider chain + var receivedMaturations: Set[VSCMaturedPacket] + + + // UTILITY FUNCTIONS & ACTIONS + def wasValidatorSetOnProvider(validatorSet: ValidatorSet): bool = { + votingPowerHistories.get(ProviderChain).toSet().exists( + historicalValSet => historicalValSet == validatorSet + ) + } + + def getCurrentValidatorSet(chain: Chain): ValidatorSet = + votingPowerHistories.get(chain).head() + + def getUpdatedValidatorSet(oldValidatorSet: ValidatorSet, validator: Node, newVotingPower: int): ValidatorSet = + if (newVotingPower > 0) + oldValidatorSet.set(validator, newVotingPower) + else + oldValidatorSet.mapRemove(validator) + + // utility action that leaves all provider state untouched + action PROVIDER_NOOP(): bool = + all { + receivedMaturations' = receivedMaturations, + } + + // utility action that leaves all consumer state untouched + action CONSUMER_NOOP(): bool = + all { + maturationTimes' = maturationTimes, + } + + + // MODEL ACTIONS + + // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, + // e.g. via undelegations, or delegations, ... + action votingPowerChange(validator: Node, amount: int): bool = + // for the provider chain, we need to adjust the voting power history + // by adding a new set + all { + amount >= 0, + val newValidatorSet = getCurrentValidatorSet(ProviderChain).getUpdatedValidatorSet(validator, amount) + // set the running validator set on the provider chain, but don't update the history yet + runningValidatorSet' = runningValidatorSet.set(ProviderChain, newValidatorSet), + // no packets are sent yet, these are only sent on endAndBeginBlock + outstandingPacketsToConsumer' = outstandingPacketsToConsumer, + outstandingPacketsToProvider' = outstandingPacketsToProvider, + receivedMaturations' = receivedMaturations, + CONSUMER_NOOP, + // voting power history is only updated on endAndBeginBlock + votingPowerHistories' = votingPowerHistories, + } + + // deliver the next outstanding packet from the consumer to the provider. + // since this model assumes a single provider chain, this just takes a single chain as argument. + action recvPacketOnProvider(consumer: Chain): bool = all { + // ensure there is a packet to be received + outstandingPacketsToProvider.get(consumer).length() > 0, + // remove packet from outstanding packets + val newPacketQueue = outstandingPacketsToProvider.get(consumer).tail() + outstandingPacketsToProvider' = outstandingPacketsToProvider.set(consumer, newPacketQueue), + // register the packet as received + val maturedPacket = outstandingPacketsToProvider.get(consumer).head() + receivedMaturations' = receivedMaturations.add(maturedPacket), + CONSUMER_NOOP, + outstandingPacketsToConsumer' = outstandingPacketsToConsumer, + votingPowerHistories' = votingPowerHistories, + // no validator set changes are made + runningValidatorSet' = runningValidatorSet, + } + + // deliver the next outstanding packet from the provider to the consumer. + // since this model assumes a single provider chain, this just takes a single chain as argument. + action recvPacketOnConsumer(consumer: Chain): bool = all { + // ensure there is a packet to be received + outstandingPacketsToConsumer.get(consumer).length() > 0, + // remove packet from outstanding packets + val newPacketQueue = outstandingPacketsToConsumer.get(consumer).tail() + outstandingPacketsToConsumer' = outstandingPacketsToConsumer.set(consumer, newPacketQueue), + val packet = outstandingPacketsToConsumer.get(consumer).head() + all { + // update the running validator set, but not the history yet, + // as that only happens when the next block is started + runningValidatorSet' = runningValidatorSet.set(consumer, packet.validatorSet), + // add the new packet and store its maturation time + val newMaturationTimes = maturationTimes.get(consumer).set(packet, curChainTimes.get(consumer) + UnbondingPeriod.get(consumer)) + maturationTimes' = maturationTimes.set(consumer, newMaturationTimes) + }, + PROVIDER_NOOP, + votingPowerHistories' = votingPowerHistories, + outstandingPacketsToProvider' = outstandingPacketsToProvider, + } + + // ends the current block and starts the next block for a given chain. + action endAndBeginBlock(chain: Chain): bool = any { + all { + chain == ProviderChain, + endAndBeginBlockForProvider, + }, + all { + chain != ProviderChain, + endAndBeginBlockForConsumer(chain), + } + } + + // gets the updated history for the current chain when ending a block, i.e. the + // running validator set is added to the history if different from the last one. + def getUpdatedHistory(chain: Chain): List[ValidatorSet] = + // update voting power history if the validator set changed + val newValidatorSet = runningValidatorSet.get(ProviderChain) + val oldValidatorSet = votingPowerHistories.get(ProviderChain).head() + if (newValidatorSet != oldValidatorSet) + votingPowerHistories.get(ProviderChain).prepend(newValidatorSet) + else + votingPowerHistories.get(ProviderChain) + + + action endAndBeginBlockForProvider(): bool = all { + // update the voting power history + votingPowerHistories' = votingPowerHistories.set(ProviderChain, getUpdatedHistory(ProviderChain)), + // the running validator set is now for sure the current validator set, + // so start with it in the next block + runningValidatorSet' = runningValidatorSet, + // send VSCPackets to consumers + outstandingPacketsToConsumer' = + // if running validator set is not equal to the last one in the history + if (runningValidatorSet.get(ProviderChain) != votingPowerHistories.get(ProviderChain).head()) + // then send a packet to each consumer + outstandingPacketsToConsumer.keys().mapBy( + (consumer) => + val packetQueue = outstandingPacketsToConsumer.get(consumer) + packetQueue.append( + { + id: packetQueue.length(), + validatorSet: runningValidatorSet.get(ProviderChain) + } + ) + ) + else + // otherwise, don't send any packets + outstandingPacketsToConsumer, + CONSUMER_NOOP, + // no packets are sent to the provider + outstandingPacketsToProvider' = outstandingPacketsToProvider, + // do not receive any maturations + receivedMaturations' = receivedMaturations, + } + + action endAndBeginBlockForConsumer(consumer: Chain): bool = all { + ConsumerChains.contains(consumer), + // update the voting power history + votingPowerHistories' = votingPowerHistories.set(consumer, getUpdatedHistory(consumer)), + // the running validator set is now for sure the current validator set, + // so start with it in the next block + runningValidatorSet' = runningValidatorSet, + // compute mature packets whose maturation time has passed + val maturedPackets = maturationTimes.get(consumer).keys().filter( + packet => + val maturationTime = maturationTimes.get(consumer).get(packet) + maturationTime <= curChainTimes.get(consumer) + ) + all { + // remove matured packets from the maturation times + maturationTimes' = maturationTimes.set(consumer, maturationTimes.get(consumer).mapRemoveAll(maturedPackets)), + // send matured packets + outstandingPacketsToProvider' = outstandingPacketsToProvider.set( + consumer, + // construct VSCMaturedPackets from the matured VSCPackets + outstandingPacketsToProvider.get(consumer).concat( + maturedPackets.map(packet => {id: packet.id}).toList() + ) + ) + }, + PROVIDER_NOOP, + // no packets are sent to consumer or received by it + outstandingPacketsToConsumer' = outstandingPacketsToConsumer, + } + + // the timestamp for each chain is advanced nondeterministically + action advanceTimestamps(): bool = + curChainTimes' = curChainTimes.keys().mapBy( + (chain) => + nondet advancement = oneOf(0.to(100)) + curChainTimes.get(chain) + advancement + ) + + // each consumer chain may nondeterministically advance in the order + // unused -> initializing -> running -> stopped + // some events may necessitate a transition, e.g. timeouts + action AdvanceConsumers: bool = + consumerStatus' = consumerStatus.keys().mapBy( + (chain) => + val curStatus = consumerStatus.get(chain) + // if the current status is unused, it may transition to running + if (curStatus == "unused") { + nondet transition = oneOf(0.to(1)) + if (transition == 0) + { + "running" + } else { + "unused" + } + } + else if (curStatus == "running") { + // the chain may transition to stopped. + // it is *forced* to stop if a packet timed out, + // or if the inactivity timeout has passed + } else { + "unused" + } + + // if the current status is initializing, it may transition to running + ) + + + action step: bool = + all { + // timestamps can be advanced in each step + advanceTimestamps, + any { + nondet node = oneOf(Nodes) + nondet amount = oneOf(1.to(10)) + votingPowerChange(node, amount), + recvPacketOnProvider(oneOf(ConsumerChains)), + recvPacketOnConsumer(oneOf(ConsumerChains)), + nondet chain = oneOf(chains) + endAndBeginBlock(chain), + } + } + + // PROPERTIES + + // Every validator set on any consumer chain MUST either be or + // have been a validator set on the provider chain. + val ValidatorSetReplication: bool = + chains.forall( + chain => chain.getCurrentValidatorSet().wasValidatorSetOnProvider() + ) +} \ No newline at end of file diff --git a/tests/difference/core/quint_model/staking.qnt b/tests/difference/core/quint_model/staking.qnt deleted file mode 100644 index bcb944cd41..0000000000 --- a/tests/difference/core/quint_model/staking.qnt +++ /dev/null @@ -1,138 +0,0 @@ -module ccv { - import extraSpells.* from "./extraSpells" - - // Things that are not modelled: - // * Reward distribution - - // TYPE DEFINITIONS - type Chain = str - type Validator = { - identifier: str, - // for simplciity, voting power is equal to amount of tokens - votingPower: int - } - type Height = int - type Timestamp = int - - type Infraction = - { - validator: Validator, - infractionType: str, - // slash fraction in percent, i.e. 80 means 80% - slashFraction: int, - // the height at which the infraction was committed - infractionHeight: Height, - // the timestamp at which the infraction was committed - infractionTime: Timestamp, - // the chain on which the infraction was committed - originChain: Chain, - } - - type Block = - { - validatorSet: Set[Validator], - blockHeight: Height, - blockTime: Timestamp, - chain: Chain, - // Infrations comitted on this chain in this block. - comittedInfractions: Set[Infraction], - // Evidence received by this chain in this block. - receivedEvidence: Set[Infraction] // only used on the provider - } - - type Slash = - { - validator: Validator, - slashAmount: int, - slashHeight: Height, - slashTime: Timestamp, - chain: Chain, - infraction: Infraction - } - - - // MODEL PARAMETERS - const UnbondingPeriod: int - - // MODEL STATE - - // The singular provider chain. - var providerChain: Chain - - // The set of (possible) consumer chains that are being tracked. - var chains: Set[Chain] - - // Stores, for each chain, the list of blocks over its entire existence. - // Each height should occur at most once, and no height should be skipped. - // Blocks should be ordered by height in descending order. - var blockHistories: Chain -> List[Block] - - // Stores, for each chain, whether it is currently a consumer chain. - var consumerStatus: Chain -> bool - - var slashes: Set[Slash] - - // UTILITY FUNCTIONS - def getCurrentHeight(chain: Chain): Height = { - blockHistories.get(chain).head().blockHeight - } - - def getLatestBlock(chain: Chain): Block = { - blockHistories.get(chain).head() - } - - def isConsumer(chain: Chain): bool = { - consumerStatus.get(chain) - } - - def wasValidatorSetOnProvider(validatorSet: Set[Validator]): bool = { - blockHistories.get(providerChain).toSet().exists( - block => block.validatorSet == validatorSet - ) - } - - // PROPERTIES - - // Every validator set on any consumer chain MUST either be or - // have been a validator set on the provider chain. - val ValidatorSetReplication: bool = - chains.filter(chain => chain.isConsumer()).forall( - chain => chain.getLatestBlock().validatorSet.wasValidatorSetOnProvider() - ) - - // TODO: This is extremely convoluted, maybe coming later? - val BondBasedConsumerVotingPower: bool = - true - - // If a validator val commits an infraction, with a slashing fraction of sf, - // on a consumer chain cc at a block height hi, - // then any evidence of misbehavior that is received by cc at height he, - // such that ts(he) < ts(hi) + UnbondingPeriod, MUST results in exactly the amount of tokens - // sf*Token(Power(cc,hi,val)) to be slashed on the provider chain. - // Furthermore, val MUST NOT be slashed more than once for the same misbehavior. - val SlashableConsumerMisbehaviour: bool = - val latestProviderBlock = providerChain.getLatestBlock() - latestProviderBlock.receivedEvidence.forall( - // for each evidence the provider chain received - evidence => - // if the evidence is received before it is outdated - (evidence.infractionTime < latestProviderBlock.blockTime - UnbondingPeriod) - implies - // the provider needs to slash the validator - val expectedSlash = - { - validator: evidence.validator, - // the amount depends on the voting power during the infraction - slashAmount: evidence.validator.votingPower * evidence.slashFraction, - slashHeight: latestProviderBlock.blockHeight, - slashTime: latestProviderBlock.blockTime, - chain: providerChain, - infraction: evidence - } - slashes.exists(slash => slash == expectedSlash) - ) - - val ValidatorUpdateInclusion: bool = - true - -} \ No newline at end of file From 2155a4f15e5d89032b6d9807c5a61049b57d94c0 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 24 Aug 2023 13:17:19 +0200 Subject: [PATCH 03/80] Add first finished draft of model --- tests/difference/core/quint_model/model.qnt | 180 ++++++++++++++++---- 1 file changed, 146 insertions(+), 34 deletions(-) diff --git a/tests/difference/core/quint_model/model.qnt b/tests/difference/core/quint_model/model.qnt index 6c78f6fb64..b89f816b9d 100644 --- a/tests/difference/core/quint_model/model.qnt +++ b/tests/difference/core/quint_model/model.qnt @@ -19,36 +19,54 @@ module ccv { // the identifier for this packet id: int, // the new validator set. in the implementation, this would be a list of validator updates - validatorSet: ValidatorSet + validatorSet: ValidatorSet, + // the time, that when passed on the receiver chain, will mean the packet is considered timed out + timeout: Timestamp } type VSCMaturedPacket = { // the id of the VSCPacket that matured - id: int + id: int, + // the time, that when passed on the receiver chain, will mean the packet is considered timed out + timeout: Timestamp } // MODEL PARAMETERS - // length of the unbonding period on each chain - const UnbondingPeriod: Chain -> int + // set of identifiers of potential nodes - const Nodes: Set[Node] + pure val Nodes: Set[Node] = + Set("A", "B", "C", "D", "E", "F", "G", "H", "I", "J") // the set of consumer chains - const ConsumerChains: Set[Chain] + pure val ConsumerChains: Set[Chain] = + Set("chain1", "chain2", "chain3") // The singular provider chain. - const ProviderChain: Chain - + pure val ProviderChain: Chain = + "provider" + pure val chains = ConsumerChains.union(Set(ProviderChain)) + // length of the unbonding period on each chain + pure val UnbondingPeriod: Chain -> int = chains.mapBy( + (chain) => + 10 + ) + // the time until a packet times out - const PacketTimeout: int + pure val PacketTimeout: int = + 5 // the time until a consumer chain is dropped by the provider due to inactivity - const InactivityTimeout: int + pure val InactivityTimeout: int = + 10 + // consumer statuses + pure val STOPPED = "stopped" + pure val RUNNING = "running" + pure val UNUSED = "unused" // MODEL STATE // --SHARED STATE @@ -88,6 +106,9 @@ module ccv { // the set of VSCMaturedPackets received by the provider chain var receivedMaturations: Set[VSCMaturedPacket] + // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness + var sentVSCPackets: Chain -> Set[VSCPacket] + // UTILITY FUNCTIONS & ACTIONS def wasValidatorSetOnProvider(validatorSet: ValidatorSet): bool = { @@ -105,6 +126,34 @@ module ccv { else oldValidatorSet.mapRemove(validator) + // returns true if the consumer has timed out and should be dropped + def consumerTimedOut(consumer: Chain): bool = + any { + // either a package from provider to consumer has timed out + outstandingPacketsToConsumer.get(consumer).select( + packet => packet.timeout <= curChainTimes.get(consumer) + ).length() > 0, + // or a package from consumer to provider has timed out + outstandingPacketsToProvider.get(consumer).select( + packet => packet.timeout <= curChainTimes.get(ProviderChain) + ).length() > 0, + // or the inactivity timeout has passed since a VSCPacket was sent to the consumer, but the + // provider has not received a VSCMaturedPacket for it + val packetsWithoutResponse = sentVSCPackets.get(consumer).filter( // get packets without response + packet => + not(receivedMaturations.exists( + maturedPacket => maturedPacket.id == packet.id + )) + ) + // among those, get packets where inactivity timeout has passed + packetsWithoutResponse.filter( + packet => + val sentAt = curChainTimes.get(ProviderChain) - PacketTimeout // compute when the packet was sent + val timesOutAt = sentAt + InactivityTimeout // compute when the packet times out + timesOutAt <= curChainTimes.get(ProviderChain) + ).size() > 0 + } + // utility action that leaves all provider state untouched action PROVIDER_NOOP(): bool = all { @@ -213,14 +262,15 @@ module ccv { outstandingPacketsToConsumer' = // if running validator set is not equal to the last one in the history if (runningValidatorSet.get(ProviderChain) != votingPowerHistories.get(ProviderChain).head()) - // then send a packet to each consumer - outstandingPacketsToConsumer.keys().mapBy( + // then send a packet to each running consumer + outstandingPacketsToConsumer.keys().filter(consumer => consumerStatus.get(consumer) == RUNNING).mapBy( (consumer) => val packetQueue = outstandingPacketsToConsumer.get(consumer) packetQueue.append( { id: packetQueue.length(), - validatorSet: runningValidatorSet.get(ProviderChain) + validatorSet: runningValidatorSet.get(ProviderChain), + timeout: curChainTimes.get(ProviderChain) + PacketTimeout } ) ) @@ -255,7 +305,7 @@ module ccv { consumer, // construct VSCMaturedPackets from the matured VSCPackets outstandingPacketsToProvider.get(consumer).concat( - maturedPackets.map(packet => {id: packet.id}).toList() + maturedPackets.map(packet => {id: packet.id, timeout: 5}).toList() ) ) }, @@ -265,46 +315,59 @@ module ccv { } // the timestamp for each chain is advanced nondeterministically - action advanceTimestamps(): bool = + action AdvanceTimestamps(): bool = curChainTimes' = curChainTimes.keys().mapBy( (chain) => nondet advancement = oneOf(0.to(100)) curChainTimes.get(chain) + advancement - ) + ) - // each consumer chain may nondeterministically advance in the order - // unused -> initializing -> running -> stopped - // some events may necessitate a transition, e.g. timeouts - action AdvanceConsumers: bool = + // each consumer chain may advance in the order + // some events may necessitate a transition, e.g. timeouts. + // shouldAdvance gives, for each consumer chain, whether it should advance if possible. + // if a chain has to advance, e.g. due to timeouts, or may not advance, the value will have no effect. + action AdvanceConsumers(shouldAdvance: Chain -> bool): bool = consumerStatus' = consumerStatus.keys().mapBy( - (chain) => + chain => val curStatus = consumerStatus.get(chain) - // if the current status is unused, it may transition to running - if (curStatus == "unused") { - nondet transition = oneOf(0.to(1)) - if (transition == 0) + if (curStatus == UNUSED) { + if (shouldAdvance.get(chain)) { - "running" + RUNNING } else { - "unused" + UNUSED } } - else if (curStatus == "running") { + else if (curStatus == RUNNING) { // the chain may transition to stopped. // it is *forced* to stop if a packet timed out, // or if the inactivity timeout has passed + if(consumerTimedOut(chain)) { + STOPPED + } else { + if (shouldAdvance.get(chain)) { + RUNNING + } else { + STOPPED + } + } } else { - "unused" + // stopped chains cannot restart, we assume a new chain would be started in that case + STOPPED } - - // if the current status is initializing, it may transition to running ) + // stores the VSCPackets sent in this step in sentVSCPackets + action StoreSentPackets: bool = + sentVSCPackets' = sentVSCPackets.keys().mapBy( + (chain) => + sentVSCPackets.get(chain).union(outstandingPacketsToConsumer.get(chain).toSet()) + ) action step: bool = - all { + all { // timestamps can be advanced in each step - advanceTimestamps, + AdvanceTimestamps, any { nondet node = oneOf(Nodes) nondet amount = oneOf(1.to(10)) @@ -313,7 +376,56 @@ module ccv { recvPacketOnConsumer(oneOf(ConsumerChains)), nondet chain = oneOf(chains) endAndBeginBlock(chain), - } + }, + StoreSentPackets, + val shouldAdvance = ConsumerChains.mapBy( + chain => + nondet should = oneOf(Set(true, false)) + should + ) + AdvanceConsumers(shouldAdvance), + } + + + def getArbitraryValidatorSet(): ValidatorSet = + val numValidators = oneOf(1.to(Nodes.size())) + // toList has nondeterministic behaviour, so this gets arbitrary validators + val validators = Nodes.toList().slice(0, numValidators).toSet() + validators.mapBy( + validator => + nondet votingPower = oneOf(1.to(10)) + votingPower + ) + + action init: bool = + all { + // voting power histories are empty + votingPowerHistories' = + chains.mapBy( + (chain) => + List() + ), + // provider chain gets an arbitrary validator set, consumer chains have none + runningValidatorSet' = + chains.mapBy( + (chain) => + if (chain == ProviderChain) getArbitraryValidatorSet else Map() + ), + // each chain starts at time 0 + curChainTimes' = chains.mapBy( + (chain) => 0 + ), + // all consumer chains are unused + consumerStatus' = chains.mapBy(chain => UNUSED), + // no packets are outstanding + outstandingPacketsToProvider' = chains.mapBy(chain => List()), + outstandingPacketsToConsumer' = chains.mapBy(chain => List()), + // no maturations have been received by provider + receivedMaturations' = Set(), + // no packets have been sent to consumers + sentVSCPackets' = chains.mapBy(chain => Set()), + // no packets have been received by consumers, so no maturation times set + maturationTimes' = chains.mapBy(chain => Map()), } // PROPERTIES From 6ca65105e8b044c03b9d0006ed212009239512af Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 25 Aug 2023 09:53:47 +0200 Subject: [PATCH 04/80] Add test run to model --- tests/difference/core/quint_model/model.qnt | 149 ++++++++++++++++---- 1 file changed, 125 insertions(+), 24 deletions(-) diff --git a/tests/difference/core/quint_model/model.qnt b/tests/difference/core/quint_model/model.qnt index b89f816b9d..aa3378bca6 100644 --- a/tests/difference/core/quint_model/model.qnt +++ b/tests/difference/core/quint_model/model.qnt @@ -68,6 +68,23 @@ module ccv { pure val RUNNING = "running" pure val UNUSED = "unused" + // utility: a map assigning each chain to 0, used for not advancing timestamps + pure val NoTimeAdvancement: Chain -> int = chains.mapBy( + (chain) => + 0 + ) + + + // utility: a map assigning each chain to false, used for not advancing consumer status + pure val NoStatusAdvancement: Chain -> bool = chains.mapBy( + (chain) => + false + ) + + // utility: the set of consumers currently running + val RunningConsumers: Set[Chain] = + ConsumerChains.filter(chain => consumerStatus.get(chain) == RUNNING) + // MODEL STATE // --SHARED STATE @@ -186,6 +203,12 @@ module ccv { CONSUMER_NOOP, // voting power history is only updated on endAndBeginBlock votingPowerHistories' = votingPowerHistories, + // consumer statusses do not change + consumerStatus' = consumerStatus, + // chain times do not change + curChainTimes' = curChainTimes, + // update the packet store on the provider + StoreSentPackets, } // deliver the next outstanding packet from the consumer to the provider. @@ -204,6 +227,12 @@ module ccv { votingPowerHistories' = votingPowerHistories, // no validator set changes are made runningValidatorSet' = runningValidatorSet, + // consumer statusses do not change + consumerStatus' = consumerStatus, + // chain times do not change + curChainTimes' = curChainTimes, + // update the packet store on the provider + StoreSentPackets, } // deliver the next outstanding packet from the provider to the consumer. @@ -226,6 +255,12 @@ module ccv { PROVIDER_NOOP, votingPowerHistories' = votingPowerHistories, outstandingPacketsToProvider' = outstandingPacketsToProvider, + // consumer statusses do not change + consumerStatus' = consumerStatus, + // chain times do not change + curChainTimes' = curChainTimes, + // update the packet store on the provider + StoreSentPackets, } // ends the current block and starts the next block for a given chain. @@ -282,6 +317,12 @@ module ccv { outstandingPacketsToProvider' = outstandingPacketsToProvider, // do not receive any maturations receivedMaturations' = receivedMaturations, + // consumer statusses do not change + consumerStatus' = consumerStatus, + // chain times do not change + curChainTimes' = curChainTimes, + // update the packet store on the provider + StoreSentPackets, } action endAndBeginBlockForConsumer(consumer: Chain): bool = all { @@ -312,22 +353,49 @@ module ccv { PROVIDER_NOOP, // no packets are sent to consumer or received by it outstandingPacketsToConsumer' = outstandingPacketsToConsumer, + // consumer statusses do not change + consumerStatus' = consumerStatus, + // chain times do not change + curChainTimes' = curChainTimes, + // update the packet store on the provider + StoreSentPackets, } - // the timestamp for each chain is advanced nondeterministically - action AdvanceTimestamps(): bool = - curChainTimes' = curChainTimes.keys().mapBy( - (chain) => - nondet advancement = oneOf(0.to(100)) - curChainTimes.get(chain) + advancement - ) + // advance timestamps for maps nondeterministically + action AdvanceTime(): bool = + val advanceAmounts = curChainTimes.keys().mapBy( + chain => + nondet amount = oneOf(1.to(10)) + amount + ) + AdvanceTimeByMap(advanceAmounts) + + // the timestamp for each chain is advanced by the given amount + action AdvanceTimeByMap(advancementAmount: Chain -> int): bool = all + { + curChainTimes' = curChainTimes.keys().mapBy( + chain => + curChainTimes.get(chain) + advancementAmount.get(chain) + ), + // all other variables are left untouched + votingPowerHistories' = votingPowerHistories, + runningValidatorSet' = runningValidatorSet, + outstandingPacketsToProvider' = outstandingPacketsToProvider, + outstandingPacketsToConsumer' = outstandingPacketsToConsumer, + receivedMaturations' = receivedMaturations, + maturationTimes' = maturationTimes, + // chain times do not change + consumerStatus' = consumerStatus, + // update the packet store on the provider + StoreSentPackets, + } // each consumer chain may advance in the order // some events may necessitate a transition, e.g. timeouts. // shouldAdvance gives, for each consumer chain, whether it should advance if possible. // if a chain has to advance, e.g. due to timeouts, or may not advance, the value will have no effect. action AdvanceConsumers(shouldAdvance: Chain -> bool): bool = - consumerStatus' = consumerStatus.keys().mapBy( + val newConsumerStatus = consumerStatus.keys().mapBy( chain => val curStatus = consumerStatus.get(chain) if (curStatus == UNUSED) { @@ -355,7 +423,30 @@ module ccv { // stopped chains cannot restart, we assume a new chain would be started in that case STOPPED } - ) + ) + all { + consumerStatus' = newConsumerStatus, + // all other variables are left untouched + votingPowerHistories' = votingPowerHistories, + runningValidatorSet' = runningValidatorSet.keys().mapBy( + chain => + if (newConsumerStatus.get(chain) == RUNNING and consumerStatus.get(chain) == UNUSED) + // consumers that went from unused to running start with the current validator set on the provider + { + runningValidatorSet.get(ProviderChain) + } else { + runningValidatorSet.get(chain) + } + ), + outstandingPacketsToProvider' = outstandingPacketsToProvider, + outstandingPacketsToConsumer' = outstandingPacketsToConsumer, + receivedMaturations' = receivedMaturations, + maturationTimes' = maturationTimes, + // chain times do not change + curChainTimes' = curChainTimes, + // update the packet store on the provider + StoreSentPackets, + } // stores the VSCPackets sent in this step in sentVSCPackets action StoreSentPackets: bool = @@ -364,20 +455,17 @@ module ccv { sentVSCPackets.get(chain).union(outstandingPacketsToConsumer.get(chain).toSet()) ) - action step: bool = - all { - // timestamps can be advanced in each step - AdvanceTimestamps, - any { - nondet node = oneOf(Nodes) - nondet amount = oneOf(1.to(10)) - votingPowerChange(node, amount), - recvPacketOnProvider(oneOf(ConsumerChains)), - recvPacketOnConsumer(oneOf(ConsumerChains)), - nondet chain = oneOf(chains) - endAndBeginBlock(chain), - }, - StoreSentPackets, + + // the main step action + action step: bool = any { + AdvanceTime, + nondet node = oneOf(Nodes) + nondet amount = oneOf(1.to(10)) + votingPowerChange(node, amount), + recvPacketOnProvider(oneOf(ConsumerChains)), + recvPacketOnConsumer(oneOf(ConsumerChains)), + nondet chain = oneOf(chains) + endAndBeginBlock(chain), val shouldAdvance = ConsumerChains.mapBy( chain => nondet should = oneOf(Set(true, false)) @@ -385,7 +473,6 @@ module ccv { ) AdvanceConsumers(shouldAdvance), } - def getArbitraryValidatorSet(): ValidatorSet = val numValidators = oneOf(1.to(Nodes.size())) @@ -397,6 +484,7 @@ module ccv { votingPower ) + // INITIALIZATION action init: bool = all { // voting power histories are empty @@ -436,4 +524,17 @@ module ccv { chains.forall( chain => chain.getCurrentValidatorSet().wasValidatorSetOnProvider() ) + + // TESTS + run VSCHappyPath: bool = { + init + // trigger a votingPowerChange on the provider chain + .then(votingPowerChange("A", 10)) + // endAndBeginBlock on provider. No consumer chains are running, so no packets are sent + .then(endAndBeginBlock(ProviderChain)) + // advance chain1 to running + .then(AdvanceConsumers(NoStatusAdvancement.set("chain1", true))) + } + + } \ No newline at end of file From e27e74b98c6f4bb2da7fd7da3124619a341c19f5 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 25 Aug 2023 15:20:01 +0200 Subject: [PATCH 05/80] Rename model, add test, use powerset for nondeterminism --- .../core/quint_model/{model.qnt => ccv.qnt} | 95 ++++++++++++++----- 1 file changed, 72 insertions(+), 23 deletions(-) rename tests/difference/core/quint_model/{model.qnt => ccv.qnt} (86%) diff --git a/tests/difference/core/quint_model/model.qnt b/tests/difference/core/quint_model/ccv.qnt similarity index 86% rename from tests/difference/core/quint_model/model.qnt rename to tests/difference/core/quint_model/ccv.qnt index aa3378bca6..86dbccf523 100644 --- a/tests/difference/core/quint_model/model.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -74,6 +74,20 @@ module ccv { 0 ) + // utility: a struct summarizing the current state + val state = + { + votingPowerHistories: votingPowerHistories, + runningValidatorSet: runningValidatorSet, + curChainTimes: curChainTimes, + consumerStatus: consumerStatus, + outstandingPacketsToProvider: outstandingPacketsToProvider, + outstandingPacketsToConsumer: outstandingPacketsToConsumer, + maturationTimes: maturationTimes, + receivedMaturations: receivedMaturations, + sentVSCPackets: sentVSCPackets, + } + // utility: a map assigning each chain to false, used for not advancing consumer status pure val NoStatusAdvancement: Chain -> bool = chains.mapBy( @@ -249,7 +263,7 @@ module ccv { // as that only happens when the next block is started runningValidatorSet' = runningValidatorSet.set(consumer, packet.validatorSet), // add the new packet and store its maturation time - val newMaturationTimes = maturationTimes.get(consumer).set(packet, curChainTimes.get(consumer) + UnbondingPeriod.get(consumer)) + val newMaturationTimes = maturationTimes.get(consumer).put(packet, curChainTimes.get(consumer) + UnbondingPeriod.get(consumer)) maturationTimes' = maturationTimes.set(consumer, newMaturationTimes) }, PROVIDER_NOOP, @@ -298,16 +312,20 @@ module ccv { // if running validator set is not equal to the last one in the history if (runningValidatorSet.get(ProviderChain) != votingPowerHistories.get(ProviderChain).head()) // then send a packet to each running consumer - outstandingPacketsToConsumer.keys().filter(consumer => consumerStatus.get(consumer) == RUNNING).mapBy( + outstandingPacketsToConsumer.keys().mapBy( (consumer) => val packetQueue = outstandingPacketsToConsumer.get(consumer) - packetQueue.append( - { - id: packetQueue.length(), - validatorSet: runningValidatorSet.get(ProviderChain), - timeout: curChainTimes.get(ProviderChain) + PacketTimeout - } - ) + if (consumerStatus.get(consumer) == RUNNING) { + packetQueue.append( + { + id: packetQueue.length(), + validatorSet: runningValidatorSet.get(ProviderChain), + timeout: curChainTimes.get(ProviderChain) + PacketTimeout + } + ) + } else { + packetQueue + } ) else // otherwise, don't send any packets @@ -474,10 +492,12 @@ module ccv { AdvanceConsumers(shouldAdvance), } + pure val nodePowerSet = Nodes.powerset() + def getArbitraryValidatorSet(): ValidatorSet = - val numValidators = oneOf(1.to(Nodes.size())) + nondet numValidators = oneOf(1.to(Nodes.size())) // toList has nondeterministic behaviour, so this gets arbitrary validators - val validators = Nodes.toList().slice(0, numValidators).toSet() + nondet validators = oneOf(nodePowerSet.filter(s => s.size() == numValidators)) validators.mapBy( validator => nondet votingPower = oneOf(1.to(10)) @@ -487,18 +507,18 @@ module ccv { // INITIALIZATION action init: bool = all { - // voting power histories are empty - votingPowerHistories' = - chains.mapBy( - (chain) => - List() - ), + val validatorSets = chains.mapBy( + (chain) => // provider chain gets an arbitrary validator set, consumer chains have none - runningValidatorSet' = - chains.mapBy( + if (chain == ProviderChain) getArbitraryValidatorSet else Map() + ) + all { + votingPowerHistories' = chains.mapBy( (chain) => - if (chain == ProviderChain) getArbitraryValidatorSet else Map() + List(validatorSets.get(chain)) ), + runningValidatorSet' = validatorSets, + }, // each chain starts at time 0 curChainTimes' = chains.mapBy( (chain) => 0 @@ -526,14 +546,43 @@ module ccv { ) // TESTS - run VSCHappyPath: bool = { + run VSCHappyPathTest: bool = { init // trigger a votingPowerChange on the provider chain .then(votingPowerChange("A", 10)) // endAndBeginBlock on provider. No consumer chains are running, so no packets are sent .then(endAndBeginBlock(ProviderChain)) - // advance chain1 to running - .then(AdvanceConsumers(NoStatusAdvancement.set("chain1", true))) + .then(all { + // no packet was sent + assert(outstandingPacketsToConsumer.get("chain1").length() == 0), + // advance chain1 to running + AdvanceConsumers(NoStatusAdvancement.set("chain1", true)) + }) + // consumer chain should have current validator set from provider + .then( + all { + // since consumer chain just started, its assumed to have the validator set from provider + assert(runningValidatorSet.get("chain1") == runningValidatorSet.get(ProviderChain)), + // trigger a votingPowerChange on the provider chain + votingPowerChange("B", 10) + } + ) + .then(endAndBeginBlock(ProviderChain)) + // now the provider should send a packet on block end + .then(all { + // a packet was sent + assert(outstandingPacketsToConsumer.get("chain1").length() == 1), + // deliver the packet to the consumer + recvPacketOnConsumer("chain1") + }) + .then(all { + // the consumer should have the new validator set + assert(runningValidatorSet.get("chain1") == runningValidatorSet.get(ProviderChain)), + // the old validator set should be in the history + assert(votingPowerHistories.get("chain1").head() == Map("A" -> 10)), + // put a last action to satisfy the action effect + AdvanceConsumers(NoStatusAdvancement) + }) } From 50fae345fa1f3a7f42ad933ff1e33390e3003c3e Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 25 Aug 2023 17:49:42 +0200 Subject: [PATCH 06/80] Reintroduce vsc changed tracking variables --- tests/difference/core/quint_model/ccv.qnt | 110 +++++++++++++--------- 1 file changed, 67 insertions(+), 43 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 86dbccf523..131a490d8a 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -140,6 +140,12 @@ module ccv { // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness var sentVSCPackets: Chain -> Set[VSCPacket] + // stores whether, in this step, the validator set considered to be changed. + // this is needed because the validator set might be considered to have changed, even though + // it is still technically identical at our level of abstraction, e.g. a validator power change on the provider + // might leave the validator set the same because a delegation and undelegation cancel each other out. + var providerValidatorSetChangedInThisBlock: bool + // UTILITY FUNCTIONS & ACTIONS def wasValidatorSetOnProvider(validatorSet: ValidatorSet): bool = { @@ -153,7 +159,7 @@ module ccv { def getUpdatedValidatorSet(oldValidatorSet: ValidatorSet, validator: Node, newVotingPower: int): ValidatorSet = if (newVotingPower > 0) - oldValidatorSet.set(validator, newVotingPower) + oldValidatorSet.put(validator, newVotingPower) else oldValidatorSet.mapRemove(validator) @@ -211,7 +217,7 @@ module ccv { // set the running validator set on the provider chain, but don't update the history yet runningValidatorSet' = runningValidatorSet.set(ProviderChain, newValidatorSet), // no packets are sent yet, these are only sent on endAndBeginBlock - outstandingPacketsToConsumer' = outstandingPacketsToConsumer, + RegisterNewOutstandingPackets(outstandingPacketsToConsumer), outstandingPacketsToProvider' = outstandingPacketsToProvider, receivedMaturations' = receivedMaturations, CONSUMER_NOOP, @@ -221,8 +227,8 @@ module ccv { consumerStatus' = consumerStatus, // chain times do not change curChainTimes' = curChainTimes, - // update the packet store on the provider - StoreSentPackets, + // the validator set is considered to have changed + providerValidatorSetChangedInThisBlock' = true, } // deliver the next outstanding packet from the consumer to the provider. @@ -237,7 +243,7 @@ module ccv { val maturedPacket = outstandingPacketsToProvider.get(consumer).head() receivedMaturations' = receivedMaturations.add(maturedPacket), CONSUMER_NOOP, - outstandingPacketsToConsumer' = outstandingPacketsToConsumer, + RegisterNewOutstandingPackets(outstandingPacketsToConsumer), votingPowerHistories' = votingPowerHistories, // no validator set changes are made runningValidatorSet' = runningValidatorSet, @@ -245,8 +251,8 @@ module ccv { consumerStatus' = consumerStatus, // chain times do not change curChainTimes' = curChainTimes, - // update the packet store on the provider - StoreSentPackets, + // the validator set was not changed by this action (but might have been changed before in this block) + providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock } // deliver the next outstanding packet from the provider to the consumer. @@ -256,7 +262,8 @@ module ccv { outstandingPacketsToConsumer.get(consumer).length() > 0, // remove packet from outstanding packets val newPacketQueue = outstandingPacketsToConsumer.get(consumer).tail() - outstandingPacketsToConsumer' = outstandingPacketsToConsumer.set(consumer, newPacketQueue), + val newOutstandingPackets = outstandingPacketsToConsumer.set(consumer, newPacketQueue) + RegisterNewOutstandingPackets(newOutstandingPackets), val packet = outstandingPacketsToConsumer.get(consumer).head() all { // update the running validator set, but not the history yet, @@ -273,8 +280,8 @@ module ccv { consumerStatus' = consumerStatus, // chain times do not change curChainTimes' = curChainTimes, - // update the packet store on the provider - StoreSentPackets, + // the validator set was not changed by this action (but might have been changed before in this block) + providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock } // ends the current block and starts the next block for a given chain. @@ -308,9 +315,9 @@ module ccv { // so start with it in the next block runningValidatorSet' = runningValidatorSet, // send VSCPackets to consumers - outstandingPacketsToConsumer' = - // if running validator set is not equal to the last one in the history - if (runningValidatorSet.get(ProviderChain) != votingPowerHistories.get(ProviderChain).head()) + val newOutstandingPackets = + // if running validator set is considered to have changed + if (providerValidatorSetChangedInThisBlock) // then send a packet to each running consumer outstandingPacketsToConsumer.keys().mapBy( (consumer) => @@ -329,7 +336,8 @@ module ccv { ) else // otherwise, don't send any packets - outstandingPacketsToConsumer, + outstandingPacketsToConsumer + RegisterNewOutstandingPackets(newOutstandingPackets), CONSUMER_NOOP, // no packets are sent to the provider outstandingPacketsToProvider' = outstandingPacketsToProvider, @@ -339,8 +347,8 @@ module ccv { consumerStatus' = consumerStatus, // chain times do not change curChainTimes' = curChainTimes, - // update the packet store on the provider - StoreSentPackets, + // the validator set was definitely not changed in the new block yet, so set to false + providerValidatorSetChangedInThisBlock' = false } action endAndBeginBlockForConsumer(consumer: Chain): bool = all { @@ -370,13 +378,14 @@ module ccv { }, PROVIDER_NOOP, // no packets are sent to consumer or received by it - outstandingPacketsToConsumer' = outstandingPacketsToConsumer, + RegisterNewOutstandingPackets(outstandingPacketsToConsumer), // consumer statusses do not change consumerStatus' = consumerStatus, // chain times do not change curChainTimes' = curChainTimes, - // update the packet store on the provider - StoreSentPackets, + // the validator set was not changed by this action (but might have been changed before in this block) + // also, this is only a new block for a consumer, so the change variable shouldn't be reset + providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock } // advance timestamps for maps nondeterministically @@ -399,13 +408,13 @@ module ccv { votingPowerHistories' = votingPowerHistories, runningValidatorSet' = runningValidatorSet, outstandingPacketsToProvider' = outstandingPacketsToProvider, - outstandingPacketsToConsumer' = outstandingPacketsToConsumer, + RegisterNewOutstandingPackets(outstandingPacketsToConsumer), receivedMaturations' = receivedMaturations, maturationTimes' = maturationTimes, // chain times do not change consumerStatus' = consumerStatus, - // update the packet store on the provider - StoreSentPackets, + // the validator set was not changed by this action (but might have been changed before in this block) + providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock } // each consumer chain may advance in the order @@ -457,20 +466,28 @@ module ccv { } ), outstandingPacketsToProvider' = outstandingPacketsToProvider, - outstandingPacketsToConsumer' = outstandingPacketsToConsumer, + RegisterNewOutstandingPackets(outstandingPacketsToConsumer), receivedMaturations' = receivedMaturations, maturationTimes' = maturationTimes, // chain times do not change curChainTimes' = curChainTimes, - // update the packet store on the provider - StoreSentPackets, + // the validator set was not changed by this action (but might have been changed before in this block) + providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + } + + // Updates the outstandingPacketsToConsumer and sentVSCPackets variables + action RegisterNewOutstandingPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = + all { + outstandingPacketsToConsumer' = newOutstandingPackets, + StoreSentPackets(newOutstandingPackets), } + // stores the VSCPackets sent in this step in sentVSCPackets - action StoreSentPackets: bool = + action StoreSentPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = sentVSCPackets' = sentVSCPackets.keys().mapBy( (chain) => - sentVSCPackets.get(chain).union(outstandingPacketsToConsumer.get(chain).toSet()) + sentVSCPackets.get(chain).union(newOutstandingPackets.get(chain).toSet()) ) @@ -534,6 +551,8 @@ module ccv { sentVSCPackets' = chains.mapBy(chain => Set()), // no packets have been received by consumers, so no maturation times set maturationTimes' = chains.mapBy(chain => Map()), + // validator set was not changed yet + providerValidatorSetChangedInThisBlock' = false } // PROPERTIES @@ -567,22 +586,27 @@ module ccv { votingPowerChange("B", 10) } ) - .then(endAndBeginBlock(ProviderChain)) - // now the provider should send a packet on block end - .then(all { - // a packet was sent - assert(outstandingPacketsToConsumer.get("chain1").length() == 1), - // deliver the packet to the consumer - recvPacketOnConsumer("chain1") - }) - .then(all { - // the consumer should have the new validator set - assert(runningValidatorSet.get("chain1") == runningValidatorSet.get(ProviderChain)), - // the old validator set should be in the history - assert(votingPowerHistories.get("chain1").head() == Map("A" -> 10)), - // put a last action to satisfy the action effect - AdvanceConsumers(NoStatusAdvancement) - }) + .then( + val valSet = runningValidatorSet.get(ProviderChain) + endAndBeginBlock(ProviderChain) + // now the provider should send a packet on block end + .then(all { + // a packet was sent + assert(outstandingPacketsToConsumer.get("chain1").length() == 1), + // deliver the packet to the consumer + recvPacketOnConsumer("chain1") + }) + .then( + // consumer needs to end a block before it has the new validator set + endAndBeginBlock("chain1") + ) + .then(all { + // the consumer should have the new validator set + assert(runningValidatorSet.get("chain1") == valSet), + // put a last action to satisfy the action effect + AdvanceConsumers(NoStatusAdvancement) + }) + ) } From 78e890aef2d319ffaab3347583eda01205315dbb Mon Sep 17 00:00:00 2001 From: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com> Date: Fri, 25 Aug 2023 18:05:24 +0200 Subject: [PATCH 07/80] Add text with what expliticly is modelled --- tests/difference/core/quint_model/ccv.qnt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 131a490d8a..7984d3b01b 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -5,6 +5,11 @@ module ccv { // * Reward distribution // * Starting/Stopping chains during execution // * Slashes + + // Things that explicitly are modelled: + // * Validator set changes are propagated from provider to consumers + // * VSC packets mature + // * Consumers can be forcefully dropped due to timeouts, or stop on their own volition // TYPE DEFINITIONS type Node = str @@ -610,4 +615,4 @@ module ccv { } -} \ No newline at end of file +} From a1d57ef47f88dd34c66dd5f61b99073767a7fdd7 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com> Date: Fri, 25 Aug 2023 20:36:40 +0200 Subject: [PATCH 08/80] Add bluespec to ccv.qnt --- tests/difference/core/quint_model/ccv.qnt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 7984d3b01b..d18930ae1d 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -1,3 +1,4 @@ +-*- mode: Bluespec; -*- module ccv { import extraSpells.* from "./extraSpells" From 6c91866a573bcca553fdfbf00af14d3aac815d48 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com> Date: Fri, 25 Aug 2023 20:37:05 +0200 Subject: [PATCH 09/80] Add bluespec to expraSpells.qnt --- tests/difference/core/quint_model/extraSpells.qnt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/extraSpells.qnt b/tests/difference/core/quint_model/extraSpells.qnt index a32a74ad8f..a959db5251 100644 --- a/tests/difference/core/quint_model/extraSpells.qnt +++ b/tests/difference/core/quint_model/extraSpells.qnt @@ -1,3 +1,4 @@ +-*- mode: Bluespec; -*- module extraSpells { pure def prepend(__list: List[a], __elem: a): List[a] = { @@ -188,4 +189,4 @@ module extraSpells { __set.union(Set(elem)) } -} \ No newline at end of file +} From 2126eac396d18977b5408e3ee550a20157359dbd Mon Sep 17 00:00:00 2001 From: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com> Date: Tue, 5 Sep 2023 13:03:45 +0200 Subject: [PATCH 10/80] Add docstring to extraSpells module --- tests/difference/core/quint_model/extraSpells.qnt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/difference/core/quint_model/extraSpells.qnt b/tests/difference/core/quint_model/extraSpells.qnt index a959db5251..cd2105beb7 100644 --- a/tests/difference/core/quint_model/extraSpells.qnt +++ b/tests/difference/core/quint_model/extraSpells.qnt @@ -1,4 +1,5 @@ -*- mode: Bluespec; -*- +// This module is just a library with utility functions (sometimes called spells in Quint). module extraSpells { pure def prepend(__list: List[a], __elem: a): List[a] = { From 1320b9517982bff596ecfc0ac99755dc75c5f1e1 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 18 Sep 2023 18:23:31 +0200 Subject: [PATCH 11/80] Start rewriting model --- tests/difference/core/quint_model/ccv.qnt | 1241 +++++++++-------- .../core/quint_model/extraSpells.qnt | 1 - ...ActionMarshalling-20230912123337-6230.fail | 18 + ...ActionMarshalling-20230912123517-6794.fail | 14 + ...ActionMarshalling-20230912123556-6970.fail | 14 + ...ActionMarshalling-20230912123609-7116.fail | 18 + ...ActionMarshalling-20230912123822-8026.fail | 8 + ...ctionMarshalling-20230913151826-12656.fail | 8 + ...ctionMarshalling-20230913151917-13146.fail | 8 + ...eadAndWriteTrace-20230913151920-13146.fail | 11 + 10 files changed, 790 insertions(+), 551 deletions(-) create mode 100644 tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123337-6230.fail create mode 100644 tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123517-6794.fail create mode 100644 tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123556-6970.fail create mode 100644 tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123609-7116.fail create mode 100644 tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123822-8026.fail create mode 100644 tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151826-12656.fail create mode 100644 tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151917-13146.fail create mode 100644 tests/e2e/testdata/rapid/TestReadAndWriteTrace/TestReadAndWriteTrace-20230913151920-13146.fail diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index d18930ae1d..4cbc327ac4 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -1,5 +1,4 @@ --*- mode: Bluespec; -*- -module ccv { +module ccv_logic { import extraSpells.* from "./extraSpells" // Things that are not modelled: @@ -12,12 +11,17 @@ module ccv { // * VSC packets mature // * Consumers can be forcefully dropped due to timeouts, or stop on their own volition + // =================== // TYPE DEFINITIONS + // =================== type Node = str type Chain = str - type ValidatorSet = Node -> int + type Power = int + type ValidatorSet = Node -> Power type Height = int type Timestamp = int + // a list of validator sets per blocks, ordered by recency + type VotingPowerHistory = List[ValidatorSet] // --PACKETS type VSCPacket = @@ -38,582 +42,719 @@ module ccv { timeout: Timestamp } - // MODEL PARAMETERS - - - // set of identifiers of potential nodes - pure val Nodes: Set[Node] = - Set("A", "B", "C", "D", "E", "F", "G", "H", "I", "J") - - // the set of consumer chains - pure val ConsumerChains: Set[Chain] = - Set("chain1", "chain2", "chain3") + // possible consumer statuses + pure val STOPPED = "stopped" // the chain was once a consumer chain, but has been dropped by the provider. + pure val RUNNING = "running" // the chain is currently a consumer chain. Running chains are those that get sent VSCPackets. + pure val UNUSED = "unused" // the chain has never been a consumer chain, and is available to become one. + // When a chain is dropped, it cannot become a consumer again - we assume that would be done by another consumer becoming running. + + + // state that each chain needs to store, whether consumer or provider. + type ChainState = { + // Stores the list of voting powers that corresponded to voting powers + // at blocks over the chains entire existence. + // Voting powers should be ordered by recency in descending order. + votingPowerHistory: VotingPowerHistory, + + // the current validator set on each chain. + // this will be included in the next block, but might not be final yet, + // e.g. there may be more modifications in the current block. + currentValidatorSet: ValidatorSet, + + // the latest timestamp that was comitted on chain + lastTimestamp: Timestamp, + } - // The singular provider chain. - pure val ProviderChain: Chain = - "provider" - - pure val chains = ConsumerChains.union(Set(ProviderChain)) - - // length of the unbonding period on each chain - pure val UnbondingPeriod: Chain -> int = chains.mapBy( - (chain) => - 10 - ) - - // the time until a packet times out - pure val PacketTimeout: int = - 5 - - // the time until a consumer chain is dropped by the provider due to inactivity - pure val InactivityTimeout: int = - 10 - - // consumer statuses - pure val STOPPED = "stopped" - pure val RUNNING = "running" - pure val UNUSED = "unused" - - // utility: a map assigning each chain to 0, used for not advancing timestamps - pure val NoTimeAdvancement: Chain -> int = chains.mapBy( - (chain) => - 0 - ) - - // utility: a struct summarizing the current state - val state = + // Defines the current state of the provider chain. Essentially, all information here is stored by the provider on-chain (or could be derived purely by information that is on-chain). + type ProviderState = { - votingPowerHistories: votingPowerHistories, - runningValidatorSet: runningValidatorSet, - curChainTimes: curChainTimes, - consumerStatus: consumerStatus, - outstandingPacketsToProvider: outstandingPacketsToProvider, - outstandingPacketsToConsumer: outstandingPacketsToConsumer, - maturationTimes: maturationTimes, - receivedMaturations: receivedMaturations, - sentVSCPackets: sentVSCPackets, - } - - - // utility: a map assigning each chain to false, used for not advancing consumer status - pure val NoStatusAdvancement: Chain -> bool = chains.mapBy( - (chain) => - false - ) - - // utility: the set of consumers currently running - val RunningConsumers: Set[Chain] = - ConsumerChains.filter(chain => consumerStatus.get(chain) == RUNNING) - - // MODEL STATE - // --SHARED STATE - - // Stores, for each chain, the list of voting powers that corresponded to voting powers - // at blocks over its entire existence. - // Voting powers should be ordered by recency in descending order. - var votingPowerHistories: Chain -> List[ValidatorSet] - - // the current validator set on each chain. - // this will be included in the next block, but might not be final yet, - // e.g. there may be more modifications in the current block. - var runningValidatorSet: Chain -> ValidatorSet - - // the current timestamp for each chain - var curChainTimes: Chain -> Timestamp - - // stores, for each chain, its current status - - // unused, running, or stopped - var consumerStatus: Chain -> str - - // --CHANNELS - // Stores, for each consumer chain, the list of packets that have been sent to the provider chain - // and have not been received yet. - var outstandingPacketsToProvider: Chain -> List[VSCMaturedPacket] + // the state that each chain needs to store + chainState: ChainState, - // Stores, for each consumer chain, the list of packets that have been sent to the consumer chain - // and have not been received yet. - var outstandingPacketsToConsumer: Chain -> List[VSCPacket] + // Stores, for each consumer chain, the list of packets that have been sent to the consumer chain + // and have not been received yet. + // In the implementation, this would roughly be the unacknowledged packets on an ibc channel. + outstandingPacketsToConsumer: Chain -> List[VSCPacket], + // the set of received VSCMaturedPackets + receivedMaturations: Set[VSCMaturedPacket], - // --CONSUMER STATE - // Stores the maturation times for VSCPackets received by consumers - var maturationTimes: Chain -> (VSCPacket -> Timestamp) + // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness + sentVSCPackets: Chain -> Set[VSCPacket], - // --PROVIDER STATE - // the set of VSCMaturedPackets received by the provider chain - var receivedMaturations: Set[VSCMaturedPacket] - - // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness - var sentVSCPackets: Chain -> Set[VSCPacket] - - // stores whether, in this step, the validator set considered to be changed. - // this is needed because the validator set might be considered to have changed, even though - // it is still technically identical at our level of abstraction, e.g. a validator power change on the provider - // might leave the validator set the same because a delegation and undelegation cancel each other out. - var providerValidatorSetChangedInThisBlock: bool - - - // UTILITY FUNCTIONS & ACTIONS - def wasValidatorSetOnProvider(validatorSet: ValidatorSet): bool = { - votingPowerHistories.get(ProviderChain).toSet().exists( - historicalValSet => historicalValSet == validatorSet - ) - } - - def getCurrentValidatorSet(chain: Chain): ValidatorSet = - votingPowerHistories.get(chain).head() - - def getUpdatedValidatorSet(oldValidatorSet: ValidatorSet, validator: Node, newVotingPower: int): ValidatorSet = - if (newVotingPower > 0) - oldValidatorSet.put(validator, newVotingPower) - else - oldValidatorSet.mapRemove(validator) - - // returns true if the consumer has timed out and should be dropped - def consumerTimedOut(consumer: Chain): bool = - any { - // either a package from provider to consumer has timed out - outstandingPacketsToConsumer.get(consumer).select( - packet => packet.timeout <= curChainTimes.get(consumer) - ).length() > 0, - // or a package from consumer to provider has timed out - outstandingPacketsToProvider.get(consumer).select( - packet => packet.timeout <= curChainTimes.get(ProviderChain) - ).length() > 0, - // or the inactivity timeout has passed since a VSCPacket was sent to the consumer, but the - // provider has not received a VSCMaturedPacket for it - val packetsWithoutResponse = sentVSCPackets.get(consumer).filter( // get packets without response - packet => - not(receivedMaturations.exists( - maturedPacket => maturedPacket.id == packet.id - )) - ) - // among those, get packets where inactivity timeout has passed - packetsWithoutResponse.filter( - packet => - val sentAt = curChainTimes.get(ProviderChain) - PacketTimeout // compute when the packet was sent - val timesOutAt = sentAt + InactivityTimeout // compute when the packet times out - timesOutAt <= curChainTimes.get(ProviderChain) - ).size() > 0 - } - - // utility action that leaves all provider state untouched - action PROVIDER_NOOP(): bool = - all { - receivedMaturations' = receivedMaturations, - } + // stores whether, in this block, the validator set has changed. + // this is needed because the validator set might be considered to have changed, even though + // it is still technically identical at our level of abstraction, e.g. a validator power change on the provider + // might leave the validator set the same because a delegation and undelegation cancel each other out. + providerValidatorSetChangedInThisBlock: bool, - // utility action that leaves all consumer state untouched - action CONSUMER_NOOP(): bool = - all { - maturationTimes' = maturationTimes, + // stores, for each consumer chain, its current status - + // unused, running, or stopped + consumerStatus: Chain -> str, } - - // MODEL ACTIONS + // Defines the current state of a consumer chain. This information is accessible to that consumer on-chain. + type ConsumerState = { + // the state that each chain needs to store + chainState: ChainState, - // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, - // e.g. via undelegations, or delegations, ... - action votingPowerChange(validator: Node, amount: int): bool = - // for the provider chain, we need to adjust the voting power history - // by adding a new set - all { - amount >= 0, - val newValidatorSet = getCurrentValidatorSet(ProviderChain).getUpdatedValidatorSet(validator, amount) - // set the running validator set on the provider chain, but don't update the history yet - runningValidatorSet' = runningValidatorSet.set(ProviderChain, newValidatorSet), - // no packets are sent yet, these are only sent on endAndBeginBlock - RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - outstandingPacketsToProvider' = outstandingPacketsToProvider, - receivedMaturations' = receivedMaturations, - CONSUMER_NOOP, - // voting power history is only updated on endAndBeginBlock - votingPowerHistories' = votingPowerHistories, - // consumer statusses do not change - consumerStatus' = consumerStatus, - // chain times do not change - curChainTimes' = curChainTimes, - // the validator set is considered to have changed - providerValidatorSetChangedInThisBlock' = true, - } + // Stores the maturation times for VSCPackets received by this consumer + maturationTimes: VSCPacket -> Timestamp, - // deliver the next outstanding packet from the consumer to the provider. - // since this model assumes a single provider chain, this just takes a single chain as argument. - action recvPacketOnProvider(consumer: Chain): bool = all { - // ensure there is a packet to be received - outstandingPacketsToProvider.get(consumer).length() > 0, - // remove packet from outstanding packets - val newPacketQueue = outstandingPacketsToProvider.get(consumer).tail() - outstandingPacketsToProvider' = outstandingPacketsToProvider.set(consumer, newPacketQueue), - // register the packet as received - val maturedPacket = outstandingPacketsToProvider.get(consumer).head() - receivedMaturations' = receivedMaturations.add(maturedPacket), - CONSUMER_NOOP, - RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - votingPowerHistories' = votingPowerHistories, - // no validator set changes are made - runningValidatorSet' = runningValidatorSet, - // consumer statusses do not change - consumerStatus' = consumerStatus, - // chain times do not change - curChainTimes' = curChainTimes, - // the validator set was not changed by this action (but might have been changed before in this block) - providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock - } + // Stores the list of packets that have been sent to the provider chain by this consumer + // and have not been received yet. + // In the implementation, essentially unacknowledged IBC packets. + outstandingPacketsToProvider: Chain -> List[VSCMaturedPacket], - // deliver the next outstanding packet from the provider to the consumer. - // since this model assumes a single provider chain, this just takes a single chain as argument. - action recvPacketOnConsumer(consumer: Chain): bool = all { - // ensure there is a packet to be received - outstandingPacketsToConsumer.get(consumer).length() > 0, - // remove packet from outstanding packets - val newPacketQueue = outstandingPacketsToConsumer.get(consumer).tail() - val newOutstandingPackets = outstandingPacketsToConsumer.set(consumer, newPacketQueue) - RegisterNewOutstandingPackets(newOutstandingPackets), - val packet = outstandingPacketsToConsumer.get(consumer).head() - all { - // update the running validator set, but not the history yet, - // as that only happens when the next block is started - runningValidatorSet' = runningValidatorSet.set(consumer, packet.validatorSet), - // add the new packet and store its maturation time - val newMaturationTimes = maturationTimes.get(consumer).put(packet, curChainTimes.get(consumer) + UnbondingPeriod.get(consumer)) - maturationTimes' = maturationTimes.set(consumer, newMaturationTimes) - }, - PROVIDER_NOOP, - votingPowerHistories' = votingPowerHistories, - outstandingPacketsToProvider' = outstandingPacketsToProvider, - // consumer statusses do not change - consumerStatus' = consumerStatus, - // chain times do not change - curChainTimes' = curChainTimes, - // the validator set was not changed by this action (but might have been changed before in this block) - providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + // Stores the list of voting powers that corresponded to voting powers + // at blocks over the chains entire existence. + // Voting powers should be ordered by recency in descending order. + votingPowerHistory: VotingPowerHistory, } - // ends the current block and starts the next block for a given chain. - action endAndBeginBlock(chain: Chain): bool = any { - all { - chain == ProviderChain, - endAndBeginBlockForProvider, - }, - all { - chain != ProviderChain, - endAndBeginBlockForConsumer(chain), - } + // the state of the protocol consists of the composition of the state of one provider chain with potentially many consumer chains. + type ProtocolState = { + providerState: ProviderState, + // the state of each consumer chain. + // note that we assume that this contains all consumer chains that may ever exist, + // and consumer chains that are currently not running will have providerState.consumerStatus == UNUSED or STOPPED + consumerStates: Set[ConsumerState] } - // gets the updated history for the current chain when ending a block, i.e. the - // running validator set is added to the history if different from the last one. - def getUpdatedHistory(chain: Chain): List[ValidatorSet] = - // update voting power history if the validator set changed - val newValidatorSet = runningValidatorSet.get(ProviderChain) - val oldValidatorSet = votingPowerHistories.get(ProviderChain).head() - if (newValidatorSet != oldValidatorSet) - votingPowerHistories.get(ProviderChain).prepend(newValidatorSet) - else - votingPowerHistories.get(ProviderChain) - - - action endAndBeginBlockForProvider(): bool = all { - // update the voting power history - votingPowerHistories' = votingPowerHistories.set(ProviderChain, getUpdatedHistory(ProviderChain)), - // the running validator set is now for sure the current validator set, - // so start with it in the next block - runningValidatorSet' = runningValidatorSet, - // send VSCPackets to consumers - val newOutstandingPackets = - // if running validator set is considered to have changed - if (providerValidatorSetChangedInThisBlock) - // then send a packet to each running consumer - outstandingPacketsToConsumer.keys().mapBy( - (consumer) => - val packetQueue = outstandingPacketsToConsumer.get(consumer) - if (consumerStatus.get(consumer) == RUNNING) { - packetQueue.append( - { - id: packetQueue.length(), - validatorSet: runningValidatorSet.get(ProviderChain), - timeout: curChainTimes.get(ProviderChain) + PacketTimeout - } - ) - } else { - packetQueue - } - ) - else - // otherwise, don't send any packets - outstandingPacketsToConsumer - RegisterNewOutstandingPackets(newOutstandingPackets), - CONSUMER_NOOP, - // no packets are sent to the provider - outstandingPacketsToProvider' = outstandingPacketsToProvider, - // do not receive any maturations - receivedMaturations' = receivedMaturations, - // consumer statusses do not change - consumerStatus' = consumerStatus, - // chain times do not change - curChainTimes' = curChainTimes, - // the validator set was definitely not changed in the new block yet, so set to false - providerValidatorSetChangedInThisBlock' = false + type Error = { + message: str } - action endAndBeginBlockForConsumer(consumer: Chain): bool = all { - ConsumerChains.contains(consumer), - // update the voting power history - votingPowerHistories' = votingPowerHistories.set(consumer, getUpdatedHistory(consumer)), - // the running validator set is now for sure the current validator set, - // so start with it in the next block - runningValidatorSet' = runningValidatorSet, - // compute mature packets whose maturation time has passed - val maturedPackets = maturationTimes.get(consumer).keys().filter( - packet => - val maturationTime = maturationTimes.get(consumer).get(packet) - maturationTime <= curChainTimes.get(consumer) - ) - all { - // remove matured packets from the maturation times - maturationTimes' = maturationTimes.set(consumer, maturationTimes.get(consumer).mapRemoveAll(maturedPackets)), - // send matured packets - outstandingPacketsToProvider' = outstandingPacketsToProvider.set( - consumer, - // construct VSCMaturedPackets from the matured VSCPackets - outstandingPacketsToProvider.get(consumer).concat( - maturedPackets.map(packet => {id: packet.id, timeout: 5}).toList() - ) - ) - }, - PROVIDER_NOOP, - // no packets are sent to consumer or received by it - RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - // consumer statusses do not change - consumerStatus' = consumerStatus, - // chain times do not change - curChainTimes' = curChainTimes, - // the validator set was not changed by this action (but might have been changed before in this block) - // also, this is only a new block for a consumer, so the change variable shouldn't be reset - providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + // we return either a result or an error. + // if hasError is true, newState may be arbitrary, but the error will be meaningful. + // if hasError is false, error may be arbitrary, but newState will be meaningful. + type Result = { + hasError: bool, + newState: ProtocolState, + error: Error } - // advance timestamps for maps nondeterministically - action AdvanceTime(): bool = - val advanceAmounts = curChainTimes.keys().mapBy( - chain => - nondet amount = oneOf(1.to(10)) - amount - ) - AdvanceTimeByMap(advanceAmounts) - - // the timestamp for each chain is advanced by the given amount - action AdvanceTimeByMap(advancementAmount: Chain -> int): bool = all + pure def Ok(newState: ProtocolState): Result = { { - curChainTimes' = curChainTimes.keys().mapBy( - chain => - curChainTimes.get(chain) + advancementAmount.get(chain) - ), - // all other variables are left untouched - votingPowerHistories' = votingPowerHistories, - runningValidatorSet' = runningValidatorSet, - outstandingPacketsToProvider' = outstandingPacketsToProvider, - RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - receivedMaturations' = receivedMaturations, - maturationTimes' = maturationTimes, - // chain times do not change - consumerStatus' = consumerStatus, - // the validator set was not changed by this action (but might have been changed before in this block) - providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock - } - - // each consumer chain may advance in the order - // some events may necessitate a transition, e.g. timeouts. - // shouldAdvance gives, for each consumer chain, whether it should advance if possible. - // if a chain has to advance, e.g. due to timeouts, or may not advance, the value will have no effect. - action AdvanceConsumers(shouldAdvance: Chain -> bool): bool = - val newConsumerStatus = consumerStatus.keys().mapBy( - chain => - val curStatus = consumerStatus.get(chain) - if (curStatus == UNUSED) { - if (shouldAdvance.get(chain)) - { - RUNNING - } else { - UNUSED - } - } - else if (curStatus == RUNNING) { - // the chain may transition to stopped. - // it is *forced* to stop if a packet timed out, - // or if the inactivity timeout has passed - if(consumerTimedOut(chain)) { - STOPPED - } else { - if (shouldAdvance.get(chain)) { - RUNNING - } else { - STOPPED - } - } - } else { - // stopped chains cannot restart, we assume a new chain would be started in that case - STOPPED + hasError: false, + newState: newState, + error: { + message: "" } - ) - all { - consumerStatus' = newConsumerStatus, - // all other variables are left untouched - votingPowerHistories' = votingPowerHistories, - runningValidatorSet' = runningValidatorSet.keys().mapBy( - chain => - if (newConsumerStatus.get(chain) == RUNNING and consumerStatus.get(chain) == UNUSED) - // consumers that went from unused to running start with the current validator set on the provider - { - runningValidatorSet.get(ProviderChain) - } else { - runningValidatorSet.get(chain) - } - ), - outstandingPacketsToProvider' = outstandingPacketsToProvider, - RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - receivedMaturations' = receivedMaturations, - maturationTimes' = maturationTimes, - // chain times do not change - curChainTimes' = curChainTimes, - // the validator set was not changed by this action (but might have been changed before in this block) - providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock } + } - // Updates the outstandingPacketsToConsumer and sentVSCPackets variables - action RegisterNewOutstandingPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = - all { - outstandingPacketsToConsumer' = newOutstandingPackets, - StoreSentPackets(newOutstandingPackets), + pure def Err(msg: str): Result = { + { + hasError: true, + newState: { + providerState: { + chainState: { + votingPowerHistory: List(), + currentValidatorSet: Map(), + lastTimestamp: 0 + }, + outstandingPacketsToConsumer: Map(), + receivedMaturations: Set(), + sentVSCPackets: Map(), + providerValidatorSetChangedInThisBlock: false, + consumerStatus: Map() + }, + consumerStates: Set() + }, + error: { + message: msg + } } + } + // =================== + // PROTOCOL LOGIC + // =================== - // stores the VSCPackets sent in this step in sentVSCPackets - action StoreSentPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = - sentVSCPackets' = sentVSCPackets.keys().mapBy( - (chain) => - sentVSCPackets.get(chain).union(newOutstandingPackets.get(chain).toSet()) - ) - + pure def getUpdatedValidatorSet(oldValidatorSet: ValidatorSet, validator: Node, newVotingPower: int): ValidatorSet = + if (newVotingPower > 0) + oldValidatorSet.put(validator, newVotingPower) + else + oldValidatorSet.mapRemove(validator) - // the main step action - action step: bool = any { - AdvanceTime, - nondet node = oneOf(Nodes) - nondet amount = oneOf(1.to(10)) - votingPowerChange(node, amount), - recvPacketOnProvider(oneOf(ConsumerChains)), - recvPacketOnConsumer(oneOf(ConsumerChains)), - nondet chain = oneOf(chains) - endAndBeginBlock(chain), - val shouldAdvance = ConsumerChains.mapBy( - chain => - nondet should = oneOf(Set(true, false)) - should - ) - AdvanceConsumers(shouldAdvance), - } - - pure val nodePowerSet = Nodes.powerset() - - def getArbitraryValidatorSet(): ValidatorSet = - nondet numValidators = oneOf(1.to(Nodes.size())) - // toList has nondeterministic behaviour, so this gets arbitrary validators - nondet validators = oneOf(nodePowerSet.filter(s => s.size() == numValidators)) - validators.mapBy( - validator => - nondet votingPower = oneOf(1.to(10)) - votingPower - ) - - // INITIALIZATION - action init: bool = - all { - val validatorSets = chains.mapBy( - (chain) => - // provider chain gets an arbitrary validator set, consumer chains have none - if (chain == ProviderChain) getArbitraryValidatorSet else Map() - ) - all { - votingPowerHistories' = chains.mapBy( - (chain) => - List(validatorSets.get(chain)) - ), - runningValidatorSet' = validatorSets, - }, - // each chain starts at time 0 - curChainTimes' = chains.mapBy( - (chain) => 0 - ), - // all consumer chains are unused - consumerStatus' = chains.mapBy(chain => UNUSED), - // no packets are outstanding - outstandingPacketsToProvider' = chains.mapBy(chain => List()), - outstandingPacketsToConsumer' = chains.mapBy(chain => List()), - // no maturations have been received by provider - receivedMaturations' = Set(), - // no packets have been sent to consumers - sentVSCPackets' = chains.mapBy(chain => Set()), - // no packets have been received by consumers, so no maturation times set - maturationTimes' = chains.mapBy(chain => Map()), - // validator set was not changed yet - providerValidatorSetChangedInThisBlock' = false - } + // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, + // e.g. via undelegations, or delegations, ... + pure def votingPowerChange(currentState: ProtocolState, validator: Node, amount: int): Result = + // adjust the current validator set on the provider - it is not entered in the voting history yet because that happens only on block end + val currentValidatorSet = currentState.providerState.currentValidatorSet + // val newValidatorSet = getUpdatedValidatorSet(currentValidatorSet, validator, amount) + // val newProviderState = currentState.providerState.with( + // "currentValidatorSet", newValidatorSet + // ) + // val newState = currentState.with( + // "providerState", newProviderState + // ) + Err("not implemented") +} - // PROPERTIES - - // Every validator set on any consumer chain MUST either be or - // have been a validator set on the provider chain. - val ValidatorSetReplication: bool = - chains.forall( - chain => chain.getCurrentValidatorSet().wasValidatorSetOnProvider() - ) - - // TESTS - run VSCHappyPathTest: bool = { - init - // trigger a votingPowerChange on the provider chain - .then(votingPowerChange("A", 10)) - // endAndBeginBlock on provider. No consumer chains are running, so no packets are sent - .then(endAndBeginBlock(ProviderChain)) - .then(all { - // no packet was sent - assert(outstandingPacketsToConsumer.get("chain1").length() == 0), - // advance chain1 to running - AdvanceConsumers(NoStatusAdvancement.set("chain1", true)) - }) - // consumer chain should have current validator set from provider - .then( - all { - // since consumer chain just started, its assumed to have the validator set from provider - assert(runningValidatorSet.get("chain1") == runningValidatorSet.get(ProviderChain)), - // trigger a votingPowerChange on the provider chain - votingPowerChange("B", 10) - } - ) - .then( - val valSet = runningValidatorSet.get(ProviderChain) - endAndBeginBlock(ProviderChain) - // now the provider should send a packet on block end - .then(all { - // a packet was sent - assert(outstandingPacketsToConsumer.get("chain1").length() == 1), - // deliver the packet to the consumer - recvPacketOnConsumer("chain1") - }) - .then( - // consumer needs to end a block before it has the new validator set - endAndBeginBlock("chain1") - ) - .then(all { - // the consumer should have the new validator set - assert(runningValidatorSet.get("chain1") == valSet), - // put a last action to satisfy the action effect - AdvanceConsumers(NoStatusAdvancement) - }) - ) - } +module ccv_tests { + import ccv_logic.* + + // // UTILITY FUNCTIONS & ACTIONS + // def wasValidatorSetOnProvider(validatorSet: ValidatorSet): bool = { + // votingPowerHistories.get(ProviderChain).toSet().exists( + // historicalValSet => historicalValSet == validatorSet + // ) + // } + + // def getCurrentValidatorSet(chain: Chain): ValidatorSet = + // votingPowerHistories.get(chain).head() + + // // returns true if the consumer has timed out and should be dropped + // def consumerTimedOut(consumer: Chain): bool = + // any { + // // either a package from provider to consumer has timed out + // outstandingPacketsToConsumer.get(consumer).select( + // packet => packet.timeout <= curChainTimes.get(consumer) + // ).length() > 0, + // // or a package from consumer to provider has timed out + // outstandingPacketsToProvider.get(consumer).select( + // packet => packet.timeout <= curChainTimes.get(ProviderChain) + // ).length() > 0, + // // or the inactivity timeout has passed since a VSCPacket was sent to the consumer, but the + // // provider has not received a VSCMaturedPacket for it + // val packetsWithoutResponse = sentVSCPackets.get(consumer).filter( // get packets without response + // packet => + // not(receivedMaturations.exists( + // maturedPacket => maturedPacket.id == packet.id + // )) + // ) + // // among those, get packets where inactivity timeout has passed + // packetsWithoutResponse.filter( + // packet => + // val sentAt = curChainTimes.get(ProviderChain) - PacketTimeout // compute when the packet was sent + // val timesOutAt = sentAt + InactivityTimeout // compute when the packet times out + // timesOutAt <= curChainTimes.get(ProviderChain) + // ).size() > 0 + // } + + // // utility action that leaves all provider state untouched + // action PROVIDER_NOOP(): bool = + // all { + // receivedMaturations' = receivedMaturations, + // } + + // // utility action that leaves all consumer state untouched + // action CONSUMER_NOOP(): bool = + // all { + // maturationTimes' = maturationTimes, + // } + + // // MODEL ACTIONS + + // // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, + // // e.g. via undelegations, or delegations, ... + // action doVotingPowerChange(validator: Node, amount: int): bool = + // // for the provider chain, we need to adjust the voting power history + // // by adding a new set + // all { + // amount >= 0, + // val newValidatorSet = getCurrentValidatorSet(ProviderChain).getUpdatedValidatorSet(validator, amount) + // // set the running validator set on the provider chain, but don't update the history yet + // runningValidatorSet' = runningValidatorSet.set(ProviderChain, newValidatorSet), + // // no packets are sent yet, these are only sent on endAndBeginBlock + // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + // outstandingPacketsToProvider' = outstandingPacketsToProvider, + // receivedMaturations' = receivedMaturations, + // CONSUMER_NOOP, + // // voting power history is only updated on endAndBeginBlock + // votingPowerHistories' = votingPowerHistories, + // // consumer statusses do not change + // consumerStatus' = consumerStatus, + // // chain times do not change + // curChainTimes' = curChainTimes, + // // the validator set is considered to have changed + // providerValidatorSetChangedInThisBlock' = true, + // } + + // // deliver the next outstanding packet from the consumer to the provider. + // // since this model assumes a single provider chain, this just takes a single chain as argument. + // action recvPacketOnProvider(consumer: Chain): bool = all { + // // ensure there is a packet to be received + // outstandingPacketsToProvider.get(consumer).length() > 0, + // // remove packet from outstanding packets + // val newPacketQueue = outstandingPacketsToProvider.get(consumer).tail() + // outstandingPacketsToProvider' = outstandingPacketsToProvider.set(consumer, newPacketQueue), + // // register the packet as received + // val maturedPacket = outstandingPacketsToProvider.get(consumer).head() + // receivedMaturations' = receivedMaturations.add(maturedPacket), + // CONSUMER_NOOP, + // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + // votingPowerHistories' = votingPowerHistories, + // // no validator set changes are made + // runningValidatorSet' = runningValidatorSet, + // // consumer statusses do not change + // consumerStatus' = consumerStatus, + // // chain times do not change + // curChainTimes' = curChainTimes, + // // the validator set was not changed by this action (but might have been changed before in this block) + // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + // } + + // // deliver the next outstanding packet from the provider to the consumer. + // // since this model assumes a single provider chain, this just takes a single chain as argument. + // action recvPacketOnConsumer(consumer: Chain): bool = all { + // // ensure there is a packet to be received + // outstandingPacketsToConsumer.get(consumer).length() > 0, + // // remove packet from outstanding packets + // val newPacketQueue = outstandingPacketsToConsumer.get(consumer).tail() + // val newOutstandingPackets = outstandingPacketsToConsumer.set(consumer, newPacketQueue) + // RegisterNewOutstandingPackets(newOutstandingPackets), + // val packet = outstandingPacketsToConsumer.get(consumer).head() + // all { + // // update the running validator set, but not the history yet, + // // as that only happens when the next block is started + // runningValidatorSet' = runningValidatorSet.set(consumer, packet.validatorSet), + // // add the new packet and store its maturation time + // val newMaturationTimes = maturationTimes.get(consumer).put(packet, curChainTimes.get(consumer) + UnbondingPeriod.get(consumer)) + // maturationTimes' = maturationTimes.set(consumer, newMaturationTimes) + // }, + // PROVIDER_NOOP, + // votingPowerHistories' = votingPowerHistories, + // outstandingPacketsToProvider' = outstandingPacketsToProvider, + // // consumer statusses do not change + // consumerStatus' = consumerStatus, + // // chain times do not change + // curChainTimes' = curChainTimes, + // // the validator set was not changed by this action (but might have been changed before in this block) + // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + // } + + // // ends the current block and starts the next block for a given chain. + // action endAndBeginBlock(chain: Chain): bool = any { + // all { + // chain == ProviderChain, + // endAndBeginBlockForProvider, + // }, + // all { + // chain != ProviderChain, + // endAndBeginBlockForConsumer(chain), + // } + // } + + // // gets the updated history for the current chain when ending a block, i.e. the + // // running validator set is added to the history if different from the last one. + // def getUpdatedHistory(chain: Chain): List[ValidatorSet] = + // // update voting power history if the validator set changed + // val newValidatorSet = runningValidatorSet.get(ProviderChain) + // val oldValidatorSet = votingPowerHistories.get(ProviderChain).head() + // if (newValidatorSet != oldValidatorSet) + // votingPowerHistories.get(ProviderChain).prepend(newValidatorSet) + // else + // votingPowerHistories.get(ProviderChain) + + + // action endAndBeginBlockForProvider(): bool = all { + // // update the voting power history + // votingPowerHistories' = votingPowerHistories.set(ProviderChain, getUpdatedHistory(ProviderChain)), + // // the running validator set is now for sure the current validator set, + // // so start with it in the next block + // runningValidatorSet' = runningValidatorSet, + // // send VSCPackets to consumers + // val newOutstandingPackets = + // // if running validator set is considered to have changed + // if (providerValidatorSetChangedInThisBlock) + // // then send a packet to each running consumer + // outstandingPacketsToConsumer.keys().mapBy( + // (consumer) => + // val packetQueue = outstandingPacketsToConsumer.get(consumer) + // if (consumerStatus.get(consumer) == RUNNING) { + // packetQueue.append( + // { + // id: packetQueue.length(), + // validatorSet: runningValidatorSet.get(ProviderChain), + // timeout: curChainTimes.get(ProviderChain) + PacketTimeout + // } + // ) + // } else { + // packetQueue + // } + // ) + // else + // // otherwise, don't send any packets + // outstandingPacketsToConsumer + // RegisterNewOutstandingPackets(newOutstandingPackets), + // CONSUMER_NOOP, + // // no packets are sent to the provider + // outstandingPacketsToProvider' = outstandingPacketsToProvider, + // // do not receive any maturations + // receivedMaturations' = receivedMaturations, + // // consumer statusses do not change + // consumerStatus' = consumerStatus, + // // chain times do not change + // curChainTimes' = curChainTimes, + // // the validator set was definitely not changed in the new block yet, so set to false + // providerValidatorSetChangedInThisBlock' = false + // } + + // action endAndBeginBlockForConsumer(consumer: Chain): bool = all { + // ConsumerChains.contains(consumer), + // // update the voting power history + // votingPowerHistories' = votingPowerHistories.set(consumer, getUpdatedHistory(consumer)), + // // the running validator set is now for sure the current validator set, + // // so start with it in the next block + // runningValidatorSet' = runningValidatorSet, + // // compute mature packets whose maturation time has passed + // val maturedPackets = maturationTimes.get(consumer).keys().filter( + // packet => + // val maturationTime = maturationTimes.get(consumer).get(packet) + // maturationTime <= curChainTimes.get(consumer) + // ) + // all { + // // remove matured packets from the maturation times + // maturationTimes' = maturationTimes.set(consumer, maturationTimes.get(consumer).mapRemoveAll(maturedPackets)), + // // send matured packets + // outstandingPacketsToProvider' = outstandingPacketsToProvider.set( + // consumer, + // // construct VSCMaturedPackets from the matured VSCPackets + // outstandingPacketsToProvider.get(consumer).concat( + // maturedPackets.map(packet => {id: packet.id, timeout: 5}).toList() + // ) + // ) + // }, + // PROVIDER_NOOP, + // // no packets are sent to consumer or received by it + // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + // // consumer statusses do not change + // consumerStatus' = consumerStatus, + // // chain times do not change + // curChainTimes' = curChainTimes, + // // the validator set was not changed by this action (but might have been changed before in this block) + // // also, this is only a new block for a consumer, so the change variable shouldn't be reset + // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + // } + + // // advance timestamps for maps nondeterministically + // action AdvanceTime(): bool = + // val advanceAmounts = curChainTimes.keys().mapBy( + // chain => + // nondet amount = oneOf(1.to(10)) + // amount + // ) + // AdvanceTimeByMap(advanceAmounts) + + // // the timestamp for each chain is advanced by the given amount + // action AdvanceTimeByMap(advancementAmount: Chain -> int): bool = all + // { + // curChainTimes' = curChainTimes.keys().mapBy( + // chain => + // curChainTimes.get(chain) + advancementAmount.get(chain) + // ), + // // all other variables are left untouched + // votingPowerHistories' = votingPowerHistories, + // runningValidatorSet' = runningValidatorSet, + // outstandingPacketsToProvider' = outstandingPacketsToProvider, + // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + // receivedMaturations' = receivedMaturations, + // maturationTimes' = maturationTimes, + // // chain times do not change + // consumerStatus' = consumerStatus, + // // the validator set was not changed by this action (but might have been changed before in this block) + // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + // } + + // // each consumer chain may advance in the order + // // some events may necessitate a transition, e.g. timeouts. + // // shouldAdvance gives, for each consumer chain, whether it should advance if possible. + // // if a chain has to advance, e.g. due to timeouts, or may not advance, the value will have no effect. + // action AdvanceConsumers(shouldAdvance: Chain -> bool): bool = + // val newConsumerStatus = consumerStatus.keys().mapBy( + // chain => + // val curStatus = consumerStatus.get(chain) + // if (curStatus == UNUSED) { + // if (shouldAdvance.get(chain)) + // { + // RUNNING + // } else { + // UNUSED + // } + // } + // else if (curStatus == RUNNING) { + // // the chain may transition to stopped. + // // it is *forced* to stop if a packet timed out, + // // or if the inactivity timeout has passed + // if(consumerTimedOut(chain)) { + // STOPPED + // } else { + // if (shouldAdvance.get(chain)) { + // RUNNING + // } else { + // STOPPED + // } + // } + // } else { + // // stopped chains cannot restart, we assume a new chain would be started in that case + // STOPPED + // } + // ) + // all { + // consumerStatus' = newConsumerStatus, + // // all other variables are left untouched + // votingPowerHistories' = votingPowerHistories, + // runningValidatorSet' = runningValidatorSet.keys().mapBy( + // chain => + // if (newConsumerStatus.get(chain) == RUNNING and consumerStatus.get(chain) == UNUSED) + // // consumers that went from unused to running start with the current validator set on the provider + // { + // runningValidatorSet.get(ProviderChain) + // } else { + // runningValidatorSet.get(chain) + // } + // ), + // outstandingPacketsToProvider' = outstandingPacketsToProvider, + // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + // receivedMaturations' = receivedMaturations, + // maturationTimes' = maturationTimes, + // // chain times do not change + // curChainTimes' = curChainTimes, + // // the validator set was not changed by this action (but might have been changed before in this block) + // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + // } + + // // Updates the outstandingPacketsToConsumer and sentVSCPackets variables + // action RegisterNewOutstandingPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = + // all { + // outstandingPacketsToConsumer' = newOutstandingPackets, + // StoreSentPackets(newOutstandingPackets), + // } + + + // // stores the VSCPackets sent in this step in sentVSCPackets + // action StoreSentPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = + // sentVSCPackets' = sentVSCPackets.keys().mapBy( + // (chain) => + // sentVSCPackets.get(chain).union(newOutstandingPackets.get(chain).toSet()) + // ) + + // // the main step action + // action step: bool = any { + // AdvanceTime, + // nondet node = oneOf(Nodes) + // nondet amount = oneOf(1.to(10)) + // votingPowerChange(node, amount), + // recvPacketOnProvider(oneOf(ConsumerChains)), + // recvPacketOnConsumer(oneOf(ConsumerChains)), + // nondet chain = oneOf(chains) + // endAndBeginBlock(chain), + // val shouldAdvance = ConsumerChains.mapBy( + // chain => + // nondet should = oneOf(Set(true, false)) + // should + // ) + // AdvanceConsumers(shouldAdvance), + // } + + // pure val nodePowerSet = Nodes.powerset() + + // def getArbitraryValidatorSet(): ValidatorSet = + // nondet numValidators = oneOf(1.to(Nodes.size())) + // // toList has nondeterministic behaviour, so this gets arbitrary validators + // nondet validators = oneOf(nodePowerSet.filter(s => s.size() == numValidators)) + // validators.mapBy( + // validator => + // nondet votingPower = oneOf(1.to(10)) + // votingPower + // ) + + // // INITIALIZATION + // action init: bool = + // all { + // val validatorSets = chains.mapBy( + // (chain) => + // // provider chain gets an arbitrary validator set, consumer chains have none + // if (chain == ProviderChain) getArbitraryValidatorSet else Map() + // ) + // all { + // votingPowerHistories' = chains.mapBy( + // (chain) => + // List(validatorSets.get(chain)) + // ), + // runningValidatorSet' = validatorSets, + // }, + // // each chain starts at time 0 + // curChainTimes' = chains.mapBy( + // (chain) => 0 + // ), + // // all consumer chains are unused + // consumerStatus' = chains.mapBy(chain => UNUSED), + // // no packets are outstanding + // outstandingPacketsToProvider' = chains.mapBy(chain => List()), + // outstandingPacketsToConsumer' = chains.mapBy(chain => List()), + // // no maturations have been received by provider + // receivedMaturations' = Set(), + // // no packets have been sent to consumers + // sentVSCPackets' = chains.mapBy(chain => Set()), + // // no packets have been received by consumers, so no maturation times set + // maturationTimes' = chains.mapBy(chain => Map()), + // // validator set was not changed yet + // providerValidatorSetChangedInThisBlock' = false + // } + + // // PROPERTIES + + // // Every validator set on any consumer chain MUST either be or + // // have been a validator set on the provider chain. + // val ValidatorSetReplication: bool = + // chains.forall( + // chain => chain.getCurrentValidatorSet().wasValidatorSetOnProvider() + // ) + + // // TESTS + // run VSCHappyPathTest: bool = { + // init + // // trigger a votingPowerChange on the provider chain + // .then(votingPowerChange("A", 10)) + // // endAndBeginBlock on provider. No consumer chains are running, so no packets are sent + // .then(endAndBeginBlock(ProviderChain)) + // .then(all { + // // no packet was sent + // assert(outstandingPacketsToConsumer.get("chain1").length() == 0), + // // advance chain1 to running + // AdvanceConsumers(NoStatusAdvancement.set("chain1", true)) + // }) + // // consumer chain should have current validator set from provider + // .then( + // all { + // // since consumer chain just started, its assumed to have the validator set from provider + // assert(runningValidatorSet.get("chain1") == runningValidatorSet.get(ProviderChain)), + // // trigger a votingPowerChange on the provider chain + // votingPowerChange("B", 10) + // } + // ) + // .then( + // val valSet = runningValidatorSet.get(ProviderChain) + // endAndBeginBlock(ProviderChain) + // // now the provider should send a packet on block end + // .then(all { + // // a packet was sent + // assert(outstandingPacketsToConsumer.get("chain1").length() == 1), + // // deliver the packet to the consumer + // recvPacketOnConsumer("chain1") + // }) + // .then( + // // consumer needs to end a block before it has the new validator set + // endAndBeginBlock("chain1") + // ) + // .then(all { + // // the consumer should have the new validator set + // assert(runningValidatorSet.get("chain1") == valSet), + // // put a last action to satisfy the action effect + // AdvanceConsumers(NoStatusAdvancement) + // }) + // ) + // } + + // // utility: the set of consumers currently running + // val RunningConsumers: Set[Chain] = + // ConsumerChains.filter(chain => consumerStatus.get(chain) == RUNNING) + + // // MODEL STATE + // // --SHARED STATE + + // // Stores, for each chain, the list of voting powers that corresponded to voting powers + // // at blocks over its entire existence. + // // Voting powers should be ordered by recency in descending order. + // var votingPowerHistories: Chain -> List[ValidatorSet] + + // // the current validator set on each chain. + // // this will be included in the next block, but might not be final yet, + // // e.g. there may be more modifications in the current block. + // var runningValidatorSet: Chain -> ValidatorSet + + // // the current timestamp for each chain + // var curChainTimes: Chain -> Timestamp + + // // stores, for each chain, its current status - + // // unused, running, or stopped + // var consumerStatus: Chain -> str + + // // --CHANNELS + // // Stores, for each consumer chain, the list of packets that have been sent to the provider chain + // // and have not been received yet. + // var outstandingPacketsToProvider: Chain -> List[VSCMaturedPacket] + + // // Stores, for each consumer chain, the list of packets that have been sent to the consumer chain + // // and have not been received yet. + // var outstandingPacketsToConsumer: Chain -> List[VSCPacket] + + + // // --CONSUMER STATE + // // Stores the maturation times for VSCPackets received by consumers + // var maturationTimes: Chain -> (VSCPacket -> Timestamp) + + // // --PROVIDER STATE + // // the set of VSCMaturedPackets received by the provider chain + // var receivedMaturations: Set[VSCMaturedPacket] + + // // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness + // var sentVSCPackets: Chain -> Set[VSCPacket] + + // // stores whether, in this step, the validator set considered to be changed. + // // this is needed because the validator set might be considered to have changed, even though + // // it is still technically identical at our level of abstraction, e.g. a validator power change on the provider + // // might leave the validator set the same because a delegation and undelegation cancel each other out. + // var providerValidatorSetChangedInThisBlock: bool + + // // utility: a struct summarizing the current state + // val state = + // { + // votingPowerHistories: votingPowerHistories, + // runningValidatorSet: runningValidatorSet, + // curChainTimes: curChainTimes, + // consumerStatus: consumerStatus, + // outstandingPacketsToProvider: outstandingPacketsToProvider, + // outstandingPacketsToConsumer: outstandingPacketsToConsumer, + // maturationTimes: maturationTimes, + // receivedMaturations: receivedMaturations, + // sentVSCPackets: sentVSCPackets, + // } + + // // set of identifiers of potential nodes + // pure val Nodes: Set[Node] = + // Set("A", "B", "C", "D", "E", "F", "G", "H", "I", "J") + + // // the set of consumer chains + // pure val ConsumerChains: Set[Chain] = + // Set("chain1", "chain2", "chain3") + + // // The singular provider chain. + // pure val ProviderChain: Chain = + // "provider" + + // pure val chains = ConsumerChains.union(Set(ProviderChain)) + + // // length of the unbonding period on each chain + // pure val UnbondingPeriod: Chain -> int = chains.mapBy( + // (chain) => + // 10 + // ) + + // // the time until a packet times out + // pure val PacketTimeout: int = + // 5 + + // // the time until a consumer chain is dropped by the provider due to inactivity + // pure val InactivityTimeout: int = + // 10 + + // // utility: a map assigning each chain to 0, used for not advancing timestamps + // pure val NoTimeAdvancement: Chain -> int = chains.mapBy( + // (chain) => + // 0 + // ) + + + // // utility: a map assigning each chain to false, used for not advancing consumer status + // pure val NoStatusAdvancement: Chain -> bool = chains.mapBy( + // (chain) => + // false + // ) } diff --git a/tests/difference/core/quint_model/extraSpells.qnt b/tests/difference/core/quint_model/extraSpells.qnt index cd2105beb7..5c98f7a384 100644 --- a/tests/difference/core/quint_model/extraSpells.qnt +++ b/tests/difference/core/quint_model/extraSpells.qnt @@ -1,4 +1,3 @@ --*- mode: Bluespec; -*- // This module is just a library with utility functions (sometimes called spells in Quint). module extraSpells { diff --git a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123337-6230.fail b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123337-6230.fail new file mode 100644 index 0000000000..f2c09a9e15 --- /dev/null +++ b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123337-6230.fail @@ -0,0 +1,18 @@ +# 2023/09/12 12:33:37 TestActionMarshalling [rapid] draw Action: main.StartChainAction{Chain:"", Validators:[]main.StartChainValidator{}, GenesisChanges:"", SkipGentx:false} +# 2023/09/12 12:33:37 TestActionMarshalling error marshalling and unmarshalling chain state: any( +# - main.StartChainAction{Validators: []main.StartChainValidator{}}, +# + map[string]any{ +# + "Chain": string(""), +# + "GenesisChanges": string(""), +# + "SkipGentx": bool(false), +# + "Validators": []any{}, +# + }, +# ) +# +v0.4.8#6863100771198181688 +0x0 +0x1 +0x0 +0x0 +0x0 +0x0 \ No newline at end of file diff --git a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123517-6794.fail b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123517-6794.fail new file mode 100644 index 0000000000..9547963143 --- /dev/null +++ b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123517-6794.fail @@ -0,0 +1,14 @@ +# 2023/09/12 12:35:17 TestActionMarshalling [rapid] draw Action: main.SendTokensAction{Chain:"", From:"", To:"", Amount:0x0} +# 2023/09/12 12:35:17 TestActionMarshalling error marshalling and unmarshalling action: got (+), want (-):   any( +# -  main.SendTokensAction{}, +# +  map[string]any{"Amount": float64(0), "Chain": string(""), "From": string(""), "To": string("")}, +#   ) +# +v0.4.8#14250065908211800578 +0x0 +0x0 +0x0 +0x0 +0x0 +0x0 +0x0 \ No newline at end of file diff --git a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123556-6970.fail b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123556-6970.fail new file mode 100644 index 0000000000..4ddf365f5c --- /dev/null +++ b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123556-6970.fail @@ -0,0 +1,14 @@ +# 2023/09/12 12:35:56 TestActionMarshalling [rapid] draw Action: main.SendTokensAction{Chain:"", From:"", To:"", Amount:0x0} +# 2023/09/12 12:35:56 TestActionMarshalling error marshalling and unmarshalling action: got (-), want (+):   any( +# -  main.SendTokensAction{}, +# +  map[string]any{"Amount": float64(0), "Chain": string(""), "From": string(""), "To": string("")}, +#   ) +# +v0.4.8#9176735344445930654 +0x0 +0x0 +0x0 +0x0 +0x0 +0x0 +0x0 \ No newline at end of file diff --git a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123609-7116.fail b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123609-7116.fail new file mode 100644 index 0000000000..89dcbcc8b2 --- /dev/null +++ b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123609-7116.fail @@ -0,0 +1,18 @@ +# 2023/09/12 12:36:09 TestActionMarshalling [rapid] draw Action: main.StartChainAction{Chain:"", Validators:[]main.StartChainValidator{}, GenesisChanges:"", SkipGentx:false} +# 2023/09/12 12:36:09 TestActionMarshalling error marshalling and unmarshalling action: got (-), want (+): any( +# - main.StartChainAction{Validators: []main.StartChainValidator{}}, +# + map[string]any{ +# + "Chain": string(""), +# + "GenesisChanges": string(""), +# + "SkipGentx": bool(false), +# + "Validators": []any{}, +# + }, +# ) +# +v0.4.8#17927886955469684979 +0x0 +0x1 +0x0 +0x0 +0x0 +0x0 \ No newline at end of file diff --git a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123822-8026.fail b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123822-8026.fail new file mode 100644 index 0000000000..d2493d87a3 --- /dev/null +++ b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123822-8026.fail @@ -0,0 +1,8 @@ +# 2023/09/12 12:38:22 TestActionMarshalling [rapid] draw Action: main.addChainToRelayerAction{Chain:"", Validator:""} +# 2023/09/12 12:38:22 TestActionMarshalling error marshalling and unmarshalling action: error unmarshalling action inside step: unknown action name: main.addChainToRelayerAction +# +v0.4.8#17613601115647214278 +0x9867f1f40f739 +0x9 +0x0 +0x0 \ No newline at end of file diff --git a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151826-12656.fail b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151826-12656.fail new file mode 100644 index 0000000000..10fd2ac639 --- /dev/null +++ b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151826-12656.fail @@ -0,0 +1,8 @@ +# 2023/09/13 15:18:26 TestActionMarshalling [rapid] draw Action: main.lightClientEquivocationAttackAction{Validator:"", Chain:""} +# 2023/09/13 15:18:26 TestActionMarshalling error marshalling and unmarshalling action: error unmarshalling action inside step: unknown action name: main.lightClientEquivocationAttackAction +# +v0.4.8#7694661539125204314 +0xc05c654ab866b +0x1f +0x0 +0x0 \ No newline at end of file diff --git a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151917-13146.fail b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151917-13146.fail new file mode 100644 index 0000000000..6fb9bfa9f7 --- /dev/null +++ b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151917-13146.fail @@ -0,0 +1,8 @@ +# 2023/09/13 15:19:17 TestActionMarshalling [rapid] draw Action: main.lightClientLunaticAttackAction{Validator:"", Chain:""} +# 2023/09/13 15:19:17 TestActionMarshalling error marshalling and unmarshalling action: error unmarshalling action inside step: unknown action name: main.lightClientLunaticAttackAction +# +v0.4.8#10796173543550944397 +0x1f2b5a0e61c3a6 +0x0 +0x0 +0x0 \ No newline at end of file diff --git a/tests/e2e/testdata/rapid/TestReadAndWriteTrace/TestReadAndWriteTrace-20230913151920-13146.fail b/tests/e2e/testdata/rapid/TestReadAndWriteTrace/TestReadAndWriteTrace-20230913151920-13146.fail new file mode 100644 index 0000000000..f8e2127feb --- /dev/null +++ b/tests/e2e/testdata/rapid/TestReadAndWriteTrace/TestReadAndWriteTrace-20230913151920-13146.fail @@ -0,0 +1,11 @@ +# 2023/09/13 15:19:20 TestReadAndWriteTrace [rapid] draw Trace: []main.Step{main.Step{Action:main.lightClientEquivocationAttackAction{Validator:"", Chain:""}, State:main.State{}}} +# 2023/09/13 15:19:20 TestReadAndWriteTrace error writing and reading trace: error reading trace from file: unknown action name: main.lightClientEquivocationAttackAction +# +v0.4.8#17668525343613541116 +0x5555555555555 +0xc05c654ab866b +0x1f +0x0 +0x0 +0x0 +0x0 \ No newline at end of file From 5fa449c8d8684b52146b2a765988ec44883b92a4 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 18 Sep 2023 18:23:42 +0200 Subject: [PATCH 12/80] Revert "Start rewriting model" This reverts commit 1320b9517982bff596ecfc0ac99755dc75c5f1e1. --- tests/difference/core/quint_model/ccv.qnt | 1241 ++++++++--------- .../core/quint_model/extraSpells.qnt | 1 + ...ActionMarshalling-20230912123337-6230.fail | 18 - ...ActionMarshalling-20230912123517-6794.fail | 14 - ...ActionMarshalling-20230912123556-6970.fail | 14 - ...ActionMarshalling-20230912123609-7116.fail | 18 - ...ActionMarshalling-20230912123822-8026.fail | 8 - ...ctionMarshalling-20230913151826-12656.fail | 8 - ...ctionMarshalling-20230913151917-13146.fail | 8 - ...eadAndWriteTrace-20230913151920-13146.fail | 11 - 10 files changed, 551 insertions(+), 790 deletions(-) delete mode 100644 tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123337-6230.fail delete mode 100644 tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123517-6794.fail delete mode 100644 tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123556-6970.fail delete mode 100644 tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123609-7116.fail delete mode 100644 tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123822-8026.fail delete mode 100644 tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151826-12656.fail delete mode 100644 tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151917-13146.fail delete mode 100644 tests/e2e/testdata/rapid/TestReadAndWriteTrace/TestReadAndWriteTrace-20230913151920-13146.fail diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 4cbc327ac4..d18930ae1d 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -1,4 +1,5 @@ -module ccv_logic { +-*- mode: Bluespec; -*- +module ccv { import extraSpells.* from "./extraSpells" // Things that are not modelled: @@ -11,17 +12,12 @@ module ccv_logic { // * VSC packets mature // * Consumers can be forcefully dropped due to timeouts, or stop on their own volition - // =================== // TYPE DEFINITIONS - // =================== type Node = str type Chain = str - type Power = int - type ValidatorSet = Node -> Power + type ValidatorSet = Node -> int type Height = int type Timestamp = int - // a list of validator sets per blocks, ordered by recency - type VotingPowerHistory = List[ValidatorSet] // --PACKETS type VSCPacket = @@ -42,719 +38,582 @@ module ccv_logic { timeout: Timestamp } - // possible consumer statuses - pure val STOPPED = "stopped" // the chain was once a consumer chain, but has been dropped by the provider. - pure val RUNNING = "running" // the chain is currently a consumer chain. Running chains are those that get sent VSCPackets. - pure val UNUSED = "unused" // the chain has never been a consumer chain, and is available to become one. - // When a chain is dropped, it cannot become a consumer again - we assume that would be done by another consumer becoming running. - - - // state that each chain needs to store, whether consumer or provider. - type ChainState = { - // Stores the list of voting powers that corresponded to voting powers - // at blocks over the chains entire existence. - // Voting powers should be ordered by recency in descending order. - votingPowerHistory: VotingPowerHistory, - - // the current validator set on each chain. - // this will be included in the next block, but might not be final yet, - // e.g. there may be more modifications in the current block. - currentValidatorSet: ValidatorSet, - - // the latest timestamp that was comitted on chain - lastTimestamp: Timestamp, - } + // MODEL PARAMETERS + + + // set of identifiers of potential nodes + pure val Nodes: Set[Node] = + Set("A", "B", "C", "D", "E", "F", "G", "H", "I", "J") + + // the set of consumer chains + pure val ConsumerChains: Set[Chain] = + Set("chain1", "chain2", "chain3") - // Defines the current state of the provider chain. Essentially, all information here is stored by the provider on-chain (or could be derived purely by information that is on-chain). - type ProviderState = + // The singular provider chain. + pure val ProviderChain: Chain = + "provider" + + pure val chains = ConsumerChains.union(Set(ProviderChain)) + + // length of the unbonding period on each chain + pure val UnbondingPeriod: Chain -> int = chains.mapBy( + (chain) => + 10 + ) + + // the time until a packet times out + pure val PacketTimeout: int = + 5 + + // the time until a consumer chain is dropped by the provider due to inactivity + pure val InactivityTimeout: int = + 10 + + // consumer statuses + pure val STOPPED = "stopped" + pure val RUNNING = "running" + pure val UNUSED = "unused" + + // utility: a map assigning each chain to 0, used for not advancing timestamps + pure val NoTimeAdvancement: Chain -> int = chains.mapBy( + (chain) => + 0 + ) + + // utility: a struct summarizing the current state + val state = { - // the state that each chain needs to store - chainState: ChainState, + votingPowerHistories: votingPowerHistories, + runningValidatorSet: runningValidatorSet, + curChainTimes: curChainTimes, + consumerStatus: consumerStatus, + outstandingPacketsToProvider: outstandingPacketsToProvider, + outstandingPacketsToConsumer: outstandingPacketsToConsumer, + maturationTimes: maturationTimes, + receivedMaturations: receivedMaturations, + sentVSCPackets: sentVSCPackets, + } + + + // utility: a map assigning each chain to false, used for not advancing consumer status + pure val NoStatusAdvancement: Chain -> bool = chains.mapBy( + (chain) => + false + ) + + // utility: the set of consumers currently running + val RunningConsumers: Set[Chain] = + ConsumerChains.filter(chain => consumerStatus.get(chain) == RUNNING) + + // MODEL STATE + // --SHARED STATE + + // Stores, for each chain, the list of voting powers that corresponded to voting powers + // at blocks over its entire existence. + // Voting powers should be ordered by recency in descending order. + var votingPowerHistories: Chain -> List[ValidatorSet] + + // the current validator set on each chain. + // this will be included in the next block, but might not be final yet, + // e.g. there may be more modifications in the current block. + var runningValidatorSet: Chain -> ValidatorSet + + // the current timestamp for each chain + var curChainTimes: Chain -> Timestamp + + // stores, for each chain, its current status - + // unused, running, or stopped + var consumerStatus: Chain -> str + + // --CHANNELS + // Stores, for each consumer chain, the list of packets that have been sent to the provider chain + // and have not been received yet. + var outstandingPacketsToProvider: Chain -> List[VSCMaturedPacket] - // Stores, for each consumer chain, the list of packets that have been sent to the consumer chain - // and have not been received yet. - // In the implementation, this would roughly be the unacknowledged packets on an ibc channel. - outstandingPacketsToConsumer: Chain -> List[VSCPacket], + // Stores, for each consumer chain, the list of packets that have been sent to the consumer chain + // and have not been received yet. + var outstandingPacketsToConsumer: Chain -> List[VSCPacket] - // the set of received VSCMaturedPackets - receivedMaturations: Set[VSCMaturedPacket], - // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness - sentVSCPackets: Chain -> Set[VSCPacket], + // --CONSUMER STATE + // Stores the maturation times for VSCPackets received by consumers + var maturationTimes: Chain -> (VSCPacket -> Timestamp) - // stores whether, in this block, the validator set has changed. - // this is needed because the validator set might be considered to have changed, even though - // it is still technically identical at our level of abstraction, e.g. a validator power change on the provider - // might leave the validator set the same because a delegation and undelegation cancel each other out. - providerValidatorSetChangedInThisBlock: bool, + // --PROVIDER STATE + // the set of VSCMaturedPackets received by the provider chain + var receivedMaturations: Set[VSCMaturedPacket] + + // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness + var sentVSCPackets: Chain -> Set[VSCPacket] + + // stores whether, in this step, the validator set considered to be changed. + // this is needed because the validator set might be considered to have changed, even though + // it is still technically identical at our level of abstraction, e.g. a validator power change on the provider + // might leave the validator set the same because a delegation and undelegation cancel each other out. + var providerValidatorSetChangedInThisBlock: bool + + + // UTILITY FUNCTIONS & ACTIONS + def wasValidatorSetOnProvider(validatorSet: ValidatorSet): bool = { + votingPowerHistories.get(ProviderChain).toSet().exists( + historicalValSet => historicalValSet == validatorSet + ) + } + + def getCurrentValidatorSet(chain: Chain): ValidatorSet = + votingPowerHistories.get(chain).head() + + def getUpdatedValidatorSet(oldValidatorSet: ValidatorSet, validator: Node, newVotingPower: int): ValidatorSet = + if (newVotingPower > 0) + oldValidatorSet.put(validator, newVotingPower) + else + oldValidatorSet.mapRemove(validator) + + // returns true if the consumer has timed out and should be dropped + def consumerTimedOut(consumer: Chain): bool = + any { + // either a package from provider to consumer has timed out + outstandingPacketsToConsumer.get(consumer).select( + packet => packet.timeout <= curChainTimes.get(consumer) + ).length() > 0, + // or a package from consumer to provider has timed out + outstandingPacketsToProvider.get(consumer).select( + packet => packet.timeout <= curChainTimes.get(ProviderChain) + ).length() > 0, + // or the inactivity timeout has passed since a VSCPacket was sent to the consumer, but the + // provider has not received a VSCMaturedPacket for it + val packetsWithoutResponse = sentVSCPackets.get(consumer).filter( // get packets without response + packet => + not(receivedMaturations.exists( + maturedPacket => maturedPacket.id == packet.id + )) + ) + // among those, get packets where inactivity timeout has passed + packetsWithoutResponse.filter( + packet => + val sentAt = curChainTimes.get(ProviderChain) - PacketTimeout // compute when the packet was sent + val timesOutAt = sentAt + InactivityTimeout // compute when the packet times out + timesOutAt <= curChainTimes.get(ProviderChain) + ).size() > 0 + } + + // utility action that leaves all provider state untouched + action PROVIDER_NOOP(): bool = + all { + receivedMaturations' = receivedMaturations, + } - // stores, for each consumer chain, its current status - - // unused, running, or stopped - consumerStatus: Chain -> str, + // utility action that leaves all consumer state untouched + action CONSUMER_NOOP(): bool = + all { + maturationTimes' = maturationTimes, } + - // Defines the current state of a consumer chain. This information is accessible to that consumer on-chain. - type ConsumerState = { - // the state that each chain needs to store - chainState: ChainState, + // MODEL ACTIONS - // Stores the maturation times for VSCPackets received by this consumer - maturationTimes: VSCPacket -> Timestamp, + // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, + // e.g. via undelegations, or delegations, ... + action votingPowerChange(validator: Node, amount: int): bool = + // for the provider chain, we need to adjust the voting power history + // by adding a new set + all { + amount >= 0, + val newValidatorSet = getCurrentValidatorSet(ProviderChain).getUpdatedValidatorSet(validator, amount) + // set the running validator set on the provider chain, but don't update the history yet + runningValidatorSet' = runningValidatorSet.set(ProviderChain, newValidatorSet), + // no packets are sent yet, these are only sent on endAndBeginBlock + RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + outstandingPacketsToProvider' = outstandingPacketsToProvider, + receivedMaturations' = receivedMaturations, + CONSUMER_NOOP, + // voting power history is only updated on endAndBeginBlock + votingPowerHistories' = votingPowerHistories, + // consumer statusses do not change + consumerStatus' = consumerStatus, + // chain times do not change + curChainTimes' = curChainTimes, + // the validator set is considered to have changed + providerValidatorSetChangedInThisBlock' = true, + } - // Stores the list of packets that have been sent to the provider chain by this consumer - // and have not been received yet. - // In the implementation, essentially unacknowledged IBC packets. - outstandingPacketsToProvider: Chain -> List[VSCMaturedPacket], + // deliver the next outstanding packet from the consumer to the provider. + // since this model assumes a single provider chain, this just takes a single chain as argument. + action recvPacketOnProvider(consumer: Chain): bool = all { + // ensure there is a packet to be received + outstandingPacketsToProvider.get(consumer).length() > 0, + // remove packet from outstanding packets + val newPacketQueue = outstandingPacketsToProvider.get(consumer).tail() + outstandingPacketsToProvider' = outstandingPacketsToProvider.set(consumer, newPacketQueue), + // register the packet as received + val maturedPacket = outstandingPacketsToProvider.get(consumer).head() + receivedMaturations' = receivedMaturations.add(maturedPacket), + CONSUMER_NOOP, + RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + votingPowerHistories' = votingPowerHistories, + // no validator set changes are made + runningValidatorSet' = runningValidatorSet, + // consumer statusses do not change + consumerStatus' = consumerStatus, + // chain times do not change + curChainTimes' = curChainTimes, + // the validator set was not changed by this action (but might have been changed before in this block) + providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + } - // Stores the list of voting powers that corresponded to voting powers - // at blocks over the chains entire existence. - // Voting powers should be ordered by recency in descending order. - votingPowerHistory: VotingPowerHistory, + // deliver the next outstanding packet from the provider to the consumer. + // since this model assumes a single provider chain, this just takes a single chain as argument. + action recvPacketOnConsumer(consumer: Chain): bool = all { + // ensure there is a packet to be received + outstandingPacketsToConsumer.get(consumer).length() > 0, + // remove packet from outstanding packets + val newPacketQueue = outstandingPacketsToConsumer.get(consumer).tail() + val newOutstandingPackets = outstandingPacketsToConsumer.set(consumer, newPacketQueue) + RegisterNewOutstandingPackets(newOutstandingPackets), + val packet = outstandingPacketsToConsumer.get(consumer).head() + all { + // update the running validator set, but not the history yet, + // as that only happens when the next block is started + runningValidatorSet' = runningValidatorSet.set(consumer, packet.validatorSet), + // add the new packet and store its maturation time + val newMaturationTimes = maturationTimes.get(consumer).put(packet, curChainTimes.get(consumer) + UnbondingPeriod.get(consumer)) + maturationTimes' = maturationTimes.set(consumer, newMaturationTimes) + }, + PROVIDER_NOOP, + votingPowerHistories' = votingPowerHistories, + outstandingPacketsToProvider' = outstandingPacketsToProvider, + // consumer statusses do not change + consumerStatus' = consumerStatus, + // chain times do not change + curChainTimes' = curChainTimes, + // the validator set was not changed by this action (but might have been changed before in this block) + providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock } - // the state of the protocol consists of the composition of the state of one provider chain with potentially many consumer chains. - type ProtocolState = { - providerState: ProviderState, - // the state of each consumer chain. - // note that we assume that this contains all consumer chains that may ever exist, - // and consumer chains that are currently not running will have providerState.consumerStatus == UNUSED or STOPPED - consumerStates: Set[ConsumerState] + // ends the current block and starts the next block for a given chain. + action endAndBeginBlock(chain: Chain): bool = any { + all { + chain == ProviderChain, + endAndBeginBlockForProvider, + }, + all { + chain != ProviderChain, + endAndBeginBlockForConsumer(chain), + } } - type Error = { - message: str + // gets the updated history for the current chain when ending a block, i.e. the + // running validator set is added to the history if different from the last one. + def getUpdatedHistory(chain: Chain): List[ValidatorSet] = + // update voting power history if the validator set changed + val newValidatorSet = runningValidatorSet.get(ProviderChain) + val oldValidatorSet = votingPowerHistories.get(ProviderChain).head() + if (newValidatorSet != oldValidatorSet) + votingPowerHistories.get(ProviderChain).prepend(newValidatorSet) + else + votingPowerHistories.get(ProviderChain) + + + action endAndBeginBlockForProvider(): bool = all { + // update the voting power history + votingPowerHistories' = votingPowerHistories.set(ProviderChain, getUpdatedHistory(ProviderChain)), + // the running validator set is now for sure the current validator set, + // so start with it in the next block + runningValidatorSet' = runningValidatorSet, + // send VSCPackets to consumers + val newOutstandingPackets = + // if running validator set is considered to have changed + if (providerValidatorSetChangedInThisBlock) + // then send a packet to each running consumer + outstandingPacketsToConsumer.keys().mapBy( + (consumer) => + val packetQueue = outstandingPacketsToConsumer.get(consumer) + if (consumerStatus.get(consumer) == RUNNING) { + packetQueue.append( + { + id: packetQueue.length(), + validatorSet: runningValidatorSet.get(ProviderChain), + timeout: curChainTimes.get(ProviderChain) + PacketTimeout + } + ) + } else { + packetQueue + } + ) + else + // otherwise, don't send any packets + outstandingPacketsToConsumer + RegisterNewOutstandingPackets(newOutstandingPackets), + CONSUMER_NOOP, + // no packets are sent to the provider + outstandingPacketsToProvider' = outstandingPacketsToProvider, + // do not receive any maturations + receivedMaturations' = receivedMaturations, + // consumer statusses do not change + consumerStatus' = consumerStatus, + // chain times do not change + curChainTimes' = curChainTimes, + // the validator set was definitely not changed in the new block yet, so set to false + providerValidatorSetChangedInThisBlock' = false } - // we return either a result or an error. - // if hasError is true, newState may be arbitrary, but the error will be meaningful. - // if hasError is false, error may be arbitrary, but newState will be meaningful. - type Result = { - hasError: bool, - newState: ProtocolState, - error: Error + action endAndBeginBlockForConsumer(consumer: Chain): bool = all { + ConsumerChains.contains(consumer), + // update the voting power history + votingPowerHistories' = votingPowerHistories.set(consumer, getUpdatedHistory(consumer)), + // the running validator set is now for sure the current validator set, + // so start with it in the next block + runningValidatorSet' = runningValidatorSet, + // compute mature packets whose maturation time has passed + val maturedPackets = maturationTimes.get(consumer).keys().filter( + packet => + val maturationTime = maturationTimes.get(consumer).get(packet) + maturationTime <= curChainTimes.get(consumer) + ) + all { + // remove matured packets from the maturation times + maturationTimes' = maturationTimes.set(consumer, maturationTimes.get(consumer).mapRemoveAll(maturedPackets)), + // send matured packets + outstandingPacketsToProvider' = outstandingPacketsToProvider.set( + consumer, + // construct VSCMaturedPackets from the matured VSCPackets + outstandingPacketsToProvider.get(consumer).concat( + maturedPackets.map(packet => {id: packet.id, timeout: 5}).toList() + ) + ) + }, + PROVIDER_NOOP, + // no packets are sent to consumer or received by it + RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + // consumer statusses do not change + consumerStatus' = consumerStatus, + // chain times do not change + curChainTimes' = curChainTimes, + // the validator set was not changed by this action (but might have been changed before in this block) + // also, this is only a new block for a consumer, so the change variable shouldn't be reset + providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock } - pure def Ok(newState: ProtocolState): Result = { + // advance timestamps for maps nondeterministically + action AdvanceTime(): bool = + val advanceAmounts = curChainTimes.keys().mapBy( + chain => + nondet amount = oneOf(1.to(10)) + amount + ) + AdvanceTimeByMap(advanceAmounts) + + // the timestamp for each chain is advanced by the given amount + action AdvanceTimeByMap(advancementAmount: Chain -> int): bool = all { - hasError: false, - newState: newState, - error: { - message: "" - } + curChainTimes' = curChainTimes.keys().mapBy( + chain => + curChainTimes.get(chain) + advancementAmount.get(chain) + ), + // all other variables are left untouched + votingPowerHistories' = votingPowerHistories, + runningValidatorSet' = runningValidatorSet, + outstandingPacketsToProvider' = outstandingPacketsToProvider, + RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + receivedMaturations' = receivedMaturations, + maturationTimes' = maturationTimes, + // chain times do not change + consumerStatus' = consumerStatus, + // the validator set was not changed by this action (but might have been changed before in this block) + providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock } - } - pure def Err(msg: str): Result = { - { - hasError: true, - newState: { - providerState: { - chainState: { - votingPowerHistory: List(), - currentValidatorSet: Map(), - lastTimestamp: 0 - }, - outstandingPacketsToConsumer: Map(), - receivedMaturations: Set(), - sentVSCPackets: Map(), - providerValidatorSetChangedInThisBlock: false, - consumerStatus: Map() - }, - consumerStates: Set() - }, - error: { - message: msg + // each consumer chain may advance in the order + // some events may necessitate a transition, e.g. timeouts. + // shouldAdvance gives, for each consumer chain, whether it should advance if possible. + // if a chain has to advance, e.g. due to timeouts, or may not advance, the value will have no effect. + action AdvanceConsumers(shouldAdvance: Chain -> bool): bool = + val newConsumerStatus = consumerStatus.keys().mapBy( + chain => + val curStatus = consumerStatus.get(chain) + if (curStatus == UNUSED) { + if (shouldAdvance.get(chain)) + { + RUNNING + } else { + UNUSED + } } + else if (curStatus == RUNNING) { + // the chain may transition to stopped. + // it is *forced* to stop if a packet timed out, + // or if the inactivity timeout has passed + if(consumerTimedOut(chain)) { + STOPPED + } else { + if (shouldAdvance.get(chain)) { + RUNNING + } else { + STOPPED + } + } + } else { + // stopped chains cannot restart, we assume a new chain would be started in that case + STOPPED + } + ) + all { + consumerStatus' = newConsumerStatus, + // all other variables are left untouched + votingPowerHistories' = votingPowerHistories, + runningValidatorSet' = runningValidatorSet.keys().mapBy( + chain => + if (newConsumerStatus.get(chain) == RUNNING and consumerStatus.get(chain) == UNUSED) + // consumers that went from unused to running start with the current validator set on the provider + { + runningValidatorSet.get(ProviderChain) + } else { + runningValidatorSet.get(chain) + } + ), + outstandingPacketsToProvider' = outstandingPacketsToProvider, + RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + receivedMaturations' = receivedMaturations, + maturationTimes' = maturationTimes, + // chain times do not change + curChainTimes' = curChainTimes, + // the validator set was not changed by this action (but might have been changed before in this block) + providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock } - } - // =================== - // PROTOCOL LOGIC - // =================== + // Updates the outstandingPacketsToConsumer and sentVSCPackets variables + action RegisterNewOutstandingPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = + all { + outstandingPacketsToConsumer' = newOutstandingPackets, + StoreSentPackets(newOutstandingPackets), + } - pure def getUpdatedValidatorSet(oldValidatorSet: ValidatorSet, validator: Node, newVotingPower: int): ValidatorSet = - if (newVotingPower > 0) - oldValidatorSet.put(validator, newVotingPower) - else - oldValidatorSet.mapRemove(validator) - - // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, - // e.g. via undelegations, or delegations, ... - pure def votingPowerChange(currentState: ProtocolState, validator: Node, amount: int): Result = - // adjust the current validator set on the provider - it is not entered in the voting history yet because that happens only on block end - val currentValidatorSet = currentState.providerState.currentValidatorSet - // val newValidatorSet = getUpdatedValidatorSet(currentValidatorSet, validator, amount) - // val newProviderState = currentState.providerState.with( - // "currentValidatorSet", newValidatorSet - // ) - // val newState = currentState.with( - // "providerState", newProviderState - // ) - Err("not implemented") -} -module ccv_tests { - import ccv_logic.* - - // // UTILITY FUNCTIONS & ACTIONS - // def wasValidatorSetOnProvider(validatorSet: ValidatorSet): bool = { - // votingPowerHistories.get(ProviderChain).toSet().exists( - // historicalValSet => historicalValSet == validatorSet - // ) - // } - - // def getCurrentValidatorSet(chain: Chain): ValidatorSet = - // votingPowerHistories.get(chain).head() - - // // returns true if the consumer has timed out and should be dropped - // def consumerTimedOut(consumer: Chain): bool = - // any { - // // either a package from provider to consumer has timed out - // outstandingPacketsToConsumer.get(consumer).select( - // packet => packet.timeout <= curChainTimes.get(consumer) - // ).length() > 0, - // // or a package from consumer to provider has timed out - // outstandingPacketsToProvider.get(consumer).select( - // packet => packet.timeout <= curChainTimes.get(ProviderChain) - // ).length() > 0, - // // or the inactivity timeout has passed since a VSCPacket was sent to the consumer, but the - // // provider has not received a VSCMaturedPacket for it - // val packetsWithoutResponse = sentVSCPackets.get(consumer).filter( // get packets without response - // packet => - // not(receivedMaturations.exists( - // maturedPacket => maturedPacket.id == packet.id - // )) - // ) - // // among those, get packets where inactivity timeout has passed - // packetsWithoutResponse.filter( - // packet => - // val sentAt = curChainTimes.get(ProviderChain) - PacketTimeout // compute when the packet was sent - // val timesOutAt = sentAt + InactivityTimeout // compute when the packet times out - // timesOutAt <= curChainTimes.get(ProviderChain) - // ).size() > 0 - // } - - // // utility action that leaves all provider state untouched - // action PROVIDER_NOOP(): bool = - // all { - // receivedMaturations' = receivedMaturations, - // } - - // // utility action that leaves all consumer state untouched - // action CONSUMER_NOOP(): bool = - // all { - // maturationTimes' = maturationTimes, - // } + // stores the VSCPackets sent in this step in sentVSCPackets + action StoreSentPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = + sentVSCPackets' = sentVSCPackets.keys().mapBy( + (chain) => + sentVSCPackets.get(chain).union(newOutstandingPackets.get(chain).toSet()) + ) + + // the main step action + action step: bool = any { + AdvanceTime, + nondet node = oneOf(Nodes) + nondet amount = oneOf(1.to(10)) + votingPowerChange(node, amount), + recvPacketOnProvider(oneOf(ConsumerChains)), + recvPacketOnConsumer(oneOf(ConsumerChains)), + nondet chain = oneOf(chains) + endAndBeginBlock(chain), + val shouldAdvance = ConsumerChains.mapBy( + chain => + nondet should = oneOf(Set(true, false)) + should + ) + AdvanceConsumers(shouldAdvance), + } + + pure val nodePowerSet = Nodes.powerset() + + def getArbitraryValidatorSet(): ValidatorSet = + nondet numValidators = oneOf(1.to(Nodes.size())) + // toList has nondeterministic behaviour, so this gets arbitrary validators + nondet validators = oneOf(nodePowerSet.filter(s => s.size() == numValidators)) + validators.mapBy( + validator => + nondet votingPower = oneOf(1.to(10)) + votingPower + ) + + // INITIALIZATION + action init: bool = + all { + val validatorSets = chains.mapBy( + (chain) => + // provider chain gets an arbitrary validator set, consumer chains have none + if (chain == ProviderChain) getArbitraryValidatorSet else Map() + ) + all { + votingPowerHistories' = chains.mapBy( + (chain) => + List(validatorSets.get(chain)) + ), + runningValidatorSet' = validatorSets, + }, + // each chain starts at time 0 + curChainTimes' = chains.mapBy( + (chain) => 0 + ), + // all consumer chains are unused + consumerStatus' = chains.mapBy(chain => UNUSED), + // no packets are outstanding + outstandingPacketsToProvider' = chains.mapBy(chain => List()), + outstandingPacketsToConsumer' = chains.mapBy(chain => List()), + // no maturations have been received by provider + receivedMaturations' = Set(), + // no packets have been sent to consumers + sentVSCPackets' = chains.mapBy(chain => Set()), + // no packets have been received by consumers, so no maturation times set + maturationTimes' = chains.mapBy(chain => Map()), + // validator set was not changed yet + providerValidatorSetChangedInThisBlock' = false + } + + // PROPERTIES + + // Every validator set on any consumer chain MUST either be or + // have been a validator set on the provider chain. + val ValidatorSetReplication: bool = + chains.forall( + chain => chain.getCurrentValidatorSet().wasValidatorSetOnProvider() + ) + + // TESTS + run VSCHappyPathTest: bool = { + init + // trigger a votingPowerChange on the provider chain + .then(votingPowerChange("A", 10)) + // endAndBeginBlock on provider. No consumer chains are running, so no packets are sent + .then(endAndBeginBlock(ProviderChain)) + .then(all { + // no packet was sent + assert(outstandingPacketsToConsumer.get("chain1").length() == 0), + // advance chain1 to running + AdvanceConsumers(NoStatusAdvancement.set("chain1", true)) + }) + // consumer chain should have current validator set from provider + .then( + all { + // since consumer chain just started, its assumed to have the validator set from provider + assert(runningValidatorSet.get("chain1") == runningValidatorSet.get(ProviderChain)), + // trigger a votingPowerChange on the provider chain + votingPowerChange("B", 10) + } + ) + .then( + val valSet = runningValidatorSet.get(ProviderChain) + endAndBeginBlock(ProviderChain) + // now the provider should send a packet on block end + .then(all { + // a packet was sent + assert(outstandingPacketsToConsumer.get("chain1").length() == 1), + // deliver the packet to the consumer + recvPacketOnConsumer("chain1") + }) + .then( + // consumer needs to end a block before it has the new validator set + endAndBeginBlock("chain1") + ) + .then(all { + // the consumer should have the new validator set + assert(runningValidatorSet.get("chain1") == valSet), + // put a last action to satisfy the action effect + AdvanceConsumers(NoStatusAdvancement) + }) + ) + } - // // MODEL ACTIONS - - // // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, - // // e.g. via undelegations, or delegations, ... - // action doVotingPowerChange(validator: Node, amount: int): bool = - // // for the provider chain, we need to adjust the voting power history - // // by adding a new set - // all { - // amount >= 0, - // val newValidatorSet = getCurrentValidatorSet(ProviderChain).getUpdatedValidatorSet(validator, amount) - // // set the running validator set on the provider chain, but don't update the history yet - // runningValidatorSet' = runningValidatorSet.set(ProviderChain, newValidatorSet), - // // no packets are sent yet, these are only sent on endAndBeginBlock - // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - // outstandingPacketsToProvider' = outstandingPacketsToProvider, - // receivedMaturations' = receivedMaturations, - // CONSUMER_NOOP, - // // voting power history is only updated on endAndBeginBlock - // votingPowerHistories' = votingPowerHistories, - // // consumer statusses do not change - // consumerStatus' = consumerStatus, - // // chain times do not change - // curChainTimes' = curChainTimes, - // // the validator set is considered to have changed - // providerValidatorSetChangedInThisBlock' = true, - // } - - // // deliver the next outstanding packet from the consumer to the provider. - // // since this model assumes a single provider chain, this just takes a single chain as argument. - // action recvPacketOnProvider(consumer: Chain): bool = all { - // // ensure there is a packet to be received - // outstandingPacketsToProvider.get(consumer).length() > 0, - // // remove packet from outstanding packets - // val newPacketQueue = outstandingPacketsToProvider.get(consumer).tail() - // outstandingPacketsToProvider' = outstandingPacketsToProvider.set(consumer, newPacketQueue), - // // register the packet as received - // val maturedPacket = outstandingPacketsToProvider.get(consumer).head() - // receivedMaturations' = receivedMaturations.add(maturedPacket), - // CONSUMER_NOOP, - // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - // votingPowerHistories' = votingPowerHistories, - // // no validator set changes are made - // runningValidatorSet' = runningValidatorSet, - // // consumer statusses do not change - // consumerStatus' = consumerStatus, - // // chain times do not change - // curChainTimes' = curChainTimes, - // // the validator set was not changed by this action (but might have been changed before in this block) - // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock - // } - - // // deliver the next outstanding packet from the provider to the consumer. - // // since this model assumes a single provider chain, this just takes a single chain as argument. - // action recvPacketOnConsumer(consumer: Chain): bool = all { - // // ensure there is a packet to be received - // outstandingPacketsToConsumer.get(consumer).length() > 0, - // // remove packet from outstanding packets - // val newPacketQueue = outstandingPacketsToConsumer.get(consumer).tail() - // val newOutstandingPackets = outstandingPacketsToConsumer.set(consumer, newPacketQueue) - // RegisterNewOutstandingPackets(newOutstandingPackets), - // val packet = outstandingPacketsToConsumer.get(consumer).head() - // all { - // // update the running validator set, but not the history yet, - // // as that only happens when the next block is started - // runningValidatorSet' = runningValidatorSet.set(consumer, packet.validatorSet), - // // add the new packet and store its maturation time - // val newMaturationTimes = maturationTimes.get(consumer).put(packet, curChainTimes.get(consumer) + UnbondingPeriod.get(consumer)) - // maturationTimes' = maturationTimes.set(consumer, newMaturationTimes) - // }, - // PROVIDER_NOOP, - // votingPowerHistories' = votingPowerHistories, - // outstandingPacketsToProvider' = outstandingPacketsToProvider, - // // consumer statusses do not change - // consumerStatus' = consumerStatus, - // // chain times do not change - // curChainTimes' = curChainTimes, - // // the validator set was not changed by this action (but might have been changed before in this block) - // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock - // } - - // // ends the current block and starts the next block for a given chain. - // action endAndBeginBlock(chain: Chain): bool = any { - // all { - // chain == ProviderChain, - // endAndBeginBlockForProvider, - // }, - // all { - // chain != ProviderChain, - // endAndBeginBlockForConsumer(chain), - // } - // } - - // // gets the updated history for the current chain when ending a block, i.e. the - // // running validator set is added to the history if different from the last one. - // def getUpdatedHistory(chain: Chain): List[ValidatorSet] = - // // update voting power history if the validator set changed - // val newValidatorSet = runningValidatorSet.get(ProviderChain) - // val oldValidatorSet = votingPowerHistories.get(ProviderChain).head() - // if (newValidatorSet != oldValidatorSet) - // votingPowerHistories.get(ProviderChain).prepend(newValidatorSet) - // else - // votingPowerHistories.get(ProviderChain) - - - // action endAndBeginBlockForProvider(): bool = all { - // // update the voting power history - // votingPowerHistories' = votingPowerHistories.set(ProviderChain, getUpdatedHistory(ProviderChain)), - // // the running validator set is now for sure the current validator set, - // // so start with it in the next block - // runningValidatorSet' = runningValidatorSet, - // // send VSCPackets to consumers - // val newOutstandingPackets = - // // if running validator set is considered to have changed - // if (providerValidatorSetChangedInThisBlock) - // // then send a packet to each running consumer - // outstandingPacketsToConsumer.keys().mapBy( - // (consumer) => - // val packetQueue = outstandingPacketsToConsumer.get(consumer) - // if (consumerStatus.get(consumer) == RUNNING) { - // packetQueue.append( - // { - // id: packetQueue.length(), - // validatorSet: runningValidatorSet.get(ProviderChain), - // timeout: curChainTimes.get(ProviderChain) + PacketTimeout - // } - // ) - // } else { - // packetQueue - // } - // ) - // else - // // otherwise, don't send any packets - // outstandingPacketsToConsumer - // RegisterNewOutstandingPackets(newOutstandingPackets), - // CONSUMER_NOOP, - // // no packets are sent to the provider - // outstandingPacketsToProvider' = outstandingPacketsToProvider, - // // do not receive any maturations - // receivedMaturations' = receivedMaturations, - // // consumer statusses do not change - // consumerStatus' = consumerStatus, - // // chain times do not change - // curChainTimes' = curChainTimes, - // // the validator set was definitely not changed in the new block yet, so set to false - // providerValidatorSetChangedInThisBlock' = false - // } - - // action endAndBeginBlockForConsumer(consumer: Chain): bool = all { - // ConsumerChains.contains(consumer), - // // update the voting power history - // votingPowerHistories' = votingPowerHistories.set(consumer, getUpdatedHistory(consumer)), - // // the running validator set is now for sure the current validator set, - // // so start with it in the next block - // runningValidatorSet' = runningValidatorSet, - // // compute mature packets whose maturation time has passed - // val maturedPackets = maturationTimes.get(consumer).keys().filter( - // packet => - // val maturationTime = maturationTimes.get(consumer).get(packet) - // maturationTime <= curChainTimes.get(consumer) - // ) - // all { - // // remove matured packets from the maturation times - // maturationTimes' = maturationTimes.set(consumer, maturationTimes.get(consumer).mapRemoveAll(maturedPackets)), - // // send matured packets - // outstandingPacketsToProvider' = outstandingPacketsToProvider.set( - // consumer, - // // construct VSCMaturedPackets from the matured VSCPackets - // outstandingPacketsToProvider.get(consumer).concat( - // maturedPackets.map(packet => {id: packet.id, timeout: 5}).toList() - // ) - // ) - // }, - // PROVIDER_NOOP, - // // no packets are sent to consumer or received by it - // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - // // consumer statusses do not change - // consumerStatus' = consumerStatus, - // // chain times do not change - // curChainTimes' = curChainTimes, - // // the validator set was not changed by this action (but might have been changed before in this block) - // // also, this is only a new block for a consumer, so the change variable shouldn't be reset - // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock - // } - - // // advance timestamps for maps nondeterministically - // action AdvanceTime(): bool = - // val advanceAmounts = curChainTimes.keys().mapBy( - // chain => - // nondet amount = oneOf(1.to(10)) - // amount - // ) - // AdvanceTimeByMap(advanceAmounts) - - // // the timestamp for each chain is advanced by the given amount - // action AdvanceTimeByMap(advancementAmount: Chain -> int): bool = all - // { - // curChainTimes' = curChainTimes.keys().mapBy( - // chain => - // curChainTimes.get(chain) + advancementAmount.get(chain) - // ), - // // all other variables are left untouched - // votingPowerHistories' = votingPowerHistories, - // runningValidatorSet' = runningValidatorSet, - // outstandingPacketsToProvider' = outstandingPacketsToProvider, - // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - // receivedMaturations' = receivedMaturations, - // maturationTimes' = maturationTimes, - // // chain times do not change - // consumerStatus' = consumerStatus, - // // the validator set was not changed by this action (but might have been changed before in this block) - // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock - // } - - // // each consumer chain may advance in the order - // // some events may necessitate a transition, e.g. timeouts. - // // shouldAdvance gives, for each consumer chain, whether it should advance if possible. - // // if a chain has to advance, e.g. due to timeouts, or may not advance, the value will have no effect. - // action AdvanceConsumers(shouldAdvance: Chain -> bool): bool = - // val newConsumerStatus = consumerStatus.keys().mapBy( - // chain => - // val curStatus = consumerStatus.get(chain) - // if (curStatus == UNUSED) { - // if (shouldAdvance.get(chain)) - // { - // RUNNING - // } else { - // UNUSED - // } - // } - // else if (curStatus == RUNNING) { - // // the chain may transition to stopped. - // // it is *forced* to stop if a packet timed out, - // // or if the inactivity timeout has passed - // if(consumerTimedOut(chain)) { - // STOPPED - // } else { - // if (shouldAdvance.get(chain)) { - // RUNNING - // } else { - // STOPPED - // } - // } - // } else { - // // stopped chains cannot restart, we assume a new chain would be started in that case - // STOPPED - // } - // ) - // all { - // consumerStatus' = newConsumerStatus, - // // all other variables are left untouched - // votingPowerHistories' = votingPowerHistories, - // runningValidatorSet' = runningValidatorSet.keys().mapBy( - // chain => - // if (newConsumerStatus.get(chain) == RUNNING and consumerStatus.get(chain) == UNUSED) - // // consumers that went from unused to running start with the current validator set on the provider - // { - // runningValidatorSet.get(ProviderChain) - // } else { - // runningValidatorSet.get(chain) - // } - // ), - // outstandingPacketsToProvider' = outstandingPacketsToProvider, - // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - // receivedMaturations' = receivedMaturations, - // maturationTimes' = maturationTimes, - // // chain times do not change - // curChainTimes' = curChainTimes, - // // the validator set was not changed by this action (but might have been changed before in this block) - // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock - // } - - // // Updates the outstandingPacketsToConsumer and sentVSCPackets variables - // action RegisterNewOutstandingPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = - // all { - // outstandingPacketsToConsumer' = newOutstandingPackets, - // StoreSentPackets(newOutstandingPackets), - // } - - - // // stores the VSCPackets sent in this step in sentVSCPackets - // action StoreSentPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = - // sentVSCPackets' = sentVSCPackets.keys().mapBy( - // (chain) => - // sentVSCPackets.get(chain).union(newOutstandingPackets.get(chain).toSet()) - // ) - - // // the main step action - // action step: bool = any { - // AdvanceTime, - // nondet node = oneOf(Nodes) - // nondet amount = oneOf(1.to(10)) - // votingPowerChange(node, amount), - // recvPacketOnProvider(oneOf(ConsumerChains)), - // recvPacketOnConsumer(oneOf(ConsumerChains)), - // nondet chain = oneOf(chains) - // endAndBeginBlock(chain), - // val shouldAdvance = ConsumerChains.mapBy( - // chain => - // nondet should = oneOf(Set(true, false)) - // should - // ) - // AdvanceConsumers(shouldAdvance), - // } - - // pure val nodePowerSet = Nodes.powerset() - - // def getArbitraryValidatorSet(): ValidatorSet = - // nondet numValidators = oneOf(1.to(Nodes.size())) - // // toList has nondeterministic behaviour, so this gets arbitrary validators - // nondet validators = oneOf(nodePowerSet.filter(s => s.size() == numValidators)) - // validators.mapBy( - // validator => - // nondet votingPower = oneOf(1.to(10)) - // votingPower - // ) - - // // INITIALIZATION - // action init: bool = - // all { - // val validatorSets = chains.mapBy( - // (chain) => - // // provider chain gets an arbitrary validator set, consumer chains have none - // if (chain == ProviderChain) getArbitraryValidatorSet else Map() - // ) - // all { - // votingPowerHistories' = chains.mapBy( - // (chain) => - // List(validatorSets.get(chain)) - // ), - // runningValidatorSet' = validatorSets, - // }, - // // each chain starts at time 0 - // curChainTimes' = chains.mapBy( - // (chain) => 0 - // ), - // // all consumer chains are unused - // consumerStatus' = chains.mapBy(chain => UNUSED), - // // no packets are outstanding - // outstandingPacketsToProvider' = chains.mapBy(chain => List()), - // outstandingPacketsToConsumer' = chains.mapBy(chain => List()), - // // no maturations have been received by provider - // receivedMaturations' = Set(), - // // no packets have been sent to consumers - // sentVSCPackets' = chains.mapBy(chain => Set()), - // // no packets have been received by consumers, so no maturation times set - // maturationTimes' = chains.mapBy(chain => Map()), - // // validator set was not changed yet - // providerValidatorSetChangedInThisBlock' = false - // } - - // // PROPERTIES - - // // Every validator set on any consumer chain MUST either be or - // // have been a validator set on the provider chain. - // val ValidatorSetReplication: bool = - // chains.forall( - // chain => chain.getCurrentValidatorSet().wasValidatorSetOnProvider() - // ) - - // // TESTS - // run VSCHappyPathTest: bool = { - // init - // // trigger a votingPowerChange on the provider chain - // .then(votingPowerChange("A", 10)) - // // endAndBeginBlock on provider. No consumer chains are running, so no packets are sent - // .then(endAndBeginBlock(ProviderChain)) - // .then(all { - // // no packet was sent - // assert(outstandingPacketsToConsumer.get("chain1").length() == 0), - // // advance chain1 to running - // AdvanceConsumers(NoStatusAdvancement.set("chain1", true)) - // }) - // // consumer chain should have current validator set from provider - // .then( - // all { - // // since consumer chain just started, its assumed to have the validator set from provider - // assert(runningValidatorSet.get("chain1") == runningValidatorSet.get(ProviderChain)), - // // trigger a votingPowerChange on the provider chain - // votingPowerChange("B", 10) - // } - // ) - // .then( - // val valSet = runningValidatorSet.get(ProviderChain) - // endAndBeginBlock(ProviderChain) - // // now the provider should send a packet on block end - // .then(all { - // // a packet was sent - // assert(outstandingPacketsToConsumer.get("chain1").length() == 1), - // // deliver the packet to the consumer - // recvPacketOnConsumer("chain1") - // }) - // .then( - // // consumer needs to end a block before it has the new validator set - // endAndBeginBlock("chain1") - // ) - // .then(all { - // // the consumer should have the new validator set - // assert(runningValidatorSet.get("chain1") == valSet), - // // put a last action to satisfy the action effect - // AdvanceConsumers(NoStatusAdvancement) - // }) - // ) - // } - - // // utility: the set of consumers currently running - // val RunningConsumers: Set[Chain] = - // ConsumerChains.filter(chain => consumerStatus.get(chain) == RUNNING) - - // // MODEL STATE - // // --SHARED STATE - - // // Stores, for each chain, the list of voting powers that corresponded to voting powers - // // at blocks over its entire existence. - // // Voting powers should be ordered by recency in descending order. - // var votingPowerHistories: Chain -> List[ValidatorSet] - - // // the current validator set on each chain. - // // this will be included in the next block, but might not be final yet, - // // e.g. there may be more modifications in the current block. - // var runningValidatorSet: Chain -> ValidatorSet - - // // the current timestamp for each chain - // var curChainTimes: Chain -> Timestamp - - // // stores, for each chain, its current status - - // // unused, running, or stopped - // var consumerStatus: Chain -> str - - // // --CHANNELS - // // Stores, for each consumer chain, the list of packets that have been sent to the provider chain - // // and have not been received yet. - // var outstandingPacketsToProvider: Chain -> List[VSCMaturedPacket] - - // // Stores, for each consumer chain, the list of packets that have been sent to the consumer chain - // // and have not been received yet. - // var outstandingPacketsToConsumer: Chain -> List[VSCPacket] - - - // // --CONSUMER STATE - // // Stores the maturation times for VSCPackets received by consumers - // var maturationTimes: Chain -> (VSCPacket -> Timestamp) - - // // --PROVIDER STATE - // // the set of VSCMaturedPackets received by the provider chain - // var receivedMaturations: Set[VSCMaturedPacket] - - // // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness - // var sentVSCPackets: Chain -> Set[VSCPacket] - - // // stores whether, in this step, the validator set considered to be changed. - // // this is needed because the validator set might be considered to have changed, even though - // // it is still technically identical at our level of abstraction, e.g. a validator power change on the provider - // // might leave the validator set the same because a delegation and undelegation cancel each other out. - // var providerValidatorSetChangedInThisBlock: bool - - // // utility: a struct summarizing the current state - // val state = - // { - // votingPowerHistories: votingPowerHistories, - // runningValidatorSet: runningValidatorSet, - // curChainTimes: curChainTimes, - // consumerStatus: consumerStatus, - // outstandingPacketsToProvider: outstandingPacketsToProvider, - // outstandingPacketsToConsumer: outstandingPacketsToConsumer, - // maturationTimes: maturationTimes, - // receivedMaturations: receivedMaturations, - // sentVSCPackets: sentVSCPackets, - // } - - // // set of identifiers of potential nodes - // pure val Nodes: Set[Node] = - // Set("A", "B", "C", "D", "E", "F", "G", "H", "I", "J") - - // // the set of consumer chains - // pure val ConsumerChains: Set[Chain] = - // Set("chain1", "chain2", "chain3") - - // // The singular provider chain. - // pure val ProviderChain: Chain = - // "provider" - - // pure val chains = ConsumerChains.union(Set(ProviderChain)) - - // // length of the unbonding period on each chain - // pure val UnbondingPeriod: Chain -> int = chains.mapBy( - // (chain) => - // 10 - // ) - - // // the time until a packet times out - // pure val PacketTimeout: int = - // 5 - - // // the time until a consumer chain is dropped by the provider due to inactivity - // pure val InactivityTimeout: int = - // 10 - - // // utility: a map assigning each chain to 0, used for not advancing timestamps - // pure val NoTimeAdvancement: Chain -> int = chains.mapBy( - // (chain) => - // 0 - // ) - - - // // utility: a map assigning each chain to false, used for not advancing consumer status - // pure val NoStatusAdvancement: Chain -> bool = chains.mapBy( - // (chain) => - // false - // ) } diff --git a/tests/difference/core/quint_model/extraSpells.qnt b/tests/difference/core/quint_model/extraSpells.qnt index 5c98f7a384..cd2105beb7 100644 --- a/tests/difference/core/quint_model/extraSpells.qnt +++ b/tests/difference/core/quint_model/extraSpells.qnt @@ -1,3 +1,4 @@ +-*- mode: Bluespec; -*- // This module is just a library with utility functions (sometimes called spells in Quint). module extraSpells { diff --git a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123337-6230.fail b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123337-6230.fail deleted file mode 100644 index f2c09a9e15..0000000000 --- a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123337-6230.fail +++ /dev/null @@ -1,18 +0,0 @@ -# 2023/09/12 12:33:37 TestActionMarshalling [rapid] draw Action: main.StartChainAction{Chain:"", Validators:[]main.StartChainValidator{}, GenesisChanges:"", SkipGentx:false} -# 2023/09/12 12:33:37 TestActionMarshalling error marshalling and unmarshalling chain state: any( -# - main.StartChainAction{Validators: []main.StartChainValidator{}}, -# + map[string]any{ -# + "Chain": string(""), -# + "GenesisChanges": string(""), -# + "SkipGentx": bool(false), -# + "Validators": []any{}, -# + }, -# ) -# -v0.4.8#6863100771198181688 -0x0 -0x1 -0x0 -0x0 -0x0 -0x0 \ No newline at end of file diff --git a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123517-6794.fail b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123517-6794.fail deleted file mode 100644 index 9547963143..0000000000 --- a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123517-6794.fail +++ /dev/null @@ -1,14 +0,0 @@ -# 2023/09/12 12:35:17 TestActionMarshalling [rapid] draw Action: main.SendTokensAction{Chain:"", From:"", To:"", Amount:0x0} -# 2023/09/12 12:35:17 TestActionMarshalling error marshalling and unmarshalling action: got (+), want (-):   any( -# -  main.SendTokensAction{}, -# +  map[string]any{"Amount": float64(0), "Chain": string(""), "From": string(""), "To": string("")}, -#   ) -# -v0.4.8#14250065908211800578 -0x0 -0x0 -0x0 -0x0 -0x0 -0x0 -0x0 \ No newline at end of file diff --git a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123556-6970.fail b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123556-6970.fail deleted file mode 100644 index 4ddf365f5c..0000000000 --- a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123556-6970.fail +++ /dev/null @@ -1,14 +0,0 @@ -# 2023/09/12 12:35:56 TestActionMarshalling [rapid] draw Action: main.SendTokensAction{Chain:"", From:"", To:"", Amount:0x0} -# 2023/09/12 12:35:56 TestActionMarshalling error marshalling and unmarshalling action: got (-), want (+):   any( -# -  main.SendTokensAction{}, -# +  map[string]any{"Amount": float64(0), "Chain": string(""), "From": string(""), "To": string("")}, -#   ) -# -v0.4.8#9176735344445930654 -0x0 -0x0 -0x0 -0x0 -0x0 -0x0 -0x0 \ No newline at end of file diff --git a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123609-7116.fail b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123609-7116.fail deleted file mode 100644 index 89dcbcc8b2..0000000000 --- a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123609-7116.fail +++ /dev/null @@ -1,18 +0,0 @@ -# 2023/09/12 12:36:09 TestActionMarshalling [rapid] draw Action: main.StartChainAction{Chain:"", Validators:[]main.StartChainValidator{}, GenesisChanges:"", SkipGentx:false} -# 2023/09/12 12:36:09 TestActionMarshalling error marshalling and unmarshalling action: got (-), want (+): any( -# - main.StartChainAction{Validators: []main.StartChainValidator{}}, -# + map[string]any{ -# + "Chain": string(""), -# + "GenesisChanges": string(""), -# + "SkipGentx": bool(false), -# + "Validators": []any{}, -# + }, -# ) -# -v0.4.8#17927886955469684979 -0x0 -0x1 -0x0 -0x0 -0x0 -0x0 \ No newline at end of file diff --git a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123822-8026.fail b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123822-8026.fail deleted file mode 100644 index d2493d87a3..0000000000 --- a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230912123822-8026.fail +++ /dev/null @@ -1,8 +0,0 @@ -# 2023/09/12 12:38:22 TestActionMarshalling [rapid] draw Action: main.addChainToRelayerAction{Chain:"", Validator:""} -# 2023/09/12 12:38:22 TestActionMarshalling error marshalling and unmarshalling action: error unmarshalling action inside step: unknown action name: main.addChainToRelayerAction -# -v0.4.8#17613601115647214278 -0x9867f1f40f739 -0x9 -0x0 -0x0 \ No newline at end of file diff --git a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151826-12656.fail b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151826-12656.fail deleted file mode 100644 index 10fd2ac639..0000000000 --- a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151826-12656.fail +++ /dev/null @@ -1,8 +0,0 @@ -# 2023/09/13 15:18:26 TestActionMarshalling [rapid] draw Action: main.lightClientEquivocationAttackAction{Validator:"", Chain:""} -# 2023/09/13 15:18:26 TestActionMarshalling error marshalling and unmarshalling action: error unmarshalling action inside step: unknown action name: main.lightClientEquivocationAttackAction -# -v0.4.8#7694661539125204314 -0xc05c654ab866b -0x1f -0x0 -0x0 \ No newline at end of file diff --git a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151917-13146.fail b/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151917-13146.fail deleted file mode 100644 index 6fb9bfa9f7..0000000000 --- a/tests/e2e/testdata/rapid/TestActionMarshalling/TestActionMarshalling-20230913151917-13146.fail +++ /dev/null @@ -1,8 +0,0 @@ -# 2023/09/13 15:19:17 TestActionMarshalling [rapid] draw Action: main.lightClientLunaticAttackAction{Validator:"", Chain:""} -# 2023/09/13 15:19:17 TestActionMarshalling error marshalling and unmarshalling action: error unmarshalling action inside step: unknown action name: main.lightClientLunaticAttackAction -# -v0.4.8#10796173543550944397 -0x1f2b5a0e61c3a6 -0x0 -0x0 -0x0 \ No newline at end of file diff --git a/tests/e2e/testdata/rapid/TestReadAndWriteTrace/TestReadAndWriteTrace-20230913151920-13146.fail b/tests/e2e/testdata/rapid/TestReadAndWriteTrace/TestReadAndWriteTrace-20230913151920-13146.fail deleted file mode 100644 index f8e2127feb..0000000000 --- a/tests/e2e/testdata/rapid/TestReadAndWriteTrace/TestReadAndWriteTrace-20230913151920-13146.fail +++ /dev/null @@ -1,11 +0,0 @@ -# 2023/09/13 15:19:20 TestReadAndWriteTrace [rapid] draw Trace: []main.Step{main.Step{Action:main.lightClientEquivocationAttackAction{Validator:"", Chain:""}, State:main.State{}}} -# 2023/09/13 15:19:20 TestReadAndWriteTrace error writing and reading trace: error reading trace from file: unknown action name: main.lightClientEquivocationAttackAction -# -v0.4.8#17668525343613541116 -0x5555555555555 -0xc05c654ab866b -0x1f -0x0 -0x0 -0x0 -0x0 \ No newline at end of file From c05d9e682e055f458d64977c6da8917b5ba0c802 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 18 Sep 2023 18:24:33 +0200 Subject: [PATCH 13/80] Start rewriting quint model --- tests/difference/core/quint_model/ccv.qnt | 1241 +++++++++-------- .../core/quint_model/extraSpells.qnt | 1 - 2 files changed, 691 insertions(+), 551 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index d18930ae1d..4cbc327ac4 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -1,5 +1,4 @@ --*- mode: Bluespec; -*- -module ccv { +module ccv_logic { import extraSpells.* from "./extraSpells" // Things that are not modelled: @@ -12,12 +11,17 @@ module ccv { // * VSC packets mature // * Consumers can be forcefully dropped due to timeouts, or stop on their own volition + // =================== // TYPE DEFINITIONS + // =================== type Node = str type Chain = str - type ValidatorSet = Node -> int + type Power = int + type ValidatorSet = Node -> Power type Height = int type Timestamp = int + // a list of validator sets per blocks, ordered by recency + type VotingPowerHistory = List[ValidatorSet] // --PACKETS type VSCPacket = @@ -38,582 +42,719 @@ module ccv { timeout: Timestamp } - // MODEL PARAMETERS - - - // set of identifiers of potential nodes - pure val Nodes: Set[Node] = - Set("A", "B", "C", "D", "E", "F", "G", "H", "I", "J") - - // the set of consumer chains - pure val ConsumerChains: Set[Chain] = - Set("chain1", "chain2", "chain3") + // possible consumer statuses + pure val STOPPED = "stopped" // the chain was once a consumer chain, but has been dropped by the provider. + pure val RUNNING = "running" // the chain is currently a consumer chain. Running chains are those that get sent VSCPackets. + pure val UNUSED = "unused" // the chain has never been a consumer chain, and is available to become one. + // When a chain is dropped, it cannot become a consumer again - we assume that would be done by another consumer becoming running. + + + // state that each chain needs to store, whether consumer or provider. + type ChainState = { + // Stores the list of voting powers that corresponded to voting powers + // at blocks over the chains entire existence. + // Voting powers should be ordered by recency in descending order. + votingPowerHistory: VotingPowerHistory, + + // the current validator set on each chain. + // this will be included in the next block, but might not be final yet, + // e.g. there may be more modifications in the current block. + currentValidatorSet: ValidatorSet, + + // the latest timestamp that was comitted on chain + lastTimestamp: Timestamp, + } - // The singular provider chain. - pure val ProviderChain: Chain = - "provider" - - pure val chains = ConsumerChains.union(Set(ProviderChain)) - - // length of the unbonding period on each chain - pure val UnbondingPeriod: Chain -> int = chains.mapBy( - (chain) => - 10 - ) - - // the time until a packet times out - pure val PacketTimeout: int = - 5 - - // the time until a consumer chain is dropped by the provider due to inactivity - pure val InactivityTimeout: int = - 10 - - // consumer statuses - pure val STOPPED = "stopped" - pure val RUNNING = "running" - pure val UNUSED = "unused" - - // utility: a map assigning each chain to 0, used for not advancing timestamps - pure val NoTimeAdvancement: Chain -> int = chains.mapBy( - (chain) => - 0 - ) - - // utility: a struct summarizing the current state - val state = + // Defines the current state of the provider chain. Essentially, all information here is stored by the provider on-chain (or could be derived purely by information that is on-chain). + type ProviderState = { - votingPowerHistories: votingPowerHistories, - runningValidatorSet: runningValidatorSet, - curChainTimes: curChainTimes, - consumerStatus: consumerStatus, - outstandingPacketsToProvider: outstandingPacketsToProvider, - outstandingPacketsToConsumer: outstandingPacketsToConsumer, - maturationTimes: maturationTimes, - receivedMaturations: receivedMaturations, - sentVSCPackets: sentVSCPackets, - } - - - // utility: a map assigning each chain to false, used for not advancing consumer status - pure val NoStatusAdvancement: Chain -> bool = chains.mapBy( - (chain) => - false - ) - - // utility: the set of consumers currently running - val RunningConsumers: Set[Chain] = - ConsumerChains.filter(chain => consumerStatus.get(chain) == RUNNING) - - // MODEL STATE - // --SHARED STATE - - // Stores, for each chain, the list of voting powers that corresponded to voting powers - // at blocks over its entire existence. - // Voting powers should be ordered by recency in descending order. - var votingPowerHistories: Chain -> List[ValidatorSet] - - // the current validator set on each chain. - // this will be included in the next block, but might not be final yet, - // e.g. there may be more modifications in the current block. - var runningValidatorSet: Chain -> ValidatorSet - - // the current timestamp for each chain - var curChainTimes: Chain -> Timestamp - - // stores, for each chain, its current status - - // unused, running, or stopped - var consumerStatus: Chain -> str - - // --CHANNELS - // Stores, for each consumer chain, the list of packets that have been sent to the provider chain - // and have not been received yet. - var outstandingPacketsToProvider: Chain -> List[VSCMaturedPacket] + // the state that each chain needs to store + chainState: ChainState, - // Stores, for each consumer chain, the list of packets that have been sent to the consumer chain - // and have not been received yet. - var outstandingPacketsToConsumer: Chain -> List[VSCPacket] + // Stores, for each consumer chain, the list of packets that have been sent to the consumer chain + // and have not been received yet. + // In the implementation, this would roughly be the unacknowledged packets on an ibc channel. + outstandingPacketsToConsumer: Chain -> List[VSCPacket], + // the set of received VSCMaturedPackets + receivedMaturations: Set[VSCMaturedPacket], - // --CONSUMER STATE - // Stores the maturation times for VSCPackets received by consumers - var maturationTimes: Chain -> (VSCPacket -> Timestamp) + // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness + sentVSCPackets: Chain -> Set[VSCPacket], - // --PROVIDER STATE - // the set of VSCMaturedPackets received by the provider chain - var receivedMaturations: Set[VSCMaturedPacket] - - // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness - var sentVSCPackets: Chain -> Set[VSCPacket] - - // stores whether, in this step, the validator set considered to be changed. - // this is needed because the validator set might be considered to have changed, even though - // it is still technically identical at our level of abstraction, e.g. a validator power change on the provider - // might leave the validator set the same because a delegation and undelegation cancel each other out. - var providerValidatorSetChangedInThisBlock: bool - - - // UTILITY FUNCTIONS & ACTIONS - def wasValidatorSetOnProvider(validatorSet: ValidatorSet): bool = { - votingPowerHistories.get(ProviderChain).toSet().exists( - historicalValSet => historicalValSet == validatorSet - ) - } - - def getCurrentValidatorSet(chain: Chain): ValidatorSet = - votingPowerHistories.get(chain).head() - - def getUpdatedValidatorSet(oldValidatorSet: ValidatorSet, validator: Node, newVotingPower: int): ValidatorSet = - if (newVotingPower > 0) - oldValidatorSet.put(validator, newVotingPower) - else - oldValidatorSet.mapRemove(validator) - - // returns true if the consumer has timed out and should be dropped - def consumerTimedOut(consumer: Chain): bool = - any { - // either a package from provider to consumer has timed out - outstandingPacketsToConsumer.get(consumer).select( - packet => packet.timeout <= curChainTimes.get(consumer) - ).length() > 0, - // or a package from consumer to provider has timed out - outstandingPacketsToProvider.get(consumer).select( - packet => packet.timeout <= curChainTimes.get(ProviderChain) - ).length() > 0, - // or the inactivity timeout has passed since a VSCPacket was sent to the consumer, but the - // provider has not received a VSCMaturedPacket for it - val packetsWithoutResponse = sentVSCPackets.get(consumer).filter( // get packets without response - packet => - not(receivedMaturations.exists( - maturedPacket => maturedPacket.id == packet.id - )) - ) - // among those, get packets where inactivity timeout has passed - packetsWithoutResponse.filter( - packet => - val sentAt = curChainTimes.get(ProviderChain) - PacketTimeout // compute when the packet was sent - val timesOutAt = sentAt + InactivityTimeout // compute when the packet times out - timesOutAt <= curChainTimes.get(ProviderChain) - ).size() > 0 - } - - // utility action that leaves all provider state untouched - action PROVIDER_NOOP(): bool = - all { - receivedMaturations' = receivedMaturations, - } + // stores whether, in this block, the validator set has changed. + // this is needed because the validator set might be considered to have changed, even though + // it is still technically identical at our level of abstraction, e.g. a validator power change on the provider + // might leave the validator set the same because a delegation and undelegation cancel each other out. + providerValidatorSetChangedInThisBlock: bool, - // utility action that leaves all consumer state untouched - action CONSUMER_NOOP(): bool = - all { - maturationTimes' = maturationTimes, + // stores, for each consumer chain, its current status - + // unused, running, or stopped + consumerStatus: Chain -> str, } - - // MODEL ACTIONS + // Defines the current state of a consumer chain. This information is accessible to that consumer on-chain. + type ConsumerState = { + // the state that each chain needs to store + chainState: ChainState, - // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, - // e.g. via undelegations, or delegations, ... - action votingPowerChange(validator: Node, amount: int): bool = - // for the provider chain, we need to adjust the voting power history - // by adding a new set - all { - amount >= 0, - val newValidatorSet = getCurrentValidatorSet(ProviderChain).getUpdatedValidatorSet(validator, amount) - // set the running validator set on the provider chain, but don't update the history yet - runningValidatorSet' = runningValidatorSet.set(ProviderChain, newValidatorSet), - // no packets are sent yet, these are only sent on endAndBeginBlock - RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - outstandingPacketsToProvider' = outstandingPacketsToProvider, - receivedMaturations' = receivedMaturations, - CONSUMER_NOOP, - // voting power history is only updated on endAndBeginBlock - votingPowerHistories' = votingPowerHistories, - // consumer statusses do not change - consumerStatus' = consumerStatus, - // chain times do not change - curChainTimes' = curChainTimes, - // the validator set is considered to have changed - providerValidatorSetChangedInThisBlock' = true, - } + // Stores the maturation times for VSCPackets received by this consumer + maturationTimes: VSCPacket -> Timestamp, - // deliver the next outstanding packet from the consumer to the provider. - // since this model assumes a single provider chain, this just takes a single chain as argument. - action recvPacketOnProvider(consumer: Chain): bool = all { - // ensure there is a packet to be received - outstandingPacketsToProvider.get(consumer).length() > 0, - // remove packet from outstanding packets - val newPacketQueue = outstandingPacketsToProvider.get(consumer).tail() - outstandingPacketsToProvider' = outstandingPacketsToProvider.set(consumer, newPacketQueue), - // register the packet as received - val maturedPacket = outstandingPacketsToProvider.get(consumer).head() - receivedMaturations' = receivedMaturations.add(maturedPacket), - CONSUMER_NOOP, - RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - votingPowerHistories' = votingPowerHistories, - // no validator set changes are made - runningValidatorSet' = runningValidatorSet, - // consumer statusses do not change - consumerStatus' = consumerStatus, - // chain times do not change - curChainTimes' = curChainTimes, - // the validator set was not changed by this action (but might have been changed before in this block) - providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock - } + // Stores the list of packets that have been sent to the provider chain by this consumer + // and have not been received yet. + // In the implementation, essentially unacknowledged IBC packets. + outstandingPacketsToProvider: Chain -> List[VSCMaturedPacket], - // deliver the next outstanding packet from the provider to the consumer. - // since this model assumes a single provider chain, this just takes a single chain as argument. - action recvPacketOnConsumer(consumer: Chain): bool = all { - // ensure there is a packet to be received - outstandingPacketsToConsumer.get(consumer).length() > 0, - // remove packet from outstanding packets - val newPacketQueue = outstandingPacketsToConsumer.get(consumer).tail() - val newOutstandingPackets = outstandingPacketsToConsumer.set(consumer, newPacketQueue) - RegisterNewOutstandingPackets(newOutstandingPackets), - val packet = outstandingPacketsToConsumer.get(consumer).head() - all { - // update the running validator set, but not the history yet, - // as that only happens when the next block is started - runningValidatorSet' = runningValidatorSet.set(consumer, packet.validatorSet), - // add the new packet and store its maturation time - val newMaturationTimes = maturationTimes.get(consumer).put(packet, curChainTimes.get(consumer) + UnbondingPeriod.get(consumer)) - maturationTimes' = maturationTimes.set(consumer, newMaturationTimes) - }, - PROVIDER_NOOP, - votingPowerHistories' = votingPowerHistories, - outstandingPacketsToProvider' = outstandingPacketsToProvider, - // consumer statusses do not change - consumerStatus' = consumerStatus, - // chain times do not change - curChainTimes' = curChainTimes, - // the validator set was not changed by this action (but might have been changed before in this block) - providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + // Stores the list of voting powers that corresponded to voting powers + // at blocks over the chains entire existence. + // Voting powers should be ordered by recency in descending order. + votingPowerHistory: VotingPowerHistory, } - // ends the current block and starts the next block for a given chain. - action endAndBeginBlock(chain: Chain): bool = any { - all { - chain == ProviderChain, - endAndBeginBlockForProvider, - }, - all { - chain != ProviderChain, - endAndBeginBlockForConsumer(chain), - } + // the state of the protocol consists of the composition of the state of one provider chain with potentially many consumer chains. + type ProtocolState = { + providerState: ProviderState, + // the state of each consumer chain. + // note that we assume that this contains all consumer chains that may ever exist, + // and consumer chains that are currently not running will have providerState.consumerStatus == UNUSED or STOPPED + consumerStates: Set[ConsumerState] } - // gets the updated history for the current chain when ending a block, i.e. the - // running validator set is added to the history if different from the last one. - def getUpdatedHistory(chain: Chain): List[ValidatorSet] = - // update voting power history if the validator set changed - val newValidatorSet = runningValidatorSet.get(ProviderChain) - val oldValidatorSet = votingPowerHistories.get(ProviderChain).head() - if (newValidatorSet != oldValidatorSet) - votingPowerHistories.get(ProviderChain).prepend(newValidatorSet) - else - votingPowerHistories.get(ProviderChain) - - - action endAndBeginBlockForProvider(): bool = all { - // update the voting power history - votingPowerHistories' = votingPowerHistories.set(ProviderChain, getUpdatedHistory(ProviderChain)), - // the running validator set is now for sure the current validator set, - // so start with it in the next block - runningValidatorSet' = runningValidatorSet, - // send VSCPackets to consumers - val newOutstandingPackets = - // if running validator set is considered to have changed - if (providerValidatorSetChangedInThisBlock) - // then send a packet to each running consumer - outstandingPacketsToConsumer.keys().mapBy( - (consumer) => - val packetQueue = outstandingPacketsToConsumer.get(consumer) - if (consumerStatus.get(consumer) == RUNNING) { - packetQueue.append( - { - id: packetQueue.length(), - validatorSet: runningValidatorSet.get(ProviderChain), - timeout: curChainTimes.get(ProviderChain) + PacketTimeout - } - ) - } else { - packetQueue - } - ) - else - // otherwise, don't send any packets - outstandingPacketsToConsumer - RegisterNewOutstandingPackets(newOutstandingPackets), - CONSUMER_NOOP, - // no packets are sent to the provider - outstandingPacketsToProvider' = outstandingPacketsToProvider, - // do not receive any maturations - receivedMaturations' = receivedMaturations, - // consumer statusses do not change - consumerStatus' = consumerStatus, - // chain times do not change - curChainTimes' = curChainTimes, - // the validator set was definitely not changed in the new block yet, so set to false - providerValidatorSetChangedInThisBlock' = false + type Error = { + message: str } - action endAndBeginBlockForConsumer(consumer: Chain): bool = all { - ConsumerChains.contains(consumer), - // update the voting power history - votingPowerHistories' = votingPowerHistories.set(consumer, getUpdatedHistory(consumer)), - // the running validator set is now for sure the current validator set, - // so start with it in the next block - runningValidatorSet' = runningValidatorSet, - // compute mature packets whose maturation time has passed - val maturedPackets = maturationTimes.get(consumer).keys().filter( - packet => - val maturationTime = maturationTimes.get(consumer).get(packet) - maturationTime <= curChainTimes.get(consumer) - ) - all { - // remove matured packets from the maturation times - maturationTimes' = maturationTimes.set(consumer, maturationTimes.get(consumer).mapRemoveAll(maturedPackets)), - // send matured packets - outstandingPacketsToProvider' = outstandingPacketsToProvider.set( - consumer, - // construct VSCMaturedPackets from the matured VSCPackets - outstandingPacketsToProvider.get(consumer).concat( - maturedPackets.map(packet => {id: packet.id, timeout: 5}).toList() - ) - ) - }, - PROVIDER_NOOP, - // no packets are sent to consumer or received by it - RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - // consumer statusses do not change - consumerStatus' = consumerStatus, - // chain times do not change - curChainTimes' = curChainTimes, - // the validator set was not changed by this action (but might have been changed before in this block) - // also, this is only a new block for a consumer, so the change variable shouldn't be reset - providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + // we return either a result or an error. + // if hasError is true, newState may be arbitrary, but the error will be meaningful. + // if hasError is false, error may be arbitrary, but newState will be meaningful. + type Result = { + hasError: bool, + newState: ProtocolState, + error: Error } - // advance timestamps for maps nondeterministically - action AdvanceTime(): bool = - val advanceAmounts = curChainTimes.keys().mapBy( - chain => - nondet amount = oneOf(1.to(10)) - amount - ) - AdvanceTimeByMap(advanceAmounts) - - // the timestamp for each chain is advanced by the given amount - action AdvanceTimeByMap(advancementAmount: Chain -> int): bool = all + pure def Ok(newState: ProtocolState): Result = { { - curChainTimes' = curChainTimes.keys().mapBy( - chain => - curChainTimes.get(chain) + advancementAmount.get(chain) - ), - // all other variables are left untouched - votingPowerHistories' = votingPowerHistories, - runningValidatorSet' = runningValidatorSet, - outstandingPacketsToProvider' = outstandingPacketsToProvider, - RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - receivedMaturations' = receivedMaturations, - maturationTimes' = maturationTimes, - // chain times do not change - consumerStatus' = consumerStatus, - // the validator set was not changed by this action (but might have been changed before in this block) - providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock - } - - // each consumer chain may advance in the order - // some events may necessitate a transition, e.g. timeouts. - // shouldAdvance gives, for each consumer chain, whether it should advance if possible. - // if a chain has to advance, e.g. due to timeouts, or may not advance, the value will have no effect. - action AdvanceConsumers(shouldAdvance: Chain -> bool): bool = - val newConsumerStatus = consumerStatus.keys().mapBy( - chain => - val curStatus = consumerStatus.get(chain) - if (curStatus == UNUSED) { - if (shouldAdvance.get(chain)) - { - RUNNING - } else { - UNUSED - } - } - else if (curStatus == RUNNING) { - // the chain may transition to stopped. - // it is *forced* to stop if a packet timed out, - // or if the inactivity timeout has passed - if(consumerTimedOut(chain)) { - STOPPED - } else { - if (shouldAdvance.get(chain)) { - RUNNING - } else { - STOPPED - } - } - } else { - // stopped chains cannot restart, we assume a new chain would be started in that case - STOPPED + hasError: false, + newState: newState, + error: { + message: "" } - ) - all { - consumerStatus' = newConsumerStatus, - // all other variables are left untouched - votingPowerHistories' = votingPowerHistories, - runningValidatorSet' = runningValidatorSet.keys().mapBy( - chain => - if (newConsumerStatus.get(chain) == RUNNING and consumerStatus.get(chain) == UNUSED) - // consumers that went from unused to running start with the current validator set on the provider - { - runningValidatorSet.get(ProviderChain) - } else { - runningValidatorSet.get(chain) - } - ), - outstandingPacketsToProvider' = outstandingPacketsToProvider, - RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - receivedMaturations' = receivedMaturations, - maturationTimes' = maturationTimes, - // chain times do not change - curChainTimes' = curChainTimes, - // the validator set was not changed by this action (but might have been changed before in this block) - providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock } + } - // Updates the outstandingPacketsToConsumer and sentVSCPackets variables - action RegisterNewOutstandingPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = - all { - outstandingPacketsToConsumer' = newOutstandingPackets, - StoreSentPackets(newOutstandingPackets), + pure def Err(msg: str): Result = { + { + hasError: true, + newState: { + providerState: { + chainState: { + votingPowerHistory: List(), + currentValidatorSet: Map(), + lastTimestamp: 0 + }, + outstandingPacketsToConsumer: Map(), + receivedMaturations: Set(), + sentVSCPackets: Map(), + providerValidatorSetChangedInThisBlock: false, + consumerStatus: Map() + }, + consumerStates: Set() + }, + error: { + message: msg + } } + } + // =================== + // PROTOCOL LOGIC + // =================== - // stores the VSCPackets sent in this step in sentVSCPackets - action StoreSentPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = - sentVSCPackets' = sentVSCPackets.keys().mapBy( - (chain) => - sentVSCPackets.get(chain).union(newOutstandingPackets.get(chain).toSet()) - ) - + pure def getUpdatedValidatorSet(oldValidatorSet: ValidatorSet, validator: Node, newVotingPower: int): ValidatorSet = + if (newVotingPower > 0) + oldValidatorSet.put(validator, newVotingPower) + else + oldValidatorSet.mapRemove(validator) - // the main step action - action step: bool = any { - AdvanceTime, - nondet node = oneOf(Nodes) - nondet amount = oneOf(1.to(10)) - votingPowerChange(node, amount), - recvPacketOnProvider(oneOf(ConsumerChains)), - recvPacketOnConsumer(oneOf(ConsumerChains)), - nondet chain = oneOf(chains) - endAndBeginBlock(chain), - val shouldAdvance = ConsumerChains.mapBy( - chain => - nondet should = oneOf(Set(true, false)) - should - ) - AdvanceConsumers(shouldAdvance), - } - - pure val nodePowerSet = Nodes.powerset() - - def getArbitraryValidatorSet(): ValidatorSet = - nondet numValidators = oneOf(1.to(Nodes.size())) - // toList has nondeterministic behaviour, so this gets arbitrary validators - nondet validators = oneOf(nodePowerSet.filter(s => s.size() == numValidators)) - validators.mapBy( - validator => - nondet votingPower = oneOf(1.to(10)) - votingPower - ) - - // INITIALIZATION - action init: bool = - all { - val validatorSets = chains.mapBy( - (chain) => - // provider chain gets an arbitrary validator set, consumer chains have none - if (chain == ProviderChain) getArbitraryValidatorSet else Map() - ) - all { - votingPowerHistories' = chains.mapBy( - (chain) => - List(validatorSets.get(chain)) - ), - runningValidatorSet' = validatorSets, - }, - // each chain starts at time 0 - curChainTimes' = chains.mapBy( - (chain) => 0 - ), - // all consumer chains are unused - consumerStatus' = chains.mapBy(chain => UNUSED), - // no packets are outstanding - outstandingPacketsToProvider' = chains.mapBy(chain => List()), - outstandingPacketsToConsumer' = chains.mapBy(chain => List()), - // no maturations have been received by provider - receivedMaturations' = Set(), - // no packets have been sent to consumers - sentVSCPackets' = chains.mapBy(chain => Set()), - // no packets have been received by consumers, so no maturation times set - maturationTimes' = chains.mapBy(chain => Map()), - // validator set was not changed yet - providerValidatorSetChangedInThisBlock' = false - } + // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, + // e.g. via undelegations, or delegations, ... + pure def votingPowerChange(currentState: ProtocolState, validator: Node, amount: int): Result = + // adjust the current validator set on the provider - it is not entered in the voting history yet because that happens only on block end + val currentValidatorSet = currentState.providerState.currentValidatorSet + // val newValidatorSet = getUpdatedValidatorSet(currentValidatorSet, validator, amount) + // val newProviderState = currentState.providerState.with( + // "currentValidatorSet", newValidatorSet + // ) + // val newState = currentState.with( + // "providerState", newProviderState + // ) + Err("not implemented") +} - // PROPERTIES - - // Every validator set on any consumer chain MUST either be or - // have been a validator set on the provider chain. - val ValidatorSetReplication: bool = - chains.forall( - chain => chain.getCurrentValidatorSet().wasValidatorSetOnProvider() - ) - - // TESTS - run VSCHappyPathTest: bool = { - init - // trigger a votingPowerChange on the provider chain - .then(votingPowerChange("A", 10)) - // endAndBeginBlock on provider. No consumer chains are running, so no packets are sent - .then(endAndBeginBlock(ProviderChain)) - .then(all { - // no packet was sent - assert(outstandingPacketsToConsumer.get("chain1").length() == 0), - // advance chain1 to running - AdvanceConsumers(NoStatusAdvancement.set("chain1", true)) - }) - // consumer chain should have current validator set from provider - .then( - all { - // since consumer chain just started, its assumed to have the validator set from provider - assert(runningValidatorSet.get("chain1") == runningValidatorSet.get(ProviderChain)), - // trigger a votingPowerChange on the provider chain - votingPowerChange("B", 10) - } - ) - .then( - val valSet = runningValidatorSet.get(ProviderChain) - endAndBeginBlock(ProviderChain) - // now the provider should send a packet on block end - .then(all { - // a packet was sent - assert(outstandingPacketsToConsumer.get("chain1").length() == 1), - // deliver the packet to the consumer - recvPacketOnConsumer("chain1") - }) - .then( - // consumer needs to end a block before it has the new validator set - endAndBeginBlock("chain1") - ) - .then(all { - // the consumer should have the new validator set - assert(runningValidatorSet.get("chain1") == valSet), - // put a last action to satisfy the action effect - AdvanceConsumers(NoStatusAdvancement) - }) - ) - } +module ccv_tests { + import ccv_logic.* + + // // UTILITY FUNCTIONS & ACTIONS + // def wasValidatorSetOnProvider(validatorSet: ValidatorSet): bool = { + // votingPowerHistories.get(ProviderChain).toSet().exists( + // historicalValSet => historicalValSet == validatorSet + // ) + // } + + // def getCurrentValidatorSet(chain: Chain): ValidatorSet = + // votingPowerHistories.get(chain).head() + + // // returns true if the consumer has timed out and should be dropped + // def consumerTimedOut(consumer: Chain): bool = + // any { + // // either a package from provider to consumer has timed out + // outstandingPacketsToConsumer.get(consumer).select( + // packet => packet.timeout <= curChainTimes.get(consumer) + // ).length() > 0, + // // or a package from consumer to provider has timed out + // outstandingPacketsToProvider.get(consumer).select( + // packet => packet.timeout <= curChainTimes.get(ProviderChain) + // ).length() > 0, + // // or the inactivity timeout has passed since a VSCPacket was sent to the consumer, but the + // // provider has not received a VSCMaturedPacket for it + // val packetsWithoutResponse = sentVSCPackets.get(consumer).filter( // get packets without response + // packet => + // not(receivedMaturations.exists( + // maturedPacket => maturedPacket.id == packet.id + // )) + // ) + // // among those, get packets where inactivity timeout has passed + // packetsWithoutResponse.filter( + // packet => + // val sentAt = curChainTimes.get(ProviderChain) - PacketTimeout // compute when the packet was sent + // val timesOutAt = sentAt + InactivityTimeout // compute when the packet times out + // timesOutAt <= curChainTimes.get(ProviderChain) + // ).size() > 0 + // } + + // // utility action that leaves all provider state untouched + // action PROVIDER_NOOP(): bool = + // all { + // receivedMaturations' = receivedMaturations, + // } + + // // utility action that leaves all consumer state untouched + // action CONSUMER_NOOP(): bool = + // all { + // maturationTimes' = maturationTimes, + // } + + // // MODEL ACTIONS + + // // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, + // // e.g. via undelegations, or delegations, ... + // action doVotingPowerChange(validator: Node, amount: int): bool = + // // for the provider chain, we need to adjust the voting power history + // // by adding a new set + // all { + // amount >= 0, + // val newValidatorSet = getCurrentValidatorSet(ProviderChain).getUpdatedValidatorSet(validator, amount) + // // set the running validator set on the provider chain, but don't update the history yet + // runningValidatorSet' = runningValidatorSet.set(ProviderChain, newValidatorSet), + // // no packets are sent yet, these are only sent on endAndBeginBlock + // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + // outstandingPacketsToProvider' = outstandingPacketsToProvider, + // receivedMaturations' = receivedMaturations, + // CONSUMER_NOOP, + // // voting power history is only updated on endAndBeginBlock + // votingPowerHistories' = votingPowerHistories, + // // consumer statusses do not change + // consumerStatus' = consumerStatus, + // // chain times do not change + // curChainTimes' = curChainTimes, + // // the validator set is considered to have changed + // providerValidatorSetChangedInThisBlock' = true, + // } + + // // deliver the next outstanding packet from the consumer to the provider. + // // since this model assumes a single provider chain, this just takes a single chain as argument. + // action recvPacketOnProvider(consumer: Chain): bool = all { + // // ensure there is a packet to be received + // outstandingPacketsToProvider.get(consumer).length() > 0, + // // remove packet from outstanding packets + // val newPacketQueue = outstandingPacketsToProvider.get(consumer).tail() + // outstandingPacketsToProvider' = outstandingPacketsToProvider.set(consumer, newPacketQueue), + // // register the packet as received + // val maturedPacket = outstandingPacketsToProvider.get(consumer).head() + // receivedMaturations' = receivedMaturations.add(maturedPacket), + // CONSUMER_NOOP, + // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + // votingPowerHistories' = votingPowerHistories, + // // no validator set changes are made + // runningValidatorSet' = runningValidatorSet, + // // consumer statusses do not change + // consumerStatus' = consumerStatus, + // // chain times do not change + // curChainTimes' = curChainTimes, + // // the validator set was not changed by this action (but might have been changed before in this block) + // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + // } + + // // deliver the next outstanding packet from the provider to the consumer. + // // since this model assumes a single provider chain, this just takes a single chain as argument. + // action recvPacketOnConsumer(consumer: Chain): bool = all { + // // ensure there is a packet to be received + // outstandingPacketsToConsumer.get(consumer).length() > 0, + // // remove packet from outstanding packets + // val newPacketQueue = outstandingPacketsToConsumer.get(consumer).tail() + // val newOutstandingPackets = outstandingPacketsToConsumer.set(consumer, newPacketQueue) + // RegisterNewOutstandingPackets(newOutstandingPackets), + // val packet = outstandingPacketsToConsumer.get(consumer).head() + // all { + // // update the running validator set, but not the history yet, + // // as that only happens when the next block is started + // runningValidatorSet' = runningValidatorSet.set(consumer, packet.validatorSet), + // // add the new packet and store its maturation time + // val newMaturationTimes = maturationTimes.get(consumer).put(packet, curChainTimes.get(consumer) + UnbondingPeriod.get(consumer)) + // maturationTimes' = maturationTimes.set(consumer, newMaturationTimes) + // }, + // PROVIDER_NOOP, + // votingPowerHistories' = votingPowerHistories, + // outstandingPacketsToProvider' = outstandingPacketsToProvider, + // // consumer statusses do not change + // consumerStatus' = consumerStatus, + // // chain times do not change + // curChainTimes' = curChainTimes, + // // the validator set was not changed by this action (but might have been changed before in this block) + // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + // } + + // // ends the current block and starts the next block for a given chain. + // action endAndBeginBlock(chain: Chain): bool = any { + // all { + // chain == ProviderChain, + // endAndBeginBlockForProvider, + // }, + // all { + // chain != ProviderChain, + // endAndBeginBlockForConsumer(chain), + // } + // } + + // // gets the updated history for the current chain when ending a block, i.e. the + // // running validator set is added to the history if different from the last one. + // def getUpdatedHistory(chain: Chain): List[ValidatorSet] = + // // update voting power history if the validator set changed + // val newValidatorSet = runningValidatorSet.get(ProviderChain) + // val oldValidatorSet = votingPowerHistories.get(ProviderChain).head() + // if (newValidatorSet != oldValidatorSet) + // votingPowerHistories.get(ProviderChain).prepend(newValidatorSet) + // else + // votingPowerHistories.get(ProviderChain) + + + // action endAndBeginBlockForProvider(): bool = all { + // // update the voting power history + // votingPowerHistories' = votingPowerHistories.set(ProviderChain, getUpdatedHistory(ProviderChain)), + // // the running validator set is now for sure the current validator set, + // // so start with it in the next block + // runningValidatorSet' = runningValidatorSet, + // // send VSCPackets to consumers + // val newOutstandingPackets = + // // if running validator set is considered to have changed + // if (providerValidatorSetChangedInThisBlock) + // // then send a packet to each running consumer + // outstandingPacketsToConsumer.keys().mapBy( + // (consumer) => + // val packetQueue = outstandingPacketsToConsumer.get(consumer) + // if (consumerStatus.get(consumer) == RUNNING) { + // packetQueue.append( + // { + // id: packetQueue.length(), + // validatorSet: runningValidatorSet.get(ProviderChain), + // timeout: curChainTimes.get(ProviderChain) + PacketTimeout + // } + // ) + // } else { + // packetQueue + // } + // ) + // else + // // otherwise, don't send any packets + // outstandingPacketsToConsumer + // RegisterNewOutstandingPackets(newOutstandingPackets), + // CONSUMER_NOOP, + // // no packets are sent to the provider + // outstandingPacketsToProvider' = outstandingPacketsToProvider, + // // do not receive any maturations + // receivedMaturations' = receivedMaturations, + // // consumer statusses do not change + // consumerStatus' = consumerStatus, + // // chain times do not change + // curChainTimes' = curChainTimes, + // // the validator set was definitely not changed in the new block yet, so set to false + // providerValidatorSetChangedInThisBlock' = false + // } + + // action endAndBeginBlockForConsumer(consumer: Chain): bool = all { + // ConsumerChains.contains(consumer), + // // update the voting power history + // votingPowerHistories' = votingPowerHistories.set(consumer, getUpdatedHistory(consumer)), + // // the running validator set is now for sure the current validator set, + // // so start with it in the next block + // runningValidatorSet' = runningValidatorSet, + // // compute mature packets whose maturation time has passed + // val maturedPackets = maturationTimes.get(consumer).keys().filter( + // packet => + // val maturationTime = maturationTimes.get(consumer).get(packet) + // maturationTime <= curChainTimes.get(consumer) + // ) + // all { + // // remove matured packets from the maturation times + // maturationTimes' = maturationTimes.set(consumer, maturationTimes.get(consumer).mapRemoveAll(maturedPackets)), + // // send matured packets + // outstandingPacketsToProvider' = outstandingPacketsToProvider.set( + // consumer, + // // construct VSCMaturedPackets from the matured VSCPackets + // outstandingPacketsToProvider.get(consumer).concat( + // maturedPackets.map(packet => {id: packet.id, timeout: 5}).toList() + // ) + // ) + // }, + // PROVIDER_NOOP, + // // no packets are sent to consumer or received by it + // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + // // consumer statusses do not change + // consumerStatus' = consumerStatus, + // // chain times do not change + // curChainTimes' = curChainTimes, + // // the validator set was not changed by this action (but might have been changed before in this block) + // // also, this is only a new block for a consumer, so the change variable shouldn't be reset + // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + // } + + // // advance timestamps for maps nondeterministically + // action AdvanceTime(): bool = + // val advanceAmounts = curChainTimes.keys().mapBy( + // chain => + // nondet amount = oneOf(1.to(10)) + // amount + // ) + // AdvanceTimeByMap(advanceAmounts) + + // // the timestamp for each chain is advanced by the given amount + // action AdvanceTimeByMap(advancementAmount: Chain -> int): bool = all + // { + // curChainTimes' = curChainTimes.keys().mapBy( + // chain => + // curChainTimes.get(chain) + advancementAmount.get(chain) + // ), + // // all other variables are left untouched + // votingPowerHistories' = votingPowerHistories, + // runningValidatorSet' = runningValidatorSet, + // outstandingPacketsToProvider' = outstandingPacketsToProvider, + // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + // receivedMaturations' = receivedMaturations, + // maturationTimes' = maturationTimes, + // // chain times do not change + // consumerStatus' = consumerStatus, + // // the validator set was not changed by this action (but might have been changed before in this block) + // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + // } + + // // each consumer chain may advance in the order + // // some events may necessitate a transition, e.g. timeouts. + // // shouldAdvance gives, for each consumer chain, whether it should advance if possible. + // // if a chain has to advance, e.g. due to timeouts, or may not advance, the value will have no effect. + // action AdvanceConsumers(shouldAdvance: Chain -> bool): bool = + // val newConsumerStatus = consumerStatus.keys().mapBy( + // chain => + // val curStatus = consumerStatus.get(chain) + // if (curStatus == UNUSED) { + // if (shouldAdvance.get(chain)) + // { + // RUNNING + // } else { + // UNUSED + // } + // } + // else if (curStatus == RUNNING) { + // // the chain may transition to stopped. + // // it is *forced* to stop if a packet timed out, + // // or if the inactivity timeout has passed + // if(consumerTimedOut(chain)) { + // STOPPED + // } else { + // if (shouldAdvance.get(chain)) { + // RUNNING + // } else { + // STOPPED + // } + // } + // } else { + // // stopped chains cannot restart, we assume a new chain would be started in that case + // STOPPED + // } + // ) + // all { + // consumerStatus' = newConsumerStatus, + // // all other variables are left untouched + // votingPowerHistories' = votingPowerHistories, + // runningValidatorSet' = runningValidatorSet.keys().mapBy( + // chain => + // if (newConsumerStatus.get(chain) == RUNNING and consumerStatus.get(chain) == UNUSED) + // // consumers that went from unused to running start with the current validator set on the provider + // { + // runningValidatorSet.get(ProviderChain) + // } else { + // runningValidatorSet.get(chain) + // } + // ), + // outstandingPacketsToProvider' = outstandingPacketsToProvider, + // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), + // receivedMaturations' = receivedMaturations, + // maturationTimes' = maturationTimes, + // // chain times do not change + // curChainTimes' = curChainTimes, + // // the validator set was not changed by this action (but might have been changed before in this block) + // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock + // } + + // // Updates the outstandingPacketsToConsumer and sentVSCPackets variables + // action RegisterNewOutstandingPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = + // all { + // outstandingPacketsToConsumer' = newOutstandingPackets, + // StoreSentPackets(newOutstandingPackets), + // } + + + // // stores the VSCPackets sent in this step in sentVSCPackets + // action StoreSentPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = + // sentVSCPackets' = sentVSCPackets.keys().mapBy( + // (chain) => + // sentVSCPackets.get(chain).union(newOutstandingPackets.get(chain).toSet()) + // ) + + // // the main step action + // action step: bool = any { + // AdvanceTime, + // nondet node = oneOf(Nodes) + // nondet amount = oneOf(1.to(10)) + // votingPowerChange(node, amount), + // recvPacketOnProvider(oneOf(ConsumerChains)), + // recvPacketOnConsumer(oneOf(ConsumerChains)), + // nondet chain = oneOf(chains) + // endAndBeginBlock(chain), + // val shouldAdvance = ConsumerChains.mapBy( + // chain => + // nondet should = oneOf(Set(true, false)) + // should + // ) + // AdvanceConsumers(shouldAdvance), + // } + + // pure val nodePowerSet = Nodes.powerset() + + // def getArbitraryValidatorSet(): ValidatorSet = + // nondet numValidators = oneOf(1.to(Nodes.size())) + // // toList has nondeterministic behaviour, so this gets arbitrary validators + // nondet validators = oneOf(nodePowerSet.filter(s => s.size() == numValidators)) + // validators.mapBy( + // validator => + // nondet votingPower = oneOf(1.to(10)) + // votingPower + // ) + + // // INITIALIZATION + // action init: bool = + // all { + // val validatorSets = chains.mapBy( + // (chain) => + // // provider chain gets an arbitrary validator set, consumer chains have none + // if (chain == ProviderChain) getArbitraryValidatorSet else Map() + // ) + // all { + // votingPowerHistories' = chains.mapBy( + // (chain) => + // List(validatorSets.get(chain)) + // ), + // runningValidatorSet' = validatorSets, + // }, + // // each chain starts at time 0 + // curChainTimes' = chains.mapBy( + // (chain) => 0 + // ), + // // all consumer chains are unused + // consumerStatus' = chains.mapBy(chain => UNUSED), + // // no packets are outstanding + // outstandingPacketsToProvider' = chains.mapBy(chain => List()), + // outstandingPacketsToConsumer' = chains.mapBy(chain => List()), + // // no maturations have been received by provider + // receivedMaturations' = Set(), + // // no packets have been sent to consumers + // sentVSCPackets' = chains.mapBy(chain => Set()), + // // no packets have been received by consumers, so no maturation times set + // maturationTimes' = chains.mapBy(chain => Map()), + // // validator set was not changed yet + // providerValidatorSetChangedInThisBlock' = false + // } + + // // PROPERTIES + + // // Every validator set on any consumer chain MUST either be or + // // have been a validator set on the provider chain. + // val ValidatorSetReplication: bool = + // chains.forall( + // chain => chain.getCurrentValidatorSet().wasValidatorSetOnProvider() + // ) + + // // TESTS + // run VSCHappyPathTest: bool = { + // init + // // trigger a votingPowerChange on the provider chain + // .then(votingPowerChange("A", 10)) + // // endAndBeginBlock on provider. No consumer chains are running, so no packets are sent + // .then(endAndBeginBlock(ProviderChain)) + // .then(all { + // // no packet was sent + // assert(outstandingPacketsToConsumer.get("chain1").length() == 0), + // // advance chain1 to running + // AdvanceConsumers(NoStatusAdvancement.set("chain1", true)) + // }) + // // consumer chain should have current validator set from provider + // .then( + // all { + // // since consumer chain just started, its assumed to have the validator set from provider + // assert(runningValidatorSet.get("chain1") == runningValidatorSet.get(ProviderChain)), + // // trigger a votingPowerChange on the provider chain + // votingPowerChange("B", 10) + // } + // ) + // .then( + // val valSet = runningValidatorSet.get(ProviderChain) + // endAndBeginBlock(ProviderChain) + // // now the provider should send a packet on block end + // .then(all { + // // a packet was sent + // assert(outstandingPacketsToConsumer.get("chain1").length() == 1), + // // deliver the packet to the consumer + // recvPacketOnConsumer("chain1") + // }) + // .then( + // // consumer needs to end a block before it has the new validator set + // endAndBeginBlock("chain1") + // ) + // .then(all { + // // the consumer should have the new validator set + // assert(runningValidatorSet.get("chain1") == valSet), + // // put a last action to satisfy the action effect + // AdvanceConsumers(NoStatusAdvancement) + // }) + // ) + // } + + // // utility: the set of consumers currently running + // val RunningConsumers: Set[Chain] = + // ConsumerChains.filter(chain => consumerStatus.get(chain) == RUNNING) + + // // MODEL STATE + // // --SHARED STATE + + // // Stores, for each chain, the list of voting powers that corresponded to voting powers + // // at blocks over its entire existence. + // // Voting powers should be ordered by recency in descending order. + // var votingPowerHistories: Chain -> List[ValidatorSet] + + // // the current validator set on each chain. + // // this will be included in the next block, but might not be final yet, + // // e.g. there may be more modifications in the current block. + // var runningValidatorSet: Chain -> ValidatorSet + + // // the current timestamp for each chain + // var curChainTimes: Chain -> Timestamp + + // // stores, for each chain, its current status - + // // unused, running, or stopped + // var consumerStatus: Chain -> str + + // // --CHANNELS + // // Stores, for each consumer chain, the list of packets that have been sent to the provider chain + // // and have not been received yet. + // var outstandingPacketsToProvider: Chain -> List[VSCMaturedPacket] + + // // Stores, for each consumer chain, the list of packets that have been sent to the consumer chain + // // and have not been received yet. + // var outstandingPacketsToConsumer: Chain -> List[VSCPacket] + + + // // --CONSUMER STATE + // // Stores the maturation times for VSCPackets received by consumers + // var maturationTimes: Chain -> (VSCPacket -> Timestamp) + + // // --PROVIDER STATE + // // the set of VSCMaturedPackets received by the provider chain + // var receivedMaturations: Set[VSCMaturedPacket] + + // // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness + // var sentVSCPackets: Chain -> Set[VSCPacket] + + // // stores whether, in this step, the validator set considered to be changed. + // // this is needed because the validator set might be considered to have changed, even though + // // it is still technically identical at our level of abstraction, e.g. a validator power change on the provider + // // might leave the validator set the same because a delegation and undelegation cancel each other out. + // var providerValidatorSetChangedInThisBlock: bool + + // // utility: a struct summarizing the current state + // val state = + // { + // votingPowerHistories: votingPowerHistories, + // runningValidatorSet: runningValidatorSet, + // curChainTimes: curChainTimes, + // consumerStatus: consumerStatus, + // outstandingPacketsToProvider: outstandingPacketsToProvider, + // outstandingPacketsToConsumer: outstandingPacketsToConsumer, + // maturationTimes: maturationTimes, + // receivedMaturations: receivedMaturations, + // sentVSCPackets: sentVSCPackets, + // } + + // // set of identifiers of potential nodes + // pure val Nodes: Set[Node] = + // Set("A", "B", "C", "D", "E", "F", "G", "H", "I", "J") + + // // the set of consumer chains + // pure val ConsumerChains: Set[Chain] = + // Set("chain1", "chain2", "chain3") + + // // The singular provider chain. + // pure val ProviderChain: Chain = + // "provider" + + // pure val chains = ConsumerChains.union(Set(ProviderChain)) + + // // length of the unbonding period on each chain + // pure val UnbondingPeriod: Chain -> int = chains.mapBy( + // (chain) => + // 10 + // ) + + // // the time until a packet times out + // pure val PacketTimeout: int = + // 5 + + // // the time until a consumer chain is dropped by the provider due to inactivity + // pure val InactivityTimeout: int = + // 10 + + // // utility: a map assigning each chain to 0, used for not advancing timestamps + // pure val NoTimeAdvancement: Chain -> int = chains.mapBy( + // (chain) => + // 0 + // ) + + + // // utility: a map assigning each chain to false, used for not advancing consumer status + // pure val NoStatusAdvancement: Chain -> bool = chains.mapBy( + // (chain) => + // false + // ) } diff --git a/tests/difference/core/quint_model/extraSpells.qnt b/tests/difference/core/quint_model/extraSpells.qnt index cd2105beb7..5c98f7a384 100644 --- a/tests/difference/core/quint_model/extraSpells.qnt +++ b/tests/difference/core/quint_model/extraSpells.qnt @@ -1,4 +1,3 @@ --*- mode: Bluespec; -*- // This module is just a library with utility functions (sometimes called spells in Quint). module extraSpells { From 4bbe033ddf663526c2904f842ec301efe8a7996f Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Tue, 19 Sep 2023 17:00:27 +0200 Subject: [PATCH 14/80] Continue seperating logic in Quint model --- tests/difference/core/quint_model/ccv.qnt | 114 ++++++++++++++++++---- 1 file changed, 97 insertions(+), 17 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 4cbc327ac4..5df198fd73 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -103,8 +103,9 @@ module ccv_logic { // Stores the list of packets that have been sent to the provider chain by this consumer // and have not been received yet. + // ordered by recency, so the head is the oldest packet. // In the implementation, essentially unacknowledged IBC packets. - outstandingPacketsToProvider: Chain -> List[VSCMaturedPacket], + outstandingPacketsToProvider: List[VSCMaturedPacket], // Stores the list of voting powers that corresponded to voting powers // at blocks over the chains entire existence. @@ -118,7 +119,7 @@ module ccv_logic { // the state of each consumer chain. // note that we assume that this contains all consumer chains that may ever exist, // and consumer chains that are currently not running will have providerState.consumerStatus == UNUSED or STOPPED - consumerStates: Set[ConsumerState] + consumerStates: Chain -> ConsumerState } type Error = { @@ -160,7 +161,7 @@ module ccv_logic { providerValidatorSetChangedInThisBlock: false, consumerStatus: Map() }, - consumerStates: Set() + consumerStates: Map(), }, error: { message: msg @@ -171,26 +172,105 @@ module ccv_logic { // =================== // PROTOCOL LOGIC // =================== + + // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, + // e.g. via undelegations, or delegations, ... + pure def votingPowerChange(currentState: ProtocolState, validator: Node, amount: int): Result = { + if (amount < 0) { + Err("Voting power changes must be positive") + } else { + pure val currentValidatorSet = currentState.providerState.chainState.currentValidatorSet + pure val newValidatorSet = getUpdatedValidatorSet(currentValidatorSet, validator, amount) + pure val newState = setProviderValidatorSet(currentState, newValidatorSet) + Ok(newState) + } + } + + // Delivers the next queued VSCMaturedPacket from a consumer chain to the provider chain. + // Only argument is the consumer chain, from which the packet will be delivered. + pure def deliverPacketToProvider(currentState: ProtocolState, sender: Chain): Result = { + if (not(isCurrentlyConsumer(sender, currentState))) { + Err("Sender is not currently a consumer - must have 'running' status!") + } else if (length(currentState.consumerStates.get(sender).outstandingPacketsToProvider) == 0) { + Err("No outstanding packets to deliver") + } else { + val packet = currentState.consumerStates.get(sender).outstandingPacketsToProvider.head() + val result = recvPacketOnProvider(currentState, sender, packet) + val tmpState = result.newState + if (result.hasError) { + Err(result.error.message) + } else { + val result2 = removeOutstandingPacketFromConsumer(tmpState, sender) + val tmpState2 = result2.newState + val err2 = result2.error + if (result2.hasError) { + Err(err2.message) + } else { + Ok(tmpState2) + } + } + } + } + + // =================== + // UTILITY FUNCTIONS + // =================== + + // receives a given packet on the provider. The arguments are the consumer chain that sent the packet, and the packet itself. + pure def recvPacketOnProvider(currentState: ProtocolState, sender: Chain, packet: VSCMaturedPacket): Result = { + if (not(isCurrentlyConsumer(sender, currentState))) { + Err("Sender is not currently a consumer - must have 'running' status!") + } else { + val currentReceivedMaturations = currentState.providerState.receivedMaturations + val newReceivedMaturations = currentReceivedMaturations.add(packet) + val newProviderState = currentState.providerState.with( + "receivedMaturations", newReceivedMaturations + ) + val newState = currentState.with( + "providerState", newProviderState + ) + Ok(newState) + } + } + + // removes the oldest outstanding packet from the consumer. on-chain, this would happen when the packet is acknowledged. + // only the oldest packet can be removed, since we model ordered channels. + pure def removeOutstandingPacketFromConsumer(currentState: ProtocolState, sender: Chain): Result = { + val currentOutstandingPackets = currentState.consumerStates.get(sender).outstandingPacketsToProvider + val newOutstandingPackets = currentOutstandingPackets.tail() + val newConsumerState = currentState.consumerState.get(sender).with( + "outstandingPacketsToProvider", newOutstandingPackets + ) + val newConsumerStates = currentState.consumerStates.set(sender, newConsumerState) + val newState = currentState.with( + "consumerStates", newConsumerStates + ) + Ok(newState) + // Err("Not implemented") + } pure def getUpdatedValidatorSet(oldValidatorSet: ValidatorSet, validator: Node, newVotingPower: int): ValidatorSet = if (newVotingPower > 0) oldValidatorSet.put(validator, newVotingPower) else oldValidatorSet.mapRemove(validator) - - // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, - // e.g. via undelegations, or delegations, ... - pure def votingPowerChange(currentState: ProtocolState, validator: Node, amount: int): Result = - // adjust the current validator set on the provider - it is not entered in the voting history yet because that happens only on block end - val currentValidatorSet = currentState.providerState.currentValidatorSet - // val newValidatorSet = getUpdatedValidatorSet(currentValidatorSet, validator, amount) - // val newProviderState = currentState.providerState.with( - // "currentValidatorSet", newValidatorSet - // ) - // val newState = currentState.with( - // "providerState", newProviderState - // ) - Err("not implemented") + + pure def setProviderValidatorSet(currentState: ProtocolState, newValidatorSet: ValidatorSet): ProtocolState = { + pure val newChainState = currentState.providerState.chainState.with( + "currentValidatorSet", newValidatorSet + ) + currentState.with( + "providerState", + currentState.providerState.with( + "chainState", newChainState + ) + ) + } + + pure def isCurrentlyConsumer(chain: Chain, currentState: ProtocolState): bool = { + val status = currentState.providerState.consumerStatus.get(chain) + status == RUNNING + } } module ccv_tests { From 5ebab39b7aacc30fa2a5963d1187860c706953d4 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Wed, 20 Sep 2023 13:23:55 +0200 Subject: [PATCH 15/80] Start debugging cryptic error message --- tests/difference/core/quint_model/ccv.qnt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 5df198fd73..d0924f9e50 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -106,11 +106,6 @@ module ccv_logic { // ordered by recency, so the head is the oldest packet. // In the implementation, essentially unacknowledged IBC packets. outstandingPacketsToProvider: List[VSCMaturedPacket], - - // Stores the list of voting powers that corresponded to voting powers - // at blocks over the chains entire existence. - // Voting powers should be ordered by recency in descending order. - votingPowerHistory: VotingPowerHistory, } // the state of the protocol consists of the composition of the state of one provider chain with potentially many consumer chains. @@ -153,7 +148,7 @@ module ccv_logic { chainState: { votingPowerHistory: List(), currentValidatorSet: Map(), - lastTimestamp: 0 + lastTimestamp: 0, }, outstandingPacketsToConsumer: Map(), receivedMaturations: Set(), From 5bca6fc7e3a50c03dba32a7ad7df2a0361cbba2d Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Wed, 20 Sep 2023 14:38:51 +0200 Subject: [PATCH 16/80] Start adding endAndBeginBlock defs --- tests/difference/core/quint_model/ccv.qnt | 123 ++++++++++++++++-- .../core/quint_model/extraSpells.qnt | 13 -- 2 files changed, 112 insertions(+), 24 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index d0924f9e50..1c250f94b8 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -9,7 +9,6 @@ module ccv_logic { // Things that explicitly are modelled: // * Validator set changes are propagated from provider to consumers // * VSC packets mature - // * Consumers can be forcefully dropped due to timeouts, or stop on their own volition // =================== // TYPE DEFINITIONS @@ -23,11 +22,10 @@ module ccv_logic { // a list of validator sets per blocks, ordered by recency type VotingPowerHistory = List[ValidatorSet] - // --PACKETS type VSCPacket = { // the identifier for this packet - id: int, + VscId: int, // the new validator set. in the implementation, this would be a list of validator updates validatorSet: ValidatorSet, // the time, that when passed on the receiver chain, will mean the packet is considered timed out @@ -41,12 +39,6 @@ module ccv_logic { // the time, that when passed on the receiver chain, will mean the packet is considered timed out timeout: Timestamp } - - // possible consumer statuses - pure val STOPPED = "stopped" // the chain was once a consumer chain, but has been dropped by the provider. - pure val RUNNING = "running" // the chain is currently a consumer chain. Running chains are those that get sent VSCPackets. - pure val UNUSED = "unused" // the chain has never been a consumer chain, and is available to become one. - // When a chain is dropped, it cannot become a consumer again - we assume that would be done by another consumer becoming running. // state that each chain needs to store, whether consumer or provider. @@ -164,6 +156,23 @@ module ccv_logic { } } + // possible consumer statuses + pure val STOPPED = "stopped" // the chain was once a consumer chain, but has been dropped by the provider. + pure val RUNNING = "running" // the chain is currently a consumer chain. Running chains are those that get sent VSCPackets. + pure val UNUSED = "unused" // the chain has never been a consumer chain, and is available to become one. + // When a chain is dropped, it cannot become a consumer again - we assume that would be done by another consumer becoming running. + + // the provider chain. + // given as a pure val so that we can switch cases based on + // whether a chain is the provider or not + pure val PROVIDER_CHAIN = "provider" + + // =================== + // PROTOCOL PARAMETERS + // =================== + + const UnbondingPeriodPerChain: Chain -> int + // =================== // PROTOCOL LOGIC // =================== @@ -207,11 +216,99 @@ module ccv_logic { } } + pure def endAndBeginBlockForProvider( + currentState: ProtocolState, + chain: Chain, + timeAdvancement: Timestamp, + newConsumerStatusses: Chain -> ConsumerState): Result = { + // commit the current running validator set on chain + val currentProviderState = currentState.providerState + val newChainState = currentState.providerState.chainState.with( + "votingPowerHistory", currentState.providerState.chainState.votingPowerHistory.prepend( + currentState.providerState.chainState.currentValidatorSet + ) + ).with( + "lastTimestamp", currentState.providerState.chainState.lastTimestamp + 1 + ) + Err("not implemented") + // votingPowerHistories' = votingPowerHistories.set(ProviderChain, getUpdatedHistory(ProviderChain)), + // // the running validator set is now for sure the current validator set, + // // so start with it in the next block + // runningValidatorSet' = runningValidatorSet, + // // send VSCPackets to consumers + // val newOutstandingPackets = + // // if running validator set is considered to have changed + // if (providerValidatorSetChangedInThisBlock) + // // then send a packet to each running consumer + // outstandingPacketsToConsumer.keys().mapBy( + // (consumer) => + // val packetQueue = outstandingPacketsToConsumer.get(consumer) + // if (consumerStatus.get(consumer) == RUNNING) { + // packetQueue.append( + // { + // id: packetQueue.length(), + // validatorSet: runningValidatorSet.get(ProviderChain), + // timeout: curChainTimes.get(ProviderChain) + PacketTimeout + // } + // ) + // } else { + // packetQueue + // } + // ) + // else + // // otherwise, don't send any packets + // outstandingPacketsToConsumer + // RegisterNewOutstandingPackets(newOutstandingPackets), + // CONSUMER_NOOP, + // // no packets are sent to the provider + // outstandingPacketsToProvider' = outstandingPacketsToProvider, + // // do not receive any maturations + // receivedMaturations' = receivedMaturations, + // // consumer statusses do not change + // consumerStatus' = consumerStatus, + // // chain times do not change + // curChainTimes' = curChainTimes, + // // the validator set was definitely not changed in the new block yet, so set to false + // providerValidatorSetChangedInThisBlock' = false + } + // =================== // UTILITY FUNCTIONS // =================== + // receives a given packet (sent by the provider) on the consumer. The arguments are the consumer chain that is receiving the packet, and the packet itself. + // To receive a packet, modify the running validator set (not the one entered into the block yet, + // but the candidate that would be put into the block if it ended now) + // and store the maturation time for the packet. + pure def recvPacketOnConsumer(currentState: ProtocolState, receiver: Chain, packet: VSCPacket): Result = { + if(not(isCurrentlyConsumer(receiver, currentState))) { + Err("Receiver is not currently a consumer - must have 'running' status!") + } else { + // update the running validator set, but not the history yet, + // as that only happens when the next block is started + val currentConsumerState = currentState.consumerStates.get(receiver) + val newConsumerState = currentConsumerState.with( + "chainState", + currentConsumerState.chainState.with( + "currentValidatorSet", packet.validatorSet + ) + ).with( + "maturationTimes", + currentConsumerState.maturationTimes.put( + packet, + currentConsumerState.chainState.lastTimestamp + UnbondingPeriodPerChain.get(receiver) + ) + ) + val newConsumerStates = currentState.consumerStates.set(receiver, newConsumerState) + val newState = currentState.with( + "consumerStates", newConsumerStates + ) + Ok(newState) + } + } + // receives a given packet on the provider. The arguments are the consumer chain that sent the packet, and the packet itself. + // To receive a packet, add it to the list of received maturations. pure def recvPacketOnProvider(currentState: ProtocolState, sender: Chain, packet: VSCMaturedPacket): Result = { if (not(isCurrentlyConsumer(sender, currentState))) { Err("Sender is not currently a consumer - must have 'running' status!") @@ -233,7 +330,7 @@ module ccv_logic { pure def removeOutstandingPacketFromConsumer(currentState: ProtocolState, sender: Chain): Result = { val currentOutstandingPackets = currentState.consumerStates.get(sender).outstandingPacketsToProvider val newOutstandingPackets = currentOutstandingPackets.tail() - val newConsumerState = currentState.consumerState.get(sender).with( + val newConsumerState = currentState.consumerStates.get(sender).with( "outstandingPacketsToProvider", newOutstandingPackets ) val newConsumerStates = currentState.consumerStates.set(sender, newConsumerState) @@ -241,15 +338,18 @@ module ccv_logic { "consumerStates", newConsumerStates ) Ok(newState) - // Err("Not implemented") } + // Updates the given oldValidatorSet by setting the validator to newVotingPower. + // If newVotingPower is zero, the validator is removed. pure def getUpdatedValidatorSet(oldValidatorSet: ValidatorSet, validator: Node, newVotingPower: int): ValidatorSet = if (newVotingPower > 0) oldValidatorSet.put(validator, newVotingPower) else oldValidatorSet.mapRemove(validator) + // Returns a ProtocolState where the current validator set on the provider is set to + // newValidatorSet. pure def setProviderValidatorSet(currentState: ProtocolState, newValidatorSet: ValidatorSet): ProtocolState = { pure val newChainState = currentState.providerState.chainState.with( "currentValidatorSet", newValidatorSet @@ -262,6 +362,7 @@ module ccv_logic { ) } + // Returns true if the given chain is currently a running consumer, false otherwise. pure def isCurrentlyConsumer(chain: Chain, currentState: ProtocolState): bool = { val status = currentState.providerState.consumerStatus.get(chain) status == RUNNING diff --git a/tests/difference/core/quint_model/extraSpells.qnt b/tests/difference/core/quint_model/extraSpells.qnt index 5c98f7a384..32f565b16a 100644 --- a/tests/difference/core/quint_model/extraSpells.qnt +++ b/tests/difference/core/quint_model/extraSpells.qnt @@ -146,19 +146,6 @@ module extraSpells { assert(m.mapRemoveAll(Set(5, 7)) == Map(3 -> 4)), assert(m.mapRemoveAll(Set(5, 99999)) == Map(3 -> 4, 7 -> 8)), } - - pure def listSorted(__list: List[a], __lt: (a, a) => bool): List[a] = { - pure def __countSmaller(__j: int): int = { - pure val __jth = __list[__j] - __list.indices().filter(__i => - __lt(__list[__i], __jth) or (__list[__i] == __jth and __i < __j) - ) - .size() - } - - pure val __permutation = __list.indices().mapBy(__i => __countSmaller(__i)) - __list.foldl([], (__l, __i) => __l.append(__list[__permutation.get(__i)])) - } //// Returns a list of all elements of a set. //// From 4f77d68b9ad06525aa7241f392e6754de364f90c Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 21 Sep 2023 10:10:28 +0200 Subject: [PATCH 17/80] Diagnose Quint parser bug --- tests/difference/core/quint_model/ccv.qnt | 162 ++++++++++++++-------- 1 file changed, 105 insertions(+), 57 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 1c250f94b8..d8e6bcbece 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -9,6 +9,10 @@ module ccv_logic { // Things that explicitly are modelled: // * Validator set changes are propagated from provider to consumers // * VSC packets mature + + // We assume that packet receive + ack happen synchronously, + // i.e. when the packet is delivered, the ack is delivered right afterwards. + // This is because it is nontrivial in practice to get a relayer to relay a packet, but not its ack. // =================== // TYPE DEFINITIONS @@ -16,6 +20,7 @@ module ccv_logic { type Node = str type Chain = str type Power = int + type VSCId = int type ValidatorSet = Node -> Power type Height = int type Timestamp = int @@ -25,19 +30,19 @@ module ccv_logic { type VSCPacket = { // the identifier for this packet - VscId: int, + id: VSCId, // the new validator set. in the implementation, this would be a list of validator updates validatorSet: ValidatorSet, - // the time, that when passed on the receiver chain, will mean the packet is considered timed out - timeout: Timestamp + // the time at which the packet was sent. used to check whether packets have timed out. + sendingTime: Timestamp } type VSCMaturedPacket = { // the id of the VSCPacket that matured - id: int, - // the time, that when passed on the receiver chain, will mean the packet is considered timed out - timeout: Timestamp + id: VSCId, + // the time at which the packet was sent. used to check whether packets have timed out. + sendingTime: Timestamp } @@ -74,6 +79,9 @@ module ccv_logic { // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness sentVSCPackets: Chain -> Set[VSCPacket], + // a mapping from (chainId, vscId) tuples to the timestamps of sent VSCPackets. + vscSendTimestamps: (Chain, VSCId) -> Timestamp, + // stores whether, in this block, the validator set has changed. // this is needed because the validator set might be considered to have changed, even though // it is still technically identical at our level of abstraction, e.g. a validator power change on the provider @@ -83,6 +91,10 @@ module ccv_logic { // stores, for each consumer chain, its current status - // unused, running, or stopped consumerStatus: Chain -> str, + + // a monotonic strictly increasing and positive ID that is used + // to uniquely identify the VSCs sent to the consumer chains. + runningVscId: int, } // Defines the current state of a consumer chain. This information is accessible to that consumer on-chain. @@ -105,7 +117,7 @@ module ccv_logic { providerState: ProviderState, // the state of each consumer chain. // note that we assume that this contains all consumer chains that may ever exist, - // and consumer chains that are currently not running will have providerState.consumerStatus == UNUSED or STOPPED + // and consumer chains that are currently not running will have providerState.consumerStatus == UNUSED or STOPPED. consumerStates: Chain -> ConsumerState } @@ -146,7 +158,9 @@ module ccv_logic { receivedMaturations: Set(), sentVSCPackets: Map(), providerValidatorSetChangedInThisBlock: false, - consumerStatus: Map() + consumerStatus: Map(), + runningVscId: 0, + vscSendTimestamps: Map(), }, consumerStates: Map(), }, @@ -171,8 +185,16 @@ module ccv_logic { // PROTOCOL PARAMETERS // =================== + // For each chain, this defines the time between the initiation of an unbonding and its maturation. const UnbondingPeriodPerChain: Chain -> int + // The maximum time duration between sending any VSCPacket to any consumer chain and receiving the + // corresponding VSCMaturedPacket, without timing out the consumer chain and consequently removing it. + const VscTimeout: int + + // The timeoutTimestamp for sending CCV packets. + const CcvTimeoutTimestamp: int + // =================== // PROTOCOL LOGIC // =================== @@ -193,7 +215,7 @@ module ccv_logic { // Delivers the next queued VSCMaturedPacket from a consumer chain to the provider chain. // Only argument is the consumer chain, from which the packet will be delivered. pure def deliverPacketToProvider(currentState: ProtocolState, sender: Chain): Result = { - if (not(isCurrentlyConsumer(sender, currentState))) { + if (not(isCurrentlyConsumer(sender, currentState.providerState))) { Err("Sender is not currently a consumer - must have 'running' status!") } else if (length(currentState.consumerStates.get(sender).outstandingPacketsToProvider) == 0) { Err("No outstanding packets to deliver") @@ -216,60 +238,79 @@ module ccv_logic { } } + // returns the providerState with the following modifications: + // * sends VSCPackets to all running consumers + // * increments the runningVscId + // This should only be called when the provider chain is ending a block, + // and only when the running validator set is considered to have changed + // and there is a consumer to send a packet to. + pure def sendVscPackets(providerState: ProviderState): ProviderState = { + providerState.with( + // send VSCPackets to consumers + "outstandingPacketsToConsumer", + // if running validator set is considered to have changed and there is a consumer to send a packet to + if (providerState.providerValidatorSetChangedInThisBlock + and getRunningConsumers(providerState).size() > 0) { + // then send a packet to each running consumer + providerState.consumerStatus.keys().mapBy( + // go through all potential consumers + (consumer) => + val packetQueue = providerState.outstandingPacketsToConsumer.get(consumer) + // if the consumer is running, send a packet + if (isCurrentlyConsumer(consumer, providerState)) { + packetQueue.append( + { + id: providerState.runningVscId, + validatorSet: providerState.chainState.currentValidatorSet, + sendingTime: providerState.chainState.lastTimestamp + } + ) + } else { + // otherwise, leave the queue as-is + packetQueue + } + ) + } else { + // running validator set is not considered to have changed + // ...so don't send any packets + providerState.outstandingPacketsToConsumer + } + ).with( + // the validator set has not changed yet in the new block + "providerValidatorSetChangedInThisBlock", false + ).with( + "runningVscId", providerState.runningVscId + 1 + ) + } + + // Ends a block on the provider. This means that the current validator set is committed on chain, + // packets are queued, and the next block is started. pure def endAndBeginBlockForProvider( currentState: ProtocolState, chain: Chain, - timeAdvancement: Timestamp, - newConsumerStatusses: Chain -> ConsumerState): Result = { + // by how much the timestamp should be advanced, + // i.e. the timestamp for the next block is oldTimestamp + timeAdvancement + timeAdvancement: Timestamp): Result = { // commit the current running validator set on chain val currentProviderState = currentState.providerState - val newChainState = currentState.providerState.chainState.with( - "votingPowerHistory", currentState.providerState.chainState.votingPowerHistory.prepend( - currentState.providerState.chainState.currentValidatorSet + val newChainState = currentProviderState.chainState.with( + "votingPowerHistory", currentProviderState.chainState.votingPowerHistory.prepend( + currentProviderState.chainState.currentValidatorSet ) ).with( - "lastTimestamp", currentState.providerState.chainState.lastTimestamp + 1 + // advance the time + "lastTimestamp", currentProviderState.chainState.lastTimestamp + timeAdvancement ) + val newProviderState = currentProviderState.with( + "chainState", newChainState + ) + val providerStateAfterSending = + if (currentProviderState.providerValidatorSetChangedInThisBlock and getRunningConsumers(currentState.providerState).size() > 0) { + newProviderState.sendVscPackets() + } else { + newProviderState + } Err("not implemented") - // votingPowerHistories' = votingPowerHistories.set(ProviderChain, getUpdatedHistory(ProviderChain)), - // // the running validator set is now for sure the current validator set, - // // so start with it in the next block - // runningValidatorSet' = runningValidatorSet, - // // send VSCPackets to consumers - // val newOutstandingPackets = - // // if running validator set is considered to have changed - // if (providerValidatorSetChangedInThisBlock) - // // then send a packet to each running consumer - // outstandingPacketsToConsumer.keys().mapBy( - // (consumer) => - // val packetQueue = outstandingPacketsToConsumer.get(consumer) - // if (consumerStatus.get(consumer) == RUNNING) { - // packetQueue.append( - // { - // id: packetQueue.length(), - // validatorSet: runningValidatorSet.get(ProviderChain), - // timeout: curChainTimes.get(ProviderChain) + PacketTimeout - // } - // ) - // } else { - // packetQueue - // } - // ) - // else - // // otherwise, don't send any packets - // outstandingPacketsToConsumer - // RegisterNewOutstandingPackets(newOutstandingPackets), - // CONSUMER_NOOP, - // // no packets are sent to the provider - // outstandingPacketsToProvider' = outstandingPacketsToProvider, - // // do not receive any maturations - // receivedMaturations' = receivedMaturations, - // // consumer statusses do not change - // consumerStatus' = consumerStatus, - // // chain times do not change - // curChainTimes' = curChainTimes, - // // the validator set was definitely not changed in the new block yet, so set to false - // providerValidatorSetChangedInThisBlock' = false } // =================== @@ -281,7 +322,7 @@ module ccv_logic { // but the candidate that would be put into the block if it ended now) // and store the maturation time for the packet. pure def recvPacketOnConsumer(currentState: ProtocolState, receiver: Chain, packet: VSCPacket): Result = { - if(not(isCurrentlyConsumer(receiver, currentState))) { + if(not(isCurrentlyConsumer(receiver, currentState.providerState))) { Err("Receiver is not currently a consumer - must have 'running' status!") } else { // update the running validator set, but not the history yet, @@ -363,10 +404,17 @@ module ccv_logic { } // Returns true if the given chain is currently a running consumer, false otherwise. - pure def isCurrentlyConsumer(chain: Chain, currentState: ProtocolState): bool = { - val status = currentState.providerState.consumerStatus.get(chain) + pure def isCurrentlyConsumer(chain: Chain, providerState: ProviderState): bool = { + val status = providerState.consumerStatus.get(chain) status == RUNNING } + + // Returns the set of all consumer chains that currently have the status RUNNING. + pure def getRunningConsumers(providerState: ProviderState): Set[Chain] = { + providerState.consumerStatus.keys().filter( + chain => providerState.consumerStatus.get(chain) == RUNNING + ) + } } module ccv_tests { From fa233d655ff0a86073f47bdebe7fce5054b7c6b7 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 21 Sep 2023 10:12:59 +0200 Subject: [PATCH 18/80] Fix type in Quint --- tests/difference/core/quint_model/ccv.qnt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index d8e6bcbece..ac5fe631a0 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -351,7 +351,7 @@ module ccv_logic { // receives a given packet on the provider. The arguments are the consumer chain that sent the packet, and the packet itself. // To receive a packet, add it to the list of received maturations. pure def recvPacketOnProvider(currentState: ProtocolState, sender: Chain, packet: VSCMaturedPacket): Result = { - if (not(isCurrentlyConsumer(sender, currentState))) { + if (not(isCurrentlyConsumer(sender, currentState.providerState))) { Err("Sender is not currently a consumer - must have 'running' status!") } else { val currentReceivedMaturations = currentState.providerState.receivedMaturations From 66663bfdf6e8c142553334f20ecc6e98fcde8a52 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 21 Sep 2023 14:15:30 +0200 Subject: [PATCH 19/80] Add endBlock actions --- tests/difference/core/quint_model/ccv.qnt | 190 ++++++++++++++++++---- 1 file changed, 155 insertions(+), 35 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index ac5fe631a0..586c132ac6 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -196,7 +196,8 @@ module ccv_logic { const CcvTimeoutTimestamp: int // =================== - // PROTOCOL LOGIC + // PROTOCOL LOGIC contains the meat of the protocol + // functions here roughly correspond to API calls that can be triggered from external sources // =================== // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, @@ -238,6 +239,159 @@ module ccv_logic { } } + // Ends a block on the provider. This means that the current validator set is committed on chain, + // packets are queued, and the next block is started. + pure def endAndBeginBlockForProvider( + currentState: ProtocolState, + // by how much the timestamp should be advanced, + // i.e. the timestamp for the next block is oldTimestamp + timeAdvancement + timeAdvancement: Timestamp, + // a set of consumers that were unused before, but should be set to running now. + consumersToStart: Set[Chain], + // a set of consumers that were running before, but should be set to stopped now. + consumersToStop: Set[Chain]): Result = { + // commit the current running validator set on chain + val currentProviderState = currentState.providerState + val newChainState = currentProviderState.chainState.endAndBeginBlockShared(timeAdvancement) + // modify the states of the consumers that should be started/stopped + val res = currentProviderState.consumerStatus.getNewConsumerStatusMap(consumersToStart, consumersToStop) + val newConsumerStatus = res._1 + val err = res._2 + if (err != "") { + Err(err) + } else { + val newProviderState = currentProviderState.with( + "chainState", newChainState + ).with( + "consumerStatus", newConsumerStatus + ) + val providerStateAfterSending = + if (currentProviderState.providerValidatorSetChangedInThisBlock and getRunningConsumers(currentState.providerState).size() > 0) { + newProviderState.sendVscPackets() + } else { + newProviderState + } + Err("not implemented") + } + } + + pure def endAndBeginBlockForConsumer( + currentState: ProtocolState, + chain: Chain, + // by how much the timestamp of the chain should be advanced for the next block + timeAdvancement: Timestamp): Result = { + if (currentState.consumerStates.keys().contains(chain)) { + Err("chain is not a consumer") + } else { + // if the chain is not a consumer, return an error + val currentConsumerState = currentState.consumerStates.get(chain) + val newChainState = currentConsumerState.chainState.endAndBeginBlockShared(timeAdvancement) + val newConsumerState = currentConsumerState.with( + "chainState", newChainState + ) + val maturedPackets = newConsumerState.maturationTimes.keys().filter( + packet => + val maturationTime = newConsumerState.maturationTimes.get(packet) + maturationTime <= newChainState.lastTimestamp + ) + val newMaturationTimes = newConsumerState.maturationTimes.mapRemoveAll(maturedPackets) + val newOutstandingPackets = newConsumerState.outstandingPacketsToProvider.concat( + maturedPackets.map( + packet => { + id: packet.id, + sendingTime: newConsumerState.chainState.lastTimestamp + } + ).toList() + ) + val newConsumerState2 = newConsumerState.with( + "maturationTimes", newMaturationTimes + ).with( + "outstandingPacketsToProvider", newOutstandingPackets + ) + val newConsumerStates = currentState.consumerStates.set(chain, newConsumerState2) + val newState = currentState.with( + "consumerStates", newConsumerStates + ) + Ok(newState) + } + } + + // =================== + // UTILITY FUNCTIONS + // which do not hold the core logic of the protocol, but are still part of it + // =================== + + pure def getRunningConsumersFromMap(consumerStatus: Chain -> str): Set[Chain] = { + consumerStatus.keys().filter( + chain => consumerStatus.get(chain) == RUNNING + ) + } + + pure def getStoppedConsumersFromMap(consumerStatus: Chain -> str): Set[Chain] = { + consumerStatus.keys().filter( + chain => consumerStatus.get(chain) == STOPPED + ) + } + + // Returns the new ConsumerStatusMap according to the consumers to start/stop. + // The second return is an error string: If it is not equal to "", + // it contains an error message, and the first return should be ignored. + pure def getNewConsumerStatusMap( + currentConsumerStatusMap: Chain -> str, + consumersToStart: Set[Chain], + consumersToStop: Set[Chain]): (Chain -> str, str) = { + val runningConsumers = getRunningConsumersFromMap(currentConsumerStatusMap) + val stoppedConsumers = getStoppedConsumersFromMap(currentConsumerStatusMap) + // if a consumer is both started and stopped, this is an error + if (consumersToStart.intersect(consumersToStop).size() > 0) { + (currentConsumerStatusMap, "Cannot start and stop a consumer at the same time") + } else { + // if a consumer is started, it must be unused + if (consumersToStart.intersect(runningConsumers).size() > 0) { + (currentConsumerStatusMap, "Cannot start a consumer that is already running") + } else { + // if a consumer is stopped, it must be running + if (consumersToStop.intersect(stoppedConsumers).size() > 0) { + (currentConsumerStatusMap, "Cannot stop a consumer that is not running") + } else { + // if a consumer is started, it must be unused + val newConsumerStatusMap = currentConsumerStatusMap.keys().mapBy( + (chain) => + if (consumersToStart.contains(chain)) { + RUNNING + } else if (consumersToStop.contains(chain)) { + STOPPED + } else { + currentConsumerStatusMap.get(chain) + } + ) + (newConsumerStatusMap, "") + } + } + } + } + + // Takes the currentValidatorSet and puts it as the newest set of the voting history + pure def enterCurValSetIntoBlock(chainState: ChainState): ChainState = { + chainState.with( + "votingPowerHistory", chainState.votingPowerHistory.prepend( + chainState.currentValidatorSet + ) + ) + } + + // Advances the timestamp in the chainState by timeAdvancement + pure def advanceTime(chainState: ChainState, timeAdvancement: Timestamp): ChainState = { + chainState.with( + "lastTimestamp", chainState.lastTimestamp + timeAdvancement + ) + } + + // common logic to update the chain state, used by both provider and consumers. + pure def endAndBeginBlockShared(chainState: ChainState, timeAdvancement: Timestamp): ChainState = { + chainState.enterCurValSetIntoBlock().advanceTime(timeAdvancement) + } + // returns the providerState with the following modifications: // * sends VSCPackets to all running consumers // * increments the runningVscId @@ -283,40 +437,6 @@ module ccv_logic { ) } - // Ends a block on the provider. This means that the current validator set is committed on chain, - // packets are queued, and the next block is started. - pure def endAndBeginBlockForProvider( - currentState: ProtocolState, - chain: Chain, - // by how much the timestamp should be advanced, - // i.e. the timestamp for the next block is oldTimestamp + timeAdvancement - timeAdvancement: Timestamp): Result = { - // commit the current running validator set on chain - val currentProviderState = currentState.providerState - val newChainState = currentProviderState.chainState.with( - "votingPowerHistory", currentProviderState.chainState.votingPowerHistory.prepend( - currentProviderState.chainState.currentValidatorSet - ) - ).with( - // advance the time - "lastTimestamp", currentProviderState.chainState.lastTimestamp + timeAdvancement - ) - val newProviderState = currentProviderState.with( - "chainState", newChainState - ) - val providerStateAfterSending = - if (currentProviderState.providerValidatorSetChangedInThisBlock and getRunningConsumers(currentState.providerState).size() > 0) { - newProviderState.sendVscPackets() - } else { - newProviderState - } - Err("not implemented") - } - - // =================== - // UTILITY FUNCTIONS - // =================== - // receives a given packet (sent by the provider) on the consumer. The arguments are the consumer chain that is receiving the packet, and the packet itself. // To receive a packet, modify the running validator set (not the one entered into the block yet, // but the candidate that would be put into the block if it ended now) From 7b489feefb1a14c660743ec25702f792dce7789f Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Tue, 26 Sep 2023 08:55:40 +0200 Subject: [PATCH 20/80] Start adding state machine module --- tests/difference/core/quint_model/ccv.qnt | 857 ++++++------------ .../core/quint_model/extraSpells.qnt | 18 + tests/difference/core/quint_model/time.qnt | 13 + 3 files changed, 296 insertions(+), 592 deletions(-) create mode 100644 tests/difference/core/quint_model/time.qnt diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 586c132ac6..43c8f9098d 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -1,29 +1,12 @@ -module ccv_logic { - import extraSpells.* from "./extraSpells" - - // Things that are not modelled: - // * Reward distribution - // * Starting/Stopping chains during execution - // * Slashes - - // Things that explicitly are modelled: - // * Validator set changes are propagated from provider to consumers - // * VSC packets mature +module CCVTypes { + import Time.* from "./Time" - // We assume that packet receive + ack happen synchronously, - // i.e. when the packet is delivered, the ack is delivered right afterwards. - // This is because it is nontrivial in practice to get a relayer to relay a packet, but not its ack. - - // =================== - // TYPE DEFINITIONS - // =================== type Node = str type Chain = str type Power = int type VSCId = int type ValidatorSet = Node -> Power type Height = int - type Timestamp = int // a list of validator sets per blocks, ordered by recency type VotingPowerHistory = List[ValidatorSet] @@ -34,7 +17,7 @@ module ccv_logic { // the new validator set. in the implementation, this would be a list of validator updates validatorSet: ValidatorSet, // the time at which the packet was sent. used to check whether packets have timed out. - sendingTime: Timestamp + sendingTime: Time } type VSCMaturedPacket = @@ -42,7 +25,7 @@ module ccv_logic { // the id of the VSCPacket that matured id: VSCId, // the time at which the packet was sent. used to check whether packets have timed out. - sendingTime: Timestamp + sendingTime: Time } @@ -59,9 +42,17 @@ module ccv_logic { currentValidatorSet: ValidatorSet, // the latest timestamp that was comitted on chain - lastTimestamp: Timestamp, + lastTimestamp: Time, } + // utility function: returns a chain state that is initialized minimally. + pure def GetEmptyChainState(): ChainState = + { + votingPowerHistory: List(), + currentValidatorSet: Map(), + lastTimestamp: 0, + } + // Defines the current state of the provider chain. Essentially, all information here is stored by the provider on-chain (or could be derived purely by information that is on-chain). type ProviderState = { @@ -80,7 +71,7 @@ module ccv_logic { sentVSCPackets: Chain -> Set[VSCPacket], // a mapping from (chainId, vscId) tuples to the timestamps of sent VSCPackets. - vscSendTimestamps: (Chain, VSCId) -> Timestamp, + vscSendTimestamps: (Chain, VSCId) -> Time, // stores whether, in this block, the validator set has changed. // this is needed because the validator set might be considered to have changed, even though @@ -97,13 +88,27 @@ module ccv_logic { runningVscId: int, } + // utility function: returns a provider state that is initialized minimally. + pure def GetEmptyProviderState(): ProviderState = + { + chainState: GetEmptyChainState, + outstandingPacketsToConsumer: Map(), + receivedMaturations: Set(), + sentVSCPackets: Map(), + vscSendTimestamps: Map(), + providerValidatorSetChangedInThisBlock: false, + consumerStatus: Map(), + runningVscId: 0, + } + + // Defines the current state of a consumer chain. This information is accessible to that consumer on-chain. type ConsumerState = { // the state that each chain needs to store chainState: ChainState, // Stores the maturation times for VSCPackets received by this consumer - maturationTimes: VSCPacket -> Timestamp, + maturationTimes: VSCPacket -> Time, // Stores the list of packets that have been sent to the provider chain by this consumer // and have not been received yet. @@ -112,6 +117,14 @@ module ccv_logic { outstandingPacketsToProvider: List[VSCMaturedPacket], } + // utility function: returns a consumer state that is initialized minimally. + pure def GetEmptyConsumerState(): ConsumerState = + { + chainState: GetEmptyChainState, + maturationTimes: Map(), + outstandingPacketsToProvider: List(), + } + // the state of the protocol consists of the composition of the state of one provider chain with potentially many consumer chains. type ProtocolState = { providerState: ProviderState, @@ -180,11 +193,36 @@ module ccv_logic { // given as a pure val so that we can switch cases based on // whether a chain is the provider or not pure val PROVIDER_CHAIN = "provider" +} + +module CCV { + // Implements the core logic of the cross-chain validation protocol. + + // Things that are not modelled: + // * Reward distribution + // * Starting/Stopping chains during execution + // * Slashes + + // Things that explicitly are modelled: + // * Validator set changes are propagated from provider to consumers + // * VSC packets mature + + // We assume that packet receive + ack happen synchronously, + // i.e. when the packet is delivered, the ack is delivered right afterwards. + // This is because it is nontrivial in practice to get a relayer to relay a packet, but not its ack. + + import extraSpells.* from "./extraSpells" + import Time.* from "./Time" + import CCVTypes.* + // =================== // PROTOCOL PARAMETERS // =================== + // the set of all possible consumer chains. + const ConsumerChains: Set[Chain] + // For each chain, this defines the time between the initiation of an unbonding and its maturation. const UnbondingPeriodPerChain: Chain -> int @@ -192,8 +230,8 @@ module ccv_logic { // corresponding VSCMaturedPacket, without timing out the consumer chain and consequently removing it. const VscTimeout: int - // The timeoutTimestamp for sending CCV packets. - const CcvTimeoutTimestamp: int + // The timeoutTimestamp for sent packets. Can differ by chain. + const CcvTimeoutPeriod: Chain -> int // =================== // PROTOCOL LOGIC contains the meat of the protocol @@ -239,13 +277,39 @@ module ccv_logic { } } + // Delivers the next queued VSCPacket from the provider chain to a consumer chain. + // Only argument is the consumer chain, to which the packet will be delivered. + pure def deliverPacketToConsumer(currentState: ProtocolState, receiver: Chain): Result = { + if (not(isCurrentlyConsumer(receiver, currentState.providerState))) { + Err("Receiver is not currently a consumer - must have 'running' status!") + } else if (length(currentState.providerState.outstandingPacketsToConsumer.get(receiver)) == 0) { + Err("No outstanding packets to deliver") + } else { + val packet = currentState.providerState.outstandingPacketsToConsumer.get(receiver).head() + val result = recvPacketOnConsumer(currentState, receiver, packet) + val tmpState = result.newState + if (result.hasError) { + Err(result.error.message) + } else { + val result2 = removeOutstandingPacketFromProvider(tmpState, receiver) + val tmpState2 = result2.newState + val err2 = result2.error + if (result2.hasError) { + Err(err2.message) + } else { + Ok(tmpState2) + } + } + } + } + // Ends a block on the provider. This means that the current validator set is committed on chain, // packets are queued, and the next block is started. pure def endAndBeginBlockForProvider( currentState: ProtocolState, // by how much the timestamp should be advanced, // i.e. the timestamp for the next block is oldTimestamp + timeAdvancement - timeAdvancement: Timestamp, + timeAdvancement: Time, // a set of consumers that were unused before, but should be set to running now. consumersToStart: Set[Chain], // a set of consumers that were running before, but should be set to stopped now. @@ -279,7 +343,7 @@ module ccv_logic { currentState: ProtocolState, chain: Chain, // by how much the timestamp of the chain should be advanced for the next block - timeAdvancement: Timestamp): Result = { + timeAdvancement: Time): Result = { if (currentState.consumerStates.keys().contains(chain)) { Err("chain is not a consumer") } else { @@ -381,14 +445,14 @@ module ccv_logic { } // Advances the timestamp in the chainState by timeAdvancement - pure def advanceTime(chainState: ChainState, timeAdvancement: Timestamp): ChainState = { + pure def advanceTime(chainState: ChainState, timeAdvancement: Time): ChainState = { chainState.with( "lastTimestamp", chainState.lastTimestamp + timeAdvancement ) } // common logic to update the chain state, used by both provider and consumers. - pure def endAndBeginBlockShared(chainState: ChainState, timeAdvancement: Timestamp): ChainState = { + pure def endAndBeginBlockShared(chainState: ChainState, timeAdvancement: Time): ChainState = { chainState.enterCurValSetIntoBlock().advanceTime(timeAdvancement) } @@ -501,6 +565,22 @@ module ccv_logic { Ok(newState) } + // removes the oldest outstanding packet (to the given consumer) from the provider. + // on-chain, this would happen when the packet is acknowledged. + // only the oldest packet can be removed, since we model ordered channels. + pure def removeOutstandingPacketFromProvider(currentState: ProtocolState, receiver: Chain): Result = { + val currentOutstandingPackets = currentState.providerState.outstandingPacketsToConsumer.get(receiver) + val newOutstandingPackets = currentOutstandingPackets.tail() + val newProviderState = currentState.providerState.with( + "outstandingPacketsToConsumer", + currentState.providerState.outstandingPacketsToConsumer.set(receiver, newOutstandingPackets) + ) + val newState = currentState.with( + "providerState", newProviderState + ) + Ok(newState) + } + // Updates the given oldValidatorSet by setting the validator to newVotingPower. // If newVotingPower is zero, the validator is removed. pure def getUpdatedValidatorSet(oldValidatorSet: ValidatorSet, validator: Node, newVotingPower: int): ValidatorSet = @@ -535,570 +615,163 @@ module ccv_logic { chain => providerState.consumerStatus.get(chain) == RUNNING ) } -} -module ccv_tests { - import ccv_logic.* - - // // UTILITY FUNCTIONS & ACTIONS - // def wasValidatorSetOnProvider(validatorSet: ValidatorSet): bool = { - // votingPowerHistories.get(ProviderChain).toSet().exists( - // historicalValSet => historicalValSet == validatorSet - // ) - // } - - // def getCurrentValidatorSet(chain: Chain): ValidatorSet = - // votingPowerHistories.get(chain).head() - - // // returns true if the consumer has timed out and should be dropped - // def consumerTimedOut(consumer: Chain): bool = - // any { - // // either a package from provider to consumer has timed out - // outstandingPacketsToConsumer.get(consumer).select( - // packet => packet.timeout <= curChainTimes.get(consumer) - // ).length() > 0, - // // or a package from consumer to provider has timed out - // outstandingPacketsToProvider.get(consumer).select( - // packet => packet.timeout <= curChainTimes.get(ProviderChain) - // ).length() > 0, - // // or the inactivity timeout has passed since a VSCPacket was sent to the consumer, but the - // // provider has not received a VSCMaturedPacket for it - // val packetsWithoutResponse = sentVSCPackets.get(consumer).filter( // get packets without response - // packet => - // not(receivedMaturations.exists( - // maturedPacket => maturedPacket.id == packet.id - // )) - // ) - // // among those, get packets where inactivity timeout has passed - // packetsWithoutResponse.filter( - // packet => - // val sentAt = curChainTimes.get(ProviderChain) - PacketTimeout // compute when the packet was sent - // val timesOutAt = sentAt + InactivityTimeout // compute when the packet times out - // timesOutAt <= curChainTimes.get(ProviderChain) - // ).size() > 0 - // } - - // // utility action that leaves all provider state untouched - // action PROVIDER_NOOP(): bool = - // all { - // receivedMaturations' = receivedMaturations, - // } - - // // utility action that leaves all consumer state untouched - // action CONSUMER_NOOP(): bool = - // all { - // maturationTimes' = maturationTimes, - // } - + // Returns whether the consumer has timed out, and an error message. + // If the second return is not equal to "", the first return should be ignored. + // If it is equal to "", the first return will be true if the consumer has timed out and should be dropped, + // or false otherwise. + def consumerTimedOut(currentState: ProtocolState, consumer: Chain): (bool, str) = + // check for errors: the consumer is not running + if (not(isCurrentlyConsumer(consumer, currentState.providerState))) { + (false, "Consumer is not currently a consumer - must have 'running' status!") + } else { + val providerState = currentState.providerState + val consumerState = currentState.consumerStates.get(consumer) - // // MODEL ACTIONS - - // // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, - // // e.g. via undelegations, or delegations, ... - // action doVotingPowerChange(validator: Node, amount: int): bool = - // // for the provider chain, we need to adjust the voting power history - // // by adding a new set - // all { - // amount >= 0, - // val newValidatorSet = getCurrentValidatorSet(ProviderChain).getUpdatedValidatorSet(validator, amount) - // // set the running validator set on the provider chain, but don't update the history yet - // runningValidatorSet' = runningValidatorSet.set(ProviderChain, newValidatorSet), - // // no packets are sent yet, these are only sent on endAndBeginBlock - // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - // outstandingPacketsToProvider' = outstandingPacketsToProvider, - // receivedMaturations' = receivedMaturations, - // CONSUMER_NOOP, - // // voting power history is only updated on endAndBeginBlock - // votingPowerHistories' = votingPowerHistories, - // // consumer statusses do not change - // consumerStatus' = consumerStatus, - // // chain times do not change - // curChainTimes' = curChainTimes, - // // the validator set is considered to have changed - // providerValidatorSetChangedInThisBlock' = true, - // } - - // // deliver the next outstanding packet from the consumer to the provider. - // // since this model assumes a single provider chain, this just takes a single chain as argument. - // action recvPacketOnProvider(consumer: Chain): bool = all { - // // ensure there is a packet to be received - // outstandingPacketsToProvider.get(consumer).length() > 0, - // // remove packet from outstanding packets - // val newPacketQueue = outstandingPacketsToProvider.get(consumer).tail() - // outstandingPacketsToProvider' = outstandingPacketsToProvider.set(consumer, newPacketQueue), - // // register the packet as received - // val maturedPacket = outstandingPacketsToProvider.get(consumer).head() - // receivedMaturations' = receivedMaturations.add(maturedPacket), - // CONSUMER_NOOP, - // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - // votingPowerHistories' = votingPowerHistories, - // // no validator set changes are made - // runningValidatorSet' = runningValidatorSet, - // // consumer statusses do not change - // consumerStatus' = consumerStatus, - // // chain times do not change - // curChainTimes' = curChainTimes, - // // the validator set was not changed by this action (but might have been changed before in this block) - // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock - // } - - // // deliver the next outstanding packet from the provider to the consumer. - // // since this model assumes a single provider chain, this just takes a single chain as argument. - // action recvPacketOnConsumer(consumer: Chain): bool = all { - // // ensure there is a packet to be received - // outstandingPacketsToConsumer.get(consumer).length() > 0, - // // remove packet from outstanding packets - // val newPacketQueue = outstandingPacketsToConsumer.get(consumer).tail() - // val newOutstandingPackets = outstandingPacketsToConsumer.set(consumer, newPacketQueue) - // RegisterNewOutstandingPackets(newOutstandingPackets), - // val packet = outstandingPacketsToConsumer.get(consumer).head() - // all { - // // update the running validator set, but not the history yet, - // // as that only happens when the next block is started - // runningValidatorSet' = runningValidatorSet.set(consumer, packet.validatorSet), - // // add the new packet and store its maturation time - // val newMaturationTimes = maturationTimes.get(consumer).put(packet, curChainTimes.get(consumer) + UnbondingPeriod.get(consumer)) - // maturationTimes' = maturationTimes.set(consumer, newMaturationTimes) - // }, - // PROVIDER_NOOP, - // votingPowerHistories' = votingPowerHistories, - // outstandingPacketsToProvider' = outstandingPacketsToProvider, - // // consumer statusses do not change - // consumerStatus' = consumerStatus, - // // chain times do not change - // curChainTimes' = curChainTimes, - // // the validator set was not changed by this action (but might have been changed before in this block) - // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock - // } - - // // ends the current block and starts the next block for a given chain. - // action endAndBeginBlock(chain: Chain): bool = any { - // all { - // chain == ProviderChain, - // endAndBeginBlockForProvider, - // }, - // all { - // chain != ProviderChain, - // endAndBeginBlockForConsumer(chain), - // } - // } - - // // gets the updated history for the current chain when ending a block, i.e. the - // // running validator set is added to the history if different from the last one. - // def getUpdatedHistory(chain: Chain): List[ValidatorSet] = - // // update voting power history if the validator set changed - // val newValidatorSet = runningValidatorSet.get(ProviderChain) - // val oldValidatorSet = votingPowerHistories.get(ProviderChain).head() - // if (newValidatorSet != oldValidatorSet) - // votingPowerHistories.get(ProviderChain).prepend(newValidatorSet) - // else - // votingPowerHistories.get(ProviderChain) - - - // action endAndBeginBlockForProvider(): bool = all { - // // update the voting power history - // votingPowerHistories' = votingPowerHistories.set(ProviderChain, getUpdatedHistory(ProviderChain)), - // // the running validator set is now for sure the current validator set, - // // so start with it in the next block - // runningValidatorSet' = runningValidatorSet, - // // send VSCPackets to consumers - // val newOutstandingPackets = - // // if running validator set is considered to have changed - // if (providerValidatorSetChangedInThisBlock) - // // then send a packet to each running consumer - // outstandingPacketsToConsumer.keys().mapBy( - // (consumer) => - // val packetQueue = outstandingPacketsToConsumer.get(consumer) - // if (consumerStatus.get(consumer) == RUNNING) { - // packetQueue.append( - // { - // id: packetQueue.length(), - // validatorSet: runningValidatorSet.get(ProviderChain), - // timeout: curChainTimes.get(ProviderChain) + PacketTimeout - // } - // ) - // } else { - // packetQueue - // } - // ) - // else - // // otherwise, don't send any packets - // outstandingPacketsToConsumer - // RegisterNewOutstandingPackets(newOutstandingPackets), - // CONSUMER_NOOP, - // // no packets are sent to the provider - // outstandingPacketsToProvider' = outstandingPacketsToProvider, - // // do not receive any maturations - // receivedMaturations' = receivedMaturations, - // // consumer statusses do not change - // consumerStatus' = consumerStatus, - // // chain times do not change - // curChainTimes' = curChainTimes, - // // the validator set was definitely not changed in the new block yet, so set to false - // providerValidatorSetChangedInThisBlock' = false - // } - - // action endAndBeginBlockForConsumer(consumer: Chain): bool = all { - // ConsumerChains.contains(consumer), - // // update the voting power history - // votingPowerHistories' = votingPowerHistories.set(consumer, getUpdatedHistory(consumer)), - // // the running validator set is now for sure the current validator set, - // // so start with it in the next block - // runningValidatorSet' = runningValidatorSet, - // // compute mature packets whose maturation time has passed - // val maturedPackets = maturationTimes.get(consumer).keys().filter( - // packet => - // val maturationTime = maturationTimes.get(consumer).get(packet) - // maturationTime <= curChainTimes.get(consumer) - // ) - // all { - // // remove matured packets from the maturation times - // maturationTimes' = maturationTimes.set(consumer, maturationTimes.get(consumer).mapRemoveAll(maturedPackets)), - // // send matured packets - // outstandingPacketsToProvider' = outstandingPacketsToProvider.set( - // consumer, - // // construct VSCMaturedPackets from the matured VSCPackets - // outstandingPacketsToProvider.get(consumer).concat( - // maturedPackets.map(packet => {id: packet.id, timeout: 5}).toList() - // ) - // ) - // }, - // PROVIDER_NOOP, - // // no packets are sent to consumer or received by it - // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - // // consumer statusses do not change - // consumerStatus' = consumerStatus, - // // chain times do not change - // curChainTimes' = curChainTimes, - // // the validator set was not changed by this action (but might have been changed before in this block) - // // also, this is only a new block for a consumer, so the change variable shouldn't be reset - // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock - // } - - // // advance timestamps for maps nondeterministically - // action AdvanceTime(): bool = - // val advanceAmounts = curChainTimes.keys().mapBy( - // chain => - // nondet amount = oneOf(1.to(10)) - // amount - // ) - // AdvanceTimeByMap(advanceAmounts) - - // // the timestamp for each chain is advanced by the given amount - // action AdvanceTimeByMap(advancementAmount: Chain -> int): bool = all - // { - // curChainTimes' = curChainTimes.keys().mapBy( - // chain => - // curChainTimes.get(chain) + advancementAmount.get(chain) - // ), - // // all other variables are left untouched - // votingPowerHistories' = votingPowerHistories, - // runningValidatorSet' = runningValidatorSet, - // outstandingPacketsToProvider' = outstandingPacketsToProvider, - // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - // receivedMaturations' = receivedMaturations, - // maturationTimes' = maturationTimes, - // // chain times do not change - // consumerStatus' = consumerStatus, - // // the validator set was not changed by this action (but might have been changed before in this block) - // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock - // } - - // // each consumer chain may advance in the order - // // some events may necessitate a transition, e.g. timeouts. - // // shouldAdvance gives, for each consumer chain, whether it should advance if possible. - // // if a chain has to advance, e.g. due to timeouts, or may not advance, the value will have no effect. - // action AdvanceConsumers(shouldAdvance: Chain -> bool): bool = - // val newConsumerStatus = consumerStatus.keys().mapBy( - // chain => - // val curStatus = consumerStatus.get(chain) - // if (curStatus == UNUSED) { - // if (shouldAdvance.get(chain)) - // { - // RUNNING - // } else { - // UNUSED - // } - // } - // else if (curStatus == RUNNING) { - // // the chain may transition to stopped. - // // it is *forced* to stop if a packet timed out, - // // or if the inactivity timeout has passed - // if(consumerTimedOut(chain)) { - // STOPPED - // } else { - // if (shouldAdvance.get(chain)) { - // RUNNING - // } else { - // STOPPED - // } - // } - // } else { - // // stopped chains cannot restart, we assume a new chain would be started in that case - // STOPPED - // } - // ) - // all { - // consumerStatus' = newConsumerStatus, - // // all other variables are left untouched - // votingPowerHistories' = votingPowerHistories, - // runningValidatorSet' = runningValidatorSet.keys().mapBy( - // chain => - // if (newConsumerStatus.get(chain) == RUNNING and consumerStatus.get(chain) == UNUSED) - // // consumers that went from unused to running start with the current validator set on the provider - // { - // runningValidatorSet.get(ProviderChain) - // } else { - // runningValidatorSet.get(chain) - // } - // ), - // outstandingPacketsToProvider' = outstandingPacketsToProvider, - // RegisterNewOutstandingPackets(outstandingPacketsToConsumer), - // receivedMaturations' = receivedMaturations, - // maturationTimes' = maturationTimes, - // // chain times do not change - // curChainTimes' = curChainTimes, - // // the validator set was not changed by this action (but might have been changed before in this block) - // providerValidatorSetChangedInThisBlock' = providerValidatorSetChangedInThisBlock - // } - - // // Updates the outstandingPacketsToConsumer and sentVSCPackets variables - // action RegisterNewOutstandingPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = - // all { - // outstandingPacketsToConsumer' = newOutstandingPackets, - // StoreSentPackets(newOutstandingPackets), - // } - - - // // stores the VSCPackets sent in this step in sentVSCPackets - // action StoreSentPackets(newOutstandingPackets: Chain -> List[VSCPacket]): bool = - // sentVSCPackets' = sentVSCPackets.keys().mapBy( - // (chain) => - // sentVSCPackets.get(chain).union(newOutstandingPackets.get(chain).toSet()) - // ) + // has a packe from provider to consumer timed out? + val outstandingPacketsToConsumer = providerState.outstandingPacketsToConsumer.get(consumer) + val providerToConsumerPacketTimedOut = outstandingPacketsToConsumer.head().sendingTime + + CcvTimeoutPeriod.get(PROVIDER_CHAIN) <= consumerState.chainState.lastTimestamp - - // // the main step action - // action step: bool = any { - // AdvanceTime, - // nondet node = oneOf(Nodes) - // nondet amount = oneOf(1.to(10)) - // votingPowerChange(node, amount), - // recvPacketOnProvider(oneOf(ConsumerChains)), - // recvPacketOnConsumer(oneOf(ConsumerChains)), - // nondet chain = oneOf(chains) - // endAndBeginBlock(chain), - // val shouldAdvance = ConsumerChains.mapBy( - // chain => - // nondet should = oneOf(Set(true, false)) - // should - // ) - // AdvanceConsumers(shouldAdvance), - // } - - // pure val nodePowerSet = Nodes.powerset() - - // def getArbitraryValidatorSet(): ValidatorSet = - // nondet numValidators = oneOf(1.to(Nodes.size())) - // // toList has nondeterministic behaviour, so this gets arbitrary validators - // nondet validators = oneOf(nodePowerSet.filter(s => s.size() == numValidators)) - // validators.mapBy( - // validator => - // nondet votingPower = oneOf(1.to(10)) - // votingPower - // ) - - // // INITIALIZATION - // action init: bool = - // all { - // val validatorSets = chains.mapBy( - // (chain) => - // // provider chain gets an arbitrary validator set, consumer chains have none - // if (chain == ProviderChain) getArbitraryValidatorSet else Map() - // ) - // all { - // votingPowerHistories' = chains.mapBy( - // (chain) => - // List(validatorSets.get(chain)) - // ), - // runningValidatorSet' = validatorSets, - // }, - // // each chain starts at time 0 - // curChainTimes' = chains.mapBy( - // (chain) => 0 - // ), - // // all consumer chains are unused - // consumerStatus' = chains.mapBy(chain => UNUSED), - // // no packets are outstanding - // outstandingPacketsToProvider' = chains.mapBy(chain => List()), - // outstandingPacketsToConsumer' = chains.mapBy(chain => List()), - // // no maturations have been received by provider - // receivedMaturations' = Set(), - // // no packets have been sent to consumers - // sentVSCPackets' = chains.mapBy(chain => Set()), - // // no packets have been received by consumers, so no maturation times set - // maturationTimes' = chains.mapBy(chain => Map()), - // // validator set was not changed yet - // providerValidatorSetChangedInThisBlock' = false - // } - - // // PROPERTIES - - // // Every validator set on any consumer chain MUST either be or - // // have been a validator set on the provider chain. - // val ValidatorSetReplication: bool = - // chains.forall( - // chain => chain.getCurrentValidatorSet().wasValidatorSetOnProvider() - // ) - - // // TESTS - // run VSCHappyPathTest: bool = { - // init - // // trigger a votingPowerChange on the provider chain - // .then(votingPowerChange("A", 10)) - // // endAndBeginBlock on provider. No consumer chains are running, so no packets are sent - // .then(endAndBeginBlock(ProviderChain)) - // .then(all { - // // no packet was sent - // assert(outstandingPacketsToConsumer.get("chain1").length() == 0), - // // advance chain1 to running - // AdvanceConsumers(NoStatusAdvancement.set("chain1", true)) - // }) - // // consumer chain should have current validator set from provider - // .then( - // all { - // // since consumer chain just started, its assumed to have the validator set from provider - // assert(runningValidatorSet.get("chain1") == runningValidatorSet.get(ProviderChain)), - // // trigger a votingPowerChange on the provider chain - // votingPowerChange("B", 10) - // } - // ) - // .then( - // val valSet = runningValidatorSet.get(ProviderChain) - // endAndBeginBlock(ProviderChain) - // // now the provider should send a packet on block end - // .then(all { - // // a packet was sent - // assert(outstandingPacketsToConsumer.get("chain1").length() == 1), - // // deliver the packet to the consumer - // recvPacketOnConsumer("chain1") - // }) - // .then( - // // consumer needs to end a block before it has the new validator set - // endAndBeginBlock("chain1") - // ) - // .then(all { - // // the consumer should have the new validator set - // assert(runningValidatorSet.get("chain1") == valSet), - // // put a last action to satisfy the action effect - // AdvanceConsumers(NoStatusAdvancement) - // }) - // ) - // } - - // // utility: the set of consumers currently running - // val RunningConsumers: Set[Chain] = - // ConsumerChains.filter(chain => consumerStatus.get(chain) == RUNNING) - - // // MODEL STATE - // // --SHARED STATE - - // // Stores, for each chain, the list of voting powers that corresponded to voting powers - // // at blocks over its entire existence. - // // Voting powers should be ordered by recency in descending order. - // var votingPowerHistories: Chain -> List[ValidatorSet] - - // // the current validator set on each chain. - // // this will be included in the next block, but might not be final yet, - // // e.g. there may be more modifications in the current block. - // var runningValidatorSet: Chain -> ValidatorSet - - // // the current timestamp for each chain - // var curChainTimes: Chain -> Timestamp - - // // stores, for each chain, its current status - - // // unused, running, or stopped - // var consumerStatus: Chain -> str - - // // --CHANNELS - // // Stores, for each consumer chain, the list of packets that have been sent to the provider chain - // // and have not been received yet. - // var outstandingPacketsToProvider: Chain -> List[VSCMaturedPacket] - - // // Stores, for each consumer chain, the list of packets that have been sent to the consumer chain - // // and have not been received yet. - // var outstandingPacketsToConsumer: Chain -> List[VSCPacket] - - - // // --CONSUMER STATE - // // Stores the maturation times for VSCPackets received by consumers - // var maturationTimes: Chain -> (VSCPacket -> Timestamp) - - // // --PROVIDER STATE - // // the set of VSCMaturedPackets received by the provider chain - // var receivedMaturations: Set[VSCMaturedPacket] - - // // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness - // var sentVSCPackets: Chain -> Set[VSCPacket] - - // // stores whether, in this step, the validator set considered to be changed. - // // this is needed because the validator set might be considered to have changed, even though - // // it is still technically identical at our level of abstraction, e.g. a validator power change on the provider - // // might leave the validator set the same because a delegation and undelegation cancel each other out. - // var providerValidatorSetChangedInThisBlock: bool - - // // utility: a struct summarizing the current state - // val state = - // { - // votingPowerHistories: votingPowerHistories, - // runningValidatorSet: runningValidatorSet, - // curChainTimes: curChainTimes, - // consumerStatus: consumerStatus, - // outstandingPacketsToProvider: outstandingPacketsToProvider, - // outstandingPacketsToConsumer: outstandingPacketsToConsumer, - // maturationTimes: maturationTimes, - // receivedMaturations: receivedMaturations, - // sentVSCPackets: sentVSCPackets, - // } - - // // set of identifiers of potential nodes - // pure val Nodes: Set[Node] = - // Set("A", "B", "C", "D", "E", "F", "G", "H", "I", "J") - - // // the set of consumer chains - // pure val ConsumerChains: Set[Chain] = - // Set("chain1", "chain2", "chain3") - - // // The singular provider chain. - // pure val ProviderChain: Chain = - // "provider" + // has a packet from consumer to provider timed out? + val outstandingPacketsToProvider = consumerState.outstandingPacketsToProvider + val consumerToProviderPacketTimedOut = outstandingPacketsToProvider.head().sendingTime + + CcvTimeoutPeriod.get(consumer) <= providerState.chainState.lastTimestamp + + + + (providerToConsumerPacketTimedOut, "") + } - // pure val chains = ConsumerChains.union(Set(ProviderChain)) - - // // length of the unbonding period on each chain - // pure val UnbondingPeriod: Chain -> int = chains.mapBy( - // (chain) => - // 10 - // ) - - // // the time until a packet times out - // pure val PacketTimeout: int = - // 5 - - // // the time until a consumer chain is dropped by the provider due to inactivity - // pure val InactivityTimeout: int = - // 10 - - // // utility: a map assigning each chain to 0, used for not advancing timestamps - // pure val NoTimeAdvancement: Chain -> int = chains.mapBy( - // (chain) => - // 0 - // ) - - - // // utility: a map assigning each chain to false, used for not advancing consumer status - // pure val NoStatusAdvancement: Chain -> bool = chains.mapBy( - // (chain) => - // false - // ) + // // either a package from provider to consumer has timed out + // currentState..get(consumer).select( + // packet => packet.timeout <= curChainTimes.get(consumer) + // ).length() > 0, + // // or a package from consumer to provider has timed out + // outstandingPacketsToProvider.get(consumer).select( + // packet => packet.timeout <= curChainTimes.get(ProviderChain) + // ).length() > 0, + // // or the inactivity timeout has passed since a VSCPacket was sent to the consumer, but the + // // provider has not received a VSCMaturedPacket for it + // val packetsWithoutResponse = sentVSCPackets.get(consumer).filter( // get packets without response + // packet => + // not(receivedMaturations.exists( + // maturedPacket => maturedPacket.id == packet.id + // )) + // ) + // // among those, get packets where inactivity timeout has passed + // packetsWithoutResponse.filter( + // packet => + // val sentAt = curChainTimes.get(ProviderChain) - PacketTimeout // compute when the packet was sent + // val timesOutAt = sentAt + InactivityTimeout // compute when the packet times out + // timesOutAt <= curChainTimes.get(ProviderChain) + // ).size() > 0 + + // =================== + // ASSUMPTIONS ON MODEL PARAMETERS + // =================== + + // the unbonding period is positive + run UnbondingPeriodPositiveTest = + UnbondingPeriodPerChain.keys().forall(chain => UnbondingPeriodPerChain.get(chain) > 0) + + // the VSC timeout is positive + run VscTimeoutPositiveTest = + VscTimeout > 0 + + // the CCV timeout is positive + run CcvTimeoutPositiveTest = + CcvTimeoutPeriod.keys().forall(chain => CcvTimeoutPeriod.get(chain) > 0) + + // ccv timeout on the provider **must** be larger than unbonding period on each chain + run CcvTimeoutLargerThanUnbondingPeriodTest = + CcvTimeoutPeriod.get(PROVIDER_CHAIN) > UnbondingPeriodPerChain.Values().Max() + + // the provider chain is not a consumer chain + run ProviderNotConsumerTest = + not(ConsumerChains.contains(PROVIDER_CHAIN)) + + // ccv timeout contains only consumers and provider, no other chains + run CcvTimeoutSubsetTest = + CcvTimeoutPeriod.keys().forall(chain => ConsumerChains.contains(chain) or chain == PROVIDER_CHAIN) + + // unbonding period contains consumers and provider, no other chains + def UnbondingPeriodInv = UnbondingPeriodPerChain.keys() == ConsumerChains.add(PROVIDER_CHAIN) + + +} + +// A basic state machine that utilizes the CCV protocol. +// Still leaves constants unassigned, just defines the state machine logic in general, +// i.e. regardless of how many chains there are, what the unbonding periods are, etc. +module CCVStatemachinLogic { + import Time.* from "./Time" + import CCV as CCV + import CCVTypes.* + + var currentState: ProtocolState + + action init: bool = all { + val providerState = GetEmptyProviderState + val consumerStates = CCV::ConsumerChains.mapBy(chain => GetEmptyConsumerState) + currentState' = { + providerState: providerState, + consumerStates: consumerStates + } + } + + action votingPowerChanges(validator: Node, amount: int): bool = + val result = CCV::votingPowerChange(currentState, validator, amount) + all { + result.hasError == false, + currentState' = result.newState, + } + + // The receiver receives the next outstanding VSCPacket from the provider. + action DeliverVSCPacket(receiver: Chain): bool = + val result = CCV::deliverPacketToConsumer(currentState, receiver) + all { + result.hasError == false, + currentState' = result.newState, + } + + action DeliverVSCMaturedPacket(sender: Chain): bool = + val result = CCV::deliverPacketToProvider(currentState, sender) + all { + result.hasError == false, + currentState' = result.newState, + } + + action EndAndBeginBlockForProvider( + timeAdvancement: Time, + consumersToStart: Set[Chain], + consumersToStop: Set[Chain]): bool = + val result = CCV::endAndBeginBlockForProvider(currentState, timeAdvancement, consumersToStart, consumersToStop) + all { + result.hasError == false, + currentState' = result.newState, + } + + action EndAndBeginBlockForConsumer( + chain: Chain, + timeAdvancement: Time): bool = + val result = CCV::endAndBeginBlockForConsumer(currentState, chain, timeAdvancement) + all { + result.hasError == false, + currentState' = result.newState, + } +} + +module CCVDefaultStateMachine { + // A basic state machine that utilizes the CCV protocol. + import Time.* from "./Time" + import CCVTypes.* + import extraSpells.* from "./extraSpells" + + pure val consumerChains = Set("consumer1", "consumer2", "consumer3") + pure val chains = consumerChains.add(PROVIDER_CHAIN) + pure val unbondingPeriods = chains.mapBy(chain => 2 * Week) + pure val ccvTimeouts = chains.mapBy(chain => 3 * Week) + + import CCV(VscTimeout = 5 * Week, CcvTimeoutPeriod = unbondingPeriods, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = chains).* } diff --git a/tests/difference/core/quint_model/extraSpells.qnt b/tests/difference/core/quint_model/extraSpells.qnt index 32f565b16a..1d7d219640 100644 --- a/tests/difference/core/quint_model/extraSpells.qnt +++ b/tests/difference/core/quint_model/extraSpells.qnt @@ -176,4 +176,22 @@ module extraSpells { __set.union(Set(elem)) } + pure def Values(__map: a -> b): Set[b] = { + __map.keys().fold(Set(), (__s, __k) => __s.add(__map.get(__k))) + } + run ValuesTest = + all { + assert(Values(Map(1 -> 2, 3 -> 4)) == Set(2, 4)), + assert(Values(Map()) == Set()) + } + + pure def Max(__set: Set[int]): int = { + __set.fold(0, (__m, __e) => max(__m, __e)) + } + + run MaxTest = + all { + assert(Max(Set(1, 2, 3)) == 3), + assert(Max(Set()) == 0) + } } diff --git a/tests/difference/core/quint_model/time.qnt b/tests/difference/core/quint_model/time.qnt new file mode 100644 index 0000000000..8497d8e1d3 --- /dev/null +++ b/tests/difference/core/quint_model/time.qnt @@ -0,0 +1,13 @@ +// A simple module for time that makes timings more readable, +// e.g. 5 * Minute. +// The base unit are seconds, i.e. to get the number of seconds in a time value, just treat it as an int. +module Time { + type Time = int + + pure val Second = 1 + pure val Minute = 60 * Second + pure val Hour = 60 * Minute + pure val Day = 24 * Hour + pure val Week = 7 * Day + pure val Year = 365 * Day +} \ No newline at end of file From b992f8c305057d38482c0dd54006336fbb3d0364 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Tue, 26 Sep 2023 17:16:22 +0200 Subject: [PATCH 21/80] Save status with crashing effect checker --- tests/difference/core/quint_model/ccv.qnt | 326 ++++++++++++++-------- 1 file changed, 215 insertions(+), 111 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 43c8f9098d..e0f5753a79 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -68,10 +68,7 @@ module CCVTypes { receivedMaturations: Set[VSCMaturedPacket], // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness - sentVSCPackets: Chain -> Set[VSCPacket], - - // a mapping from (chainId, vscId) tuples to the timestamps of sent VSCPackets. - vscSendTimestamps: (Chain, VSCId) -> Time, + sentVSCPackets: Chain -> List[VSCPacket], // stores whether, in this block, the validator set has changed. // this is needed because the validator set might be considered to have changed, even though @@ -95,7 +92,6 @@ module CCVTypes { outstandingPacketsToConsumer: Map(), receivedMaturations: Set(), sentVSCPackets: Map(), - vscSendTimestamps: Map(), providerValidatorSetChangedInThisBlock: false, consumerStatus: Map(), runningVscId: 0, @@ -173,7 +169,6 @@ module CCVTypes { providerValidatorSetChangedInThisBlock: false, consumerStatus: Map(), runningVscId: 0, - vscSendTimestamps: Map(), }, consumerStates: Map(), }, @@ -231,7 +226,7 @@ module CCV { const VscTimeout: int // The timeoutTimestamp for sent packets. Can differ by chain. - const CcvTimeoutPeriod: Chain -> int + const CcvTimeout: Chain -> int // =================== // PROTOCOL LOGIC contains the meat of the protocol @@ -253,6 +248,8 @@ module CCV { // Delivers the next queued VSCMaturedPacket from a consumer chain to the provider chain. // Only argument is the consumer chain, from which the packet will be delivered. + // If this packet will time out on the provider on delivery, + // the consumer will be dropped. pure def deliverPacketToProvider(currentState: ProtocolState, sender: Chain): Result = { if (not(isCurrentlyConsumer(sender, currentState.providerState))) { Err("Sender is not currently a consumer - must have 'running' status!") @@ -260,18 +257,44 @@ module CCV { Err("No outstanding packets to deliver") } else { val packet = currentState.consumerStates.get(sender).outstandingPacketsToProvider.head() - val result = recvPacketOnProvider(currentState, sender, packet) - val tmpState = result.newState - if (result.hasError) { - Err(result.error.message) + // if the packet has timed out, drop the consumer. its state doesn't matter anymore + val timeout = CcvTimeout.get(sender) + if(packet.sendingTime + CcvTimeout.get(sender) > currentState.providerState.chainState.lastTimestamp) { + // drop consumer + val result = getNewConsumerStatusMap( + currentState.providerState.consumerStatus, + Set(), + Set(sender) + ) + + val newConsumerStatus = result._1 + val err = result._2 + if (err != "") { + Err(err) + } else { + val newProviderState = currentState.providerState.with( + "consumerStatus", newConsumerStatus + ) + val newState = currentState.with( + "providerState", newProviderState + ) + Ok(newState) + } } else { - val result2 = removeOutstandingPacketFromConsumer(tmpState, sender) - val tmpState2 = result2.newState - val err2 = result2.error - if (result2.hasError) { - Err(err2.message) + // the packet has not timed out, so receive it on the provider + val result = recvPacketOnProvider(currentState, sender, packet) + val tmpState = result.newState + if (result.hasError) { + Err(result.error.message) } else { - Ok(tmpState2) + val result2 = removeOutstandingPacketFromConsumer(tmpState, sender) + val tmpState2 = result2.newState + val err2 = result2.error + if (result2.hasError) { + Err(err2.message) + } else { + Ok(tmpState2) + } } } } @@ -279,6 +302,8 @@ module CCV { // Delivers the next queued VSCPacket from the provider chain to a consumer chain. // Only argument is the consumer chain, to which the packet will be delivered. + // If this packet will time out on the consumer on delivery, + // the consumer will be dropped. pure def deliverPacketToConsumer(currentState: ProtocolState, receiver: Chain): Result = { if (not(isCurrentlyConsumer(receiver, currentState.providerState))) { Err("Receiver is not currently a consumer - must have 'running' status!") @@ -286,25 +311,54 @@ module CCV { Err("No outstanding packets to deliver") } else { val packet = currentState.providerState.outstandingPacketsToConsumer.get(receiver).head() - val result = recvPacketOnConsumer(currentState, receiver, packet) - val tmpState = result.newState - if (result.hasError) { - Err(result.error.message) + // check if the consumer timed out + if (packet.sendingTime + CcvTimeout.get(PROVIDER_CHAIN) > currentState.consumerStates.get(receiver).chainState.lastTimestamp) { + // drop consumer + val result = getNewConsumerStatusMap( + currentState.providerState.consumerStatus, + Set(), + Set(receiver) + ) + + val newConsumerStatus = result._1 + val err = result._2 + if (err != "") { + Err(err) + } else { + val newProviderState = currentState.providerState.with( + "consumerStatus", newConsumerStatus + ) + val newState = currentState.with( + "providerState", newProviderState + ) + // Ok(newState) + Err("not implemented") + } } else { - val result2 = removeOutstandingPacketFromProvider(tmpState, receiver) - val tmpState2 = result2.newState - val err2 = result2.error - if (result2.hasError) { - Err(err2.message) + // the packet has not timed out, so receive it on the consumer + val result = recvPacketOnConsumer(currentState, receiver, packet) + val tmpState = result.newState + if (result.hasError) { + Err(result.error.message) } else { - Ok(tmpState2) + val result2 = removeOutstandingPacketFromProvider(tmpState, receiver) + val tmpState2 = result2.newState + val err2 = result2.error + if (result2.hasError) { + Err(err2.message) + } else { + Ok(tmpState2) + } } } } } + + // Ends a block on the provider. This means that the current validator set is committed on chain, - // packets are queued, and the next block is started. + // packets are queued, and the next block is started. Also, consumers that have passed + // the VSCTimeout without responding to a pending vscpacket are dropped. pure def endAndBeginBlockForProvider( currentState: ProtocolState, // by how much the timestamp should be advanced, @@ -313,29 +367,44 @@ module CCV { // a set of consumers that were unused before, but should be set to running now. consumersToStart: Set[Chain], // a set of consumers that were running before, but should be set to stopped now. + // This argument only needs to contain "voluntary" stops - + // forced stops, e.g. because a consumer timed out, + // will be added automatically. consumersToStop: Set[Chain]): Result = { // commit the current running validator set on chain val currentProviderState = currentState.providerState val newChainState = currentProviderState.chainState.endAndBeginBlockShared(timeAdvancement) + val providerStateAfterTimeAdvancement = currentProviderState.with( + "chainState", newChainState + ) + + // check for VSC timeouts + val timedOutConsumers = getRunningConsumers(providerStateAfterTimeAdvancement).filter( + consumer => + val res = TimeoutDueToVSCTimeout(currentState, consumer) + res._1 + ) + // modify the states of the consumers that should be started/stopped - val res = currentProviderState.consumerStatus.getNewConsumerStatusMap(consumersToStart, consumersToStop) + val res = providerStateAfterTimeAdvancement.consumerStatus.getNewConsumerStatusMap(consumersToStart, consumersToStop.union(timedOutConsumers)) val newConsumerStatus = res._1 val err = res._2 if (err != "") { Err(err) } else { - val newProviderState = currentProviderState.with( - "chainState", newChainState - ).with( + val providerStateAfterConsumerAdvancement = providerStateAfterTimeAdvancement.with( "consumerStatus", newConsumerStatus ) val providerStateAfterSending = if (currentProviderState.providerValidatorSetChangedInThisBlock and getRunningConsumers(currentState.providerState).size() > 0) { - newProviderState.sendVscPackets() + providerStateAfterConsumerAdvancement.sendVscPackets() } else { - newProviderState + providerStateAfterConsumerAdvancement } - Err("not implemented") + val newState = currentState.with( + "providerState", providerStateAfterSending + ) + Ok(newState) } } @@ -463,42 +532,44 @@ module CCV { // and only when the running validator set is considered to have changed // and there is a consumer to send a packet to. pure def sendVscPackets(providerState: ProviderState): ProviderState = { + val newSentPacketsPerConsumer = ConsumerChains.mapBy( + (consumer) => + // if validator set changed and the consumer is running, send a packet + if (providerState.providerValidatorSetChangedInThisBlock and + isCurrentlyConsumer(consumer, providerState)) { + List({ + id: providerState.runningVscId, + validatorSet: providerState.chainState.currentValidatorSet, + sendingTime: providerState.chainState.lastTimestamp + }) + } else { + List() + } + ) providerState.with( // send VSCPackets to consumers - "outstandingPacketsToConsumer", - // if running validator set is considered to have changed and there is a consumer to send a packet to - if (providerState.providerValidatorSetChangedInThisBlock - and getRunningConsumers(providerState).size() > 0) { - // then send a packet to each running consumer - providerState.consumerStatus.keys().mapBy( - // go through all potential consumers - (consumer) => - val packetQueue = providerState.outstandingPacketsToConsumer.get(consumer) - // if the consumer is running, send a packet - if (isCurrentlyConsumer(consumer, providerState)) { - packetQueue.append( - { - id: providerState.runningVscId, - validatorSet: providerState.chainState.currentValidatorSet, - sendingTime: providerState.chainState.lastTimestamp - } - ) - } else { - // otherwise, leave the queue as-is - packetQueue - } + "outstandingPacketsToConsumer", + ConsumerChains.mapBy( + (consumer) => + providerState.outstandingPacketsToConsumer.get(consumer).concat( + newSentPacketsPerConsumer.get(consumer) + ) + ) + ).with( + // update the sent VSCPackets + "sentVSCPackets", + ConsumerChains.mapBy( + (consumer) => + providerState.sentVSCPackets.get(consumer).concat( + newSentPacketsPerConsumer.get(consumer) ) - } else { - // running validator set is not considered to have changed - // ...so don't send any packets - providerState.outstandingPacketsToConsumer - } + ) ).with( // the validator set has not changed yet in the new block "providerValidatorSetChangedInThisBlock", false ).with( "runningVscId", providerState.runningVscId + 1 - ) + ) } // receives a given packet (sent by the provider) on the consumer. The arguments are the consumer chain that is receiving the packet, and the packet itself. @@ -537,12 +608,17 @@ module CCV { pure def recvPacketOnProvider(currentState: ProtocolState, sender: Chain, packet: VSCMaturedPacket): Result = { if (not(isCurrentlyConsumer(sender, currentState.providerState))) { Err("Sender is not currently a consumer - must have 'running' status!") + } else if (currentState.providerState.sentVSCPackets.get(sender).head().id != packet.id) { + // the packet is not the oldest sentVSCPacket, something went wrong + Err("Received maturation is not for the oldest sentVSCPacket") } else { val currentReceivedMaturations = currentState.providerState.receivedMaturations val newReceivedMaturations = currentReceivedMaturations.add(packet) val newProviderState = currentState.providerState.with( "receivedMaturations", newReceivedMaturations ) + // prune the sentVSCPacket + val newSentVSCPacket = currentState.providerState.sentVSCPackets.get(sender).tail() val newState = currentState.with( "providerState", newProviderState ) @@ -616,11 +692,11 @@ module CCV { ) } - // Returns whether the consumer has timed out, and an error message. + // Returns whether the consumer has timed out due to the VSCTimeout, and an error message. // If the second return is not equal to "", the first return should be ignored. // If it is equal to "", the first return will be true if the consumer has timed out and should be dropped, // or false otherwise. - def consumerTimedOut(currentState: ProtocolState, consumer: Chain): (bool, str) = + pure def TimeoutDueToVSCTimeout(currentState: ProtocolState, consumer: Chain): (bool, str) = // check for errors: the consumer is not running if (not(isCurrentlyConsumer(consumer, currentState.providerState))) { (false, "Consumer is not currently a consumer - must have 'running' status!") @@ -628,44 +704,16 @@ module CCV { val providerState = currentState.providerState val consumerState = currentState.consumerStates.get(consumer) - // has a packe from provider to consumer timed out? - val outstandingPacketsToConsumer = providerState.outstandingPacketsToConsumer.get(consumer) - val providerToConsumerPacketTimedOut = outstandingPacketsToConsumer.head().sendingTime + - CcvTimeoutPeriod.get(PROVIDER_CHAIN) <= consumerState.chainState.lastTimestamp - - // has a packet from consumer to provider timed out? - val outstandingPacketsToProvider = consumerState.outstandingPacketsToProvider - val consumerToProviderPacketTimedOut = outstandingPacketsToProvider.head().sendingTime + - CcvTimeoutPeriod.get(consumer) <= providerState.chainState.lastTimestamp - - - - (providerToConsumerPacketTimedOut, "") + // has a packet been sent on the provider more than VSCTimeout ago, but we have not received an answer since then? + val sentVSCPackets = providerState.sentVSCPackets.get(consumer) + val oldestSentVSCPacket = sentVSCPackets.head() // if length is 0, this is undefined, but we check for this before we use it + if(sentVSCPackets.length() > 0 and oldestSentVSCPacket.sendingTime + VscTimeout < providerState.chainState.lastTimestamp) { + (true, "") + } else { + // no timeout yet, it has not been VscTimeout since that packet was sent + (false, "") + } } - - // // either a package from provider to consumer has timed out - // currentState..get(consumer).select( - // packet => packet.timeout <= curChainTimes.get(consumer) - // ).length() > 0, - // // or a package from consumer to provider has timed out - // outstandingPacketsToProvider.get(consumer).select( - // packet => packet.timeout <= curChainTimes.get(ProviderChain) - // ).length() > 0, - // // or the inactivity timeout has passed since a VSCPacket was sent to the consumer, but the - // // provider has not received a VSCMaturedPacket for it - // val packetsWithoutResponse = sentVSCPackets.get(consumer).filter( // get packets without response - // packet => - // not(receivedMaturations.exists( - // maturedPacket => maturedPacket.id == packet.id - // )) - // ) - // // among those, get packets where inactivity timeout has passed - // packetsWithoutResponse.filter( - // packet => - // val sentAt = curChainTimes.get(ProviderChain) - PacketTimeout // compute when the packet was sent - // val timesOutAt = sentAt + InactivityTimeout // compute when the packet times out - // timesOutAt <= curChainTimes.get(ProviderChain) - // ).size() > 0 // =================== // ASSUMPTIONS ON MODEL PARAMETERS @@ -681,11 +729,11 @@ module CCV { // the CCV timeout is positive run CcvTimeoutPositiveTest = - CcvTimeoutPeriod.keys().forall(chain => CcvTimeoutPeriod.get(chain) > 0) + CcvTimeout.keys().forall(chain => CcvTimeout.get(chain) > 0) // ccv timeout on the provider **must** be larger than unbonding period on each chain run CcvTimeoutLargerThanUnbondingPeriodTest = - CcvTimeoutPeriod.get(PROVIDER_CHAIN) > UnbondingPeriodPerChain.Values().Max() + CcvTimeout.get(PROVIDER_CHAIN) > UnbondingPeriodPerChain.Values().Max() // the provider chain is not a consumer chain run ProviderNotConsumerTest = @@ -693,7 +741,7 @@ module CCV { // ccv timeout contains only consumers and provider, no other chains run CcvTimeoutSubsetTest = - CcvTimeoutPeriod.keys().forall(chain => ConsumerChains.contains(chain) or chain == PROVIDER_CHAIN) + CcvTimeout.keys().forall(chain => ConsumerChains.contains(chain) or chain == PROVIDER_CHAIN) // unbonding period contains consumers and provider, no other chains def UnbondingPeriodInv = UnbondingPeriodPerChain.keys() == ConsumerChains.add(PROVIDER_CHAIN) @@ -711,23 +759,46 @@ module CCVStatemachinLogic { var currentState: ProtocolState + const InitialValidatorSet: ValidatorSet + action init: bool = all { val providerState = GetEmptyProviderState val consumerStates = CCV::ConsumerChains.mapBy(chain => GetEmptyConsumerState) + val providerStateWithConsumers = providerState.with( + "consumerStatus", + CCV::ConsumerChains.mapBy(chain => UNUSED) + ).with( + "outstandingPacketsToConsumer", + CCV::ConsumerChains.mapBy(chain => List()) + ).with( + "sentVSCPackets", + CCV::ConsumerChains.mapBy(chain => List()) + ).with( + // set the validator set to be the initial validator set in the history + "chainState", providerState.chainState.with( + "votingPowerHistory", List(InitialValidatorSet) + ) + ).with( + // set the current validator set + "chainState", providerState.chainState.with( + "currentValidatorSet", InitialValidatorSet + ) + ) currentState' = { providerState: providerState, consumerStates: consumerStates } } - action votingPowerChanges(validator: Node, amount: int): bool = - val result = CCV::votingPowerChange(currentState, validator, amount) + action VotingPowerChange(validator: Node, newVotingPower: int): bool = + val result = CCV::votingPowerChange(currentState, validator, newVotingPower) all { - result.hasError == false, - currentState' = result.newState, - } + result.hasError == false, + currentState' = result.newState, + } // The receiver receives the next outstanding VSCPacket from the provider. + // This will time out the consumer if the packet timeout has passed on the receiver. action DeliverVSCPacket(receiver: Chain): bool = val result = CCV::deliverPacketToConsumer(currentState, receiver) all { @@ -735,6 +806,8 @@ module CCVStatemachinLogic { currentState' = result.newState, } + // The provider receives the next outstanding VSCMaturedPacket from the sender. + // This will time out the consumer if the packet timeout has passed on the provider. action DeliverVSCMaturedPacket(sender: Chain): bool = val result = CCV::deliverPacketToProvider(currentState, sender) all { @@ -773,5 +846,36 @@ module CCVDefaultStateMachine { pure val unbondingPeriods = chains.mapBy(chain => 2 * Week) pure val ccvTimeouts = chains.mapBy(chain => 3 * Week) - import CCV(VscTimeout = 5 * Week, CcvTimeoutPeriod = unbondingPeriods, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = chains).* + pure val nodes = Set("node1", "node2", "node3", "node4", "node5", "node6", "node7", "node8", "node9", "node10") + pure val initialValidatorSet = nodes.mapBy(node => 100) + + import CCV(VscTimeout = 5 * Week, CcvTimeout = unbondingPeriods, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = chains).* + import CCVStatemachinLogic(InitialValidatorSet = initialValidatorSet).* + + run InitTest: bool = { + init.then( + all { + assert(ConsumerChains == chains), + assert(currentState.providerState.consumerStatus == Map( + "consumer1" -> UNUSED, + "consumer2" -> UNUSED, + "consumer3" -> UNUSED + )), + assert(currentState.providerState.outstandingPacketsToConsumer == Map( + "consumer1" -> List(), + "consumer2" -> List(), + "consumer3" -> List() + )), + assert(currentState.providerState.sentVSCPackets == Map( + "consumer1" -> List(), + "consumer2" -> List(), + "consumer3" -> List() + )), + assert(currentState.consumerStates.keys() == chains), + assert(currentState.providerState.chainState.votingPowerHistory == List(InitialValidatorSet)), + assert(currentState.providerState.chainState.currentValidatorSet == InitialValidatorSet), + assert(currentState.providerState.chainState.lastTimestamp == 0), + VotingPowerChange("node1", 50) + }) + } } From baaddb7b1671e0e772512c75be7a391bccd1de48 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Tue, 26 Sep 2023 18:18:58 +0200 Subject: [PATCH 22/80] Resolve issue by removing undefined field --- tests/difference/core/quint_model/ccv.qnt | 26 +++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index e0f5753a79..84bbc9e7e0 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -754,25 +754,27 @@ module CCV { // i.e. regardless of how many chains there are, what the unbonding periods are, etc. module CCVStatemachinLogic { import Time.* from "./Time" - import CCV as CCV + import CCV.* import CCVTypes.* + import extraSpells.* from "./extraSpells" + var currentState: ProtocolState const InitialValidatorSet: ValidatorSet action init: bool = all { val providerState = GetEmptyProviderState - val consumerStates = CCV::ConsumerChains.mapBy(chain => GetEmptyConsumerState) + val consumerStates = ConsumerChains.mapBy(chain => GetEmptyConsumerState) val providerStateWithConsumers = providerState.with( "consumerStatus", - CCV::ConsumerChains.mapBy(chain => UNUSED) + ConsumerChains.mapBy(chain => UNUSED) ).with( "outstandingPacketsToConsumer", - CCV::ConsumerChains.mapBy(chain => List()) + ConsumerChains.mapBy(chain => List()) ).with( "sentVSCPackets", - CCV::ConsumerChains.mapBy(chain => List()) + ConsumerChains.mapBy(chain => List()) ).with( // set the validator set to be the initial validator set in the history "chainState", providerState.chainState.with( @@ -791,7 +793,7 @@ module CCVStatemachinLogic { } action VotingPowerChange(validator: Node, newVotingPower: int): bool = - val result = CCV::votingPowerChange(currentState, validator, newVotingPower) + val result = votingPowerChange(currentState, validator, newVotingPower) all { result.hasError == false, currentState' = result.newState, @@ -800,7 +802,7 @@ module CCVStatemachinLogic { // The receiver receives the next outstanding VSCPacket from the provider. // This will time out the consumer if the packet timeout has passed on the receiver. action DeliverVSCPacket(receiver: Chain): bool = - val result = CCV::deliverPacketToConsumer(currentState, receiver) + val result = deliverPacketToConsumer(currentState, receiver) all { result.hasError == false, currentState' = result.newState, @@ -809,7 +811,7 @@ module CCVStatemachinLogic { // The provider receives the next outstanding VSCMaturedPacket from the sender. // This will time out the consumer if the packet timeout has passed on the provider. action DeliverVSCMaturedPacket(sender: Chain): bool = - val result = CCV::deliverPacketToProvider(currentState, sender) + val result = deliverPacketToProvider(currentState, sender) all { result.hasError == false, currentState' = result.newState, @@ -819,7 +821,7 @@ module CCVStatemachinLogic { timeAdvancement: Time, consumersToStart: Set[Chain], consumersToStop: Set[Chain]): bool = - val result = CCV::endAndBeginBlockForProvider(currentState, timeAdvancement, consumersToStart, consumersToStop) + val result = endAndBeginBlockForProvider(currentState, timeAdvancement, consumersToStart, consumersToStop) all { result.hasError == false, currentState' = result.newState, @@ -828,7 +830,7 @@ module CCVStatemachinLogic { action EndAndBeginBlockForConsumer( chain: Chain, timeAdvancement: Time): bool = - val result = CCV::endAndBeginBlockForConsumer(currentState, chain, timeAdvancement) + val result = endAndBeginBlockForConsumer(currentState, chain, timeAdvancement) all { result.hasError == false, currentState' = result.newState, @@ -849,13 +851,11 @@ module CCVDefaultStateMachine { pure val nodes = Set("node1", "node2", "node3", "node4", "node5", "node6", "node7", "node8", "node9", "node10") pure val initialValidatorSet = nodes.mapBy(node => 100) - import CCV(VscTimeout = 5 * Week, CcvTimeout = unbondingPeriods, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = chains).* - import CCVStatemachinLogic(InitialValidatorSet = initialValidatorSet).* + import CCVStatemachinLogic(InitialValidatorSet = initialValidatorSet, VscTimeout = 5 * Week, CcvTimeout = unbondingPeriods, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = chains).* run InitTest: bool = { init.then( all { - assert(ConsumerChains == chains), assert(currentState.providerState.consumerStatus == Map( "consumer1" -> UNUSED, "consumer2" -> UNUSED, From 2c1341d6453b9326c9f8dcdd6ee18c07c50dac83 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Wed, 27 Sep 2023 09:08:12 +0200 Subject: [PATCH 23/80] Remove add --- tests/difference/core/quint_model/ccv.qnt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 84bbc9e7e0..fc180a2b35 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -613,7 +613,7 @@ module CCV { Err("Received maturation is not for the oldest sentVSCPacket") } else { val currentReceivedMaturations = currentState.providerState.receivedMaturations - val newReceivedMaturations = currentReceivedMaturations.add(packet) + val newReceivedMaturations = currentReceivedMaturations.union(Set(packet)) val newProviderState = currentState.providerState.with( "receivedMaturations", newReceivedMaturations ) @@ -742,10 +742,6 @@ module CCV { // ccv timeout contains only consumers and provider, no other chains run CcvTimeoutSubsetTest = CcvTimeout.keys().forall(chain => ConsumerChains.contains(chain) or chain == PROVIDER_CHAIN) - - // unbonding period contains consumers and provider, no other chains - def UnbondingPeriodInv = UnbondingPeriodPerChain.keys() == ConsumerChains.add(PROVIDER_CHAIN) - } @@ -844,7 +840,7 @@ module CCVDefaultStateMachine { import extraSpells.* from "./extraSpells" pure val consumerChains = Set("consumer1", "consumer2", "consumer3") - pure val chains = consumerChains.add(PROVIDER_CHAIN) + pure val chains = consumerChains.union(Set(PROVIDER_CHAIN)) pure val unbondingPeriods = chains.mapBy(chain => 2 * Week) pure val ccvTimeouts = chains.mapBy(chain => 3 * Week) From e09968d94a4e5a84bf144e5f0737e1f529494772 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Wed, 27 Sep 2023 14:35:55 +0200 Subject: [PATCH 24/80] Fix init --- tests/difference/core/quint_model/ccv.qnt | 29 ++++++++++------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index fc180a2b35..32f3ac5a88 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -719,30 +719,28 @@ module CCV { // ASSUMPTIONS ON MODEL PARAMETERS // =================== - // the unbonding period is positive run UnbondingPeriodPositiveTest = UnbondingPeriodPerChain.keys().forall(chain => UnbondingPeriodPerChain.get(chain) > 0) - // the VSC timeout is positive run VscTimeoutPositiveTest = VscTimeout > 0 - // the CCV timeout is positive run CcvTimeoutPositiveTest = CcvTimeout.keys().forall(chain => CcvTimeout.get(chain) > 0) - // ccv timeout on the provider **must** be larger than unbonding period on each chain run CcvTimeoutLargerThanUnbondingPeriodTest = CcvTimeout.get(PROVIDER_CHAIN) > UnbondingPeriodPerChain.Values().Max() - // the provider chain is not a consumer chain - run ProviderNotConsumerTest = + run ProviderIsNotAConsumerTest = not(ConsumerChains.contains(PROVIDER_CHAIN)) - // ccv timeout contains only consumers and provider, no other chains - run CcvTimeoutSubsetTest = - CcvTimeout.keys().forall(chain => ConsumerChains.contains(chain) or chain == PROVIDER_CHAIN) - + // ccv timeout contains exactly consumers and provider, no other chains + run CcvTimeoutKeysTest = + CcvTimeout.keys() == ConsumerChains.union(Set(PROVIDER_CHAIN)) + + // unbonding period contains exactly consumers and provider, no other chains + run UnbondingPeriodKeysTest = + UnbondingPeriodPerChain.keys() == ConsumerChains.union(Set(PROVIDER_CHAIN)) } // A basic state machine that utilizes the CCV protocol. @@ -775,15 +773,12 @@ module CCVStatemachinLogic { // set the validator set to be the initial validator set in the history "chainState", providerState.chainState.with( "votingPowerHistory", List(InitialValidatorSet) - ) - ).with( - // set the current validator set - "chainState", providerState.chainState.with( + ).with( "currentValidatorSet", InitialValidatorSet ) ) currentState' = { - providerState: providerState, + providerState: providerStateWithConsumers, consumerStates: consumerStates } } @@ -847,7 +842,7 @@ module CCVDefaultStateMachine { pure val nodes = Set("node1", "node2", "node3", "node4", "node5", "node6", "node7", "node8", "node9", "node10") pure val initialValidatorSet = nodes.mapBy(node => 100) - import CCVStatemachinLogic(InitialValidatorSet = initialValidatorSet, VscTimeout = 5 * Week, CcvTimeout = unbondingPeriods, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = chains).* + import CCVStatemachinLogic(InitialValidatorSet = initialValidatorSet, VscTimeout = 5 * Week, CcvTimeout = unbondingPeriods, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = consumerChains).* run InitTest: bool = { init.then( @@ -867,7 +862,7 @@ module CCVDefaultStateMachine { "consumer2" -> List(), "consumer3" -> List() )), - assert(currentState.consumerStates.keys() == chains), + assert(currentState.consumerStates.keys() == consumerChains), assert(currentState.providerState.chainState.votingPowerHistory == List(InitialValidatorSet)), assert(currentState.providerState.chainState.currentValidatorSet == InitialValidatorSet), assert(currentState.providerState.chainState.lastTimestamp == 0), From 55ab5955d71c4e5ea783cdd1a9a2a9de84cad797 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 28 Sep 2023 08:50:07 +0200 Subject: [PATCH 25/80] Snapshot spec with parser crasher --- tests/difference/core/quint_model/ccv.qnt | 243 +++++++++++++++++----- 1 file changed, 192 insertions(+), 51 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 32f3ac5a88..f6b8eb19cc 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -130,6 +130,13 @@ module CCVTypes { consumerStates: Chain -> ConsumerState } + // gets a protocol state that is initialized minimally. + pure def GetEmptyProtocolState(): ProtocolState = + { + providerState: GetEmptyProviderState, + consumerStates: Map(), + } + type Error = { message: str } @@ -298,7 +305,31 @@ module CCV { } } } - } + } + + // Defines a test state to test the deliverPacketToProvider function against. + pure val _DeliverPacketToProvider_TestState = + val currentState = GetEmptyProtocolState + val sender = "sender" + val providerState = currentState.providerState + val consumerState = GetEmptyConsumerState + // add the consumer to the consumerStates + val consumerStates = currentState.consumerStates.set(sender, consumerState) + val providerState2 = providerState.with( + "consumerStatus", providerState.consumerStatus.set(sender, RUNNING) + ) + val providerState3 = providerState2.with( + "outstandingPacketsToConsumer", providerState2.outstandingPacketsToConsumer.set(sender, List({ + id: 0, + validatorSet: Map(), + sendingTime: 0 + })) + ) + currentState.with( + "providerState", providerState3 + ).with( + "consumerStates", consumerStates + ) // Delivers the next queued VSCPacket from the provider chain to a consumer chain. // Only argument is the consumer chain, to which the packet will be delivered. @@ -504,6 +535,7 @@ module CCV { } } + // Takes the currentValidatorSet and puts it as the newest set of the voting history pure def enterCurValSetIntoBlock(chainState: ChainState): ChainState = { chainState.with( @@ -714,49 +746,28 @@ module CCV { (false, "") } } +} - // =================== - // ASSUMPTIONS ON MODEL PARAMETERS - // =================== - - run UnbondingPeriodPositiveTest = - UnbondingPeriodPerChain.keys().forall(chain => UnbondingPeriodPerChain.get(chain) > 0) - - run VscTimeoutPositiveTest = - VscTimeout > 0 - - run CcvTimeoutPositiveTest = - CcvTimeout.keys().forall(chain => CcvTimeout.get(chain) > 0) - - run CcvTimeoutLargerThanUnbondingPeriodTest = - CcvTimeout.get(PROVIDER_CHAIN) > UnbondingPeriodPerChain.Values().Max() - run ProviderIsNotAConsumerTest = - not(ConsumerChains.contains(PROVIDER_CHAIN)) +module CCVDefaultStateMachine { + // A basic state machine that utilizes the CCV protocol. + import Time.* from "./Time" + import CCVTypes.* + import extraSpells.* from "./extraSpells" - // ccv timeout contains exactly consumers and provider, no other chains - run CcvTimeoutKeysTest = - CcvTimeout.keys() == ConsumerChains.union(Set(PROVIDER_CHAIN)) + pure val consumerChains = Set("consumer1", "consumer2", "consumer3") + pure val chains = consumerChains.union(Set(PROVIDER_CHAIN)) + pure val unbondingPeriods = chains.mapBy(chain => 2 * Week) + pure val ccvTimeouts = chains.mapBy(chain => 3 * Week) - // unbonding period contains exactly consumers and provider, no other chains - run UnbondingPeriodKeysTest = - UnbondingPeriodPerChain.keys() == ConsumerChains.union(Set(PROVIDER_CHAIN)) -} + pure val nodes = Set("node1", "node2", "node3", "node4", "node5", "node6", "node7", "node8", "node9", "node10") + pure val InitialValidatorSet = nodes.mapBy(node => 100) -// A basic state machine that utilizes the CCV protocol. -// Still leaves constants unassigned, just defines the state machine logic in general, -// i.e. regardless of how many chains there are, what the unbonding periods are, etc. -module CCVStatemachinLogic { - import Time.* from "./Time" - import CCV.* - import CCVTypes.* + import CCV(VscTimeout = 5 * Week, CcvTimeout = ccvTimeouts, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = consumerChains).* - import extraSpells.* from "./extraSpells" var currentState: ProtocolState - const InitialValidatorSet: ValidatorSet - action init: bool = all { val providerState = GetEmptyProviderState val consumerStates = ConsumerChains.mapBy(chain => GetEmptyConsumerState) @@ -826,23 +837,141 @@ module CCVStatemachinLogic { result.hasError == false, currentState' = result.newState, } -} -module CCVDefaultStateMachine { - // A basic state machine that utilizes the CCV protocol. - import Time.* from "./Time" - import CCVTypes.* - import extraSpells.* from "./extraSpells" + // negative voting powers give an error + run VotingPowerNegativeTest = + votingPowerChange( + GetEmptyProtocolState, + "validator", + -1 + ).hasError + + run VotingPowerOkTest = + val result = votingPowerChange( + GetEmptyProtocolState, + "validator", + 0 + ) + not(result.hasError) and + result.newState.providerState.chainState.currentValidatorSet.keys().contains("validator") and + result.newState.providerState.chainState.currentValidatorSet.get("validator") == 0 + + // make sure that VotingPowerChange ONLY changes the current validator set, not the history + run VotingPowerChangeDoesNotChangeHistoryTest = + val result = votingPowerChange( + GetEmptyProtocolState, + "validator", + 0 + ) + not(result.hasError) and + result.newState.providerState.chainState.votingPowerHistory == List() + + run DeliverPacketToProviderHappyPathTest = + val result = deliverPacketToProvider(_DeliverPacketToProvider_TestState, "sender") + val newProviderState = result.newState.providerState + val newConsumerState = result.newState.consumerStates.get("sender") + not(result.hasError) and + newProviderState.receivedMaturations.size() == 1 and + newConsumerState.outstandingPacketsToProvider.length() == 0 + + run DeliverPacketToProviderTimeoutTest = + // set the timestamp to be after the timeout + val testState = _DeliverPacketToProvider_TestState.with( + "providerState", _DeliverPacketToProvider_TestState.providerState.with( + "chainState", _DeliverPacketToProvider_TestState.providerState.chainState.with( + "lastTimestamp", CcvTimeout.get("sender") + 1 + ) + ) + ) + val result = deliverPacketToProvider(testState, "sender") + val newProviderState = result.newState.providerState + val newConsumerState = result.newState.consumerStates.get("sender") + not(result.hasError) and + newProviderState.receivedMaturations.size() == 0 and + newConsumerState.outstandingPacketsToProvider.length() == 0 and + newProviderState.consumerStatus.get("sender") == STOPPED + + run ConsumerStatusMapHappyPathTest = + val currentConsumerStatusMap = Map( + "chain1" -> UNUSED, + "chain2" -> RUNNING, + "chain3" -> STOPPED + ) + val res = getNewConsumerStatusMap( + currentConsumerStatusMap, + Set("chain1"), + Set("chain3") + ) + res._2 == "" and + res._1.get("chain1") == RUNNING and + res._1.get("chain2") == RUNNING and + res._1.get("chain3") == UNUSED + + run ConsumerStatusMapAlreadyRunningTest = + val currentConsumerStatusMap = Map( + "chain1" -> UNUSED, + "chain2" -> RUNNING, + "chain3" -> STOPPED + ) + val res = getNewConsumerStatusMap( + currentConsumerStatusMap, + Set("chain2"), + Set("chain3") + ) + res._2 == "Cannot start a consumer that is already running" - pure val consumerChains = Set("consumer1", "consumer2", "consumer3") - pure val chains = consumerChains.union(Set(PROVIDER_CHAIN)) - pure val unbondingPeriods = chains.mapBy(chain => 2 * Week) - pure val ccvTimeouts = chains.mapBy(chain => 3 * Week) + run ConsumerStatusMapAlreadyStoppedTest = + val currentConsumerStatusMap = Map( + "chain1" -> UNUSED, + "chain2" -> RUNNING, + "chain3" -> STOPPED + ) + val res = getNewConsumerStatusMap( + currentConsumerStatusMap, + Set("chain1"), + Set("chain3") + ) + res._2 == "Cannot stop a consumer that is not running" - pure val nodes = Set("node1", "node2", "node3", "node4", "node5", "node6", "node7", "node8", "node9", "node10") - pure val initialValidatorSet = nodes.mapBy(node => 100) + run ChainBothInStartAndStopTest = + val currentConsumerStatusMap = Map( + "chain1" -> UNUSED, + "chain2" -> RUNNING, + "chain3" -> STOPPED + ) + val res = getNewConsumerStatusMap( + currentConsumerStatusMap, + Set("chain1"), + Set("chain1") + ) + res._2 == "Cannot start and stop a consumer at the same time" - import CCVStatemachinLogic(InitialValidatorSet = initialValidatorSet, VscTimeout = 5 * Week, CcvTimeout = unbondingPeriods, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = consumerChains).* + // =================== + // ASSUMPTIONS ON MODEL PARAMETERS + // =================== + + run UnbondingPeriodPositiveTest = + UnbondingPeriodPerChain.keys().forall(chain => UnbondingPeriodPerChain.get(chain) > 0) + + run VscTimeoutPositiveTest = + VscTimeout > 0 + + run CcvTimeoutPositiveTest = + CcvTimeout.keys().forall(chain => CcvTimeout.get(chain) > 0) + + run CcvTimeoutLargerThanUnbondingPeriodTest = + CcvTimeout.get(PROVIDER_CHAIN) > UnbondingPeriodPerChain.Values().Max() + + run ProviderIsNotAConsumerTest = + not(ConsumerChains.contains(PROVIDER_CHAIN)) + + // ccv timeout contains exactly consumers and provider, no other chains + run CcvTimeoutKeysTest = + CcvTimeout.keys() == ConsumerChains.union(Set(PROVIDER_CHAIN)) + + // unbonding period contains exactly consumers and provider, no other chains + run UnbondingPeriodKeysTest = + UnbondingPeriodPerChain.keys() == ConsumerChains.union(Set(PROVIDER_CHAIN)) run InitTest: bool = { init.then( @@ -866,7 +995,19 @@ module CCVDefaultStateMachine { assert(currentState.providerState.chainState.votingPowerHistory == List(InitialValidatorSet)), assert(currentState.providerState.chainState.currentValidatorSet == InitialValidatorSet), assert(currentState.providerState.chainState.lastTimestamp == 0), - VotingPowerChange("node1", 50) - }) - } + val firstState = currentState // snapshot the first state + VotingPowerChange("node1", 50).then(all { + // ensure that the only change is that the voting power of node1 is changed + assert(currentState == firstState.with( + "providerState", firstState.providerState.with( + "chainState", firstState.providerState.chainState.with( + "currentValidatorSet", firstState.providerState.chainState.currentValidatorSet.put("node1", 50) + ) + ) + )), + currentState' = currentState + }) + } + ) + } } From 0897e8ccc3834dfa580bd7b3089d8a5051ab778d Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 28 Sep 2023 09:54:22 +0200 Subject: [PATCH 26/80] Snapshot model --- tests/difference/core/quint_model/ccv.qnt | 211 ++++++++++++++-------- 1 file changed, 137 insertions(+), 74 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index f6b8eb19cc..149474e5e6 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -314,12 +314,12 @@ module CCV { val providerState = currentState.providerState val consumerState = GetEmptyConsumerState // add the consumer to the consumerStates - val consumerStates = currentState.consumerStates.set(sender, consumerState) + val consumerStates = currentState.consumerStates.put(sender, consumerState) val providerState2 = providerState.with( - "consumerStatus", providerState.consumerStatus.set(sender, RUNNING) + "consumerStatus", providerState.consumerStatus.put(sender, RUNNING) ) val providerState3 = providerState2.with( - "outstandingPacketsToConsumer", providerState2.outstandingPacketsToConsumer.set(sender, List({ + "outstandingPacketsToConsumer", providerState2.outstandingPacketsToConsumer.put(sender, List({ id: 0, validatorSet: Map(), sendingTime: 0 @@ -746,6 +746,33 @@ module CCV { (false, "") } } + + // =================== + // ASSUMPTIONS ON MODEL PARAMETERS + // =================== + + run UnbondingPeriodPositiveTest = + UnbondingPeriodPerChain.keys().forall(chain => UnbondingPeriodPerChain.get(chain) > 0) + + run VscTimeoutPositiveTest = + VscTimeout > 0 + + run CcvTimeoutPositiveTest = + CcvTimeout.keys().forall(chain => CcvTimeout.get(chain) > 0) + + run CcvTimeoutLargerThanUnbondingPeriodTest = + CcvTimeout.get(PROVIDER_CHAIN) > UnbondingPeriodPerChain.Values().Max() + + run ProviderIsNotAConsumerTest = + not(ConsumerChains.contains(PROVIDER_CHAIN)) + + // ccv timeout contains exactly consumers and provider, no other chains + run CcvTimeoutKeysTest = + CcvTimeout.keys() == ConsumerChains.union(Set(PROVIDER_CHAIN)) + + // unbonding period contains exactly consumers and provider, no other chains + run UnbondingPeriodKeysTest = + UnbondingPeriodPerChain.keys() == ConsumerChains.union(Set(PROVIDER_CHAIN)) } @@ -838,26 +865,102 @@ module CCVDefaultStateMachine { currentState' = result.newState, } + run InitTest: bool = { + init.then( + all { + assert(currentState.providerState.consumerStatus == Map( + "consumer1" -> UNUSED, + "consumer2" -> UNUSED, + "consumer3" -> UNUSED + )), + assert(currentState.providerState.outstandingPacketsToConsumer == Map( + "consumer1" -> List(), + "consumer2" -> List(), + "consumer3" -> List() + )), + assert(currentState.providerState.sentVSCPackets == Map( + "consumer1" -> List(), + "consumer2" -> List(), + "consumer3" -> List() + )), + assert(currentState.consumerStates.keys() == consumerChains), + assert(currentState.providerState.chainState.votingPowerHistory == List(InitialValidatorSet)), + assert(currentState.providerState.chainState.currentValidatorSet == InitialValidatorSet), + assert(currentState.providerState.chainState.lastTimestamp == 0), + val firstState = currentState // snapshot the first state + VotingPowerChange("node1", 50).then(all { + // ensure that the only change is that the voting power of node1 is changed + assert(currentState == firstState.with( + "providerState", firstState.providerState.with( + "chainState", firstState.providerState.chainState.with( + "currentValidatorSet", firstState.providerState.chainState.currentValidatorSet.put("node1", 50) + ) + ) + )), + currentState' = currentState + }) + } + ) + } + +} + +// contains test logic for the stateless functions in the CCV module +module CCVLogicTest { + import CCVTypes.* + import Time.* from "./Time" + import extraSpells.* from "./extraSpells" + + pure val consumerChains = Set("sender", "receiver") + pure val chains = consumerChains.union(Set(PROVIDER_CHAIN)) + pure val unbondingPeriods = chains.mapBy(chain => 2 * Week) + pure val ccvTimeouts = chains.mapBy(chain => 3 * Week) + + import CCV(VscTimeout = 5 * Week, CcvTimeout = ccvTimeouts, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = consumerChains).* + // negative voting powers give an error run VotingPowerNegativeTest = + { votingPowerChange( GetEmptyProtocolState, "validator", -1 ).hasError + } run VotingPowerOkTest = + { val result = votingPowerChange( GetEmptyProtocolState, "validator", - 0 + 5 ) not(result.hasError) and result.newState.providerState.chainState.currentValidatorSet.keys().contains("validator") and - result.newState.providerState.chainState.currentValidatorSet.get("validator") == 0 + result.newState.providerState.chainState.currentValidatorSet.get("validator") == 5 + } + + // validators that get zero voting power are removed + run VotingPowerZeroTest = + { + val tmpResult = votingPowerChange( + GetEmptyProtocolState, + "validator", + 5 + ) + val finalResult = votingPowerChange( + tmpResult.newState, + "validator", + 0 + ) + not(finalResult.hasError) and + not(finalResult.newState.providerState.chainState.currentValidatorSet.keys().contains("validator")) + } + // make sure that VotingPowerChange ONLY changes the current validator set, not the history run VotingPowerChangeDoesNotChangeHistoryTest = + { val result = votingPowerChange( GetEmptyProtocolState, "validator", @@ -865,16 +968,32 @@ module CCVDefaultStateMachine { ) not(result.hasError) and result.newState.providerState.chainState.votingPowerHistory == List() + } run DeliverPacketToProviderHappyPathTest = - val result = deliverPacketToProvider(_DeliverPacketToProvider_TestState, "sender") + { + // add a packet on the consumer + val testState = _DeliverPacketToProvider_TestState.with( + "consumerStates", _DeliverPacketToProvider_TestState.consumerStates.put( + "sender", _DeliverPacketToProvider_TestState.consumerStates.get("sender").with( + "outstandingPacketsToProvider", List({ + id: 0, + sendingTime: 0 + }) + ) + ) + ) + + val result = deliverPacketToProvider(testState, "sender") val newProviderState = result.newState.providerState val newConsumerState = result.newState.consumerStates.get("sender") not(result.hasError) and newProviderState.receivedMaturations.size() == 1 and newConsumerState.outstandingPacketsToProvider.length() == 0 + } run DeliverPacketToProviderTimeoutTest = + { // set the timestamp to be after the timeout val testState = _DeliverPacketToProvider_TestState.with( "providerState", _DeliverPacketToProvider_TestState.providerState.with( @@ -890,8 +1009,10 @@ module CCVDefaultStateMachine { newProviderState.receivedMaturations.size() == 0 and newConsumerState.outstandingPacketsToProvider.length() == 0 and newProviderState.consumerStatus.get("sender") == STOPPED + } run ConsumerStatusMapHappyPathTest = + { val currentConsumerStatusMap = Map( "chain1" -> UNUSED, "chain2" -> RUNNING, @@ -900,14 +1021,16 @@ module CCVDefaultStateMachine { val res = getNewConsumerStatusMap( currentConsumerStatusMap, Set("chain1"), - Set("chain3") + Set("chain2") ) res._2 == "" and res._1.get("chain1") == RUNNING and - res._1.get("chain2") == RUNNING and - res._1.get("chain3") == UNUSED + res._1.get("chain2") == STOPPED and + res._1.get("chain3") == STOPPED + } run ConsumerStatusMapAlreadyRunningTest = + { val currentConsumerStatusMap = Map( "chain1" -> UNUSED, "chain2" -> RUNNING, @@ -919,8 +1042,10 @@ module CCVDefaultStateMachine { Set("chain3") ) res._2 == "Cannot start a consumer that is already running" + } run ConsumerStatusMapAlreadyStoppedTest = + { val currentConsumerStatusMap = Map( "chain1" -> UNUSED, "chain2" -> RUNNING, @@ -932,8 +1057,10 @@ module CCVDefaultStateMachine { Set("chain3") ) res._2 == "Cannot stop a consumer that is not running" + } run ChainBothInStartAndStopTest = + { val currentConsumerStatusMap = Map( "chain1" -> UNUSED, "chain2" -> RUNNING, @@ -945,69 +1072,5 @@ module CCVDefaultStateMachine { Set("chain1") ) res._2 == "Cannot start and stop a consumer at the same time" - - // =================== - // ASSUMPTIONS ON MODEL PARAMETERS - // =================== - - run UnbondingPeriodPositiveTest = - UnbondingPeriodPerChain.keys().forall(chain => UnbondingPeriodPerChain.get(chain) > 0) - - run VscTimeoutPositiveTest = - VscTimeout > 0 - - run CcvTimeoutPositiveTest = - CcvTimeout.keys().forall(chain => CcvTimeout.get(chain) > 0) - - run CcvTimeoutLargerThanUnbondingPeriodTest = - CcvTimeout.get(PROVIDER_CHAIN) > UnbondingPeriodPerChain.Values().Max() - - run ProviderIsNotAConsumerTest = - not(ConsumerChains.contains(PROVIDER_CHAIN)) - - // ccv timeout contains exactly consumers and provider, no other chains - run CcvTimeoutKeysTest = - CcvTimeout.keys() == ConsumerChains.union(Set(PROVIDER_CHAIN)) - - // unbonding period contains exactly consumers and provider, no other chains - run UnbondingPeriodKeysTest = - UnbondingPeriodPerChain.keys() == ConsumerChains.union(Set(PROVIDER_CHAIN)) - - run InitTest: bool = { - init.then( - all { - assert(currentState.providerState.consumerStatus == Map( - "consumer1" -> UNUSED, - "consumer2" -> UNUSED, - "consumer3" -> UNUSED - )), - assert(currentState.providerState.outstandingPacketsToConsumer == Map( - "consumer1" -> List(), - "consumer2" -> List(), - "consumer3" -> List() - )), - assert(currentState.providerState.sentVSCPackets == Map( - "consumer1" -> List(), - "consumer2" -> List(), - "consumer3" -> List() - )), - assert(currentState.consumerStates.keys() == consumerChains), - assert(currentState.providerState.chainState.votingPowerHistory == List(InitialValidatorSet)), - assert(currentState.providerState.chainState.currentValidatorSet == InitialValidatorSet), - assert(currentState.providerState.chainState.lastTimestamp == 0), - val firstState = currentState // snapshot the first state - VotingPowerChange("node1", 50).then(all { - // ensure that the only change is that the voting power of node1 is changed - assert(currentState == firstState.with( - "providerState", firstState.providerState.with( - "chainState", firstState.providerState.chainState.with( - "currentValidatorSet", firstState.providerState.chainState.currentValidatorSet.put("node1", 50) - ) - ) - )), - currentState' = currentState - }) - } - ) - } + } } From d227aeec0d6ebd2727ef47a4a5796f929033737e Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 28 Sep 2023 14:39:52 +0200 Subject: [PATCH 27/80] Start debugging tests --- tests/difference/core/quint_model/ccv.qnt | 125 +++++++++++++++------- 1 file changed, 85 insertions(+), 40 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 149474e5e6..0956e4e9bc 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -257,16 +257,19 @@ module CCV { // Only argument is the consumer chain, from which the packet will be delivered. // If this packet will time out on the provider on delivery, // the consumer will be dropped. - pure def deliverPacketToProvider(currentState: ProtocolState, sender: Chain): Result = { + // The first return is the result of the operation, the second result is a boolean + // that indicates whether the consumer timed out or not. + // If the result has an error, the second return should be ignored. + pure def deliverPacketToProvider(currentState: ProtocolState, sender: Chain): (Result, bool) = { if (not(isCurrentlyConsumer(sender, currentState.providerState))) { - Err("Sender is not currently a consumer - must have 'running' status!") + (Err("Sender is not currently a consumer - must have 'running' status!"), false) } else if (length(currentState.consumerStates.get(sender).outstandingPacketsToProvider) == 0) { - Err("No outstanding packets to deliver") + (Err("No outstanding packets to deliver"), false) } else { val packet = currentState.consumerStates.get(sender).outstandingPacketsToProvider.head() // if the packet has timed out, drop the consumer. its state doesn't matter anymore val timeout = CcvTimeout.get(sender) - if(packet.sendingTime + CcvTimeout.get(sender) > currentState.providerState.chainState.lastTimestamp) { + if(packet.sendingTime + CcvTimeout.get(sender) < currentState.providerState.chainState.lastTimestamp) { // drop consumer val result = getNewConsumerStatusMap( currentState.providerState.consumerStatus, @@ -277,7 +280,7 @@ module CCV { val newConsumerStatus = result._1 val err = result._2 if (err != "") { - Err(err) + (Err(err), false) } else { val newProviderState = currentState.providerState.with( "consumerStatus", newConsumerStatus @@ -285,22 +288,22 @@ module CCV { val newState = currentState.with( "providerState", newProviderState ) - Ok(newState) + (Ok(newState), true) // true because the packet timed out } } else { // the packet has not timed out, so receive it on the provider val result = recvPacketOnProvider(currentState, sender, packet) val tmpState = result.newState if (result.hasError) { - Err(result.error.message) + (Err(result.error.message), false) } else { val result2 = removeOutstandingPacketFromConsumer(tmpState, sender) val tmpState2 = result2.newState val err2 = result2.error if (result2.hasError) { - Err(err2.message) + (Err(err2.message), false) } else { - Ok(tmpState2) + (Ok(tmpState2), false) // false because the packet did not time out } } } @@ -335,15 +338,18 @@ module CCV { // Only argument is the consumer chain, to which the packet will be delivered. // If this packet will time out on the consumer on delivery, // the consumer will be dropped. - pure def deliverPacketToConsumer(currentState: ProtocolState, receiver: Chain): Result = { + // The first return is the result of the operation, the second result is a boolean + // that indicates whether the consumer timed out or not. + // If the result has an error, the second return should be ignored. + pure def deliverPacketToConsumer(currentState: ProtocolState, receiver: Chain): (Result, bool) = { if (not(isCurrentlyConsumer(receiver, currentState.providerState))) { - Err("Receiver is not currently a consumer - must have 'running' status!") + (Err("Receiver is not currently a consumer - must have 'running' status!"), false) } else if (length(currentState.providerState.outstandingPacketsToConsumer.get(receiver)) == 0) { - Err("No outstanding packets to deliver") + (Err("No outstanding packets to deliver"), false) } else { val packet = currentState.providerState.outstandingPacketsToConsumer.get(receiver).head() // check if the consumer timed out - if (packet.sendingTime + CcvTimeout.get(PROVIDER_CHAIN) > currentState.consumerStates.get(receiver).chainState.lastTimestamp) { + if (packet.sendingTime + CcvTimeout.get(PROVIDER_CHAIN) < currentState.consumerStates.get(receiver).chainState.lastTimestamp) { // drop consumer val result = getNewConsumerStatusMap( currentState.providerState.consumerStatus, @@ -354,7 +360,7 @@ module CCV { val newConsumerStatus = result._1 val err = result._2 if (err != "") { - Err(err) + (Err(err), false) } else { val newProviderState = currentState.providerState.with( "consumerStatus", newConsumerStatus @@ -362,23 +368,22 @@ module CCV { val newState = currentState.with( "providerState", newProviderState ) - // Ok(newState) - Err("not implemented") + (Ok(newState), true) // true because the packet timed out } } else { // the packet has not timed out, so receive it on the consumer val result = recvPacketOnConsumer(currentState, receiver, packet) val tmpState = result.newState if (result.hasError) { - Err(result.error.message) + (Err(result.error.message), false) } else { val result2 = removeOutstandingPacketFromProvider(tmpState, receiver) val tmpState2 = result2.newState val err2 = result2.error if (result2.hasError) { - Err(err2.message) + (Err(err2.message), false) } else { - Ok(tmpState2) + (Ok(tmpState2), false) // false because the packet did not time out } } } @@ -831,7 +836,8 @@ module CCVDefaultStateMachine { // The receiver receives the next outstanding VSCPacket from the provider. // This will time out the consumer if the packet timeout has passed on the receiver. action DeliverVSCPacket(receiver: Chain): bool = - val result = deliverPacketToConsumer(currentState, receiver) + val resultAndTimeout = deliverPacketToConsumer(currentState, receiver) + val result = resultAndTimeout._1 all { result.hasError == false, currentState' = result.newState, @@ -840,7 +846,8 @@ module CCVDefaultStateMachine { // The provider receives the next outstanding VSCMaturedPacket from the sender. // This will time out the consumer if the packet timeout has passed on the provider. action DeliverVSCMaturedPacket(sender: Chain): bool = - val result = deliverPacketToProvider(currentState, sender) + val resultAndTimeout = deliverPacketToProvider(currentState, sender) + val result = resultAndTimeout._1 all { result.hasError == false, currentState' = result.newState, @@ -970,21 +977,44 @@ module CCVLogicTest { result.newState.providerState.chainState.votingPowerHistory == List() } - run DeliverPacketToProviderHappyPathTest = - { - // add a packet on the consumer - val testState = _DeliverPacketToProvider_TestState.with( - "consumerStates", _DeliverPacketToProvider_TestState.consumerStates.put( - "sender", _DeliverPacketToProvider_TestState.consumerStates.get("sender").with( - "outstandingPacketsToProvider", List({ - id: 0, - sendingTime: 0 - }) - ) + // add a packet on the consumer + pure val DeliverPacketToProviderHappyPathTest_testState = _DeliverPacketToProvider_TestState.with( + "consumerStates", _DeliverPacketToProvider_TestState.consumerStates.put( + "sender", _DeliverPacketToProvider_TestState.consumerStates.get("sender").with( + "outstandingPacketsToProvider", List({ + id: 0, + sendingTime: 0 + }) + ) + ) + ).with( + // put an entry into sentVSCPacket on the provider that corresponds to the packet we put on the consumer + "providerState", _DeliverPacketToProvider_TestState.providerState.with( + "sentVSCPackets", _DeliverPacketToProvider_TestState.providerState.sentVSCPackets.put( + "sender", List({ + id: 0, + validatorSet: _DeliverPacketToProvider_TestState.providerState.chainState.currentValidatorSet, + sendingTime: 0 + }) ) ) + ) + + pure val DeliverPacketToProviderHappyPathTest_resultAndTimeout = deliverPacketToProvider(DeliverPacketToProviderHappyPathTest_testState, "sender") + + // test is split to be easier to pinpoint which assertion failed + run DidNotTimeOut_DeliverPacketToProviderHappyPathTest = + { + val result = DeliverPacketToProviderHappyPathTest_resultAndTimeout._1 + val timeout = DeliverPacketToProviderHappyPathTest_resultAndTimeout._2 + not(result.hasError) and + not(timeout) + } - val result = deliverPacketToProvider(testState, "sender") + run StateModificationOK_DeliverPacketToProviderHappyPathTest = + { + val result = DeliverPacketToProviderHappyPathTest_resultAndTimeout._1 + val timedOut = DeliverPacketToProviderHappyPathTest_resultAndTimeout._2 val newProviderState = result.newState.providerState val newConsumerState = result.newState.consumerStates.get("sender") not(result.hasError) and @@ -992,17 +1022,32 @@ module CCVLogicTest { newConsumerState.outstandingPacketsToProvider.length() == 0 } - run DeliverPacketToProviderTimeoutTest = - { - // set the timestamp to be after the timeout - val testState = _DeliverPacketToProvider_TestState.with( - "providerState", _DeliverPacketToProvider_TestState.providerState.with( - "chainState", _DeliverPacketToProvider_TestState.providerState.chainState.with( + // add a packet on the consumer + pure val DeliverPacketToProviderTimeoutTest_testState = DeliverPacketToProviderHappyPathTest_testState.with( + "providerState", DeliverPacketToProviderHappyPathTest_testState.providerState.with( + "chainState", DeliverPacketToProviderHappyPathTest_testState.providerState.chainState.with( + // set the timestamp to be after the timeout "lastTimestamp", CcvTimeout.get("sender") + 1 ) ) ) - val result = deliverPacketToProvider(testState, "sender") + + pure val DeliverPacketToProviderTimeoutTest_resultAndTimeout = deliverPacketToProvider(DeliverPacketToProviderTimeoutTest_testState, "sender") + + run DidTimeOut_DeliverPacketToProviderTimeoutTest = + { + val result = DeliverPacketToProviderTimeoutTest_resultAndTimeout._1 + val timedOut = DeliverPacketToProviderTimeoutTest_resultAndTimeout._2 + val newProviderState = result.newState.providerState + val newConsumerState = result.newState.consumerStates.get("sender") + not(result.hasError) and + timedOut + } + + run StateModificationOK_DeliverPacketToProviderTimeoutTest = + { + val result = DeliverPacketToProviderTimeoutTest_resultAndTimeout._1 + val timedOut = DeliverPacketToProviderTimeoutTest_resultAndTimeout._2 val newProviderState = result.newState.providerState val newConsumerState = result.newState.consumerStates.get("sender") not(result.hasError) and From 09b1b8780a40c3912e32ddb14c77a0a5fbb2079c Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 28 Sep 2023 18:23:47 +0200 Subject: [PATCH 28/80] Finish test for quint model --- tests/difference/core/quint_model/ccv.qnt | 114 ++++++++++++++++++---- 1 file changed, 96 insertions(+), 18 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 0956e4e9bc..65a3418e4e 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -248,7 +248,14 @@ module CCV { } else { pure val currentValidatorSet = currentState.providerState.chainState.currentValidatorSet pure val newValidatorSet = getUpdatedValidatorSet(currentValidatorSet, validator, amount) - pure val newState = setProviderValidatorSet(currentState, newValidatorSet) + // set the validator set changed flag + val newProviderState = currentState.providerState.with( + "providerValidatorSetChangedInThisBlock", true + ) + pure val tmpState = currentState.with( + "providerState", newProviderState + ) + pure val newState = setProviderValidatorSet(tmpState, newValidatorSet) Ok(newState) } } @@ -432,7 +439,9 @@ module CCV { "consumerStatus", newConsumerStatus ) val providerStateAfterSending = - if (currentProviderState.providerValidatorSetChangedInThisBlock and getRunningConsumers(currentState.providerState).size() > 0) { + if (currentProviderState.providerValidatorSetChangedInThisBlock and + // important: check this on the provider state after the consumer advancement, not on the current state. + getRunningConsumers(providerStateAfterConsumerAdvancement).size() > 0) { providerStateAfterConsumerAdvancement.sendVscPackets() } else { providerStateAfterConsumerAdvancement @@ -449,7 +458,7 @@ module CCV { chain: Chain, // by how much the timestamp of the chain should be advanced for the next block timeAdvancement: Time): Result = { - if (currentState.consumerStates.keys().contains(chain)) { + if (not(currentState.consumerStates.keys().contains(chain))) { Err("chain is not a consumer") } else { // if the chain is not a consumer, return an error @@ -872,7 +881,15 @@ module CCVDefaultStateMachine { currentState' = result.newState, } - run InitTest: bool = { + // Test a simple happy path where: + // * the consumer chain is set to running + // * a validator set change happens + // * a block is ended on the provider, i.e. a packet is sent to the consumer + // * the consumer receives the packet + // * the chains wait until the unbonding period is over + // * the consumer sends a VSCMaturedPacket to the provider + // * the provider receives the VSCMaturedPacket + run HappyPathTest: bool = { init.then( all { assert(currentState.providerState.consumerStatus == Map( @@ -894,21 +911,64 @@ module CCVDefaultStateMachine { assert(currentState.providerState.chainState.votingPowerHistory == List(InitialValidatorSet)), assert(currentState.providerState.chainState.currentValidatorSet == InitialValidatorSet), assert(currentState.providerState.chainState.lastTimestamp == 0), - val firstState = currentState // snapshot the first state - VotingPowerChange("node1", 50).then(all { - // ensure that the only change is that the voting power of node1 is changed - assert(currentState == firstState.with( - "providerState", firstState.providerState.with( - "chainState", firstState.providerState.chainState.with( - "currentValidatorSet", firstState.providerState.chainState.currentValidatorSet.put("node1", 50) - ) - ) - )), - currentState' = currentState - }) - } + VotingPowerChange("node1", 50) + }) + .then( + all { + // the validator set has changed + assert(currentState.providerState.chainState.currentValidatorSet == InitialValidatorSet.put("node1", 50)), + // start consumer1 + EndAndBeginBlockForProvider(1 * Second, Set("consumer1"), Set()) + }) + .then( + all { + // consumer1 was started + assert(currentState.providerState.consumerStatus.get("consumer1") == RUNNING), + // a packet was sent to consumer1 + assert(currentState.providerState.outstandingPacketsToConsumer.get("consumer1").length() == 1), + // the validator set on the provider was entered into the history + assert(currentState.providerState.chainState.votingPowerHistory == List(InitialValidatorSet.put("node1", 50), InitialValidatorSet)), + // deliver the packet + DeliverVSCPacket("consumer1") + } + ) + .then( + all { + // make sure the packet was removed from the provider + assert(currentState.providerState.outstandingPacketsToConsumer.get("consumer1").length() == 0), + // ensure the maturation time was entered on the consumer + assert(currentState.consumerStates.get("consumer1").maturationTimes.keys().size() == 1), + // the validator set was put as the current validator set + assert(currentState.consumerStates.get("consumer1").chainState.currentValidatorSet == InitialValidatorSet.put("node1", 50)), + // advance time on provider until the unbonding period is over + EndAndBeginBlockForProvider(UnbondingPeriodPerChain.get("consumer1"), Set(), Set()), + } + ) + .then( + // advance time on consumer until the unbonding period is over + EndAndBeginBlockForConsumer("consumer1", UnbondingPeriodPerChain.get("consumer1")) + ) + .then( + all { + // the packet has matured, so it was sent by the consumer + assert(currentState.consumerStates.get("consumer1").outstandingPacketsToProvider.length() == 1), + // it was removed from the maturationTimes + assert(currentState.consumerStates.get("consumer1").maturationTimes.keys().size() == 0), + // receive the packet on the provider + DeliverVSCMaturedPacket("consumer1") + } + ) + .then( + all { + // the packet was received on the provider + assert(currentState.providerState.receivedMaturations.size() == 1), + // the packet was removed from the consumer + assert(currentState.consumerStates.get("consumer1").outstandingPacketsToProvider.length() == 0), + currentState' = currentState // just so this still has an effect + } ) } + } @@ -964,6 +1024,25 @@ module CCVLogicTest { not(finalResult.newState.providerState.chainState.currentValidatorSet.keys().contains("validator")) } + run VotingPowerSetsFlagTest = + { + // change voting power + val tmpResult = votingPowerChange( + GetEmptyProtocolState, + "validator", + 5 + ) + // but then set it back to the initial value + val finalResult = votingPowerChange( + tmpResult.newState, + "validator", + 0 + ) + // still should set the flag + not(finalResult.hasError) and + finalResult.newState.providerState.providerValidatorSetChangedInThisBlock + } + // make sure that VotingPowerChange ONLY changes the current validator set, not the history run VotingPowerChangeDoesNotChangeHistoryTest = @@ -1052,7 +1131,6 @@ module CCVLogicTest { val newConsumerState = result.newState.consumerStates.get("sender") not(result.hasError) and newProviderState.receivedMaturations.size() == 0 and - newConsumerState.outstandingPacketsToProvider.length() == 0 and newProviderState.consumerStatus.get("sender") == STOPPED } From 96c101f710ea92d0f97c90f22ff6cdab5ef01cd2 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 29 Sep 2023 10:37:48 +0200 Subject: [PATCH 29/80] Add README and improve folder structure --- tests/difference/core/quint_model/README.md | 20 + tests/difference/core/quint_model/ccv.qnt | 415 +----------------- .../core/quint_model/ccv_statemachine.qnt | 220 ++++++++++ .../difference/core/quint_model/ccv_test.qnt | 225 ++++++++++ .../{ => libraries}/extraSpells.qnt | 0 .../core/quint_model/{ => libraries}/time.qnt | 0 6 files changed, 468 insertions(+), 412 deletions(-) create mode 100644 tests/difference/core/quint_model/README.md create mode 100644 tests/difference/core/quint_model/ccv_statemachine.qnt create mode 100644 tests/difference/core/quint_model/ccv_test.qnt rename tests/difference/core/quint_model/{ => libraries}/extraSpells.qnt (100%) rename tests/difference/core/quint_model/{ => libraries}/time.qnt (100%) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md new file mode 100644 index 0000000000..30de96350f --- /dev/null +++ b/tests/difference/core/quint_model/README.md @@ -0,0 +1,20 @@ +This folder contains a Quint model for the core logic of Cross-Chain Validation (CCV). + +### File structure +The files are as follows: +- ccv.qnt: Contains the type definitions, data structures, functional logic for CCV. +The core of the protocol. +- ccv_statemachine.qnt: Contains the state machine layer for CCV. Very roughly speaking, this could be seen as "e2e tests". +Also contains invariants. +- ccv_test.qnt: Contains unit tests for the functional layer of CCV. +- libararies/*: Libraries that don't belong to CCV, but are used by it. + +### Model details + +To see the data structures used in the model, see the ProtocolState type in ccv.qnt. + +The "public" endpoints of the model are those functions that take as an input the protocol state, and return a Result. +Other functions are for utility. + +The parameters of the protocol are defined as consts in ccv.qnt. + diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 65a3418e4e..fbb9b08fed 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -1,5 +1,5 @@ module CCVTypes { - import Time.* from "./Time" + import Time.* from "./libraries/Time" type Node = str type Chain = str @@ -213,8 +213,8 @@ module CCV { // i.e. when the packet is delivered, the ack is delivered right afterwards. // This is because it is nontrivial in practice to get a relayer to relay a packet, but not its ack. - import extraSpells.* from "./extraSpells" - import Time.* from "./Time" + import Time.* from "./libraries/Time" + import extraSpells.* from "./libraries/extraSpells" import CCVTypes.* @@ -788,412 +788,3 @@ module CCV { run UnbondingPeriodKeysTest = UnbondingPeriodPerChain.keys() == ConsumerChains.union(Set(PROVIDER_CHAIN)) } - - -module CCVDefaultStateMachine { - // A basic state machine that utilizes the CCV protocol. - import Time.* from "./Time" - import CCVTypes.* - import extraSpells.* from "./extraSpells" - - pure val consumerChains = Set("consumer1", "consumer2", "consumer3") - pure val chains = consumerChains.union(Set(PROVIDER_CHAIN)) - pure val unbondingPeriods = chains.mapBy(chain => 2 * Week) - pure val ccvTimeouts = chains.mapBy(chain => 3 * Week) - - pure val nodes = Set("node1", "node2", "node3", "node4", "node5", "node6", "node7", "node8", "node9", "node10") - pure val InitialValidatorSet = nodes.mapBy(node => 100) - - import CCV(VscTimeout = 5 * Week, CcvTimeout = ccvTimeouts, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = consumerChains).* - - - var currentState: ProtocolState - - action init: bool = all { - val providerState = GetEmptyProviderState - val consumerStates = ConsumerChains.mapBy(chain => GetEmptyConsumerState) - val providerStateWithConsumers = providerState.with( - "consumerStatus", - ConsumerChains.mapBy(chain => UNUSED) - ).with( - "outstandingPacketsToConsumer", - ConsumerChains.mapBy(chain => List()) - ).with( - "sentVSCPackets", - ConsumerChains.mapBy(chain => List()) - ).with( - // set the validator set to be the initial validator set in the history - "chainState", providerState.chainState.with( - "votingPowerHistory", List(InitialValidatorSet) - ).with( - "currentValidatorSet", InitialValidatorSet - ) - ) - currentState' = { - providerState: providerStateWithConsumers, - consumerStates: consumerStates - } - } - - action VotingPowerChange(validator: Node, newVotingPower: int): bool = - val result = votingPowerChange(currentState, validator, newVotingPower) - all { - result.hasError == false, - currentState' = result.newState, - } - - // The receiver receives the next outstanding VSCPacket from the provider. - // This will time out the consumer if the packet timeout has passed on the receiver. - action DeliverVSCPacket(receiver: Chain): bool = - val resultAndTimeout = deliverPacketToConsumer(currentState, receiver) - val result = resultAndTimeout._1 - all { - result.hasError == false, - currentState' = result.newState, - } - - // The provider receives the next outstanding VSCMaturedPacket from the sender. - // This will time out the consumer if the packet timeout has passed on the provider. - action DeliverVSCMaturedPacket(sender: Chain): bool = - val resultAndTimeout = deliverPacketToProvider(currentState, sender) - val result = resultAndTimeout._1 - all { - result.hasError == false, - currentState' = result.newState, - } - - action EndAndBeginBlockForProvider( - timeAdvancement: Time, - consumersToStart: Set[Chain], - consumersToStop: Set[Chain]): bool = - val result = endAndBeginBlockForProvider(currentState, timeAdvancement, consumersToStart, consumersToStop) - all { - result.hasError == false, - currentState' = result.newState, - } - - action EndAndBeginBlockForConsumer( - chain: Chain, - timeAdvancement: Time): bool = - val result = endAndBeginBlockForConsumer(currentState, chain, timeAdvancement) - all { - result.hasError == false, - currentState' = result.newState, - } - - // Test a simple happy path where: - // * the consumer chain is set to running - // * a validator set change happens - // * a block is ended on the provider, i.e. a packet is sent to the consumer - // * the consumer receives the packet - // * the chains wait until the unbonding period is over - // * the consumer sends a VSCMaturedPacket to the provider - // * the provider receives the VSCMaturedPacket - run HappyPathTest: bool = { - init.then( - all { - assert(currentState.providerState.consumerStatus == Map( - "consumer1" -> UNUSED, - "consumer2" -> UNUSED, - "consumer3" -> UNUSED - )), - assert(currentState.providerState.outstandingPacketsToConsumer == Map( - "consumer1" -> List(), - "consumer2" -> List(), - "consumer3" -> List() - )), - assert(currentState.providerState.sentVSCPackets == Map( - "consumer1" -> List(), - "consumer2" -> List(), - "consumer3" -> List() - )), - assert(currentState.consumerStates.keys() == consumerChains), - assert(currentState.providerState.chainState.votingPowerHistory == List(InitialValidatorSet)), - assert(currentState.providerState.chainState.currentValidatorSet == InitialValidatorSet), - assert(currentState.providerState.chainState.lastTimestamp == 0), - VotingPowerChange("node1", 50) - }) - .then( - all { - // the validator set has changed - assert(currentState.providerState.chainState.currentValidatorSet == InitialValidatorSet.put("node1", 50)), - // start consumer1 - EndAndBeginBlockForProvider(1 * Second, Set("consumer1"), Set()) - }) - .then( - all { - // consumer1 was started - assert(currentState.providerState.consumerStatus.get("consumer1") == RUNNING), - // a packet was sent to consumer1 - assert(currentState.providerState.outstandingPacketsToConsumer.get("consumer1").length() == 1), - // the validator set on the provider was entered into the history - assert(currentState.providerState.chainState.votingPowerHistory == List(InitialValidatorSet.put("node1", 50), InitialValidatorSet)), - // deliver the packet - DeliverVSCPacket("consumer1") - } - ) - .then( - all { - // make sure the packet was removed from the provider - assert(currentState.providerState.outstandingPacketsToConsumer.get("consumer1").length() == 0), - // ensure the maturation time was entered on the consumer - assert(currentState.consumerStates.get("consumer1").maturationTimes.keys().size() == 1), - // the validator set was put as the current validator set - assert(currentState.consumerStates.get("consumer1").chainState.currentValidatorSet == InitialValidatorSet.put("node1", 50)), - // advance time on provider until the unbonding period is over - EndAndBeginBlockForProvider(UnbondingPeriodPerChain.get("consumer1"), Set(), Set()), - } - ) - .then( - // advance time on consumer until the unbonding period is over - EndAndBeginBlockForConsumer("consumer1", UnbondingPeriodPerChain.get("consumer1")) - ) - .then( - all { - // the packet has matured, so it was sent by the consumer - assert(currentState.consumerStates.get("consumer1").outstandingPacketsToProvider.length() == 1), - // it was removed from the maturationTimes - assert(currentState.consumerStates.get("consumer1").maturationTimes.keys().size() == 0), - // receive the packet on the provider - DeliverVSCMaturedPacket("consumer1") - } - ) - .then( - all { - // the packet was received on the provider - assert(currentState.providerState.receivedMaturations.size() == 1), - // the packet was removed from the consumer - assert(currentState.consumerStates.get("consumer1").outstandingPacketsToProvider.length() == 0), - currentState' = currentState // just so this still has an effect - } - ) - } - - -} - -// contains test logic for the stateless functions in the CCV module -module CCVLogicTest { - import CCVTypes.* - import Time.* from "./Time" - import extraSpells.* from "./extraSpells" - - pure val consumerChains = Set("sender", "receiver") - pure val chains = consumerChains.union(Set(PROVIDER_CHAIN)) - pure val unbondingPeriods = chains.mapBy(chain => 2 * Week) - pure val ccvTimeouts = chains.mapBy(chain => 3 * Week) - - import CCV(VscTimeout = 5 * Week, CcvTimeout = ccvTimeouts, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = consumerChains).* - - // negative voting powers give an error - run VotingPowerNegativeTest = - { - votingPowerChange( - GetEmptyProtocolState, - "validator", - -1 - ).hasError - } - - run VotingPowerOkTest = - { - val result = votingPowerChange( - GetEmptyProtocolState, - "validator", - 5 - ) - not(result.hasError) and - result.newState.providerState.chainState.currentValidatorSet.keys().contains("validator") and - result.newState.providerState.chainState.currentValidatorSet.get("validator") == 5 - } - - // validators that get zero voting power are removed - run VotingPowerZeroTest = - { - val tmpResult = votingPowerChange( - GetEmptyProtocolState, - "validator", - 5 - ) - val finalResult = votingPowerChange( - tmpResult.newState, - "validator", - 0 - ) - not(finalResult.hasError) and - not(finalResult.newState.providerState.chainState.currentValidatorSet.keys().contains("validator")) - } - - run VotingPowerSetsFlagTest = - { - // change voting power - val tmpResult = votingPowerChange( - GetEmptyProtocolState, - "validator", - 5 - ) - // but then set it back to the initial value - val finalResult = votingPowerChange( - tmpResult.newState, - "validator", - 0 - ) - // still should set the flag - not(finalResult.hasError) and - finalResult.newState.providerState.providerValidatorSetChangedInThisBlock - } - - - // make sure that VotingPowerChange ONLY changes the current validator set, not the history - run VotingPowerChangeDoesNotChangeHistoryTest = - { - val result = votingPowerChange( - GetEmptyProtocolState, - "validator", - 0 - ) - not(result.hasError) and - result.newState.providerState.chainState.votingPowerHistory == List() - } - - // add a packet on the consumer - pure val DeliverPacketToProviderHappyPathTest_testState = _DeliverPacketToProvider_TestState.with( - "consumerStates", _DeliverPacketToProvider_TestState.consumerStates.put( - "sender", _DeliverPacketToProvider_TestState.consumerStates.get("sender").with( - "outstandingPacketsToProvider", List({ - id: 0, - sendingTime: 0 - }) - ) - ) - ).with( - // put an entry into sentVSCPacket on the provider that corresponds to the packet we put on the consumer - "providerState", _DeliverPacketToProvider_TestState.providerState.with( - "sentVSCPackets", _DeliverPacketToProvider_TestState.providerState.sentVSCPackets.put( - "sender", List({ - id: 0, - validatorSet: _DeliverPacketToProvider_TestState.providerState.chainState.currentValidatorSet, - sendingTime: 0 - }) - ) - ) - ) - - pure val DeliverPacketToProviderHappyPathTest_resultAndTimeout = deliverPacketToProvider(DeliverPacketToProviderHappyPathTest_testState, "sender") - - // test is split to be easier to pinpoint which assertion failed - run DidNotTimeOut_DeliverPacketToProviderHappyPathTest = - { - val result = DeliverPacketToProviderHappyPathTest_resultAndTimeout._1 - val timeout = DeliverPacketToProviderHappyPathTest_resultAndTimeout._2 - not(result.hasError) and - not(timeout) - } - - run StateModificationOK_DeliverPacketToProviderHappyPathTest = - { - val result = DeliverPacketToProviderHappyPathTest_resultAndTimeout._1 - val timedOut = DeliverPacketToProviderHappyPathTest_resultAndTimeout._2 - val newProviderState = result.newState.providerState - val newConsumerState = result.newState.consumerStates.get("sender") - not(result.hasError) and - newProviderState.receivedMaturations.size() == 1 and - newConsumerState.outstandingPacketsToProvider.length() == 0 - } - - // add a packet on the consumer - pure val DeliverPacketToProviderTimeoutTest_testState = DeliverPacketToProviderHappyPathTest_testState.with( - "providerState", DeliverPacketToProviderHappyPathTest_testState.providerState.with( - "chainState", DeliverPacketToProviderHappyPathTest_testState.providerState.chainState.with( - // set the timestamp to be after the timeout - "lastTimestamp", CcvTimeout.get("sender") + 1 - ) - ) - ) - - pure val DeliverPacketToProviderTimeoutTest_resultAndTimeout = deliverPacketToProvider(DeliverPacketToProviderTimeoutTest_testState, "sender") - - run DidTimeOut_DeliverPacketToProviderTimeoutTest = - { - val result = DeliverPacketToProviderTimeoutTest_resultAndTimeout._1 - val timedOut = DeliverPacketToProviderTimeoutTest_resultAndTimeout._2 - val newProviderState = result.newState.providerState - val newConsumerState = result.newState.consumerStates.get("sender") - not(result.hasError) and - timedOut - } - - run StateModificationOK_DeliverPacketToProviderTimeoutTest = - { - val result = DeliverPacketToProviderTimeoutTest_resultAndTimeout._1 - val timedOut = DeliverPacketToProviderTimeoutTest_resultAndTimeout._2 - val newProviderState = result.newState.providerState - val newConsumerState = result.newState.consumerStates.get("sender") - not(result.hasError) and - newProviderState.receivedMaturations.size() == 0 and - newProviderState.consumerStatus.get("sender") == STOPPED - } - - run ConsumerStatusMapHappyPathTest = - { - val currentConsumerStatusMap = Map( - "chain1" -> UNUSED, - "chain2" -> RUNNING, - "chain3" -> STOPPED - ) - val res = getNewConsumerStatusMap( - currentConsumerStatusMap, - Set("chain1"), - Set("chain2") - ) - res._2 == "" and - res._1.get("chain1") == RUNNING and - res._1.get("chain2") == STOPPED and - res._1.get("chain3") == STOPPED - } - - run ConsumerStatusMapAlreadyRunningTest = - { - val currentConsumerStatusMap = Map( - "chain1" -> UNUSED, - "chain2" -> RUNNING, - "chain3" -> STOPPED - ) - val res = getNewConsumerStatusMap( - currentConsumerStatusMap, - Set("chain2"), - Set("chain3") - ) - res._2 == "Cannot start a consumer that is already running" - } - - run ConsumerStatusMapAlreadyStoppedTest = - { - val currentConsumerStatusMap = Map( - "chain1" -> UNUSED, - "chain2" -> RUNNING, - "chain3" -> STOPPED - ) - val res = getNewConsumerStatusMap( - currentConsumerStatusMap, - Set("chain1"), - Set("chain3") - ) - res._2 == "Cannot stop a consumer that is not running" - } - - run ChainBothInStartAndStopTest = - { - val currentConsumerStatusMap = Map( - "chain1" -> UNUSED, - "chain2" -> RUNNING, - "chain3" -> STOPPED - ) - val res = getNewConsumerStatusMap( - currentConsumerStatusMap, - Set("chain1"), - Set("chain1") - ) - res._2 == "Cannot start and stop a consumer at the same time" - } -} diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt new file mode 100644 index 0000000000..142db75431 --- /dev/null +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -0,0 +1,220 @@ +module CCVDefaultStateMachine { + // A basic state machine that utilizes the CCV protocol. + import Time.* from "./libraries/time" + import extraSpells.* from "./libraries/extraSpells" + import CCVTypes.* from "./ccv" + + pure val consumerChains = Set("consumer1", "consumer2", "consumer3") + pure val chains = consumerChains.union(Set(PROVIDER_CHAIN)) + pure val unbondingPeriods = chains.mapBy(chain => 2 * Week) + pure val ccvTimeouts = chains.mapBy(chain => 3 * Week) + + pure val nodes = Set("node1", "node2", "node3", "node4", "node5", "node6", "node7", "node8", "node9", "node10") + pure val InitialValidatorSet = nodes.mapBy(node => 100) + + import CCV(VscTimeout = 5 * Week, CcvTimeout = ccvTimeouts, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = consumerChains).* from "./ccv" + + + var currentState: ProtocolState + + action init: bool = all { + val providerState = GetEmptyProviderState + val consumerStates = ConsumerChains.mapBy(chain => GetEmptyConsumerState) + val providerStateWithConsumers = providerState.with( + "consumerStatus", + ConsumerChains.mapBy(chain => UNUSED) + ).with( + "outstandingPacketsToConsumer", + ConsumerChains.mapBy(chain => List()) + ).with( + "sentVSCPackets", + ConsumerChains.mapBy(chain => List()) + ).with( + // set the validator set to be the initial validator set in the history + "chainState", providerState.chainState.with( + "votingPowerHistory", List(InitialValidatorSet) + ).with( + "currentValidatorSet", InitialValidatorSet + ) + ) + currentState' = { + providerState: providerStateWithConsumers, + consumerStates: consumerStates + } + } + + action VotingPowerChange(validator: Node, newVotingPower: int): bool = + val result = votingPowerChange(currentState, validator, newVotingPower) + all { + result.hasError == false, + currentState' = result.newState, + } + + // The receiver receives the next outstanding VSCPacket from the provider. + // This will time out the consumer if the packet timeout has passed on the receiver. + action DeliverVSCPacket(receiver: Chain): bool = + val resultAndTimeout = deliverPacketToConsumer(currentState, receiver) + val result = resultAndTimeout._1 + all { + result.hasError == false, + currentState' = result.newState, + } + + // The provider receives the next outstanding VSCMaturedPacket from the sender. + // This will time out the consumer if the packet timeout has passed on the provider. + action DeliverVSCMaturedPacket(sender: Chain): bool = + val resultAndTimeout = deliverPacketToProvider(currentState, sender) + val result = resultAndTimeout._1 + all { + result.hasError == false, + currentState' = result.newState, + } + + action EndAndBeginBlockForProvider( + timeAdvancement: Time, + consumersToStart: Set[Chain], + consumersToStop: Set[Chain]): bool = + val result = endAndBeginBlockForProvider(currentState, timeAdvancement, consumersToStart, consumersToStop) + all { + result.hasError == false, + currentState' = result.newState, + } + + action EndAndBeginBlockForConsumer( + chain: Chain, + timeAdvancement: Time): bool = + val result = endAndBeginBlockForConsumer(currentState, chain, timeAdvancement) + all { + result.hasError == false, + currentState' = result.newState, + } + + action step = any { + nondet node = oneOf(nodes) + // very restricted set of voting powers. exact values are not important, + // and this keeps the state space smaller. + // 0 for getting a validator out of the validator set, and two non-zero values + nondet newVotingPower = oneOf(0, 50, 100) + VotingPowerChange(node, newVotingPower), + + nondet chain = oneOf(consumerChains) + // a few different values for time advancements. + // to keep the number of possible steps small, we only have a few different values. + // Roughly, 1s for very small advances (like between blocks), + // and then longer values for increasingly severe downtime scenarios. + // Note that these can still be combined, so in effect we can get all time advancements by any amount of seconds. + nondet timeAdvancement = oneOf(1 * Second, 1 * Day, 1 * Week, 1 * Month) + EndAndBeginBlockForConsumer(chain, timeAdvancement), + + val runningConsumers = currentState.providerState.consumerStatus.filter((chain, status) => status == RUNNING).keys() + val unusedConsumers = currentState.providerState.consumerStatus.filter((chain, status) => status == UNUSED).keys() + nondet consumersToStart = oneOf(runningConsumers.powerset()) + nondet consumersToStop = oneOf(unusedConsumers.powerset()) + nondet timeAdvancement = oneOf(1 * Second, 1 * Day, 1 * Week, 1 * Month) + EndAndBeginBlockForProvider(timeAdvancement, consumersToStart, consumersToStop), + + // + // try to send a packet. we could filter by chains that can actually send, + // but it's probably not much faster than just trying and failing. + nondet sender = oneOf(consumerChains) + DeliverVSCMaturedPacket(sender), + + // again, we could filter by chains that can actually receive, + // but it's probably not much faster than just trying and failing. + nondet recciver = oneOf(consumerChains) + DeliverVSCPacket(recciver), + } + + // ================== + // MANUAL TEST CASES + // ================== + // Manually written test cases to get confidence in the base operation of the protocol. + + // Test a simple happy path where: + // * the consumer chain is set to running + // * a validator set change happens + // * a block is ended on the provider, i.e. a packet is sent to the consumer + // * the consumer receives the packet + // * the chains wait until the unbonding period is over + // * the consumer sends a VSCMaturedPacket to the provider + // * the provider receives the VSCMaturedPacket + run HappyPathTest: bool = { + init.then( + all { + assert(currentState.providerState.consumerStatus == Map( + "consumer1" -> UNUSED, + "consumer2" -> UNUSED, + "consumer3" -> UNUSED + )), + assert(currentState.providerState.outstandingPacketsToConsumer == Map( + "consumer1" -> List(), + "consumer2" -> List(), + "consumer3" -> List() + )), + assert(currentState.providerState.sentVSCPackets == Map( + "consumer1" -> List(), + "consumer2" -> List(), + "consumer3" -> List() + )), + assert(currentState.consumerStates.keys() == consumerChains), + assert(currentState.providerState.chainState.votingPowerHistory == List(InitialValidatorSet)), + assert(currentState.providerState.chainState.currentValidatorSet == InitialValidatorSet), + assert(currentState.providerState.chainState.lastTimestamp == 0), + VotingPowerChange("node1", 50) + }) + .then( + all { + // the validator set has changed + assert(currentState.providerState.chainState.currentValidatorSet == InitialValidatorSet.put("node1", 50)), + // start consumer1 + EndAndBeginBlockForProvider(1 * Second, Set("consumer1"), Set()) + }) + .then( + all { + // consumer1 was started + assert(currentState.providerState.consumerStatus.get("consumer1") == RUNNING), + // a packet was sent to consumer1 + assert(currentState.providerState.outstandingPacketsToConsumer.get("consumer1").length() == 1), + // the validator set on the provider was entered into the history + assert(currentState.providerState.chainState.votingPowerHistory == List(InitialValidatorSet.put("node1", 50), InitialValidatorSet)), + // deliver the packet + DeliverVSCPacket("consumer1") + } + ) + .then( + all { + // make sure the packet was removed from the provider + assert(currentState.providerState.outstandingPacketsToConsumer.get("consumer1").length() == 0), + // ensure the maturation time was entered on the consumer + assert(currentState.consumerStates.get("consumer1").maturationTimes.keys().size() == 1), + // the validator set was put as the current validator set + assert(currentState.consumerStates.get("consumer1").chainState.currentValidatorSet == InitialValidatorSet.put("node1", 50)), + // advance time on provider until the unbonding period is over + EndAndBeginBlockForProvider(UnbondingPeriodPerChain.get("consumer1"), Set(), Set()), + } + ) + .then( + // advance time on consumer until the unbonding period is over + EndAndBeginBlockForConsumer("consumer1", UnbondingPeriodPerChain.get("consumer1")) + ) + .then( + all { + // the packet has matured, so it was sent by the consumer + assert(currentState.consumerStates.get("consumer1").outstandingPacketsToProvider.length() == 1), + // it was removed from the maturationTimes + assert(currentState.consumerStates.get("consumer1").maturationTimes.keys().size() == 0), + // receive the packet on the provider + DeliverVSCMaturedPacket("consumer1") + } + ) + .then( + all { + // the packet was received on the provider + assert(currentState.providerState.receivedMaturations.size() == 1), + // the packet was removed from the consumer + assert(currentState.consumerStates.get("consumer1").outstandingPacketsToProvider.length() == 0), + currentState' = currentState // just so this still has an effect + } + ) + } +} \ No newline at end of file diff --git a/tests/difference/core/quint_model/ccv_test.qnt b/tests/difference/core/quint_model/ccv_test.qnt new file mode 100644 index 0000000000..31c46c0e62 --- /dev/null +++ b/tests/difference/core/quint_model/ccv_test.qnt @@ -0,0 +1,225 @@ +// contains test logic for the stateless functions in the CCV module +module CCVTest { + import CCVTypes.* from "./ccv" + import Time.* from "./libraries/Time" + import extraSpells.* from "./libraries/extraSpells" + + pure val consumerChains = Set("sender", "receiver") + pure val chains = consumerChains.union(Set(PROVIDER_CHAIN)) + pure val unbondingPeriods = chains.mapBy(chain => 2 * Week) + pure val ccvTimeouts = chains.mapBy(chain => 3 * Week) + + import CCV(VscTimeout = 5 * Week, CcvTimeout = ccvTimeouts, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = consumerChains).* from "./ccv" + + // negative voting powers give an error + run VotingPowerNegativeTest = + { + votingPowerChange( + GetEmptyProtocolState, + "validator", + -1 + ).hasError + } + + run VotingPowerOkTest = + { + val result = votingPowerChange( + GetEmptyProtocolState, + "validator", + 5 + ) + not(result.hasError) and + result.newState.providerState.chainState.currentValidatorSet.keys().contains("validator") and + result.newState.providerState.chainState.currentValidatorSet.get("validator") == 5 + } + + // validators that get zero voting power are removed + run VotingPowerZeroTest = + { + val tmpResult = votingPowerChange( + GetEmptyProtocolState, + "validator", + 5 + ) + val finalResult = votingPowerChange( + tmpResult.newState, + "validator", + 0 + ) + not(finalResult.hasError) and + not(finalResult.newState.providerState.chainState.currentValidatorSet.keys().contains("validator")) + } + + run VotingPowerSetsFlagTest = + { + // change voting power + val tmpResult = votingPowerChange( + GetEmptyProtocolState, + "validator", + 5 + ) + // but then set it back to the initial value + val finalResult = votingPowerChange( + tmpResult.newState, + "validator", + 0 + ) + // still should set the flag + not(finalResult.hasError) and + finalResult.newState.providerState.providerValidatorSetChangedInThisBlock + } + + + // make sure that VotingPowerChange ONLY changes the current validator set, not the history + run VotingPowerChangeDoesNotChangeHistoryTest = + { + val result = votingPowerChange( + GetEmptyProtocolState, + "validator", + 0 + ) + not(result.hasError) and + result.newState.providerState.chainState.votingPowerHistory == List() + } + + // add a packet on the consumer + pure val DeliverPacketToProviderHappyPathTest_testState = _DeliverPacketToProvider_TestState.with( + "consumerStates", _DeliverPacketToProvider_TestState.consumerStates.put( + "sender", _DeliverPacketToProvider_TestState.consumerStates.get("sender").with( + "outstandingPacketsToProvider", List({ + id: 0, + sendingTime: 0 + }) + ) + ) + ).with( + // put an entry into sentVSCPacket on the provider that corresponds to the packet we put on the consumer + "providerState", _DeliverPacketToProvider_TestState.providerState.with( + "sentVSCPackets", _DeliverPacketToProvider_TestState.providerState.sentVSCPackets.put( + "sender", List({ + id: 0, + validatorSet: _DeliverPacketToProvider_TestState.providerState.chainState.currentValidatorSet, + sendingTime: 0 + }) + ) + ) + ) + + pure val DeliverPacketToProviderHappyPathTest_resultAndTimeout = deliverPacketToProvider(DeliverPacketToProviderHappyPathTest_testState, "sender") + + // test is split to be easier to pinpoint which assertion failed + run DidNotTimeOut_DeliverPacketToProviderHappyPathTest = + { + val result = DeliverPacketToProviderHappyPathTest_resultAndTimeout._1 + val timeout = DeliverPacketToProviderHappyPathTest_resultAndTimeout._2 + not(result.hasError) and + not(timeout) + } + + run StateModificationOK_DeliverPacketToProviderHappyPathTest = + { + val result = DeliverPacketToProviderHappyPathTest_resultAndTimeout._1 + val timedOut = DeliverPacketToProviderHappyPathTest_resultAndTimeout._2 + val newProviderState = result.newState.providerState + val newConsumerState = result.newState.consumerStates.get("sender") + not(result.hasError) and + newProviderState.receivedMaturations.size() == 1 and + newConsumerState.outstandingPacketsToProvider.length() == 0 + } + + // add a packet on the consumer + pure val DeliverPacketToProviderTimeoutTest_testState = DeliverPacketToProviderHappyPathTest_testState.with( + "providerState", DeliverPacketToProviderHappyPathTest_testState.providerState.with( + "chainState", DeliverPacketToProviderHappyPathTest_testState.providerState.chainState.with( + // set the timestamp to be after the timeout + "lastTimestamp", CcvTimeout.get("sender") + 1 + ) + ) + ) + + pure val DeliverPacketToProviderTimeoutTest_resultAndTimeout = deliverPacketToProvider(DeliverPacketToProviderTimeoutTest_testState, "sender") + + run DidTimeOut_DeliverPacketToProviderTimeoutTest = + { + val result = DeliverPacketToProviderTimeoutTest_resultAndTimeout._1 + val timedOut = DeliverPacketToProviderTimeoutTest_resultAndTimeout._2 + val newProviderState = result.newState.providerState + val newConsumerState = result.newState.consumerStates.get("sender") + not(result.hasError) and + timedOut + } + + run StateModificationOK_DeliverPacketToProviderTimeoutTest = + { + val result = DeliverPacketToProviderTimeoutTest_resultAndTimeout._1 + val timedOut = DeliverPacketToProviderTimeoutTest_resultAndTimeout._2 + val newProviderState = result.newState.providerState + val newConsumerState = result.newState.consumerStates.get("sender") + not(result.hasError) and + newProviderState.receivedMaturations.size() == 0 and + newProviderState.consumerStatus.get("sender") == STOPPED + } + + run ConsumerStatusMapHappyPathTest = + { + val currentConsumerStatusMap = Map( + "chain1" -> UNUSED, + "chain2" -> RUNNING, + "chain3" -> STOPPED + ) + val res = getNewConsumerStatusMap( + currentConsumerStatusMap, + Set("chain1"), + Set("chain2") + ) + res._2 == "" and + res._1.get("chain1") == RUNNING and + res._1.get("chain2") == STOPPED and + res._1.get("chain3") == STOPPED + } + + run ConsumerStatusMapAlreadyRunningTest = + { + val currentConsumerStatusMap = Map( + "chain1" -> UNUSED, + "chain2" -> RUNNING, + "chain3" -> STOPPED + ) + val res = getNewConsumerStatusMap( + currentConsumerStatusMap, + Set("chain2"), + Set("chain3") + ) + res._2 == "Cannot start a consumer that is already running" + } + + run ConsumerStatusMapAlreadyStoppedTest = + { + val currentConsumerStatusMap = Map( + "chain1" -> UNUSED, + "chain2" -> RUNNING, + "chain3" -> STOPPED + ) + val res = getNewConsumerStatusMap( + currentConsumerStatusMap, + Set("chain1"), + Set("chain3") + ) + res._2 == "Cannot stop a consumer that is not running" + } + + run ChainBothInStartAndStopTest = + { + val currentConsumerStatusMap = Map( + "chain1" -> UNUSED, + "chain2" -> RUNNING, + "chain3" -> STOPPED + ) + val res = getNewConsumerStatusMap( + currentConsumerStatusMap, + Set("chain1"), + Set("chain1") + ) + res._2 == "Cannot start and stop a consumer at the same time" + } +} \ No newline at end of file diff --git a/tests/difference/core/quint_model/extraSpells.qnt b/tests/difference/core/quint_model/libraries/extraSpells.qnt similarity index 100% rename from tests/difference/core/quint_model/extraSpells.qnt rename to tests/difference/core/quint_model/libraries/extraSpells.qnt diff --git a/tests/difference/core/quint_model/time.qnt b/tests/difference/core/quint_model/libraries/time.qnt similarity index 100% rename from tests/difference/core/quint_model/time.qnt rename to tests/difference/core/quint_model/libraries/time.qnt From aa2989e40e6fb4578adb5e6b94752c36670f3cdc Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 29 Sep 2023 10:54:08 +0200 Subject: [PATCH 30/80] Fix import --- .../core/quint_model/ccv_statemachine.qnt | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 142db75431..2b4e857078 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -1,8 +1,8 @@ module CCVDefaultStateMachine { // A basic state machine that utilizes the CCV protocol. - import Time.* from "./libraries/time" - import extraSpells.* from "./libraries/extraSpells" import CCVTypes.* from "./ccv" + import Time.* from "./libraries/Time" + import extraSpells.* from "./libraries/extraSpells" pure val consumerChains = Set("consumer1", "consumer2", "consumer3") pure val chains = consumerChains.union(Set(PROVIDER_CHAIN)) @@ -89,12 +89,19 @@ module CCVDefaultStateMachine { currentState' = result.newState, } + // a few different values for time advancements. + // to keep the number of possible steps small, we only have a few different values. + // Roughly, 1s for very small advances (like between blocks), + // and then longer values for increasingly severe downtime scenarios. + // Note that these can still be combined, so in effect we can get all time advancements by any amount of seconds. + pure val timeAdvancements = Set(1 * Second, 1 * Day, 1 * Week, 4 * Week) + action step = any { nondet node = oneOf(nodes) // very restricted set of voting powers. exact values are not important, // and this keeps the state space smaller. // 0 for getting a validator out of the validator set, and two non-zero values - nondet newVotingPower = oneOf(0, 50, 100) + nondet newVotingPower = oneOf(Set(0, 50, 100)) VotingPowerChange(node, newVotingPower), nondet chain = oneOf(consumerChains) @@ -103,14 +110,15 @@ module CCVDefaultStateMachine { // Roughly, 1s for very small advances (like between blocks), // and then longer values for increasingly severe downtime scenarios. // Note that these can still be combined, so in effect we can get all time advancements by any amount of seconds. - nondet timeAdvancement = oneOf(1 * Second, 1 * Day, 1 * Week, 1 * Month) + nondet timeAdvancement = oneOf(timeAdvancements) EndAndBeginBlockForConsumer(chain, timeAdvancement), - val runningConsumers = currentState.providerState.consumerStatus.filter((chain, status) => status == RUNNING).keys() - val unusedConsumers = currentState.providerState.consumerStatus.filter((chain, status) => status == UNUSED).keys() + val consumerStatus = currentState.providerState.consumerStatus + val runningConsumers = consumerStatus.keys().filter(chain => consumerStatus.get(chain) == RUNNING) + val unusedConsumers = consumerStatus.keys().filter(chain => consumerStatus.get(chain) == UNUSED) nondet consumersToStart = oneOf(runningConsumers.powerset()) nondet consumersToStop = oneOf(unusedConsumers.powerset()) - nondet timeAdvancement = oneOf(1 * Second, 1 * Day, 1 * Week, 1 * Month) + nondet timeAdvancement = oneOf(timeAdvancements) EndAndBeginBlockForProvider(timeAdvancement, consumersToStart, consumersToStop), // From c291303159ce3c28cf00484e34252e07fd94bffc Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 29 Sep 2023 12:51:31 +0200 Subject: [PATCH 31/80] Add some invariants --- tests/difference/core/quint_model/ccv.qnt | 7 ++ .../core/quint_model/ccv_statemachine.qnt | 104 +++++++++++++++++- 2 files changed, 107 insertions(+), 4 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index fbb9b08fed..3f6a8e1982 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -738,6 +738,13 @@ module CCV { ) } + // Returns the set of all consumer chains that currently have the status UNUSED. + pure def getUnusedConsumers(providerState: ProviderState): Set[Chain] = { + providerState.consumerStatus.keys().filter( + chain => providerState.consumerStatus.get(chain) == UNUSED + ) + } + // Returns whether the consumer has timed out due to the VSCTimeout, and an error message. // If the second return is not equal to "", the first return should be ignored. // If it is equal to "", the first return will be true if the consumer has timed out and should be dropped, diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 2b4e857078..024731e446 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -16,6 +16,14 @@ module CCVDefaultStateMachine { var currentState: ProtocolState + + // bookkeeping + var lastAction: str + + // some utility stateful vals to make invariants easier to define + val providerValidatorHistory = currentState.providerState.chainState.votingPowerHistory + val runningConsumers = getRunningConsumers(currentState.providerState) + val unusedConsumers = getUnusedConsumers(currentState.providerState) action init: bool = all { val providerState = GetEmptyProviderState @@ -40,7 +48,8 @@ module CCVDefaultStateMachine { currentState' = { providerState: providerStateWithConsumers, consumerStates: consumerStates - } + }, + lastAction' = "init" } action VotingPowerChange(validator: Node, newVotingPower: int): bool = @@ -48,6 +57,7 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, + lastAction' = "VotingPowerChange" } // The receiver receives the next outstanding VSCPacket from the provider. @@ -58,6 +68,7 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, + lastAction' = "DeliverVSCPacket" } // The provider receives the next outstanding VSCMaturedPacket from the sender. @@ -68,6 +79,7 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, + lastAction' = "DeliverVSCMaturedPacket" } action EndAndBeginBlockForProvider( @@ -78,6 +90,7 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, + lastAction' = "EndAndBeginBlockForProvider" } action EndAndBeginBlockForConsumer( @@ -87,6 +100,7 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, + lastAction' = "EndAndBeginBlockForConsumer" } // a few different values for time advancements. @@ -114,8 +128,6 @@ module CCVDefaultStateMachine { EndAndBeginBlockForConsumer(chain, timeAdvancement), val consumerStatus = currentState.providerState.consumerStatus - val runningConsumers = consumerStatus.keys().filter(chain => consumerStatus.get(chain) == RUNNING) - val unusedConsumers = consumerStatus.keys().filter(chain => consumerStatus.get(chain) == UNUSED) nondet consumersToStart = oneOf(runningConsumers.powerset()) nondet consumersToStop = oneOf(unusedConsumers.powerset()) nondet timeAdvancement = oneOf(timeAdvancements) @@ -133,6 +145,89 @@ module CCVDefaultStateMachine { DeliverVSCPacket(recciver), } + // ================== + // INVARIANT CHECKS + // ================== + + + // Every validator set on any consumer chain MUST either be or have been + // a validator set on the provider chain. + val ValidatorSetHasExistedInv = + ConsumerChains.forall(chain => + currentState.consumerStates.get(chain).chainState.votingPowerHistory.toSet().forall( + validatorSet => providerValidatorHistory.toSet().contains(validatorSet) + ) + ) + + // Any update in the power of a validator on the provider + // MUST be present in a ValidatorSetChangePacket that is sent to all registered consumer chains + val ValidatorUpdatesArePropagated = + // when the provider has just entered a validator set into a block... + if (lastAction == "EndAndBeginBlockForProvider") { + val providerValSetInCurBlock = providerValidatorHistory.head() + // ... for each consumer that is running then ... + runningConsumers.forall( + // ...the validator set is in a sent packet + consumer => currentState.providerState.sentVSCPackets.get(consumer).toSet().exists( + packet => packet.validatorSet == providerValSetInCurBlock + ) + ) + } else { + true + } + + +// \* Invariants from https://github.com/cosmos/interchain-security/blob/main/docs/quality_assurance.md + +// (* +// 6.02 - Any update in the power of a validator val on the provider, as a result of +// - (increase) Delegate() / Redelegate() to val +// - (increase) val joining the provider validator set +// - (decrease) Undelegate() / Redelegate() from val +// - (decrease) Slash(val) +// - (decrease) val leaving the provider validator set +// MUST be present in a ValidatorSetChangePacket that is sent to all registered consumer chains +// *) +// Inv602 == +// \A packet \in DOMAIN votingPowerHist: +// \A c \in LiveConsumers: +// LET packetsToC == PacketOrder(c) IN +// \E i \in DOMAIN packetsToC: +// packetsToC[i] = packet + +// (* +// 6.03 - Every consumer chain receives the same sequence of +// ValidatorSetChangePackets in the same order. + +// Note: consider only prefixes on received packets (ccvChannelsResolved) +// *) +// Inv603 == +// \A c1,c2 \in LiveConsumers: +// \A i \in (DOMAIN ccvChannelsResolved[c1] \intersect DOMAIN ccvChannelsResolved[c2]): +// ccvChannelsResolved[c1][i] = ccvChannelsResolved[c2][i] + +// (* +// 7.01 - For every ValidatorSetChangePacket received by a consumer chain at +// time t, a MaturedVSCPacket is sent back to the provider in the first block +// with a timestamp >= t + UnbondingPeriod + +// Modification: not necessarily _first_ block with that timestamp, +// since we don't model height _and_ time. Also, only true for ACTIVE chains. +// *) +// Inv701 == +// boundedDrift => MaturedBeforeTimeout + +// (* +// 7.02 - If an unbonding operation resulted in a ValidatorSetChangePacket sent +// to all registered consumer chains, then it cannot complete before receiving +// matching MaturedVSCPackets from these consumer chains +// (unless some of these consumer chains are removed) + +// We can define change completion, but we don't model it. Best approximation: +// *) +// Inv702 == +// boundedDrift => EventuallyMatureOnProvider + // ================== // MANUAL TEST CASES // ================== @@ -221,7 +316,8 @@ module CCVDefaultStateMachine { assert(currentState.providerState.receivedMaturations.size() == 1), // the packet was removed from the consumer assert(currentState.consumerStates.get("consumer1").outstandingPacketsToProvider.length() == 0), - currentState' = currentState // just so this still has an effect + currentState' = currentState, // just so this still has an effect + lastAction' = "HappyPathTest" } ) } From 94a0acb96b39b80f75df8082f2a0bb6dc1acd999 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 29 Sep 2023 13:25:25 +0200 Subject: [PATCH 32/80] Refactor Consumer advancement --- tests/difference/core/quint_model/README.md | 4 + tests/difference/core/quint_model/ccv.qnt | 115 ++++++++++++------ .../difference/core/quint_model/ccv_test.qnt | 10 +- 3 files changed, 87 insertions(+), 42 deletions(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 30de96350f..24e620bf45 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -18,3 +18,7 @@ Other functions are for utility. The parameters of the protocol are defined as consts in ccv.qnt. +### Invariants + +The invariants I am checking are in ccv_statemachine.qnt, and are as follows: +- ValidatorUpdatesArePropagated: When a validator power update is comitted on chain, a packet containing that change in voting power is sent to all running consumers. Check via `quint run --invariant ValidatorUpdatesArePropagated ccv_statemachine.qnt --main CCVDefaultStateMachine` \ No newline at end of file diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 3f6a8e1982..09abd1c0ab 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -278,9 +278,8 @@ module CCV { val timeout = CcvTimeout.get(sender) if(packet.sendingTime + CcvTimeout.get(sender) < currentState.providerState.chainState.lastTimestamp) { // drop consumer - val result = getNewConsumerStatusMap( + val result = stopConsumers( currentState.providerState.consumerStatus, - Set(), Set(sender) ) @@ -358,9 +357,8 @@ module CCV { // check if the consumer timed out if (packet.sendingTime + CcvTimeout.get(PROVIDER_CHAIN) < currentState.consumerStates.get(receiver).chainState.lastTimestamp) { // drop consumer - val result = getNewConsumerStatusMap( + val result = stopConsumers( currentState.providerState.consumerStatus, - Set(), Set(receiver) ) @@ -428,16 +426,19 @@ module CCV { res._1 ) - // modify the states of the consumers that should be started/stopped - val res = providerStateAfterTimeAdvancement.consumerStatus.getNewConsumerStatusMap(consumersToStart, consumersToStop.union(timedOutConsumers)) + // start/stop chains + val res = providerStateAfterTimeAdvancement.consumerStatus.StartStopConsumers( + consumersToStart, + consumersToStop + ) val newConsumerStatus = res._1 val err = res._2 + val providerStateAfterConsumerAdvancement = providerStateAfterTimeAdvancement.with( + "consumerStatus", newConsumerStatus + ) if (err != "") { Err(err) } else { - val providerStateAfterConsumerAdvancement = providerStateAfterTimeAdvancement.with( - "consumerStatus", newConsumerStatus - ) val providerStateAfterSending = if (currentProviderState.providerValidatorSetChangedInThisBlock and // important: check this on the provider state after the consumer advancement, not on the current state. @@ -511,43 +512,83 @@ module CCV { ) } - // Returns the new ConsumerStatusMap according to the consumers to start/stop. + // Returns the new ConsumerStatusMap according to the consumers to stop. // The second return is an error string: If it is not equal to "", // it contains an error message, and the first return should be ignored. - pure def getNewConsumerStatusMap( + pure def stopConsumers( currentConsumerStatusMap: Chain -> str, - consumersToStart: Set[Chain], consumersToStop: Set[Chain]): (Chain -> str, str) = { - val runningConsumers = getRunningConsumersFromMap(currentConsumerStatusMap) - val stoppedConsumers = getStoppedConsumersFromMap(currentConsumerStatusMap) + val runningConsumers = currentConsumerStatusMap.keys().filter( + chain => currentConsumerStatusMap.get(chain) == RUNNING + ) // if a consumer is both started and stopped, this is an error - if (consumersToStart.intersect(consumersToStop).size() > 0) { - (currentConsumerStatusMap, "Cannot start and stop a consumer at the same time") - } else { - // if a consumer is started, it must be unused - if (consumersToStart.intersect(runningConsumers).size() > 0) { - (currentConsumerStatusMap, "Cannot start a consumer that is already running") + // if a consumer is stopped, it must be running + if (consumersToStop.exclude(runningConsumers).size() > 0) { + (currentConsumerStatusMap, "Cannot stop a consumer that is not running") } else { - // if a consumer is stopped, it must be running - if (consumersToStop.intersect(stoppedConsumers).size() > 0) { - (currentConsumerStatusMap, "Cannot stop a consumer that is not running") - } else { - // if a consumer is started, it must be unused - val newConsumerStatusMap = currentConsumerStatusMap.keys().mapBy( - (chain) => - if (consumersToStart.contains(chain)) { - RUNNING - } else if (consumersToStop.contains(chain)) { - STOPPED - } else { - currentConsumerStatusMap.get(chain) - } - ) - (newConsumerStatusMap, "") - } + // if a consumer is started, it must be unused + val newConsumerStatusMap = currentConsumerStatusMap.keys().mapBy( + (chain) => + if (consumersToStop.contains(chain)) { + STOPPED + } else { + currentConsumerStatusMap.get(chain) + } + ) + (newConsumerStatusMap, "") + } + } + + // Returns the new ConsumerStatusMap according to the consumers to start. + // The second return is an error string: If it is not equal to "", + // it contains an error message, and the first return should be ignored. + pure def startConsumers( + currentConsumerStatusMap: Chain -> str, + consumersToStart: Set[Chain]): (Chain -> str, str) = { + val unusedConsumers = currentConsumerStatusMap.keys().filter( + chain => currentConsumerStatusMap.get(chain) == UNUSED + ) + // if a consumer is both started and stopped, this is an error + // if a consumer is stopped, it must be running + if (consumersToStart.exclude(unusedConsumers).size() > 0) { + (currentConsumerStatusMap, "cannot start a consumer that is not unused") + } else { + // if a consumer is started, it must be unused + val newConsumerStatusMap = currentConsumerStatusMap.keys().mapBy( + (chain) => + if (consumersToStart.contains(chain)) { + RUNNING + } else { + currentConsumerStatusMap.get(chain) + } + ) + (newConsumerStatusMap, "") } } + + pure def StartStopConsumers( + currentConsumerStatusMap: Chain -> str, + consumersToStart: Set[Chain], + consumersToStop: Set[Chain] + ): (Chain -> str, str) = { + // check if any consumer is both started and stopped + if (consumersToStart.intersect(consumersToStop).size() > 0) { + (currentConsumerStatusMap, "Cannot start and stop a consumer at the same time") + } else { + val res1 = currentConsumerStatusMap.startConsumers(consumersToStart) + val newConsumerStatus = res1._1 + val err1 = res1._2 + val res2 = newConsumerStatus.stopConsumers(consumersToStop) + val err2 = res2._2 + if (err1 != "") { + (currentConsumerStatusMap, err1) + } else if (err2 != "") { + (currentConsumerStatusMap, err2) + } else { + (res2._1, "") + } } + } // Takes the currentValidatorSet and puts it as the newest set of the voting history diff --git a/tests/difference/core/quint_model/ccv_test.qnt b/tests/difference/core/quint_model/ccv_test.qnt index 31c46c0e62..d84d8f0ea4 100644 --- a/tests/difference/core/quint_model/ccv_test.qnt +++ b/tests/difference/core/quint_model/ccv_test.qnt @@ -167,7 +167,7 @@ module CCVTest { "chain2" -> RUNNING, "chain3" -> STOPPED ) - val res = getNewConsumerStatusMap( + val res = StartStopConsumers( currentConsumerStatusMap, Set("chain1"), Set("chain2") @@ -185,12 +185,12 @@ module CCVTest { "chain2" -> RUNNING, "chain3" -> STOPPED ) - val res = getNewConsumerStatusMap( + val res = StartStopConsumers( currentConsumerStatusMap, Set("chain2"), Set("chain3") ) - res._2 == "Cannot start a consumer that is already running" + res._2 == "cannot start a consumer that is not unused" } run ConsumerStatusMapAlreadyStoppedTest = @@ -200,7 +200,7 @@ module CCVTest { "chain2" -> RUNNING, "chain3" -> STOPPED ) - val res = getNewConsumerStatusMap( + val res = StartStopConsumers( currentConsumerStatusMap, Set("chain1"), Set("chain3") @@ -215,7 +215,7 @@ module CCVTest { "chain2" -> RUNNING, "chain3" -> STOPPED ) - val res = getNewConsumerStatusMap( + val res = StartStopConsumers( currentConsumerStatusMap, Set("chain1"), Set("chain1") From 8818531faf9c27c55756053863b86e0311edff32 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 29 Sep 2023 15:12:05 +0200 Subject: [PATCH 33/80] Snapshot error --- tests/difference/core/quint_model/README.md | 3 +- tests/difference/core/quint_model/ccv.qnt | 8 +++ .../core/quint_model/ccv_statemachine.qnt | 44 ++++++++++------- .../quint_model/libraries/extraSpells.qnt | 49 +++++++++++++++++++ 4 files changed, 86 insertions(+), 18 deletions(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 24e620bf45..910cbe7232 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -21,4 +21,5 @@ The parameters of the protocol are defined as consts in ccv.qnt. ### Invariants The invariants I am checking are in ccv_statemachine.qnt, and are as follows: -- ValidatorUpdatesArePropagated: When a validator power update is comitted on chain, a packet containing that change in voting power is sent to all running consumers. Check via `quint run --invariant ValidatorUpdatesArePropagated ccv_statemachine.qnt --main CCVDefaultStateMachine` \ No newline at end of file +- ValidatorUpdatesArePropagated: When a validator power update is comitted on chain, a packet containing that change in voting power is sent to all running consumers. Check via `quint run --invariant ValidatorUpdatesArePropagated ccv_statemachine.qnt --main CCVDefaultStateMachine` +- \ No newline at end of file diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 09abd1c0ab..72a0e0d933 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -106,6 +106,10 @@ module CCVTypes { // Stores the maturation times for VSCPackets received by this consumer maturationTimes: VSCPacket -> Time, + // stores the received vscpackets in descending order of recency, + // i.e. newest first. + receivedVSCPackets: List[VSCPacket], + // Stores the list of packets that have been sent to the provider chain by this consumer // and have not been received yet. // ordered by recency, so the head is the oldest packet. @@ -119,6 +123,7 @@ module CCVTypes { chainState: GetEmptyChainState, maturationTimes: Map(), outstandingPacketsToProvider: List(), + receivedVSCPackets: List(), } // the state of the protocol consists of the composition of the state of one provider chain with potentially many consumer chains. @@ -681,6 +686,9 @@ module CCV { packet, currentConsumerState.chainState.lastTimestamp + UnbondingPeriodPerChain.get(receiver) ) + ).with( + "receivedVSCPackets", + currentConsumerState.receivedVSCPackets.prepend(packet) ) val newConsumerStates = currentState.consumerStates.set(receiver, newConsumerState) val newState = currentState.with( diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 024731e446..8f3b918f22 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -153,7 +153,7 @@ module CCVDefaultStateMachine { // Every validator set on any consumer chain MUST either be or have been // a validator set on the provider chain. val ValidatorSetHasExistedInv = - ConsumerChains.forall(chain => + runningConsumers.forall(chain => currentState.consumerStates.get(chain).chainState.votingPowerHistory.toSet().forall( validatorSet => providerValidatorHistory.toSet().contains(validatorSet) ) @@ -176,24 +176,34 @@ module CCVDefaultStateMachine { true } + // Every consumer chain receives the same sequence of + // ValidatorSetChangePackets in the same order. + // NOTE: since not all consumer chains are running all the time, + // we need a slightly weaker invariant: + // For consumer chains c1, c2, if both c1 and c2 received a packet p1 sent at t1 and a packet p2 sent at t2, + // then both have received ALL packets that were sent between t1 and t2. + val SameVSCPacketsInv = + runningConsumers.forall( + consumer1 => runningConsumers.forall( + consumer2 => { + val packets1 = currentState.consumerStates.get(consumer1).receivedVSCPackets + val packets2 = currentState.consumerStates.get(consumer2).receivedVSCPackets + val commonPackets = packets1.toSet().intersect(packets2.toSet()) + if (commonPackets.size() == 0) { + true // they don't share any packets, so nothing to check + } else { + // get oldest common packet + val oldestCommonPacket = commonPackets.MinBy(packet => packet.sendingTime, packets1.head()) + false + } + } + ) + ) -// \* Invariants from https://github.com/cosmos/interchain-security/blob/main/docs/quality_assurance.md + -// (* -// 6.02 - Any update in the power of a validator val on the provider, as a result of -// - (increase) Delegate() / Redelegate() to val -// - (increase) val joining the provider validator set -// - (decrease) Undelegate() / Redelegate() from val -// - (decrease) Slash(val) -// - (decrease) val leaving the provider validator set -// MUST be present in a ValidatorSetChangePacket that is sent to all registered consumer chains -// *) -// Inv602 == -// \A packet \in DOMAIN votingPowerHist: -// \A c \in LiveConsumers: -// LET packetsToC == PacketOrder(c) IN -// \E i \in DOMAIN packetsToC: -// packetsToC[i] = packet + +// \* Invariants from https://github.com/cosmos/interchain-security/blob/main/docs/quality_assurance.md // (* // 6.03 - Every consumer chain receives the same sequence of diff --git a/tests/difference/core/quint_model/libraries/extraSpells.qnt b/tests/difference/core/quint_model/libraries/extraSpells.qnt index 1d7d219640..54b5feca09 100644 --- a/tests/difference/core/quint_model/libraries/extraSpells.qnt +++ b/tests/difference/core/quint_model/libraries/extraSpells.qnt @@ -194,4 +194,53 @@ module extraSpells { assert(Max(Set(1, 2, 3)) == 3), assert(Max(Set()) == 0) } + + pure def HasSubsequence(__this: List[a], __other: List[a]): bool = { + if(__other.length() > __this.length()) { + false + } else { + 0.to(__this.length() - __other.length()) // go through all possible starting points of __other in __this + .exists( + __start => __this.slice(__start, __start + __other.length()) == __other + ) + } + } + + run HasSubsequenceTest = + all { + assert(List(1, 2, 3, 4).HasSubsequence(List(1, 2))), + assert(List(1, 2, 3, 4).HasSubsequence(List(2, 3))), + assert(List(1, 2, 3, 4).HasSubsequence(List(3, 4))), + assert(List(1, 2, 3, 4).HasSubsequence(List(1, 2, 3))), + assert(not(List(1, 2, 3, 4).HasSubsequence(List(1, 3)))), + assert(not(List().HasSubsequence(List(1)))), + assert(List().HasSubsequence(List())), + assert(List(1).HasSubsequence(List())), + assert(List(1).HasSubsequence(List(1))), + } + + // Returns the maximum element of a set, according to a given function. + // __i should be part of the set if it is nonempty. If the set is empty, __i will be returned. + // If two elements are equally large, an arbitrary one will be returned. + pure def MaxBy(__set: Set[a], __f: a => int, __i: a): a = { + __set.fold( + __i, + (__m, __e) => if(__f(__m) > __f(__e)) {__m } else {__e} + ) + } + + run MaxByTest = + all { + assert(MaxBy(Set(1, 2, 3), __x => __x, 0) == 3), + assert(MaxBy(Set(1, 2, 3), __x => -__x, 0) == 1), + assert(MaxBy(Set(), __x => __x, 0) == 0), + } + + // Like MaxBy, but returns the minimum element. + pure def MinBy(__set: Set[a], __f: a => int, __i: a): a = { + __set.fold( + __i, + (__m, __e) => if(__f(__m) < __f(__e)) {__m } else {__e} + ) + } } From 633f8bb3ff005b26eb1f22df52112a5c0a28e48a Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 29 Sep 2023 15:33:35 +0200 Subject: [PATCH 34/80] Make time module upper case --- .../core/quint_model/ccv_statemachine.qnt | 28 ++++++++----------- .../libraries/{time.qnt => Time.qnt} | 0 2 files changed, 12 insertions(+), 16 deletions(-) rename tests/difference/core/quint_model/libraries/{time.qnt => Time.qnt} (100%) diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 8f3b918f22..b8ad1a82f3 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -192,30 +192,26 @@ module CCVDefaultStateMachine { if (commonPackets.size() == 0) { true // they don't share any packets, so nothing to check } else { - // get oldest common packet - val oldestCommonPacket = commonPackets.MinBy(packet => packet.sendingTime, packets1.head()) - false + val oldestCommonPacket = packets1.head() + val newestCommonPacket = packets1[packets1.length() - 1] + // get all packets sent between the oldest and newest common packet + val packetsBetween1 = packets1.select( + packet => packet.sendingTime >= oldestCommonPacket.sendingTime and packet.sendingTime <= newestCommonPacket.sendingTime + ) + val packetsBetween2 = packets2.select( + packet => packet.sendingTime >= oldestCommonPacket.sendingTime and packet.sendingTime <= newestCommonPacket.sendingTime + ) + // these should be the same on both chains + packetsBetween1 == packetsBetween2 } } ) ) - - + // val MaturedBeforeTimeoutInv = // \* Invariants from https://github.com/cosmos/interchain-security/blob/main/docs/quality_assurance.md -// (* -// 6.03 - Every consumer chain receives the same sequence of -// ValidatorSetChangePackets in the same order. - -// Note: consider only prefixes on received packets (ccvChannelsResolved) -// *) -// Inv603 == -// \A c1,c2 \in LiveConsumers: -// \A i \in (DOMAIN ccvChannelsResolved[c1] \intersect DOMAIN ccvChannelsResolved[c2]): -// ccvChannelsResolved[c1][i] = ccvChannelsResolved[c2][i] - // (* // 7.01 - For every ValidatorSetChangePacket received by a consumer chain at // time t, a MaturedVSCPacket is sent back to the provider in the first block diff --git a/tests/difference/core/quint_model/libraries/time.qnt b/tests/difference/core/quint_model/libraries/Time.qnt similarity index 100% rename from tests/difference/core/quint_model/libraries/time.qnt rename to tests/difference/core/quint_model/libraries/Time.qnt From f28d074ce70ebc9c37c08d34388f8ffbb9abcc59 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 29 Sep 2023 16:05:32 +0200 Subject: [PATCH 35/80] Add invariants --- tests/difference/core/quint_model/README.md | 18 ++++++++-- .../core/quint_model/ccv_statemachine.qnt | 36 ++++++++++++++++++- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 910cbe7232..6d1ad8d2be 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -20,6 +20,18 @@ The parameters of the protocol are defined as consts in ccv.qnt. ### Invariants -The invariants I am checking are in ccv_statemachine.qnt, and are as follows: -- ValidatorUpdatesArePropagated: When a validator power update is comitted on chain, a packet containing that change in voting power is sent to all running consumers. Check via `quint run --invariant ValidatorUpdatesArePropagated ccv_statemachine.qnt --main CCVDefaultStateMachine` -- \ No newline at end of file +The invariants I am checking are in ccv_statemachine.qnt. +Check a single invariant by running +`quint run --invariant INVARIANT_NAME ccv_statemachine.qnt --main CCVDefaultStateMachine`, +or all invariants by running this command: + +Invariants are as follows: +- ValidatorUpdatesArePropagated: When a validator power update is comitted on chain, a packet containing that change in voting power is sent to all running consumers. +- ValidatorSetHasExistedInv: Every validator set on consumer chains is/was a validator set on the provider. +- SameVSCPacketsInv: Ensure that consumer chains receive the same VSCPackets in the same order. +Because of nuances with starting/stopping consumers, this invariant is not as simple as it sounds. In detail: +For consumer chains c1, c2, if both c1 and c2 received a packet p1 sent at t1 and a packet p2 sent at t2, +then both have received ALL packets that were sent between t1 and t2 in the same order. +- MatureOnTimeInv: For every ValidatorSetChangePacket received by a consumer chain at +time t, a MaturedVSCPacket is sent back to the provider in the first block +with a timestamp >= t + UnbondingPeriod on that consumer. diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index b8ad1a82f3..4a6ac2e558 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -208,7 +208,41 @@ module CCVDefaultStateMachine { ) ) - // val MaturedBeforeTimeoutInv = + // For every ValidatorSetChangePacket received by a consumer chain at + // time t, a MaturedVSCPacket is sent back to the provider in the first block + // with a timestamp >= t + UnbondingPeriod + // NOTE: because we remove the maturationTimes entry when we send the packets, + // it suffices to check that there is never an entry in maturationTimes + // that is older than the current time minus the unbonding period. + val MatureOnTimeInv = + runningConsumers.forall( + consumer => { + val maturationTimes = currentState.consumerStates.get(consumer).maturationTimes + maturationTimes.keys().forall( + packet => packet.sendingTime + UnbondingPeriodPerChain.get(consumer) <= currentState.providerState.chainState.lastTimestamp + ) + } + ) + + // If we send a VSCPacket, this is eventually responded to by all consumers + // that were running at the time the packet was sent (and are still running). + // Since we remove sentVSCPackets when we receive responses for them, + // we just check that if a sentVSCPacket has been sent more than + // VSCTimeout ago, the consumer must have been dropped. + // In practice, when this is true, a pending unbonding can mature. + val EventuallyMatureOnProviderInv = + runningConsumers.forall( + consumer => { + val sentPackets = currentState.providerState.sentVSCPackets.get(consumer).toSet() + sentPackets.forall( + packet => + // consumer still has time to respond + currentState.providerState.chainState.lastTimestamp <= packet.sendingTime + VscTimeout or + // consumer was dropped due to inactivity + currentState.providerState.consumerStatus.get(consumer) == STOPPED + ) + } + ) // \* Invariants from https://github.com/cosmos/interchain-security/blob/main/docs/quality_assurance.md From c0363f21d2115a03676e5fef3be3ab5860d9b300 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 29 Sep 2023 16:07:29 +0200 Subject: [PATCH 36/80] Clean up invariants --- tests/difference/core/quint_model/README.md | 2 ++ .../core/quint_model/ccv_statemachine.qnt | 24 ------------------- 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 6d1ad8d2be..2d5b57d0fc 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -35,3 +35,5 @@ then both have received ALL packets that were sent between t1 and t2 in the same - MatureOnTimeInv: For every ValidatorSetChangePacket received by a consumer chain at time t, a MaturedVSCPacket is sent back to the provider in the first block with a timestamp >= t + UnbondingPeriod on that consumer. +- EventuallyMatureOnProviderInv: If we send a VSCPacket, this is eventually responded to by all consumers +that were running at the time the packet was sent (and are still running). \ No newline at end of file diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 4a6ac2e558..60f9d77152 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -244,30 +244,6 @@ module CCVDefaultStateMachine { } ) -// \* Invariants from https://github.com/cosmos/interchain-security/blob/main/docs/quality_assurance.md - -// (* -// 7.01 - For every ValidatorSetChangePacket received by a consumer chain at -// time t, a MaturedVSCPacket is sent back to the provider in the first block -// with a timestamp >= t + UnbondingPeriod - -// Modification: not necessarily _first_ block with that timestamp, -// since we don't model height _and_ time. Also, only true for ACTIVE chains. -// *) -// Inv701 == -// boundedDrift => MaturedBeforeTimeout - -// (* -// 7.02 - If an unbonding operation resulted in a ValidatorSetChangePacket sent -// to all registered consumer chains, then it cannot complete before receiving -// matching MaturedVSCPackets from these consumer chains -// (unless some of these consumer chains are removed) - -// We can define change completion, but we don't model it. Best approximation: -// *) -// Inv702 == -// boundedDrift => EventuallyMatureOnProvider - // ================== // MANUAL TEST CASES // ================== From b9d8caf82511b0ac878883f008c2ed00c474361f Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 29 Sep 2023 16:14:21 +0200 Subject: [PATCH 37/80] Add script to run many invariants --- tests/difference/core/quint_model/README.md | 3 ++- tests/difference/core/quint_model/run_invariants.sh | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100755 tests/difference/core/quint_model/run_invariants.sh diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 2d5b57d0fc..228c791349 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -23,7 +23,8 @@ The parameters of the protocol are defined as consts in ccv.qnt. The invariants I am checking are in ccv_statemachine.qnt. Check a single invariant by running `quint run --invariant INVARIANT_NAME ccv_statemachine.qnt --main CCVDefaultStateMachine`, -or all invariants by running this command: +or all invariants one after another with the help of the script `run_invariants.sh`. +Each invariant takes about a minute to run. Invariants are as follows: - ValidatorUpdatesArePropagated: When a validator power update is comitted on chain, a packet containing that change in voting power is sent to all running consumers. diff --git a/tests/difference/core/quint_model/run_invariants.sh b/tests/difference/core/quint_model/run_invariants.sh new file mode 100755 index 0000000000..575b444e28 --- /dev/null +++ b/tests/difference/core/quint_model/run_invariants.sh @@ -0,0 +1,5 @@ +quint run --invariant ValidatorUpdatesArePropagated ccv_statemachine.qnt --main CCVDefaultStateMachine +quint run --invariant ValidatorSetHasExistedInv ccv_statemachine.qnt --main CCVDefaultStateMachine +quint run --invariant SameVSCPacketsInv ccv_statemachine.qnt --main CCVDefaultStateMachine +quint run --invariant MatureOnTimeInv ccv_statemachine.qnt --main CCVDefaultStateMachine +quint run --invariant EventuallyMatureOnProviderInv ccv_statemachine.qnt --main CCVDefaultStateMachine \ No newline at end of file From e494a094ce629537303e6673bcd374fcc31fafc0 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 2 Oct 2023 10:19:19 +0200 Subject: [PATCH 38/80] Update model --- tests/difference/core/quint_model/README.md | 32 ++++-- tests/difference/core/quint_model/ccv.qnt | 48 ++++++--- .../core/quint_model/ccv_statemachine.qnt | 97 +++++++++++++------ .../difference/core/quint_model/ccv_test.qnt | 14 ++- .../quint_model/libraries/extraSpells.qnt | 27 ++++-- .../core/quint_model/run_invariants.sh | 6 +- 6 files changed, 160 insertions(+), 64 deletions(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 228c791349..a6451b1396 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -18,6 +18,10 @@ Other functions are for utility. The parameters of the protocol are defined as consts in ccv.qnt. +### Tests + +To run unit tests, run `quint test ccv_test.qnt`. + ### Invariants The invariants I am checking are in ccv_statemachine.qnt. @@ -27,14 +31,30 @@ or all invariants one after another with the help of the script `run_invariants. Each invariant takes about a minute to run. Invariants are as follows: -- ValidatorUpdatesArePropagated: When a validator power update is comitted on chain, a packet containing that change in voting power is sent to all running consumers. -- ValidatorSetHasExistedInv: Every validator set on consumer chains is/was a validator set on the provider. -- SameVSCPacketsInv: Ensure that consumer chains receive the same VSCPackets in the same order. +- [ ] ValidatorUpdatesArePropagated: When a validator power update is comitted on chain, a packet containing that change in voting power is sent to all running consumers. +- [ ] ValidatorSetHasExistedInv: Every validator set on consumer chains is/was a validator set on the provider. +- [ ] SameVSCPacketsInv: Ensure that consumer chains receive the same VSCPackets in the same order. Because of nuances with starting/stopping consumers, this invariant is not as simple as it sounds. In detail: For consumer chains c1, c2, if both c1 and c2 received a packet p1 sent at t1 and a packet p2 sent at t2, then both have received ALL packets that were sent between t1 and t2 in the same order. -- MatureOnTimeInv: For every ValidatorSetChangePacket received by a consumer chain at +- [ ] MatureOnTimeInv: For every ValidatorSetChangePacket received by a consumer chain at time t, a MaturedVSCPacket is sent back to the provider in the first block with a timestamp >= t + UnbondingPeriod on that consumer. -- EventuallyMatureOnProviderInv: If we send a VSCPacket, this is eventually responded to by all consumers -that were running at the time the packet was sent (and are still running). \ No newline at end of file +- [ ] EventuallyMatureOnProviderInv: If we send a VSCPacket, this is eventually responded to by all consumers +that were running at the time the packet was sent (and are still running). + +### Sanity Checks + +Sanity checks verify that certain patterns of behaviour can appear in the model. +In detail, they are invariant checks that we expect to fail. +They usually negate the appearance of some behaviour, i.e. not(DesirableBehaviour). +Then, a counterexample for this is an example trace exhibiting the behaviour. + +They are run like invariant checks, i.e. `quint run --invariant SANITY_CHECK_NAME ccv_statemachine.qnt --main CCVDefaultStateMachine`. +The available sanity checks are: +- CanRunConsumer +- CanStopConsumer +- CanTimeoutConsumer +- CanSendVSCPackets +- CanSendVSCMaturedPackets + \ No newline at end of file diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 72a0e0d933..f329955955 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -191,7 +191,8 @@ module CCVTypes { } // possible consumer statuses - pure val STOPPED = "stopped" // the chain was once a consumer chain, but has been dropped by the provider. + pure val STOPPED = "stopped" // the chain was once a consumer chain, but has been voluntarily dropped by the provider. + pure val TIMEDOUT = "timedout" // the chain has timed out and was dropped by the provider. This is only used for involuntary drops. pure val RUNNING = "running" // the chain is currently a consumer chain. Running chains are those that get sent VSCPackets. pure val UNUSED = "unused" // the chain has never been a consumer chain, and is available to become one. // When a chain is dropped, it cannot become a consumer again - we assume that would be done by another consumer becoming running. @@ -285,6 +286,7 @@ module CCV { // drop consumer val result = stopConsumers( currentState.providerState.consumerStatus, + Set(), Set(sender) ) @@ -364,6 +366,7 @@ module CCV { // drop consumer val result = stopConsumers( currentState.providerState.consumerStatus, + Set(), Set(receiver) ) @@ -434,7 +437,8 @@ module CCV { // start/stop chains val res = providerStateAfterTimeAdvancement.consumerStatus.StartStopConsumers( consumersToStart, - consumersToStop + consumersToStop, + timedOutConsumers ) val newConsumerStatus = res._1 val err = res._2 @@ -505,6 +509,17 @@ module CCV { // which do not hold the core logic of the protocol, but are still part of it // =================== + // Get the running consumer that is furthest away from the provider in terms of timestamp. + pure def getFurthestConsumer(currentState: ProtocolState): Chain = { + val furthestConsumer = getRunningConsumers(currentState.providerState).MaxBy( + consumer => abs( + currentState.providerState.chainState.lastTimestamp - + currentState.consumerStates.get(consumer).chainState.lastTimestamp + ) + ) + furthestConsumer + } + pure def getRunningConsumersFromMap(consumerStatus: Chain -> str): Set[Chain] = { consumerStatus.keys().filter( chain => consumerStatus.get(chain) == RUNNING @@ -517,12 +532,15 @@ module CCV { ) } - // Returns the new ConsumerStatusMap according to the consumers to stop. + // Returns the new ConsumerStatusMap according to the consumers to stop + // and the consumers to time out. + // If a consumer is both stopped and timed out, it will be timed out. // The second return is an error string: If it is not equal to "", // it contains an error message, and the first return should be ignored. pure def stopConsumers( currentConsumerStatusMap: Chain -> str, - consumersToStop: Set[Chain]): (Chain -> str, str) = { + consumersToStop: Set[Chain], + consumersToTimeout: Set[Chain]): (Chain -> str, str) = { val runningConsumers = currentConsumerStatusMap.keys().filter( chain => currentConsumerStatusMap.get(chain) == RUNNING ) @@ -534,7 +552,9 @@ module CCV { // if a consumer is started, it must be unused val newConsumerStatusMap = currentConsumerStatusMap.keys().mapBy( (chain) => - if (consumersToStop.contains(chain)) { + if (consumersToTimeout.contains(chain)) { + TIMEDOUT + } else if (consumersToStop.contains(chain)) { STOPPED } else { currentConsumerStatusMap.get(chain) @@ -574,7 +594,8 @@ module CCV { pure def StartStopConsumers( currentConsumerStatusMap: Chain -> str, consumersToStart: Set[Chain], - consumersToStop: Set[Chain] + consumersToStop: Set[Chain], + consumersToTimeout: Set[Chain] ): (Chain -> str, str) = { // check if any consumer is both started and stopped if (consumersToStart.intersect(consumersToStop).size() > 0) { @@ -583,7 +604,7 @@ module CCV { val res1 = currentConsumerStatusMap.startConsumers(consumersToStart) val newConsumerStatus = res1._1 val err1 = res1._2 - val res2 = newConsumerStatus.stopConsumers(consumersToStop) + val res2 = newConsumerStatus.stopConsumers(consumersToStop, consumersToTimeout) val err2 = res2._2 if (err1 != "") { (currentConsumerStatusMap, err1) @@ -808,11 +829,16 @@ module CCV { // has a packet been sent on the provider more than VSCTimeout ago, but we have not received an answer since then? val sentVSCPackets = providerState.sentVSCPackets.get(consumer) - val oldestSentVSCPacket = sentVSCPackets.head() // if length is 0, this is undefined, but we check for this before we use it - if(sentVSCPackets.length() > 0 and oldestSentVSCPacket.sendingTime + VscTimeout < providerState.chainState.lastTimestamp) { - (true, "") + if(sentVSCPackets.length() > 0) { + val oldestSentVSCPacket = sentVSCPackets.head() // if length is 0, this is undefined, but we check for this before we use it + if(oldestSentVSCPacket.sendingTime + VscTimeout < providerState.chainState.lastTimestamp) { + (true, "") + } else { + // no timeout yet, it has not been VscTimeout since that packet was sent + (false, "") + } } else { - // no timeout yet, it has not been VscTimeout since that packet was sent + // no packet has been sent yet, so no timeout (false, "") } } diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 60f9d77152..a0e81a5186 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -18,7 +18,7 @@ module CCVDefaultStateMachine { var currentState: ProtocolState // bookkeeping - var lastAction: str + var trace: List[str] // some utility stateful vals to make invariants easier to define val providerValidatorHistory = currentState.providerState.chainState.votingPowerHistory @@ -49,7 +49,7 @@ module CCVDefaultStateMachine { providerState: providerStateWithConsumers, consumerStates: consumerStates }, - lastAction' = "init" + trace' = List("init") } action VotingPowerChange(validator: Node, newVotingPower: int): bool = @@ -57,7 +57,7 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, - lastAction' = "VotingPowerChange" + trace' = trace.append("VotingPowerChange") } // The receiver receives the next outstanding VSCPacket from the provider. @@ -68,7 +68,7 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, - lastAction' = "DeliverVSCPacket" + trace' = trace.append("DeliverVSCPacket") } // The provider receives the next outstanding VSCMaturedPacket from the sender. @@ -79,7 +79,7 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, - lastAction' = "DeliverVSCMaturedPacket" + trace' = trace.append("DeliverVSCMaturedPacket") } action EndAndBeginBlockForProvider( @@ -90,7 +90,7 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, - lastAction' = "EndAndBeginBlockForProvider" + trace' = trace.append("EndAndBeginBlockForProvider") } action EndAndBeginBlockForConsumer( @@ -100,7 +100,7 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, - lastAction' = "EndAndBeginBlockForConsumer" + trace' = trace.append("EndAndBeginBlockForConsumer") } // a few different values for time advancements. @@ -110,38 +110,36 @@ module CCVDefaultStateMachine { // Note that these can still be combined, so in effect we can get all time advancements by any amount of seconds. pure val timeAdvancements = Set(1 * Second, 1 * Day, 1 * Week, 4 * Week) + // step allows the most generic nondeterminism, in particular it becomes relatively likely + // that over a long enough runtime, all consumers would time out by mismatching their time advancements, + // and each endblock has a good chance to stop consumers, ... + // step is thus suited to test also unhappy paths. action step = any { - nondet node = oneOf(nodes) - // very restricted set of voting powers. exact values are not important, - // and this keeps the state space smaller. - // 0 for getting a validator out of the validator set, and two non-zero values - nondet newVotingPower = oneOf(Set(0, 50, 100)) - VotingPowerChange(node, newVotingPower), - - nondet chain = oneOf(consumerChains) - // a few different values for time advancements. - // to keep the number of possible steps small, we only have a few different values. - // Roughly, 1s for very small advances (like between blocks), - // and then longer values for increasingly severe downtime scenarios. - // Note that these can still be combined, so in effect we can get all time advancements by any amount of seconds. + nondet chain = oneOf(runningConsumers) nondet timeAdvancement = oneOf(timeAdvancements) EndAndBeginBlockForConsumer(chain, timeAdvancement), val consumerStatus = currentState.providerState.consumerStatus - nondet consumersToStart = oneOf(runningConsumers.powerset()) - nondet consumersToStop = oneOf(unusedConsumers.powerset()) + nondet consumersToStart = oneOf(unusedConsumers.powerset()) + nondet consumersToStop = oneOf(runningConsumers.powerset()) nondet timeAdvancement = oneOf(timeAdvancements) EndAndBeginBlockForProvider(timeAdvancement, consumersToStart, consumersToStop), - // + nondet node = oneOf(nodes) + // very restricted set of voting powers. exact values are not important, + // and this keeps the state space smaller. + // 0 for getting a validator out of the validator set, and two non-zero values + nondet newVotingPower = oneOf(Set(0, 50, 100)) + VotingPowerChange(node, newVotingPower), + // try to send a packet. we could filter by chains that can actually send, // but it's probably not much faster than just trying and failing. - nondet sender = oneOf(consumerChains) + nondet sender = oneOf(runningConsumers) DeliverVSCMaturedPacket(sender), // again, we could filter by chains that can actually receive, // but it's probably not much faster than just trying and failing. - nondet recciver = oneOf(consumerChains) + nondet recciver = oneOf(runningConsumers) DeliverVSCPacket(recciver), } @@ -163,7 +161,7 @@ module CCVDefaultStateMachine { // MUST be present in a ValidatorSetChangePacket that is sent to all registered consumer chains val ValidatorUpdatesArePropagated = // when the provider has just entered a validator set into a block... - if (lastAction == "EndAndBeginBlockForProvider") { + if (trace == trace.append("EndAndBeginBlockForProvider")) { val providerValSetInCurBlock = providerValidatorHistory.head() // ... for each consumer that is running then ... runningConsumers.forall( @@ -238,12 +236,53 @@ module CCVDefaultStateMachine { packet => // consumer still has time to respond currentState.providerState.chainState.lastTimestamp <= packet.sendingTime + VscTimeout or - // consumer was dropped due to inactivity - currentState.providerState.consumerStatus.get(consumer) == STOPPED + // consumer was dropped + currentState.providerState.consumerStatus.get(consumer) == STOPPED or + currentState.providerState.consumerStatus.get(consumer) == TIMEDOUT ) } ) + // ================= + // SANITY CHECKS + // ================= + // some invariants that should fail, + // to check that certain behaviours can be exhibited. + // The name of the invariants is the name of the behaviour + // we want to see, and its definition will *negate* that behaviour, so + // we expect these to fail when checked as invariants. + + // We can run consumers. + val CanRunConsumer = + not(ConsumerChains.exists( + consumer => + currentState.providerState.consumerStatus.get(consumer) == RUNNING + )) + + val CanStopConsumer = + not(ConsumerChains.exists( + consumer => + currentState.providerState.consumerStatus.get(consumer) == STOPPED + )) + + val CanTimeoutConsumer = + not(ConsumerChains.exists( + consumer => + currentState.providerState.consumerStatus.get(consumer) == TIMEDOUT + )) + + val CanSendVSCPackets = + not(ConsumerChains.exists( + consumer => + currentState.providerState.outstandingPacketsToConsumer.get(consumer).length() > 0 + )) + + val CanSendVSCMaturedPackets = + not(ConsumerChains.exists( + consumer => + currentState.consumerStates.get(consumer).outstandingPacketsToProvider.length() > 0 + )) + // ================== // MANUAL TEST CASES // ================== @@ -333,7 +372,7 @@ module CCVDefaultStateMachine { // the packet was removed from the consumer assert(currentState.consumerStates.get("consumer1").outstandingPacketsToProvider.length() == 0), currentState' = currentState, // just so this still has an effect - lastAction' = "HappyPathTest" + trace' = trace.append("HappyPathTest") } ) } diff --git a/tests/difference/core/quint_model/ccv_test.qnt b/tests/difference/core/quint_model/ccv_test.qnt index d84d8f0ea4..d416c0508e 100644 --- a/tests/difference/core/quint_model/ccv_test.qnt +++ b/tests/difference/core/quint_model/ccv_test.qnt @@ -157,7 +157,7 @@ module CCVTest { val newConsumerState = result.newState.consumerStates.get("sender") not(result.hasError) and newProviderState.receivedMaturations.size() == 0 and - newProviderState.consumerStatus.get("sender") == STOPPED + newProviderState.consumerStatus.get("sender") == TIMEDOUT } run ConsumerStatusMapHappyPathTest = @@ -170,7 +170,8 @@ module CCVTest { val res = StartStopConsumers( currentConsumerStatusMap, Set("chain1"), - Set("chain2") + Set("chain2"), + Set() ) res._2 == "" and res._1.get("chain1") == RUNNING and @@ -188,7 +189,8 @@ module CCVTest { val res = StartStopConsumers( currentConsumerStatusMap, Set("chain2"), - Set("chain3") + Set("chain3"), + Set() ) res._2 == "cannot start a consumer that is not unused" } @@ -203,7 +205,8 @@ module CCVTest { val res = StartStopConsumers( currentConsumerStatusMap, Set("chain1"), - Set("chain3") + Set("chain3"), + Set() ) res._2 == "Cannot stop a consumer that is not running" } @@ -218,7 +221,8 @@ module CCVTest { val res = StartStopConsumers( currentConsumerStatusMap, Set("chain1"), - Set("chain1") + Set("chain1"), + Set() ) res._2 == "Cannot start and stop a consumer at the same time" } diff --git a/tests/difference/core/quint_model/libraries/extraSpells.qnt b/tests/difference/core/quint_model/libraries/extraSpells.qnt index 54b5feca09..9c1fb4034d 100644 --- a/tests/difference/core/quint_model/libraries/extraSpells.qnt +++ b/tests/difference/core/quint_model/libraries/extraSpells.qnt @@ -185,14 +185,26 @@ module extraSpells { assert(Values(Map()) == Set()) } + // Returns the maximal element of the set. + // If the set is empty, the function call will fail at runtime. pure def Max(__set: Set[int]): int = { - __set.fold(0, (__m, __e) => max(__m, __e)) + __set.fold(oneOf(__set), (__m, __e) => max(__m, __e)) } run MaxTest = all { assert(Max(Set(1, 2, 3)) == 3), - assert(Max(Set()) == 0) + } + + // Returns the minimal element of the set. + // If the set is empty, the function call will fail at runtime. + pure def Min(__set: Set[int]): int = { + __set.fold(oneOf(__set), (__m, __e) => if(__m < __e) __m else __e) + } + + run MinTest = + all { + assert(Min(Set(1, 2, 3)) == 1), } pure def HasSubsequence(__this: List[a], __other: List[a]): bool = { @@ -220,20 +232,19 @@ module extraSpells { } // Returns the maximum element of a set, according to a given function. - // __i should be part of the set if it is nonempty. If the set is empty, __i will be returned. // If two elements are equally large, an arbitrary one will be returned. - pure def MaxBy(__set: Set[a], __f: a => int, __i: a): a = { + // If the set is empty, the function call will fail at runtime. + pure def MaxBy(__set: Set[a], __f: a => int): a = { __set.fold( - __i, + oneOf(__set), (__m, __e) => if(__f(__m) > __f(__e)) {__m } else {__e} ) } run MaxByTest = all { - assert(MaxBy(Set(1, 2, 3), __x => __x, 0) == 3), - assert(MaxBy(Set(1, 2, 3), __x => -__x, 0) == 1), - assert(MaxBy(Set(), __x => __x, 0) == 0), + assert(MaxBy(Set(1, 2, 3), __x => __x) == 3), + assert(MaxBy(Set(1, 2, 3), __x => -__x) == 1), } // Like MaxBy, but returns the minimum element. diff --git a/tests/difference/core/quint_model/run_invariants.sh b/tests/difference/core/quint_model/run_invariants.sh index 575b444e28..9e68690152 100755 --- a/tests/difference/core/quint_model/run_invariants.sh +++ b/tests/difference/core/quint_model/run_invariants.sh @@ -1,5 +1 @@ -quint run --invariant ValidatorUpdatesArePropagated ccv_statemachine.qnt --main CCVDefaultStateMachine -quint run --invariant ValidatorSetHasExistedInv ccv_statemachine.qnt --main CCVDefaultStateMachine -quint run --invariant SameVSCPacketsInv ccv_statemachine.qnt --main CCVDefaultStateMachine -quint run --invariant MatureOnTimeInv ccv_statemachine.qnt --main CCVDefaultStateMachine -quint run --invariant EventuallyMatureOnProviderInv ccv_statemachine.qnt --main CCVDefaultStateMachine \ No newline at end of file +quint run --invariant "all{ValidatorUpdatesArePropagated,ValidatorSetHasExistedInv,SameVSCPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv}" ccv_statemachine.qnt --main CCVDefaultStateMachine --max-steps 200000 --max-samples 200 --out out.log \ No newline at end of file From 289ccad3c7d8fc3cd1fbaa9b5116c7737af42414 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 2 Oct 2023 10:46:51 +0200 Subject: [PATCH 39/80] Update model for bug reporting] --- tests/difference/core/quint_model/README.md | 3 ++- tests/difference/core/quint_model/ccv.qnt | 27 +++++++++++++++++-- .../core/quint_model/ccv_statemachine.qnt | 23 +++++++++++----- .../core/quint_model/run_sanity_checks.sh | 1 + 4 files changed, 44 insertions(+), 10 deletions(-) create mode 100755 tests/difference/core/quint_model/run_sanity_checks.sh diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index a6451b1396..696cb183a9 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -57,4 +57,5 @@ The available sanity checks are: - CanTimeoutConsumer - CanSendVSCPackets - CanSendVSCMaturedPackets - \ No newline at end of file + +Run all sanity checks by running `run_sanity_checks.sh`. \ No newline at end of file diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index f329955955..7d9edf884e 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -445,6 +445,29 @@ module CCV { val providerStateAfterConsumerAdvancement = providerStateAfterTimeAdvancement.with( "consumerStatus", newConsumerStatus ) + + // for each consumer we just set to running, set its initial validator set to be the current one on the provider. + val newConsumerStateMap = + currentState.consumerStates.keys().mapBy( + (consumer) => + if (consumersToStart.contains(consumer)) { + val currentConsumerState = currentState.consumerStates.get(consumer) + val newConsumerState = currentConsumerState.with( + "chainState", currentConsumerState.chainState.with( + "currentValidatorSet", providerStateAfterConsumerAdvancement.chainState.currentValidatorSet + ) + ) + (consumer, newConsumerState) + } else { + (consumer, currentState.consumerStates.get(consumer)) + } + ) + val newState = currentState.with( + "providerState", providerStateAfterConsumerAdvancement + ).with( + "consumerStates", newConsumerStateMap + ) + if (err != "") { Err(err) } else { @@ -456,10 +479,10 @@ module CCV { } else { providerStateAfterConsumerAdvancement } - val newState = currentState.with( + val finalState = newState.with( "providerState", providerStateAfterSending ) - Ok(newState) + Ok(finalState) } } diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index a0e81a5186..5c5a4bd00a 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -115,9 +115,12 @@ module CCVDefaultStateMachine { // and each endblock has a good chance to stop consumers, ... // step is thus suited to test also unhappy paths. action step = any { - nondet chain = oneOf(runningConsumers) - nondet timeAdvancement = oneOf(timeAdvancements) - EndAndBeginBlockForConsumer(chain, timeAdvancement), + all { + runningConsumers.size() > 0, // ensure there is a running consumer, otherwise this action does not make sense + nondet chain = oneOf(runningConsumers) + nondet timeAdvancement = oneOf(timeAdvancements) + EndAndBeginBlockForConsumer(chain, timeAdvancement), + }, val consumerStatus = currentState.providerState.consumerStatus nondet consumersToStart = oneOf(unusedConsumers.powerset()) @@ -134,13 +137,19 @@ module CCVDefaultStateMachine { // try to send a packet. we could filter by chains that can actually send, // but it's probably not much faster than just trying and failing. - nondet sender = oneOf(runningConsumers) - DeliverVSCMaturedPacket(sender), + all { + runningConsumers.size() > 0, // ensure there is a running consumer, otherwise this action does not make sense + nondet sender = oneOf(runningConsumers) + DeliverVSCMaturedPacket(sender), + }, // again, we could filter by chains that can actually receive, // but it's probably not much faster than just trying and failing. - nondet recciver = oneOf(runningConsumers) - DeliverVSCPacket(recciver), + all { + runningConsumers.size() > 0, // ensure there is a running consumer, otherwise this action does not make sense + nondet recciver = oneOf(runningConsumers) + DeliverVSCPacket(recciver), + }, } // ================== diff --git a/tests/difference/core/quint_model/run_sanity_checks.sh b/tests/difference/core/quint_model/run_sanity_checks.sh new file mode 100755 index 0000000000..546d5468f1 --- /dev/null +++ b/tests/difference/core/quint_model/run_sanity_checks.sh @@ -0,0 +1 @@ +quint run --invariant "all{CanRunConsumer,CanStopConsumer,CanTimeoutConsumer,CanSendVSCPackets,CanSendVSCMaturedPackets}" ccv_statemachine.qnt --main CCVDefaultStateMachine --max-steps 2000 --max-samples 200 \ No newline at end of file From 45cfc5cd5414579221c45a9ec1c558d6ee4e558f Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 2 Oct 2023 11:03:08 +0200 Subject: [PATCH 40/80] Remove sanity check script --- tests/difference/core/quint_model/README.md | 4 +--- tests/difference/core/quint_model/ccv.qnt | 4 ++-- tests/difference/core/quint_model/run_sanity_checks.sh | 1 - 3 files changed, 3 insertions(+), 6 deletions(-) delete mode 100755 tests/difference/core/quint_model/run_sanity_checks.sh diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 696cb183a9..503bf9ee5e 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -56,6 +56,4 @@ The available sanity checks are: - CanStopConsumer - CanTimeoutConsumer - CanSendVSCPackets -- CanSendVSCMaturedPackets - -Run all sanity checks by running `run_sanity_checks.sh`. \ No newline at end of file +- CanSendVSCMaturedPackets \ No newline at end of file diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 7d9edf884e..d557da1b5a 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -457,9 +457,9 @@ module CCV { "currentValidatorSet", providerStateAfterConsumerAdvancement.chainState.currentValidatorSet ) ) - (consumer, newConsumerState) + newConsumerState } else { - (consumer, currentState.consumerStates.get(consumer)) + currentState.consumerStates.get(consumer) } ) val newState = currentState.with( diff --git a/tests/difference/core/quint_model/run_sanity_checks.sh b/tests/difference/core/quint_model/run_sanity_checks.sh deleted file mode 100755 index 546d5468f1..0000000000 --- a/tests/difference/core/quint_model/run_sanity_checks.sh +++ /dev/null @@ -1 +0,0 @@ -quint run --invariant "all{CanRunConsumer,CanStopConsumer,CanTimeoutConsumer,CanSendVSCPackets,CanSendVSCMaturedPackets}" ccv_statemachine.qnt --main CCVDefaultStateMachine --max-steps 2000 --max-samples 200 \ No newline at end of file From 4fdc2ffac153430738243cdc8bed8e97bf999ccc Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 2 Oct 2023 13:43:30 +0200 Subject: [PATCH 41/80] Fix model and randomly run invariant checks --- tests/difference/core/quint_model/README.md | 21 ++-- tests/difference/core/quint_model/ccv.qnt | 19 ++-- .../core/quint_model/ccv_statemachine.qnt | 107 +++++++++++++++--- .../quint_model/libraries/extraSpells.qnt | 4 +- .../core/quint_model/run_invariants.sh | 2 +- tests/difference/core/quint_model/trace.itf | 1 + 6 files changed, 124 insertions(+), 30 deletions(-) create mode 100644 tests/difference/core/quint_model/trace.itf diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 503bf9ee5e..9c2197170e 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -20,27 +20,34 @@ The parameters of the protocol are defined as consts in ccv.qnt. ### Tests -To run unit tests, run `quint test ccv_test.qnt`. +To run unit tests, run +``` +quint test ccv_test.qnt --main CCVTest +``` +and +``` +quint test ccv_statemachine.qnt --main CCVDefaultStateMachine +``` ### Invariants -The invariants I am checking are in ccv_statemachine.qnt. +The invariants to check are in ccv_statemachine.qnt. Check a single invariant by running `quint run --invariant INVARIANT_NAME ccv_statemachine.qnt --main CCVDefaultStateMachine`, or all invariants one after another with the help of the script `run_invariants.sh`. Each invariant takes about a minute to run. Invariants are as follows: -- [ ] ValidatorUpdatesArePropagated: When a validator power update is comitted on chain, a packet containing that change in voting power is sent to all running consumers. -- [ ] ValidatorSetHasExistedInv: Every validator set on consumer chains is/was a validator set on the provider. -- [ ] SameVSCPacketsInv: Ensure that consumer chains receive the same VSCPackets in the same order. +- [X] ValidatorUpdatesArePropagated: When a validator power update is comitted on chain, a packet containing that change in voting power is sent to all running consumers. +- [X] ValidatorSetHasExistedInv: Every validator set on consumer chains is/was a validator set on the provider. +- [X] SameVSCPacketsInv: Ensure that consumer chains receive the same VSCPackets in the same order. Because of nuances with starting/stopping consumers, this invariant is not as simple as it sounds. In detail: For consumer chains c1, c2, if both c1 and c2 received a packet p1 sent at t1 and a packet p2 sent at t2, then both have received ALL packets that were sent between t1 and t2 in the same order. -- [ ] MatureOnTimeInv: For every ValidatorSetChangePacket received by a consumer chain at +- [X] MatureOnTimeInv: For every ValidatorSetChangePacket received by a consumer chain at time t, a MaturedVSCPacket is sent back to the provider in the first block with a timestamp >= t + UnbondingPeriod on that consumer. -- [ ] EventuallyMatureOnProviderInv: If we send a VSCPacket, this is eventually responded to by all consumers +- [X] EventuallyMatureOnProviderInv: If we send a VSCPacket, this is eventually responded to by all consumers that were running at the time the packet was sent (and are still running). ### Sanity Checks diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index d557da1b5a..a04eb0caaf 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -405,9 +405,9 @@ module CCV { - // Ends a block on the provider. This means that the current validator set is committed on chain, - // packets are queued, and the next block is started. Also, consumers that have passed - // the VSCTimeout without responding to a pending vscpacket are dropped. + /// Ends a block on the provider. This means that the current validator set is committed on chain, + /// packets are queued, and the next block is started. Also, consumers that have passed + /// the VSCTimeout without responding to a pending vscpacket are dropped. pure def endAndBeginBlockForProvider( currentState: ProtocolState, // by how much the timestamp should be advanced, @@ -427,13 +427,18 @@ module CCV { "chainState", newChainState ) + val tmpState = currentState.with( + "providerState", providerStateAfterTimeAdvancement + ) + // check for VSC timeouts val timedOutConsumers = getRunningConsumers(providerStateAfterTimeAdvancement).filter( consumer => - val res = TimeoutDueToVSCTimeout(currentState, consumer) + val res = TimeoutDueToVSCTimeout(tmpState, consumer) res._1 ) + // start/stop chains val res = providerStateAfterTimeAdvancement.consumerStatus.StartStopConsumers( consumersToStart, @@ -448,10 +453,10 @@ module CCV { // for each consumer we just set to running, set its initial validator set to be the current one on the provider. val newConsumerStateMap = - currentState.consumerStates.keys().mapBy( + tmpState.consumerStates.keys().mapBy( (consumer) => if (consumersToStart.contains(consumer)) { - val currentConsumerState = currentState.consumerStates.get(consumer) + val currentConsumerState = tmpState.consumerStates.get(consumer) val newConsumerState = currentConsumerState.with( "chainState", currentConsumerState.chainState.with( "currentValidatorSet", providerStateAfterConsumerAdvancement.chainState.currentValidatorSet @@ -462,7 +467,7 @@ module CCV { currentState.consumerStates.get(consumer) } ) - val newState = currentState.with( + val newState = tmpState.with( "providerState", providerStateAfterConsumerAdvancement ).with( "consumerStates", newConsumerStateMap diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 5c5a4bd00a..5b994a79de 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -199,8 +199,8 @@ module CCVDefaultStateMachine { if (commonPackets.size() == 0) { true // they don't share any packets, so nothing to check } else { - val oldestCommonPacket = packets1.head() - val newestCommonPacket = packets1[packets1.length() - 1] + val newestCommonPacket = commonPackets.MaxBy(packet => packet.sendingTime) + val oldestCommonPacket = commonPackets.MinBy(packet => packet.sendingTime) // get all packets sent between the oldest and newest common packet val packetsBetween1 = packets1.select( packet => packet.sendingTime >= oldestCommonPacket.sendingTime and packet.sendingTime <= newestCommonPacket.sendingTime @@ -220,13 +220,14 @@ module CCVDefaultStateMachine { // with a timestamp >= t + UnbondingPeriod // NOTE: because we remove the maturationTimes entry when we send the packets, // it suffices to check that there is never an entry in maturationTimes - // that is older than the current time minus the unbonding period. + // that has already matured, i.e. where the maturationTime is smaller-or-equal than the lastTimestamp val MatureOnTimeInv = runningConsumers.forall( consumer => { val maturationTimes = currentState.consumerStates.get(consumer).maturationTimes maturationTimes.keys().forall( - packet => packet.sendingTime + UnbondingPeriodPerChain.get(consumer) <= currentState.providerState.chainState.lastTimestamp + // check that the maturation time is in the future + packet => maturationTimes.get(packet) >= currentState.consumerStates.get(consumer).chainState.lastTimestamp ) } ) @@ -244,7 +245,7 @@ module CCVDefaultStateMachine { sentPackets.forall( packet => // consumer still has time to respond - currentState.providerState.chainState.lastTimestamp <= packet.sendingTime + VscTimeout or + not(packet.sendingTime + VscTimeout < currentState.providerState.chainState.lastTimestamp) or // consumer was dropped currentState.providerState.consumerStatus.get(consumer) == STOPPED or currentState.providerState.consumerStatus.get(consumer) == TIMEDOUT @@ -291,20 +292,26 @@ module CCVDefaultStateMachine { consumer => currentState.consumerStates.get(consumer).outstandingPacketsToProvider.length() > 0 )) + + val CanReceiveMaturations = + not(ConsumerChains.exists( + consumer => + currentState.providerState.receivedMaturations.size() > 0 + )) // ================== // MANUAL TEST CASES // ================== // Manually written test cases to get confidence in the base operation of the protocol. - // Test a simple happy path where: - // * the consumer chain is set to running - // * a validator set change happens - // * a block is ended on the provider, i.e. a packet is sent to the consumer - // * the consumer receives the packet - // * the chains wait until the unbonding period is over - // * the consumer sends a VSCMaturedPacket to the provider - // * the provider receives the VSCMaturedPacket + /// Test a simple happy path where: + /// * the consumer chain is set to running + /// * a validator set change happens + /// * a block is ended on the provider, i.e. a packet is sent to the consumer + /// * the consumer receives the packet + /// * the chains wait until the unbonding period is over + /// * the consumer sends a VSCMaturedPacket to the provider + /// * the provider receives the VSCMaturedPacket run HappyPathTest: bool = { init.then( all { @@ -385,4 +392,78 @@ module CCVDefaultStateMachine { } ) } + + /// a manual test case for the SameVSCPacketsInv, since it needs very specific behaviour to even apply. + run SameVSCPacketsManualTest = + init.then( + // start all consumers except for consumer3 + EndAndBeginBlockForProvider(1 * Second, Set("consumer1", "consumer2"), Set()) + ).then( + // change voting power + VotingPowerChange("node1", 50) + ).then( + // send packet to consumer1 and consumer2 + EndAndBeginBlockForProvider(1 * Second, Set(), Set()) + ).then( + // deliver the packets + DeliverVSCPacket("consumer1") + ).then( + // deliver to consumer2 + DeliverVSCPacket("consumer2") + ).then( + // start consumer3 + EndAndBeginBlockForProvider(1 * Second, Set("consumer3"), Set()) + ).then( + // do another voting power change + VotingPowerChange("node2", 50) + ).then( + // send packets + EndAndBeginBlockForProvider(1 * Second, Set(), Set()) + ).then( + //deliver to consumer1 + DeliverVSCPacket("consumer1") + ).then( + // deliver to consumer2 + DeliverVSCPacket("consumer2") + ).then( + // deliver to consumer3 + DeliverVSCPacket("consumer3") + ) + .then( + // the SameVSCPacketInv should hold here + all { + assert(SameVSCPacketsInv), + // action does not matter, but needed to have uniform effect + step + } + ) + + // a manual test for the EventuallyMatureOnProvider invariant + run VSCTimeoutManualTest = + init + .then( + // start all consumer chains + EndAndBeginBlockForProvider(1 * Second, ConsumerChains, Set()) + ) + .then( + // change voting power + VotingPowerChange("node1", 50) + ) + .then( + // send packets + EndAndBeginBlockForProvider(1 * Second, Set(), Set()) + ) + .then( + // advance time on provider by VSCTimeout + 1 Second + EndAndBeginBlockForProvider(VscTimeout + 5 * Second, Set(), Set()) + ) + // .then( + // all { + // // the consumer chains should have timed out + // assert(ConsumerChains.forall( + // chain => currentState.providerState.consumerStatus.get(chain) == TIMEDOUT + // )), + // VotingPowerChange("node2", 50)// action needs to be there but does not matter + // } + // ) } \ No newline at end of file diff --git a/tests/difference/core/quint_model/libraries/extraSpells.qnt b/tests/difference/core/quint_model/libraries/extraSpells.qnt index 9c1fb4034d..04ae907f5d 100644 --- a/tests/difference/core/quint_model/libraries/extraSpells.qnt +++ b/tests/difference/core/quint_model/libraries/extraSpells.qnt @@ -248,9 +248,9 @@ module extraSpells { } // Like MaxBy, but returns the minimum element. - pure def MinBy(__set: Set[a], __f: a => int, __i: a): a = { + pure def MinBy(__set: Set[a], __f: a => int): a = { __set.fold( - __i, + oneOf(__set), (__m, __e) => if(__f(__m) < __f(__e)) {__m } else {__e} ) } diff --git a/tests/difference/core/quint_model/run_invariants.sh b/tests/difference/core/quint_model/run_invariants.sh index 9e68690152..5ea6b3d387 100755 --- a/tests/difference/core/quint_model/run_invariants.sh +++ b/tests/difference/core/quint_model/run_invariants.sh @@ -1 +1 @@ -quint run --invariant "all{ValidatorUpdatesArePropagated,ValidatorSetHasExistedInv,SameVSCPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv}" ccv_statemachine.qnt --main CCVDefaultStateMachine --max-steps 200000 --max-samples 200 --out out.log \ No newline at end of file +quint run --invariant "all{ValidatorUpdatesArePropagated,ValidatorSetHasExistedInv,SameVSCPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv}" ccv_statemachine.qnt --main CCVDefaultStateMachine --max-steps 500 --max-samples 200 --out out.log \ No newline at end of file diff --git a/tests/difference/core/quint_model/trace.itf b/tests/difference/core/quint_model/trace.itf new file mode 100644 index 0000000000..6bdbe79609 --- /dev/null +++ b/tests/difference/core/quint_model/trace.itf @@ -0,0 +1 @@ +{"#meta":{"format":"ITF","format-description":"https://apalache.informal.systems/docs/adr/015adr-trace.html","source":"ccv_statemachine.qnt","status":"violation","description":"Created by Quint on Mon Oct 02 2023 11:57:40 GMT+0200 (Central European Summer Time)","timestamp":1696240660150},"vars":["trace","currentState"],"states":[{"#meta":{"index":0},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","unused"],["consumer2","unused"],["consumer3","unused"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"0"},"sentVSCPackets":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]}}},"trace":["init"]},{"#meta":{"index":1},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","unused"],["consumer2","unused"],["consumer3","unused"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"0"},"sentVSCPackets":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]}}},"trace":["init","VotingPowerChange"]},{"#meta":{"index":2},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider"]},{"#meta":{"index":3},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"1"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer"]},{"#meta":{"index":4},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"1"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"1209601"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket"]},{"#meta":{"index":5},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"1"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"1209601"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange"]},{"#meta":{"index":6},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"1"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"1209601"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer"]},{"#meta":{"index":7},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"1"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"1209601"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer"]},{"#meta":{"index":8},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"1"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"1209601"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange"]},{"#meta":{"index":9},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"1"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"1209601"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange"]},{"#meta":{"index":10},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419201"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}}],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer"]},{"#meta":{"index":11},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"3715200"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419201"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}}],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket"]},{"#meta":{"index":12},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"3715200"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419201"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket"]},{"#meta":{"index":13},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"3715200"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419201"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange"]},{"#meta":{"index":14},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"4924800"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419201"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer"]},{"#meta":{"index":15},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"4924800"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419201"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket"]},{"#meta":{"index":16},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7344000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419201"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer"]},{"#meta":{"index":17},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7344000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"4838401"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer"]},{"#meta":{"index":18},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7344000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7257601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer"]},{"#meta":{"index":19},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7344000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"9676801"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer"]},{"#meta":{"index":20},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"9676801"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer"]},{"#meta":{"index":21},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer"]},{"#meta":{"index":22},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3024000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"2"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider"]},{"#meta":{"index":23},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3024000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"2"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer"]},{"#meta":{"index":24},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"3628800"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3024000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"2"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket"]},{"#meta":{"index":25},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"3628800"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3024000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"2"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer"]},{"#meta":{"index":26},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"3628800"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3024000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"2"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange"]},{"#meta":{"index":27},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3110400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"3628800"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3024000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"2"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer"]},{"#meta":{"index":28},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3110400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"3628800"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3024000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"2"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer","VotingPowerChange"]},{"#meta":{"index":29},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3110400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"3628800"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5443200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"3"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForProvider"]},{"#meta":{"index":30},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3110400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"3628800"}],[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"4320000"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5443200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"3"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForProvider","DeliverVSCPacket"]},{"#meta":{"index":31},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5529600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"5529600"}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5529600"}}],"receivedVSCPackets":[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5443200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"3"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForProvider","DeliverVSCPacket","EndAndBeginBlockForConsumer"]},{"#meta":{"index":32},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5529601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"5529600"}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5529600"}}],"receivedVSCPackets":[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5443200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"3"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForProvider","DeliverVSCPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer"]},{"#meta":{"index":33},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5529601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5529600"}}],"receivedVSCPackets":[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5443200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}},{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"5529600"}}]},"runningVscId":{"#bigint":"3"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForProvider","DeliverVSCPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket"]},{"#meta":{"index":34},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5529601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5529600"}}],"receivedVSCPackets":[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"7862400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}},{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"5529600"}}]},"runningVscId":{"#bigint":"3"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForProvider","DeliverVSCPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForProvider"]}]} \ No newline at end of file From 99744ff34049ccdd55da3ff2bd3c7d460a4fee99 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 2 Oct 2023 13:45:32 +0200 Subject: [PATCH 42/80] Remove trace --- tests/difference/core/quint_model/trace.itf | 1 - 1 file changed, 1 deletion(-) delete mode 100644 tests/difference/core/quint_model/trace.itf diff --git a/tests/difference/core/quint_model/trace.itf b/tests/difference/core/quint_model/trace.itf deleted file mode 100644 index 6bdbe79609..0000000000 --- a/tests/difference/core/quint_model/trace.itf +++ /dev/null @@ -1 +0,0 @@ -{"#meta":{"format":"ITF","format-description":"https://apalache.informal.systems/docs/adr/015adr-trace.html","source":"ccv_statemachine.qnt","status":"violation","description":"Created by Quint on Mon Oct 02 2023 11:57:40 GMT+0200 (Central European Summer Time)","timestamp":1696240660150},"vars":["trace","currentState"],"states":[{"#meta":{"index":0},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","unused"],["consumer2","unused"],["consumer3","unused"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"0"},"sentVSCPackets":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]}}},"trace":["init"]},{"#meta":{"index":1},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","unused"],["consumer2","unused"],["consumer3","unused"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"0"},"sentVSCPackets":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]}}},"trace":["init","VotingPowerChange"]},{"#meta":{"index":2},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider"]},{"#meta":{"index":3},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"1"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer"]},{"#meta":{"index":4},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"1"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"1209601"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket"]},{"#meta":{"index":5},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"1"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"1209601"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange"]},{"#meta":{"index":6},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"1"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"1209601"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer"]},{"#meta":{"index":7},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"1"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"1209601"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer"]},{"#meta":{"index":8},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"1"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"1209601"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange"]},{"#meta":{"index":9},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"1"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"1209601"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange"]},{"#meta":{"index":10},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419201"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}}],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer"]},{"#meta":{"index":11},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"3715200"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419201"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}}],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket"]},{"#meta":{"index":12},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"3715200"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419201"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket"]},{"#meta":{"index":13},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}},{"#bigint":"3715200"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419201"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange"]},{"#meta":{"index":14},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"4924800"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419201"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer"]},{"#meta":{"index":15},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"4924800"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419201"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket"]},{"#meta":{"index":16},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7344000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"2419201"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer"]},{"#meta":{"index":17},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7344000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"4838401"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer"]},{"#meta":{"index":18},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7344000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7257601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer"]},{"#meta":{"index":19},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7344000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"9676801"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer"]},{"#meta":{"index":20},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"9676801"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer"]},{"#meta":{"index":21},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","running"],["consumer2","unused"],["consumer3","running"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"1"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer"]},{"#meta":{"index":22},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"0"},"votingPowerHistory":[]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3024000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"2"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider"]},{"#meta":{"index":23},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3024000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"2"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer"]},{"#meta":{"index":24},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2419200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"3628800"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3024000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"2"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket"]},{"#meta":{"index":25},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"3628800"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3024000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"2"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer"]},{"#meta":{"index":26},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"2505600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"3628800"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3024000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"2"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange"]},{"#meta":{"index":27},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3110400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"3628800"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3024000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"2"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer"]},{"#meta":{"index":28},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3110400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"3628800"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3024000"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":true,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"2"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer","VotingPowerChange"]},{"#meta":{"index":29},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3110400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"3628800"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5443200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"3"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForProvider"]},{"#meta":{"index":30},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"3110400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"3628800"}],[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"#bigint":"4320000"}]]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5443200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"3"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForProvider","DeliverVSCPacket"]},{"#meta":{"index":31},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5529600"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"5529600"}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5529600"}}],"receivedVSCPackets":[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5443200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"3"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForProvider","DeliverVSCPacket","EndAndBeginBlockForConsumer"]},{"#meta":{"index":32},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5529601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"5529600"}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5529600"}}],"receivedVSCPackets":[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5443200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}}]},"runningVscId":{"#bigint":"3"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForProvider","DeliverVSCPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer"]},{"#meta":{"index":33},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5529601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5529600"}}],"receivedVSCPackets":[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5443200"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}},{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"5529600"}}]},"runningVscId":{"#bigint":"3"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForProvider","DeliverVSCPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket"]},{"#meta":{"index":34},"currentState":{"consumerStates":{"#map":[["consumer1",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"7430400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}],["consumer2",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"5529601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5529600"}}],"receivedVSCPackets":[{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]}],["consumer3",{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},"lastTimestamp":{"#bigint":"10281601"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"maturationTimes":{"#map":[]},"outstandingPacketsToProvider":[],"receivedVSCPackets":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]}]]},"providerState":{"chainState":{"currentValidatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},"lastTimestamp":{"#bigint":"7862400"},"votingPowerHistory":[{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]},{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}]},"consumerStatus":{"#map":[["consumer1","stopped"],["consumer2","running"],["consumer3","stopped"]]},"outstandingPacketsToConsumer":{"#map":[["consumer1",[]],["consumer2",[]],["consumer3",[]]]},"providerValidatorSetChangedInThisBlock":false,"receivedMaturations":{"#set":[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419201"}},{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"4924800"}},{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"5529600"}}]},"runningVscId":{"#bigint":"3"},"sentVSCPackets":{"#map":[["consumer1",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]],["consumer2",[{"id":{"#bigint":"1"},"sendingTime":{"#bigint":"3024000"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}},{"id":{"#bigint":"2"},"sendingTime":{"#bigint":"5443200"},"validatorSet":{"#map":[["node1",{"#bigint":"50"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"50"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"50"}],["node5",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"50"}]]}}]],["consumer3",[{"id":{"#bigint":"0"},"sendingTime":{"#bigint":"2419200"},"validatorSet":{"#map":[["node1",{"#bigint":"100"}],["node10",{"#bigint":"100"}],["node2",{"#bigint":"100"}],["node3",{"#bigint":"100"}],["node4",{"#bigint":"100"}],["node5",{"#bigint":"100"}],["node6",{"#bigint":"100"}],["node7",{"#bigint":"100"}],["node8",{"#bigint":"100"}],["node9",{"#bigint":"100"}]]}}]]]}}},"trace":["init","VotingPowerChange","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","VotingPowerChange","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","VotingPowerChange","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCPacket","DeliverVSCMaturedPacket","VotingPowerChange","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","EndAndBeginBlockForProvider","EndAndBeginBlockForConsumer","DeliverVSCPacket","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForConsumer","VotingPowerChange","EndAndBeginBlockForProvider","DeliverVSCPacket","EndAndBeginBlockForConsumer","EndAndBeginBlockForConsumer","DeliverVSCMaturedPacket","EndAndBeginBlockForProvider"]}]} \ No newline at end of file From 1bc4610ec05b8d32baf590d44b989e0ef2727a0a Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 2 Oct 2023 13:46:16 +0200 Subject: [PATCH 43/80] Add model checking to README --- tests/difference/core/quint_model/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 9c2197170e..7687c50036 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -50,6 +50,12 @@ with a timestamp >= t + UnbondingPeriod on that consumer. - [X] EventuallyMatureOnProviderInv: If we send a VSCPacket, this is eventually responded to by all consumers that were running at the time the packet was sent (and are still running). +Invariants can also be model-checked by Apalache, using this command: +``` +quint verify --invariant ValidatorUpdatesArePropagated,ValidatorSetHasExistedInv,SameVSCPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv --main CCVDefaultState +Machine ccv_statemachine.qnt +``` + ### Sanity Checks Sanity checks verify that certain patterns of behaviour can appear in the model. From 9e4f9c41b47abf527c46f3be02f363d0a9fe5ff3 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 2 Oct 2023 14:02:39 +0200 Subject: [PATCH 44/80] Add bluespec --- tests/difference/core/quint_model/ccv.qnt | 1 + tests/difference/core/quint_model/ccv_statemachine.qnt | 1 + tests/difference/core/quint_model/ccv_test.qnt | 2 ++ tests/difference/core/quint_model/libraries/Time.qnt | 2 ++ tests/difference/core/quint_model/libraries/extraSpells.qnt | 2 ++ 5 files changed, 8 insertions(+) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index a04eb0caaf..6731b0b6ff 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -1,3 +1,4 @@ +// -- mode: Bluespec; -- module CCVTypes { import Time.* from "./libraries/Time" diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 5b994a79de..94bd652656 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -1,3 +1,4 @@ +// -- mode: Bluespec; -- module CCVDefaultStateMachine { // A basic state machine that utilizes the CCV protocol. import CCVTypes.* from "./ccv" diff --git a/tests/difference/core/quint_model/ccv_test.qnt b/tests/difference/core/quint_model/ccv_test.qnt index d416c0508e..c01d886963 100644 --- a/tests/difference/core/quint_model/ccv_test.qnt +++ b/tests/difference/core/quint_model/ccv_test.qnt @@ -1,3 +1,5 @@ +// -- mode: Bluespec; -- + // contains test logic for the stateless functions in the CCV module module CCVTest { import CCVTypes.* from "./ccv" diff --git a/tests/difference/core/quint_model/libraries/Time.qnt b/tests/difference/core/quint_model/libraries/Time.qnt index 8497d8e1d3..06b81a3f64 100644 --- a/tests/difference/core/quint_model/libraries/Time.qnt +++ b/tests/difference/core/quint_model/libraries/Time.qnt @@ -1,3 +1,5 @@ +// -- mode: Bluespec; -- + // A simple module for time that makes timings more readable, // e.g. 5 * Minute. // The base unit are seconds, i.e. to get the number of seconds in a time value, just treat it as an int. diff --git a/tests/difference/core/quint_model/libraries/extraSpells.qnt b/tests/difference/core/quint_model/libraries/extraSpells.qnt index 04ae907f5d..22d731599c 100644 --- a/tests/difference/core/quint_model/libraries/extraSpells.qnt +++ b/tests/difference/core/quint_model/libraries/extraSpells.qnt @@ -1,3 +1,5 @@ +// -- mode: Bluespec; -- + // This module is just a library with utility functions (sometimes called spells in Quint). module extraSpells { From ca50ee2ca5a4c0f4344c3ebef26e206a3a14fdfb Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 2 Oct 2023 14:04:03 +0200 Subject: [PATCH 45/80] Try fixed bluespec --- tests/difference/core/quint_model/ccv_test.qnt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/ccv_test.qnt b/tests/difference/core/quint_model/ccv_test.qnt index c01d886963..a6b09a1a60 100644 --- a/tests/difference/core/quint_model/ccv_test.qnt +++ b/tests/difference/core/quint_model/ccv_test.qnt @@ -1,4 +1,4 @@ -// -- mode: Bluespec; -- +// -*- mode: Bluespec; -*- // contains test logic for the stateless functions in the CCV module module CCVTest { From a80ce703ca5ecd61fa4b77408609aacc649201d0 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 2 Oct 2023 14:05:11 +0200 Subject: [PATCH 46/80] Fix bluespec definitions --- tests/difference/core/quint_model/ccv.qnt | 2 +- tests/difference/core/quint_model/ccv_statemachine.qnt | 2 +- tests/difference/core/quint_model/libraries/Time.qnt | 3 +-- tests/difference/core/quint_model/libraries/extraSpells.qnt | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 6731b0b6ff..141b5bf06d 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -1,4 +1,4 @@ -// -- mode: Bluespec; -- +// -*- mode: Bluespec; -*- module CCVTypes { import Time.* from "./libraries/Time" diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 94bd652656..e12fdf7d85 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -1,4 +1,4 @@ -// -- mode: Bluespec; -- +// -*- mode: Bluespec; -*- module CCVDefaultStateMachine { // A basic state machine that utilizes the CCV protocol. import CCVTypes.* from "./ccv" diff --git a/tests/difference/core/quint_model/libraries/Time.qnt b/tests/difference/core/quint_model/libraries/Time.qnt index 06b81a3f64..a85d97697d 100644 --- a/tests/difference/core/quint_model/libraries/Time.qnt +++ b/tests/difference/core/quint_model/libraries/Time.qnt @@ -1,5 +1,4 @@ -// -- mode: Bluespec; -- - +// -*- mode: Bluespec; -*- // A simple module for time that makes timings more readable, // e.g. 5 * Minute. // The base unit are seconds, i.e. to get the number of seconds in a time value, just treat it as an int. diff --git a/tests/difference/core/quint_model/libraries/extraSpells.qnt b/tests/difference/core/quint_model/libraries/extraSpells.qnt index 22d731599c..24f37d919d 100644 --- a/tests/difference/core/quint_model/libraries/extraSpells.qnt +++ b/tests/difference/core/quint_model/libraries/extraSpells.qnt @@ -1,4 +1,4 @@ -// -- mode: Bluespec; -- +// -*- mode: Bluespec; -*- // This module is just a library with utility functions (sometimes called spells in Quint). module extraSpells { From 918e71a186c6bf808ebcec1b2785e7f966f7e5c3 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com> Date: Thu, 5 Oct 2023 17:29:34 +0200 Subject: [PATCH 47/80] Update tests/difference/core/quint_model/README.md Co-authored-by: insumity --- tests/difference/core/quint_model/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 7687c50036..d7b9ebd78e 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -7,7 +7,7 @@ The core of the protocol. - ccv_statemachine.qnt: Contains the state machine layer for CCV. Very roughly speaking, this could be seen as "e2e tests". Also contains invariants. - ccv_test.qnt: Contains unit tests for the functional layer of CCV. -- libararies/*: Libraries that don't belong to CCV, but are used by it. +- libraries/*: Libraries that don't belong to CCV, but are used by it. ### Model details From 8da4cfe951cd3944ae79cf41e1535aa36189e441 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com> Date: Thu, 5 Oct 2023 17:29:43 +0200 Subject: [PATCH 48/80] Update tests/difference/core/quint_model/README.md Co-authored-by: insumity --- tests/difference/core/quint_model/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index d7b9ebd78e..a420737801 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -11,7 +11,7 @@ Also contains invariants. ### Model details -To see the data structures used in the model, see the ProtocolState type in ccv.qnt. +To see the data structures used in the model, see the `ProtocolState` type in ccv.qnt. The "public" endpoints of the model are those functions that take as an input the protocol state, and return a Result. Other functions are for utility. From 2a682368c7c1df44e017ab6b37b5bf29b9831f84 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 5 Oct 2023 17:50:44 +0200 Subject: [PATCH 49/80] Fix minor issues --- tests/difference/core/quint_model/ccv.qnt | 24 ------------------- .../core/quint_model/ccv_statemachine.qnt | 5 ++-- .../difference/core/quint_model/ccv_test.qnt | 24 +++++++++++++++++++ 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 141b5bf06d..43dca0ccc2 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -324,30 +324,6 @@ module CCV { } } - // Defines a test state to test the deliverPacketToProvider function against. - pure val _DeliverPacketToProvider_TestState = - val currentState = GetEmptyProtocolState - val sender = "sender" - val providerState = currentState.providerState - val consumerState = GetEmptyConsumerState - // add the consumer to the consumerStates - val consumerStates = currentState.consumerStates.put(sender, consumerState) - val providerState2 = providerState.with( - "consumerStatus", providerState.consumerStatus.put(sender, RUNNING) - ) - val providerState3 = providerState2.with( - "outstandingPacketsToConsumer", providerState2.outstandingPacketsToConsumer.put(sender, List({ - id: 0, - validatorSet: Map(), - sendingTime: 0 - })) - ) - currentState.with( - "providerState", providerState3 - ).with( - "consumerStates", consumerStates - ) - // Delivers the next queued VSCPacket from the provider chain to a consumer chain. // Only argument is the consumer chain, to which the packet will be delivered. // If this packet will time out on the consumer on delivery, diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index e12fdf7d85..b4229c05e0 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -169,9 +169,10 @@ module CCVDefaultStateMachine { // Any update in the power of a validator on the provider // MUST be present in a ValidatorSetChangePacket that is sent to all registered consumer chains - val ValidatorUpdatesArePropagated = + val ValUpdatePrecondition = trace[trace.length()-1] == "EndAndBeginBlockForProvider" + val ValidatorUpdatesArePropagated = // when the provider has just entered a validator set into a block... - if (trace == trace.append("EndAndBeginBlockForProvider")) { + if (ValUpdatePrecondition and currentState.providerState.providerValidatorSetChangedInThisBlock) { val providerValSetInCurBlock = providerValidatorHistory.head() // ... for each consumer that is running then ... runningConsumers.forall( diff --git a/tests/difference/core/quint_model/ccv_test.qnt b/tests/difference/core/quint_model/ccv_test.qnt index a6b09a1a60..7f3e6a69fd 100644 --- a/tests/difference/core/quint_model/ccv_test.qnt +++ b/tests/difference/core/quint_model/ccv_test.qnt @@ -84,6 +84,30 @@ module CCVTest { result.newState.providerState.chainState.votingPowerHistory == List() } + // Defines a test state to test the deliverPacketToProvider function against. + pure val _DeliverPacketToProvider_TestState = + val currentState = GetEmptyProtocolState + val sender = "sender" + val providerState = currentState.providerState + val consumerState = GetEmptyConsumerState + // add the consumer to the consumerStates + val consumerStates = currentState.consumerStates.put(sender, consumerState) + val providerState2 = providerState.with( + "consumerStatus", providerState.consumerStatus.put(sender, RUNNING) + ) + val providerState3 = providerState2.with( + "outstandingPacketsToConsumer", providerState2.outstandingPacketsToConsumer.put(sender, List({ + id: 0, + validatorSet: Map(), + sendingTime: 0 + })) + ) + currentState.with( + "providerState", providerState3 + ).with( + "consumerStates", consumerStates + ) + // add a packet on the consumer pure val DeliverPacketToProviderHappyPathTest_testState = _DeliverPacketToProvider_TestState.with( "consumerStates", _DeliverPacketToProvider_TestState.consumerStates.put( From 2ad4debe00fdfe6e441a2375a8a773a161d0667a Mon Sep 17 00:00:00 2001 From: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com> Date: Fri, 6 Oct 2023 08:41:36 +0200 Subject: [PATCH 50/80] Update tests/difference/core/quint_model/README.md Co-authored-by: insumity --- tests/difference/core/quint_model/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index a420737801..183f42137e 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -13,7 +13,7 @@ Also contains invariants. To see the data structures used in the model, see the `ProtocolState` type in ccv.qnt. -The "public" endpoints of the model are those functions that take as an input the protocol state, and return a Result. +The "public" endpoints of the model are those functions that take as an input the protocol state, and return a `Result`. Other functions are for utility. The parameters of the protocol are defined as consts in ccv.qnt. From 9d408428939f21336e50148413fe9b967f8f8305 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com> Date: Fri, 6 Oct 2023 08:41:43 +0200 Subject: [PATCH 51/80] Update tests/difference/core/quint_model/README.md Co-authored-by: insumity --- tests/difference/core/quint_model/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 183f42137e..906b93e90f 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -16,7 +16,7 @@ To see the data structures used in the model, see the `ProtocolState` type in cc The "public" endpoints of the model are those functions that take as an input the protocol state, and return a `Result`. Other functions are for utility. -The parameters of the protocol are defined as consts in ccv.qnt. +The parameters of the protocol are defined as consts in [ccv.qnt](ccv.qnt). ### Tests From 3eeb3fd5bc21ac1273f498d369e96be59ac3d53a Mon Sep 17 00:00:00 2001 From: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com> Date: Fri, 6 Oct 2023 08:44:50 +0200 Subject: [PATCH 52/80] Update tests/difference/core/quint_model/README.md Co-authored-by: insumity --- tests/difference/core/quint_model/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 906b93e90f..66e34fd947 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -31,7 +31,7 @@ quint test ccv_statemachine.qnt --main CCVDefaultStateMachine ### Invariants -The invariants to check are in ccv_statemachine.qnt. +The invariants to check are in [ccv_statemachine.qnt](ccv_statemachine.qnt). Check a single invariant by running `quint run --invariant INVARIANT_NAME ccv_statemachine.qnt --main CCVDefaultStateMachine`, or all invariants one after another with the help of the script `run_invariants.sh`. From 2000272940a84186d9bdc32eaf22e1250e5c4090 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 6 Oct 2023 08:47:51 +0200 Subject: [PATCH 53/80] Correct verify command by adding \ --- tests/difference/core/quint_model/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 66e34fd947..a2f66945b4 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -52,8 +52,8 @@ that were running at the time the packet was sent (and are still running). Invariants can also be model-checked by Apalache, using this command: ``` -quint verify --invariant ValidatorUpdatesArePropagated,ValidatorSetHasExistedInv,SameVSCPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv --main CCVDefaultState -Machine ccv_statemachine.qnt +quint verify --invariant ValidatorUpdatesArePropagated,ValidatorSetHasExistedInv,SameVSCPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv \ +--main CCVDefaultStateMachine ccv_statemachine.qnt ``` ### Sanity Checks From 7cd826bb8ba3990fe4384e81a423c24db8524c6b Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 6 Oct 2023 08:49:27 +0200 Subject: [PATCH 54/80] Add Inv to ValidatorUpdatesArePropagated --- tests/difference/core/quint_model/README.md | 4 ++-- tests/difference/core/quint_model/ccv_statemachine.qnt | 2 +- tests/difference/core/quint_model/run_invariants.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index a2f66945b4..4a36b4976b 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -38,7 +38,7 @@ or all invariants one after another with the help of the script `run_invariants. Each invariant takes about a minute to run. Invariants are as follows: -- [X] ValidatorUpdatesArePropagated: When a validator power update is comitted on chain, a packet containing that change in voting power is sent to all running consumers. +- [X] ValidatorUpdatesArePropagatedInv: When a validator power update is comitted on chain, a packet containing that change in voting power is sent to all running consumers. - [X] ValidatorSetHasExistedInv: Every validator set on consumer chains is/was a validator set on the provider. - [X] SameVSCPacketsInv: Ensure that consumer chains receive the same VSCPackets in the same order. Because of nuances with starting/stopping consumers, this invariant is not as simple as it sounds. In detail: @@ -52,7 +52,7 @@ that were running at the time the packet was sent (and are still running). Invariants can also be model-checked by Apalache, using this command: ``` -quint verify --invariant ValidatorUpdatesArePropagated,ValidatorSetHasExistedInv,SameVSCPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv \ +quint verify --invariant ValidatorUpdatesArePropagatedInv,ValidatorSetHasExistedInv,SameVSCPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv \ --main CCVDefaultStateMachine ccv_statemachine.qnt ``` diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index b4229c05e0..51edafcf58 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -170,7 +170,7 @@ module CCVDefaultStateMachine { // Any update in the power of a validator on the provider // MUST be present in a ValidatorSetChangePacket that is sent to all registered consumer chains val ValUpdatePrecondition = trace[trace.length()-1] == "EndAndBeginBlockForProvider" - val ValidatorUpdatesArePropagated = + val ValidatorUpdatesArePropagatedInv = // when the provider has just entered a validator set into a block... if (ValUpdatePrecondition and currentState.providerState.providerValidatorSetChangedInThisBlock) { val providerValSetInCurBlock = providerValidatorHistory.head() diff --git a/tests/difference/core/quint_model/run_invariants.sh b/tests/difference/core/quint_model/run_invariants.sh index 5ea6b3d387..142095682f 100755 --- a/tests/difference/core/quint_model/run_invariants.sh +++ b/tests/difference/core/quint_model/run_invariants.sh @@ -1 +1 @@ -quint run --invariant "all{ValidatorUpdatesArePropagated,ValidatorSetHasExistedInv,SameVSCPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv}" ccv_statemachine.qnt --main CCVDefaultStateMachine --max-steps 500 --max-samples 200 --out out.log \ No newline at end of file +quint run --invariant "all{ValidatorUpdatesArePropagatedInv,ValidatorSetHasExistedInv,SameVSCPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv}" ccv_statemachine.qnt --main CCVDefaultStateMachine --max-steps 500 --max-samples 200 --out out.log \ No newline at end of file From 7df2b1ffcbb02270011fc05ffd4bd5134bacc068 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com> Date: Fri, 6 Oct 2023 08:51:33 +0200 Subject: [PATCH 55/80] Update tests/difference/core/quint_model/README.md Co-authored-by: insumity --- tests/difference/core/quint_model/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 4a36b4976b..bfd7795d02 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -60,7 +60,7 @@ quint verify --invariant ValidatorUpdatesArePropagatedInv,ValidatorSetHasExisted Sanity checks verify that certain patterns of behaviour can appear in the model. In detail, they are invariant checks that we expect to fail. -They usually negate the appearance of some behaviour, i.e. not(DesirableBehaviour). +They usually negate the appearance of some behaviour, i.e. `not(DesirableBehaviour)`. Then, a counterexample for this is an example trace exhibiting the behaviour. They are run like invariant checks, i.e. `quint run --invariant SANITY_CHECK_NAME ccv_statemachine.qnt --main CCVDefaultStateMachine`. From 3633dc443b5afbf4c04f087a79604d17df50011d Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Tue, 10 Oct 2023 12:56:43 +0200 Subject: [PATCH 56/80] Apply comments --- tests/difference/core/quint_model/ccv.qnt | 102 +++++++++--------- .../core/quint_model/ccv_statemachine.qnt | 74 ++++++------- .../difference/core/quint_model/ccv_test.qnt | 4 +- 3 files changed, 90 insertions(+), 90 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 43dca0ccc2..fe605d450b 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -5,26 +5,26 @@ module CCVTypes { type Node = str type Chain = str type Power = int - type VSCId = int + type VscId = int type ValidatorSet = Node -> Power type Height = int // a list of validator sets per blocks, ordered by recency type VotingPowerHistory = List[ValidatorSet] - type VSCPacket = + type VscPacket = { // the identifier for this packet - id: VSCId, + id: VscId, // the new validator set. in the implementation, this would be a list of validator updates validatorSet: ValidatorSet, // the time at which the packet was sent. used to check whether packets have timed out. sendingTime: Time } - type VSCMaturedPacket = + type VscMaturedPacket = { - // the id of the VSCPacket that matured - id: VSCId, + // the id of the VscPacket that matured + id: VscId, // the time at which the packet was sent. used to check whether packets have timed out. sendingTime: Time } @@ -61,15 +61,15 @@ module CCVTypes { chainState: ChainState, // Stores, for each consumer chain, the list of packets that have been sent to the consumer chain - // and have not been received yet. + // and *have not been received yet*. // In the implementation, this would roughly be the unacknowledged packets on an ibc channel. - outstandingPacketsToConsumer: Chain -> List[VSCPacket], + outstandingPacketsToConsumer: Chain -> List[VscPacket], - // the set of received VSCMaturedPackets - receivedMaturations: Set[VSCMaturedPacket], + // the set of received VscMaturedPackets + receivedMaturations: Set[VscMaturedPacket], - // stores which VSC Packets have been sent to compare with receivedMaturations to detect timeouts due to non-responsiveness - sentVSCPackets: Chain -> List[VSCPacket], + // Stores VscPackets which have been sent but where the provider has *not received a response yet*. + sentVscPackets: Chain -> List[VscPacket], // stores whether, in this block, the validator set has changed. // this is needed because the validator set might be considered to have changed, even though @@ -82,7 +82,7 @@ module CCVTypes { consumerStatus: Chain -> str, // a monotonic strictly increasing and positive ID that is used - // to uniquely identify the VSCs sent to the consumer chains. + // to uniquely identify the Vscs sent to the consumer chains. runningVscId: int, } @@ -92,7 +92,7 @@ module CCVTypes { chainState: GetEmptyChainState, outstandingPacketsToConsumer: Map(), receivedMaturations: Set(), - sentVSCPackets: Map(), + sentVscPackets: Map(), providerValidatorSetChangedInThisBlock: false, consumerStatus: Map(), runningVscId: 0, @@ -104,18 +104,18 @@ module CCVTypes { // the state that each chain needs to store chainState: ChainState, - // Stores the maturation times for VSCPackets received by this consumer - maturationTimes: VSCPacket -> Time, + // Stores the maturation times for VscPackets received by this consumer + maturationTimes: VscPacket -> Time, // stores the received vscpackets in descending order of recency, // i.e. newest first. - receivedVSCPackets: List[VSCPacket], + receivedVscPackets: List[VscPacket], // Stores the list of packets that have been sent to the provider chain by this consumer // and have not been received yet. // ordered by recency, so the head is the oldest packet. // In the implementation, essentially unacknowledged IBC packets. - outstandingPacketsToProvider: List[VSCMaturedPacket], + outstandingPacketsToProvider: List[VscMaturedPacket], } // utility function: returns a consumer state that is initialized minimally. @@ -124,7 +124,7 @@ module CCVTypes { chainState: GetEmptyChainState, maturationTimes: Map(), outstandingPacketsToProvider: List(), - receivedVSCPackets: List(), + receivedVscPackets: List(), } // the state of the protocol consists of the composition of the state of one provider chain with potentially many consumer chains. @@ -178,7 +178,7 @@ module CCVTypes { }, outstandingPacketsToConsumer: Map(), receivedMaturations: Set(), - sentVSCPackets: Map(), + sentVscPackets: Map(), providerValidatorSetChangedInThisBlock: false, consumerStatus: Map(), runningVscId: 0, @@ -194,7 +194,7 @@ module CCVTypes { // possible consumer statuses pure val STOPPED = "stopped" // the chain was once a consumer chain, but has been voluntarily dropped by the provider. pure val TIMEDOUT = "timedout" // the chain has timed out and was dropped by the provider. This is only used for involuntary drops. - pure val RUNNING = "running" // the chain is currently a consumer chain. Running chains are those that get sent VSCPackets. + pure val RUNNING = "running" // the chain is currently a consumer chain. Running chains are those that get sent VscPackets. pure val UNUSED = "unused" // the chain has never been a consumer chain, and is available to become one. // When a chain is dropped, it cannot become a consumer again - we assume that would be done by another consumer becoming running. @@ -214,7 +214,7 @@ module CCV { // Things that explicitly are modelled: // * Validator set changes are propagated from provider to consumers - // * VSC packets mature + // * Vsc packets mature // We assume that packet receive + ack happen synchronously, // i.e. when the packet is delivered, the ack is delivered right afterwards. @@ -235,8 +235,8 @@ module CCV { // For each chain, this defines the time between the initiation of an unbonding and its maturation. const UnbondingPeriodPerChain: Chain -> int - // The maximum time duration between sending any VSCPacket to any consumer chain and receiving the - // corresponding VSCMaturedPacket, without timing out the consumer chain and consequently removing it. + // The maximum time duration between sending any VscPacket to any consumer chain and receiving the + // corresponding VscMaturedPacket, without timing out the consumer chain and consequently removing it. const VscTimeout: int // The timeoutTimestamp for sent packets. Can differ by chain. @@ -267,7 +267,7 @@ module CCV { } } - // Delivers the next queued VSCMaturedPacket from a consumer chain to the provider chain. + // Delivers the next queued VscMaturedPacket from a consumer chain to the provider chain. // Only argument is the consumer chain, from which the packet will be delivered. // If this packet will time out on the provider on delivery, // the consumer will be dropped. @@ -324,7 +324,7 @@ module CCV { } } - // Delivers the next queued VSCPacket from the provider chain to a consumer chain. + // Delivers the next queued VscPacket from the provider chain to a consumer chain. // Only argument is the consumer chain, to which the packet will be delivered. // If this packet will time out on the consumer on delivery, // the consumer will be dropped. @@ -384,7 +384,7 @@ module CCV { /// Ends a block on the provider. This means that the current validator set is committed on chain, /// packets are queued, and the next block is started. Also, consumers that have passed - /// the VSCTimeout without responding to a pending vscpacket are dropped. + /// the VscTimeout without responding to a pending vscpacket are dropped. pure def endAndBeginBlockForProvider( currentState: ProtocolState, // by how much the timestamp should be advanced, @@ -408,10 +408,10 @@ module CCV { "providerState", providerStateAfterTimeAdvancement ) - // check for VSC timeouts + // check for Vsc timeouts val timedOutConsumers = getRunningConsumers(providerStateAfterTimeAdvancement).filter( consumer => - val res = TimeoutDueToVSCTimeout(tmpState, consumer) + val res = TimeoutDueToVscTimeout(tmpState, consumer) res._1 ) @@ -474,9 +474,9 @@ module CCV { // by how much the timestamp of the chain should be advanced for the next block timeAdvancement: Time): Result = { if (not(currentState.consumerStates.keys().contains(chain))) { + // if the chain is not a consumer, return an error Err("chain is not a consumer") } else { - // if the chain is not a consumer, return an error val currentConsumerState = currentState.consumerStates.get(chain) val newChainState = currentConsumerState.chainState.endAndBeginBlockShared(timeAdvancement) val newConsumerState = currentConsumerState.with( @@ -644,7 +644,7 @@ module CCV { } // returns the providerState with the following modifications: - // * sends VSCPackets to all running consumers + // * sends VscPackets to all running consumers // * increments the runningVscId // This should only be called when the provider chain is ending a block, // and only when the running validator set is considered to have changed @@ -665,7 +665,7 @@ module CCV { } ) providerState.with( - // send VSCPackets to consumers + // send VscPackets to consumers "outstandingPacketsToConsumer", ConsumerChains.mapBy( (consumer) => @@ -674,11 +674,11 @@ module CCV { ) ) ).with( - // update the sent VSCPackets - "sentVSCPackets", + // update the sent VscPackets + "sentVscPackets", ConsumerChains.mapBy( (consumer) => - providerState.sentVSCPackets.get(consumer).concat( + providerState.sentVscPackets.get(consumer).concat( newSentPacketsPerConsumer.get(consumer) ) ) @@ -694,7 +694,7 @@ module CCV { // To receive a packet, modify the running validator set (not the one entered into the block yet, // but the candidate that would be put into the block if it ended now) // and store the maturation time for the packet. - pure def recvPacketOnConsumer(currentState: ProtocolState, receiver: Chain, packet: VSCPacket): Result = { + pure def recvPacketOnConsumer(currentState: ProtocolState, receiver: Chain, packet: VscPacket): Result = { if(not(isCurrentlyConsumer(receiver, currentState.providerState))) { Err("Receiver is not currently a consumer - must have 'running' status!") } else { @@ -713,8 +713,8 @@ module CCV { currentConsumerState.chainState.lastTimestamp + UnbondingPeriodPerChain.get(receiver) ) ).with( - "receivedVSCPackets", - currentConsumerState.receivedVSCPackets.prepend(packet) + "receivedVscPackets", + currentConsumerState.receivedVscPackets.prepend(packet) ) val newConsumerStates = currentState.consumerStates.set(receiver, newConsumerState) val newState = currentState.with( @@ -726,20 +726,20 @@ module CCV { // receives a given packet on the provider. The arguments are the consumer chain that sent the packet, and the packet itself. // To receive a packet, add it to the list of received maturations. - pure def recvPacketOnProvider(currentState: ProtocolState, sender: Chain, packet: VSCMaturedPacket): Result = { + pure def recvPacketOnProvider(currentState: ProtocolState, sender: Chain, packet: VscMaturedPacket): Result = { if (not(isCurrentlyConsumer(sender, currentState.providerState))) { Err("Sender is not currently a consumer - must have 'running' status!") - } else if (currentState.providerState.sentVSCPackets.get(sender).head().id != packet.id) { - // the packet is not the oldest sentVSCPacket, something went wrong - Err("Received maturation is not for the oldest sentVSCPacket") + } else if (currentState.providerState.sentVscPackets.get(sender).head().id != packet.id) { + // the packet is not the oldest sentVscPacket, something went wrong + Err("Received maturation is not for the oldest sentVscPacket") } else { val currentReceivedMaturations = currentState.providerState.receivedMaturations val newReceivedMaturations = currentReceivedMaturations.union(Set(packet)) val newProviderState = currentState.providerState.with( "receivedMaturations", newReceivedMaturations ) - // prune the sentVSCPacket - val newSentVSCPacket = currentState.providerState.sentVSCPackets.get(sender).tail() + // prune the sentVscPacket + val newSentVscPacket = currentState.providerState.sentVscPackets.get(sender).tail() val newState = currentState.with( "providerState", newProviderState ) @@ -820,11 +820,11 @@ module CCV { ) } - // Returns whether the consumer has timed out due to the VSCTimeout, and an error message. + // Returns whether the consumer has timed out due to the VscTimeout, and an error message. // If the second return is not equal to "", the first return should be ignored. // If it is equal to "", the first return will be true if the consumer has timed out and should be dropped, // or false otherwise. - pure def TimeoutDueToVSCTimeout(currentState: ProtocolState, consumer: Chain): (bool, str) = + pure def TimeoutDueToVscTimeout(currentState: ProtocolState, consumer: Chain): (bool, str) = // check for errors: the consumer is not running if (not(isCurrentlyConsumer(consumer, currentState.providerState))) { (false, "Consumer is not currently a consumer - must have 'running' status!") @@ -832,11 +832,11 @@ module CCV { val providerState = currentState.providerState val consumerState = currentState.consumerStates.get(consumer) - // has a packet been sent on the provider more than VSCTimeout ago, but we have not received an answer since then? - val sentVSCPackets = providerState.sentVSCPackets.get(consumer) - if(sentVSCPackets.length() > 0) { - val oldestSentVSCPacket = sentVSCPackets.head() // if length is 0, this is undefined, but we check for this before we use it - if(oldestSentVSCPacket.sendingTime + VscTimeout < providerState.chainState.lastTimestamp) { + // has a packet been sent on the provider more than VscTimeout ago, but we have not received an answer since then? + val sentVscPackets = providerState.sentVscPackets.get(consumer) + if(sentVscPackets.length() > 0) { + val oldestSentVscPacket = sentVscPackets.head() // if length is 0, this is undefined, but we check for this before we use it + if(oldestSentVscPacket.sendingTime + VscTimeout < providerState.chainState.lastTimestamp) { (true, "") } else { // no timeout yet, it has not been VscTimeout since that packet was sent diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 51edafcf58..b75d2b2d3e 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -36,7 +36,7 @@ module CCVDefaultStateMachine { "outstandingPacketsToConsumer", ConsumerChains.mapBy(chain => List()) ).with( - "sentVSCPackets", + "sentVscPackets", ConsumerChains.mapBy(chain => List()) ).with( // set the validator set to be the initial validator set in the history @@ -61,26 +61,26 @@ module CCVDefaultStateMachine { trace' = trace.append("VotingPowerChange") } - // The receiver receives the next outstanding VSCPacket from the provider. + // The receiver receives the next outstanding VscPacket from the provider. // This will time out the consumer if the packet timeout has passed on the receiver. - action DeliverVSCPacket(receiver: Chain): bool = + action DeliverVscPacket(receiver: Chain): bool = val resultAndTimeout = deliverPacketToConsumer(currentState, receiver) val result = resultAndTimeout._1 all { result.hasError == false, currentState' = result.newState, - trace' = trace.append("DeliverVSCPacket") + trace' = trace.append("DeliverVscPacket") } - // The provider receives the next outstanding VSCMaturedPacket from the sender. + // The provider receives the next outstanding VscMaturedPacket from the sender. // This will time out the consumer if the packet timeout has passed on the provider. - action DeliverVSCMaturedPacket(sender: Chain): bool = + action DeliverVscMaturedPacket(sender: Chain): bool = val resultAndTimeout = deliverPacketToProvider(currentState, sender) val result = resultAndTimeout._1 all { result.hasError == false, currentState' = result.newState, - trace' = trace.append("DeliverVSCMaturedPacket") + trace' = trace.append("DeliverVscMaturedPacket") } action EndAndBeginBlockForProvider( @@ -141,7 +141,7 @@ module CCVDefaultStateMachine { all { runningConsumers.size() > 0, // ensure there is a running consumer, otherwise this action does not make sense nondet sender = oneOf(runningConsumers) - DeliverVSCMaturedPacket(sender), + DeliverVscMaturedPacket(sender), }, // again, we could filter by chains that can actually receive, @@ -149,7 +149,7 @@ module CCVDefaultStateMachine { all { runningConsumers.size() > 0, // ensure there is a running consumer, otherwise this action does not make sense nondet recciver = oneOf(runningConsumers) - DeliverVSCPacket(recciver), + DeliverVscPacket(recciver), }, } @@ -177,7 +177,7 @@ module CCVDefaultStateMachine { // ... for each consumer that is running then ... runningConsumers.forall( // ...the validator set is in a sent packet - consumer => currentState.providerState.sentVSCPackets.get(consumer).toSet().exists( + consumer => currentState.providerState.sentVscPackets.get(consumer).toSet().exists( packet => packet.validatorSet == providerValSetInCurBlock ) ) @@ -191,12 +191,12 @@ module CCVDefaultStateMachine { // we need a slightly weaker invariant: // For consumer chains c1, c2, if both c1 and c2 received a packet p1 sent at t1 and a packet p2 sent at t2, // then both have received ALL packets that were sent between t1 and t2. - val SameVSCPacketsInv = + val SameVscPacketsInv = runningConsumers.forall( consumer1 => runningConsumers.forall( consumer2 => { - val packets1 = currentState.consumerStates.get(consumer1).receivedVSCPackets - val packets2 = currentState.consumerStates.get(consumer2).receivedVSCPackets + val packets1 = currentState.consumerStates.get(consumer1).receivedVscPackets + val packets2 = currentState.consumerStates.get(consumer2).receivedVscPackets val commonPackets = packets1.toSet().intersect(packets2.toSet()) if (commonPackets.size() == 0) { true // they don't share any packets, so nothing to check @@ -218,7 +218,7 @@ module CCVDefaultStateMachine { ) // For every ValidatorSetChangePacket received by a consumer chain at - // time t, a MaturedVSCPacket is sent back to the provider in the first block + // time t, a MaturedVscPacket is sent back to the provider in the first block // with a timestamp >= t + UnbondingPeriod // NOTE: because we remove the maturationTimes entry when we send the packets, // it suffices to check that there is never an entry in maturationTimes @@ -234,16 +234,16 @@ module CCVDefaultStateMachine { } ) - // If we send a VSCPacket, this is eventually responded to by all consumers + // If we send a VscPacket, this is eventually responded to by all consumers // that were running at the time the packet was sent (and are still running). - // Since we remove sentVSCPackets when we receive responses for them, - // we just check that if a sentVSCPacket has been sent more than - // VSCTimeout ago, the consumer must have been dropped. + // Since we remove sentVscPackets when we receive responses for them, + // we just check that if a sentVscPacket has been sent more than + // VscTimeout ago, the consumer must have been dropped. // In practice, when this is true, a pending unbonding can mature. val EventuallyMatureOnProviderInv = runningConsumers.forall( consumer => { - val sentPackets = currentState.providerState.sentVSCPackets.get(consumer).toSet() + val sentPackets = currentState.providerState.sentVscPackets.get(consumer).toSet() sentPackets.forall( packet => // consumer still has time to respond @@ -283,13 +283,13 @@ module CCVDefaultStateMachine { currentState.providerState.consumerStatus.get(consumer) == TIMEDOUT )) - val CanSendVSCPackets = + val CanSendVscPackets = not(ConsumerChains.exists( consumer => currentState.providerState.outstandingPacketsToConsumer.get(consumer).length() > 0 )) - val CanSendVSCMaturedPackets = + val CanSendVscMaturedPackets = not(ConsumerChains.exists( consumer => currentState.consumerStates.get(consumer).outstandingPacketsToProvider.length() > 0 @@ -312,8 +312,8 @@ module CCVDefaultStateMachine { /// * a block is ended on the provider, i.e. a packet is sent to the consumer /// * the consumer receives the packet /// * the chains wait until the unbonding period is over - /// * the consumer sends a VSCMaturedPacket to the provider - /// * the provider receives the VSCMaturedPacket + /// * the consumer sends a VscMaturedPacket to the provider + /// * the provider receives the VscMaturedPacket run HappyPathTest: bool = { init.then( all { @@ -327,7 +327,7 @@ module CCVDefaultStateMachine { "consumer2" -> List(), "consumer3" -> List() )), - assert(currentState.providerState.sentVSCPackets == Map( + assert(currentState.providerState.sentVscPackets == Map( "consumer1" -> List(), "consumer2" -> List(), "consumer3" -> List() @@ -354,7 +354,7 @@ module CCVDefaultStateMachine { // the validator set on the provider was entered into the history assert(currentState.providerState.chainState.votingPowerHistory == List(InitialValidatorSet.put("node1", 50), InitialValidatorSet)), // deliver the packet - DeliverVSCPacket("consumer1") + DeliverVscPacket("consumer1") } ) .then( @@ -380,7 +380,7 @@ module CCVDefaultStateMachine { // it was removed from the maturationTimes assert(currentState.consumerStates.get("consumer1").maturationTimes.keys().size() == 0), // receive the packet on the provider - DeliverVSCMaturedPacket("consumer1") + DeliverVscMaturedPacket("consumer1") } ) .then( @@ -395,8 +395,8 @@ module CCVDefaultStateMachine { ) } - /// a manual test case for the SameVSCPacketsInv, since it needs very specific behaviour to even apply. - run SameVSCPacketsManualTest = + /// a manual test case for the SameVscPacketsInv, since it needs very specific behaviour to even apply. + run SameVscPacketsManualTest = init.then( // start all consumers except for consumer3 EndAndBeginBlockForProvider(1 * Second, Set("consumer1", "consumer2"), Set()) @@ -408,10 +408,10 @@ module CCVDefaultStateMachine { EndAndBeginBlockForProvider(1 * Second, Set(), Set()) ).then( // deliver the packets - DeliverVSCPacket("consumer1") + DeliverVscPacket("consumer1") ).then( // deliver to consumer2 - DeliverVSCPacket("consumer2") + DeliverVscPacket("consumer2") ).then( // start consumer3 EndAndBeginBlockForProvider(1 * Second, Set("consumer3"), Set()) @@ -423,25 +423,25 @@ module CCVDefaultStateMachine { EndAndBeginBlockForProvider(1 * Second, Set(), Set()) ).then( //deliver to consumer1 - DeliverVSCPacket("consumer1") + DeliverVscPacket("consumer1") ).then( // deliver to consumer2 - DeliverVSCPacket("consumer2") + DeliverVscPacket("consumer2") ).then( // deliver to consumer3 - DeliverVSCPacket("consumer3") + DeliverVscPacket("consumer3") ) .then( - // the SameVSCPacketInv should hold here + // the SameVscPacketInv should hold here all { - assert(SameVSCPacketsInv), + assert(SameVscPacketsInv), // action does not matter, but needed to have uniform effect step } ) // a manual test for the EventuallyMatureOnProvider invariant - run VSCTimeoutManualTest = + run VscTimeoutManualTest = init .then( // start all consumer chains @@ -456,7 +456,7 @@ module CCVDefaultStateMachine { EndAndBeginBlockForProvider(1 * Second, Set(), Set()) ) .then( - // advance time on provider by VSCTimeout + 1 Second + // advance time on provider by VscTimeout + 1 Second EndAndBeginBlockForProvider(VscTimeout + 5 * Second, Set(), Set()) ) // .then( diff --git a/tests/difference/core/quint_model/ccv_test.qnt b/tests/difference/core/quint_model/ccv_test.qnt index 7f3e6a69fd..9638aa2818 100644 --- a/tests/difference/core/quint_model/ccv_test.qnt +++ b/tests/difference/core/quint_model/ccv_test.qnt @@ -119,9 +119,9 @@ module CCVTest { ) ) ).with( - // put an entry into sentVSCPacket on the provider that corresponds to the packet we put on the consumer + // put an entry into sentVscPacket on the provider that corresponds to the packet we put on the consumer "providerState", _DeliverPacketToProvider_TestState.providerState.with( - "sentVSCPackets", _DeliverPacketToProvider_TestState.providerState.sentVSCPackets.put( + "sentVscPackets", _DeliverPacketToProvider_TestState.providerState.sentVscPackets.put( "sender", List({ id: 0, validatorSet: _DeliverPacketToProvider_TestState.providerState.chainState.currentValidatorSet, From dc7e687535bf6b01b4e6b8e65b0e2b7f86b4ad38 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Tue, 10 Oct 2023 12:57:25 +0200 Subject: [PATCH 57/80] Rename VSC to Vsc --- tests/difference/core/quint_model/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index bfd7795d02..9213b091c3 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -40,19 +40,19 @@ Each invariant takes about a minute to run. Invariants are as follows: - [X] ValidatorUpdatesArePropagatedInv: When a validator power update is comitted on chain, a packet containing that change in voting power is sent to all running consumers. - [X] ValidatorSetHasExistedInv: Every validator set on consumer chains is/was a validator set on the provider. -- [X] SameVSCPacketsInv: Ensure that consumer chains receive the same VSCPackets in the same order. +- [X] SameVscPacketsInv: Ensure that consumer chains receive the same VscPackets in the same order. Because of nuances with starting/stopping consumers, this invariant is not as simple as it sounds. In detail: For consumer chains c1, c2, if both c1 and c2 received a packet p1 sent at t1 and a packet p2 sent at t2, then both have received ALL packets that were sent between t1 and t2 in the same order. - [X] MatureOnTimeInv: For every ValidatorSetChangePacket received by a consumer chain at -time t, a MaturedVSCPacket is sent back to the provider in the first block +time t, a MaturedVscPacket is sent back to the provider in the first block with a timestamp >= t + UnbondingPeriod on that consumer. -- [X] EventuallyMatureOnProviderInv: If we send a VSCPacket, this is eventually responded to by all consumers +- [X] EventuallyMatureOnProviderInv: If we send a VscPacket, this is eventually responded to by all consumers that were running at the time the packet was sent (and are still running). Invariants can also be model-checked by Apalache, using this command: ``` -quint verify --invariant ValidatorUpdatesArePropagatedInv,ValidatorSetHasExistedInv,SameVSCPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv \ +quint verify --invariant ValidatorUpdatesArePropagatedInv,ValidatorSetHasExistedInv,SameVscPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv \ --main CCVDefaultStateMachine ccv_statemachine.qnt ``` @@ -68,5 +68,5 @@ The available sanity checks are: - CanRunConsumer - CanStopConsumer - CanTimeoutConsumer -- CanSendVSCPackets -- CanSendVSCMaturedPackets \ No newline at end of file +- CanSendVscPackets +- CanSendVscMaturedPackets \ No newline at end of file From 728b02460c590cfea0d6645f68b02f1e9247ed58 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Tue, 10 Oct 2023 15:17:27 +0200 Subject: [PATCH 58/80] Return plain ProtocolState in cases where no error is returned anyways --- tests/difference/core/quint_model/ccv.qnt | 28 ++++++----------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index fe605d450b..b4523a8c23 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -250,7 +250,7 @@ module CCV { // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, // e.g. via undelegations, or delegations, ... pure def votingPowerChange(currentState: ProtocolState, validator: Node, amount: int): Result = { - if (amount < 0) { + if (amount <= 0) { Err("Voting power changes must be positive") } else { pure val currentValidatorSet = currentState.providerState.chainState.currentValidatorSet @@ -311,14 +311,7 @@ module CCV { if (result.hasError) { (Err(result.error.message), false) } else { - val result2 = removeOutstandingPacketFromConsumer(tmpState, sender) - val tmpState2 = result2.newState - val err2 = result2.error - if (result2.hasError) { - (Err(err2.message), false) - } else { - (Ok(tmpState2), false) // false because the packet did not time out - } + (Ok(removeOutstandingPacketFromConsumer(tmpState, sender)), false) // false because the packet did not time out } } } @@ -367,14 +360,7 @@ module CCV { if (result.hasError) { (Err(result.error.message), false) } else { - val result2 = removeOutstandingPacketFromProvider(tmpState, receiver) - val tmpState2 = result2.newState - val err2 = result2.error - if (result2.hasError) { - (Err(err2.message), false) - } else { - (Ok(tmpState2), false) // false because the packet did not time out - } + (Ok(removeOutstandingPacketFromProvider(tmpState, receiver)), false) // false because the packet did not time out } } } @@ -749,7 +735,7 @@ module CCV { // removes the oldest outstanding packet from the consumer. on-chain, this would happen when the packet is acknowledged. // only the oldest packet can be removed, since we model ordered channels. - pure def removeOutstandingPacketFromConsumer(currentState: ProtocolState, sender: Chain): Result = { + pure def removeOutstandingPacketFromConsumer(currentState: ProtocolState, sender: Chain): ProtocolState = { val currentOutstandingPackets = currentState.consumerStates.get(sender).outstandingPacketsToProvider val newOutstandingPackets = currentOutstandingPackets.tail() val newConsumerState = currentState.consumerStates.get(sender).with( @@ -759,13 +745,13 @@ module CCV { val newState = currentState.with( "consumerStates", newConsumerStates ) - Ok(newState) + newState } // removes the oldest outstanding packet (to the given consumer) from the provider. // on-chain, this would happen when the packet is acknowledged. // only the oldest packet can be removed, since we model ordered channels. - pure def removeOutstandingPacketFromProvider(currentState: ProtocolState, receiver: Chain): Result = { + pure def removeOutstandingPacketFromProvider(currentState: ProtocolState, receiver: Chain): ProtocolState = { val currentOutstandingPackets = currentState.providerState.outstandingPacketsToConsumer.get(receiver) val newOutstandingPackets = currentOutstandingPackets.tail() val newProviderState = currentState.providerState.with( @@ -775,7 +761,7 @@ module CCV { val newState = currentState.with( "providerState", newProviderState ) - Ok(newState) + newState } // Updates the given oldValidatorSet by setting the validator to newVotingPower. From 641d84506222c949e03f43fcaba59ec5ed6b0b96 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Tue, 10 Oct 2023 15:36:47 +0200 Subject: [PATCH 59/80] Remove unused defs --- tests/difference/core/quint_model/ccv.qnt | 48 +++++-------------- .../core/quint_model/ccv_statemachine.qnt | 8 ++-- .../difference/core/quint_model/ccv_test.qnt | 10 ++-- 3 files changed, 21 insertions(+), 45 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index b4523a8c23..ecd97521b3 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -78,7 +78,7 @@ module CCVTypes { providerValidatorSetChangedInThisBlock: bool, // stores, for each consumer chain, its current status - - // unused, running, or stopped + // not consumer, running, or stopped consumerStatus: Chain -> str, // a monotonic strictly increasing and positive ID that is used @@ -132,7 +132,7 @@ module CCVTypes { providerState: ProviderState, // the state of each consumer chain. // note that we assume that this contains all consumer chains that may ever exist, - // and consumer chains that are currently not running will have providerState.consumerStatus == UNUSED or STOPPED. + // and consumer chains that are currently not running will have providerState.consumerStatus == NOT_CONSUMER or STOPPED. consumerStates: Chain -> ConsumerState } @@ -195,7 +195,7 @@ module CCVTypes { pure val STOPPED = "stopped" // the chain was once a consumer chain, but has been voluntarily dropped by the provider. pure val TIMEDOUT = "timedout" // the chain has timed out and was dropped by the provider. This is only used for involuntary drops. pure val RUNNING = "running" // the chain is currently a consumer chain. Running chains are those that get sent VscPackets. - pure val UNUSED = "unused" // the chain has never been a consumer chain, and is available to become one. + pure val NOT_CONSUMER = "not consumer" // the chain has never been a consumer chain, and is available to become one. // When a chain is dropped, it cannot become a consumer again - we assume that would be done by another consumer becoming running. // the provider chain. @@ -376,7 +376,7 @@ module CCV { // by how much the timestamp should be advanced, // i.e. the timestamp for the next block is oldTimestamp + timeAdvancement timeAdvancement: Time, - // a set of consumers that were unused before, but should be set to running now. + // a set of consumers that were not consumers before, but should be set to running now. consumersToStart: Set[Chain], // a set of consumers that were running before, but should be set to stopped now. // This argument only needs to contain "voluntary" stops - @@ -500,29 +500,6 @@ module CCV { // which do not hold the core logic of the protocol, but are still part of it // =================== - // Get the running consumer that is furthest away from the provider in terms of timestamp. - pure def getFurthestConsumer(currentState: ProtocolState): Chain = { - val furthestConsumer = getRunningConsumers(currentState.providerState).MaxBy( - consumer => abs( - currentState.providerState.chainState.lastTimestamp - - currentState.consumerStates.get(consumer).chainState.lastTimestamp - ) - ) - furthestConsumer - } - - pure def getRunningConsumersFromMap(consumerStatus: Chain -> str): Set[Chain] = { - consumerStatus.keys().filter( - chain => consumerStatus.get(chain) == RUNNING - ) - } - - pure def getStoppedConsumersFromMap(consumerStatus: Chain -> str): Set[Chain] = { - consumerStatus.keys().filter( - chain => consumerStatus.get(chain) == STOPPED - ) - } - // Returns the new ConsumerStatusMap according to the consumers to stop // and the consumers to time out. // If a consumer is both stopped and timed out, it will be timed out. @@ -540,7 +517,6 @@ module CCV { if (consumersToStop.exclude(runningConsumers).size() > 0) { (currentConsumerStatusMap, "Cannot stop a consumer that is not running") } else { - // if a consumer is started, it must be unused val newConsumerStatusMap = currentConsumerStatusMap.keys().mapBy( (chain) => if (consumersToTimeout.contains(chain)) { @@ -561,15 +537,15 @@ module CCV { pure def startConsumers( currentConsumerStatusMap: Chain -> str, consumersToStart: Set[Chain]): (Chain -> str, str) = { - val unusedConsumers = currentConsumerStatusMap.keys().filter( - chain => currentConsumerStatusMap.get(chain) == UNUSED + val nonConsumers = currentConsumerStatusMap.keys().filter( + chain => currentConsumerStatusMap.get(chain) == NOT_CONSUMER ) // if a consumer is both started and stopped, this is an error // if a consumer is stopped, it must be running - if (consumersToStart.exclude(unusedConsumers).size() > 0) { - (currentConsumerStatusMap, "cannot start a consumer that is not unused") + if (consumersToStart.exclude(nonConsumers).size() > 0) { + (currentConsumerStatusMap, "cannot start a consumer that is stopped or already a consumer") } else { - // if a consumer is started, it must be unused + // if a consumer is started, it must be a nonconsumer val newConsumerStatusMap = currentConsumerStatusMap.keys().mapBy( (chain) => if (consumersToStart.contains(chain)) { @@ -799,10 +775,10 @@ module CCV { ) } - // Returns the set of all consumer chains that currently have the status UNUSED. - pure def getUnusedConsumers(providerState: ProviderState): Set[Chain] = { + // Returns the set of all consumer chains that currently have the status NOT_CONSUMER. + pure def getNonConsumers(providerState: ProviderState): Set[Chain] = { providerState.consumerStatus.keys().filter( - chain => providerState.consumerStatus.get(chain) == UNUSED + chain => providerState.consumerStatus.get(chain) == NOT_CONSUMER ) } diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index b75d2b2d3e..bc7ec44fbd 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -31,7 +31,7 @@ module CCVDefaultStateMachine { val consumerStates = ConsumerChains.mapBy(chain => GetEmptyConsumerState) val providerStateWithConsumers = providerState.with( "consumerStatus", - ConsumerChains.mapBy(chain => UNUSED) + ConsumerChains.mapBy(chain => NOT_CONSUMER) ).with( "outstandingPacketsToConsumer", ConsumerChains.mapBy(chain => List()) @@ -318,9 +318,9 @@ module CCVDefaultStateMachine { init.then( all { assert(currentState.providerState.consumerStatus == Map( - "consumer1" -> UNUSED, - "consumer2" -> UNUSED, - "consumer3" -> UNUSED + "consumer1" -> NOT_CONSUMER, + "consumer2" -> NOT_CONSUMER, + "consumer3" -> NOT_CONSUMER )), assert(currentState.providerState.outstandingPacketsToConsumer == Map( "consumer1" -> List(), diff --git a/tests/difference/core/quint_model/ccv_test.qnt b/tests/difference/core/quint_model/ccv_test.qnt index 9638aa2818..9493e69d6a 100644 --- a/tests/difference/core/quint_model/ccv_test.qnt +++ b/tests/difference/core/quint_model/ccv_test.qnt @@ -189,7 +189,7 @@ module CCVTest { run ConsumerStatusMapHappyPathTest = { val currentConsumerStatusMap = Map( - "chain1" -> UNUSED, + "chain1" -> NOT_CONSUMER, "chain2" -> RUNNING, "chain3" -> STOPPED ) @@ -208,7 +208,7 @@ module CCVTest { run ConsumerStatusMapAlreadyRunningTest = { val currentConsumerStatusMap = Map( - "chain1" -> UNUSED, + "chain1" -> NOT_CONSUMER, "chain2" -> RUNNING, "chain3" -> STOPPED ) @@ -218,13 +218,13 @@ module CCVTest { Set("chain3"), Set() ) - res._2 == "cannot start a consumer that is not unused" + res._2 == "cannot start a consumer that is stopped or running" } run ConsumerStatusMapAlreadyStoppedTest = { val currentConsumerStatusMap = Map( - "chain1" -> UNUSED, + "chain1" -> NOT_CONSUMER, "chain2" -> RUNNING, "chain3" -> STOPPED ) @@ -240,7 +240,7 @@ module CCVTest { run ChainBothInStartAndStopTest = { val currentConsumerStatusMap = Map( - "chain1" -> UNUSED, + "chain1" -> NOT_CONSUMER, "chain2" -> RUNNING, "chain3" -> STOPPED ) From c2aa6d049e5804eb29ef68ce51a191aa9f904ac8 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Tue, 10 Oct 2023 15:54:11 +0200 Subject: [PATCH 60/80] Fix indentation --- tests/difference/core/quint_model/ccv.qnt | 63 +++++++++---------- .../core/quint_model/ccv_statemachine.qnt | 4 +- 2 files changed, 32 insertions(+), 35 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index ecd97521b3..c7f1e0c566 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -512,24 +512,23 @@ module CCV { val runningConsumers = currentConsumerStatusMap.keys().filter( chain => currentConsumerStatusMap.get(chain) == RUNNING ) - // if a consumer is both started and stopped, this is an error - // if a consumer is stopped, it must be running - if (consumersToStop.exclude(runningConsumers).size() > 0) { - (currentConsumerStatusMap, "Cannot stop a consumer that is not running") - } else { - val newConsumerStatusMap = currentConsumerStatusMap.keys().mapBy( - (chain) => - if (consumersToTimeout.contains(chain)) { - TIMEDOUT - } else if (consumersToStop.contains(chain)) { - STOPPED - } else { - currentConsumerStatusMap.get(chain) - } - ) - (newConsumerStatusMap, "") - } + // all consumers to stop must be running right now, else we have an error + if (consumersToStop.exclude(runningConsumers).size() > 0) { + (currentConsumerStatusMap, "Cannot stop a consumer that is not running") + } else { + val newConsumerStatusMap = currentConsumerStatusMap.keys().mapBy( + (chain) => + if (consumersToTimeout.contains(chain)) { + TIMEDOUT + } else if (consumersToStop.contains(chain)) { + STOPPED + } else { + currentConsumerStatusMap.get(chain) + } + ) + (newConsumerStatusMap, "") } + } // Returns the new ConsumerStatusMap according to the consumers to start. // The second return is an error string: If it is not equal to "", @@ -540,23 +539,21 @@ module CCV { val nonConsumers = currentConsumerStatusMap.keys().filter( chain => currentConsumerStatusMap.get(chain) == NOT_CONSUMER ) - // if a consumer is both started and stopped, this is an error - // if a consumer is stopped, it must be running - if (consumersToStart.exclude(nonConsumers).size() > 0) { - (currentConsumerStatusMap, "cannot start a consumer that is stopped or already a consumer") - } else { - // if a consumer is started, it must be a nonconsumer - val newConsumerStatusMap = currentConsumerStatusMap.keys().mapBy( - (chain) => - if (consumersToStart.contains(chain)) { - RUNNING - } else { - currentConsumerStatusMap.get(chain) - } - ) - (newConsumerStatusMap, "") - } + // all consumers to start must be nonConsumers right now, otherwise we have an error + if (consumersToStart.exclude(nonConsumers).size() > 0) { + (currentConsumerStatusMap, "cannot start a consumer that is stopped or already a consumer") + } else { + val newConsumerStatusMap = currentConsumerStatusMap.keys().mapBy( + (chain) => + if (consumersToStart.contains(chain)) { + RUNNING + } else { + currentConsumerStatusMap.get(chain) + } + ) + (newConsumerStatusMap, "") } + } pure def StartStopConsumers( currentConsumerStatusMap: Chain -> str, diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index bc7ec44fbd..5b75716a5f 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -24,7 +24,7 @@ module CCVDefaultStateMachine { // some utility stateful vals to make invariants easier to define val providerValidatorHistory = currentState.providerState.chainState.votingPowerHistory val runningConsumers = getRunningConsumers(currentState.providerState) - val unusedConsumers = getUnusedConsumers(currentState.providerState) + val nonConsumers = getNonConsumers(currentState.providerState) action init: bool = all { val providerState = GetEmptyProviderState @@ -124,7 +124,7 @@ module CCVDefaultStateMachine { }, val consumerStatus = currentState.providerState.consumerStatus - nondet consumersToStart = oneOf(unusedConsumers.powerset()) + nondet consumersToStart = oneOf(nonConsumers.powerset()) nondet consumersToStop = oneOf(runningConsumers.powerset()) nondet timeAdvancement = oneOf(timeAdvancements) EndAndBeginBlockForProvider(timeAdvancement, consumersToStart, consumersToStop), From 75b1e111aec18faaacc73c1ef030924c7f8af239 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Tue, 10 Oct 2023 15:54:48 +0200 Subject: [PATCH 61/80] Rename to isRunningConsumer --- tests/difference/core/quint_model/ccv.qnt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index c7f1e0c566..ea6c5058fa 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -275,7 +275,7 @@ module CCV { // that indicates whether the consumer timed out or not. // If the result has an error, the second return should be ignored. pure def deliverPacketToProvider(currentState: ProtocolState, sender: Chain): (Result, bool) = { - if (not(isCurrentlyConsumer(sender, currentState.providerState))) { + if (not(isRunningConsumer(sender, currentState.providerState))) { (Err("Sender is not currently a consumer - must have 'running' status!"), false) } else if (length(currentState.consumerStates.get(sender).outstandingPacketsToProvider) == 0) { (Err("No outstanding packets to deliver"), false) @@ -325,7 +325,7 @@ module CCV { // that indicates whether the consumer timed out or not. // If the result has an error, the second return should be ignored. pure def deliverPacketToConsumer(currentState: ProtocolState, receiver: Chain): (Result, bool) = { - if (not(isCurrentlyConsumer(receiver, currentState.providerState))) { + if (not(isRunningConsumer(receiver, currentState.providerState))) { (Err("Receiver is not currently a consumer - must have 'running' status!"), false) } else if (length(currentState.providerState.outstandingPacketsToConsumer.get(receiver)) == 0) { (Err("No outstanding packets to deliver"), false) @@ -613,7 +613,7 @@ module CCV { (consumer) => // if validator set changed and the consumer is running, send a packet if (providerState.providerValidatorSetChangedInThisBlock and - isCurrentlyConsumer(consumer, providerState)) { + isRunningConsumer(consumer, providerState)) { List({ id: providerState.runningVscId, validatorSet: providerState.chainState.currentValidatorSet, @@ -654,7 +654,7 @@ module CCV { // but the candidate that would be put into the block if it ended now) // and store the maturation time for the packet. pure def recvPacketOnConsumer(currentState: ProtocolState, receiver: Chain, packet: VscPacket): Result = { - if(not(isCurrentlyConsumer(receiver, currentState.providerState))) { + if(not(isRunningConsumer(receiver, currentState.providerState))) { Err("Receiver is not currently a consumer - must have 'running' status!") } else { // update the running validator set, but not the history yet, @@ -686,7 +686,7 @@ module CCV { // receives a given packet on the provider. The arguments are the consumer chain that sent the packet, and the packet itself. // To receive a packet, add it to the list of received maturations. pure def recvPacketOnProvider(currentState: ProtocolState, sender: Chain, packet: VscMaturedPacket): Result = { - if (not(isCurrentlyConsumer(sender, currentState.providerState))) { + if (not(isRunningConsumer(sender, currentState.providerState))) { Err("Sender is not currently a consumer - must have 'running' status!") } else if (currentState.providerState.sentVscPackets.get(sender).head().id != packet.id) { // the packet is not the oldest sentVscPacket, something went wrong @@ -760,7 +760,7 @@ module CCV { } // Returns true if the given chain is currently a running consumer, false otherwise. - pure def isCurrentlyConsumer(chain: Chain, providerState: ProviderState): bool = { + pure def isRunningConsumer(chain: Chain, providerState: ProviderState): bool = { val status = providerState.consumerStatus.get(chain) status == RUNNING } @@ -785,7 +785,7 @@ module CCV { // or false otherwise. pure def TimeoutDueToVscTimeout(currentState: ProtocolState, consumer: Chain): (bool, str) = // check for errors: the consumer is not running - if (not(isCurrentlyConsumer(consumer, currentState.providerState))) { + if (not(isRunningConsumer(consumer, currentState.providerState))) { (false, "Consumer is not currently a consumer - must have 'running' status!") } else { val providerState = currentState.providerState From f46554b1640db24625df4399d95c00921f5f50b3 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Tue, 10 Oct 2023 16:00:10 +0200 Subject: [PATCH 62/80] Unify naming for extraSpells --- tests/difference/core/quint_model/ccv.qnt | 2 +- .../core/quint_model/ccv_statemachine.qnt | 4 +- .../quint_model/libraries/extraSpells.qnt | 54 ++++++------------- 3 files changed, 19 insertions(+), 41 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index ea6c5058fa..dd9107695d 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -821,7 +821,7 @@ module CCV { CcvTimeout.keys().forall(chain => CcvTimeout.get(chain) > 0) run CcvTimeoutLargerThanUnbondingPeriodTest = - CcvTimeout.get(PROVIDER_CHAIN) > UnbondingPeriodPerChain.Values().Max() + CcvTimeout.get(PROVIDER_CHAIN) > UnbondingPeriodPerChain.values().max() run ProviderIsNotAConsumerTest = not(ConsumerChains.contains(PROVIDER_CHAIN)) diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 5b75716a5f..a15ed2c830 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -201,8 +201,8 @@ module CCVDefaultStateMachine { if (commonPackets.size() == 0) { true // they don't share any packets, so nothing to check } else { - val newestCommonPacket = commonPackets.MaxBy(packet => packet.sendingTime) - val oldestCommonPacket = commonPackets.MinBy(packet => packet.sendingTime) + val newestCommonPacket = commonPackets.maxBy(packet => packet.sendingTime) + val oldestCommonPacket = commonPackets.minBy(packet => packet.sendingTime) // get all packets sent between the oldest and newest common packet val packetsBetween1 = packets1.select( packet => packet.sendingTime >= oldestCommonPacket.sendingTime and packet.sendingTime <= newestCommonPacket.sendingTime diff --git a/tests/difference/core/quint_model/libraries/extraSpells.qnt b/tests/difference/core/quint_model/libraries/extraSpells.qnt index 24f37d919d..414ce8f949 100644 --- a/tests/difference/core/quint_model/libraries/extraSpells.qnt +++ b/tests/difference/core/quint_model/libraries/extraSpells.qnt @@ -37,24 +37,6 @@ module extraSpells { assert(requires(4 < 3, "false: 4 < 3") == "false: 4 < 3"), } - - /// Compute the maximum of two integers. - /// - /// - @param __i first integer - /// - @param __j second integer - /// - @returns the maximum of __i and __j - pure def max(__i: int, __j: int): int = { - if (__i > __j) __i else __j - } - - run maxTest = all { - assert(max(3, 4) == 4), - assert(max(6, 3) == 6), - assert(max(10, 10) == 10), - assert(max(-3, -5) == -3), - assert(max(-5, -3) == -3), - } - /// Compute the absolute value of an integer /// /// - @param __i : an integer whose absolute value we are interested in @@ -178,35 +160,31 @@ module extraSpells { __set.union(Set(elem)) } - pure def Values(__map: a -> b): Set[b] = { + pure def values(__map: a -> b): Set[b] = { __map.keys().fold(Set(), (__s, __k) => __s.add(__map.get(__k))) } - run ValuesTest = + run valuesTest = all { - assert(Values(Map(1 -> 2, 3 -> 4)) == Set(2, 4)), - assert(Values(Map()) == Set()) + assert(values(Map(1 -> 2, 3 -> 4)) == Set(2, 4)), + assert(values(Map()) == Set()) } // Returns the maximal element of the set. // If the set is empty, the function call will fail at runtime. - pure def Max(__set: Set[int]): int = { - __set.fold(oneOf(__set), (__m, __e) => max(__m, __e)) - } + pure def max(__set: Set[int]): int = maxBy(__set, __a => __a) - run MaxTest = + run maxTest = all { - assert(Max(Set(1, 2, 3)) == 3), + assert(max(Set(1, 2, 3)) == 3), } // Returns the minimal element of the set. // If the set is empty, the function call will fail at runtime. - pure def Min(__set: Set[int]): int = { - __set.fold(oneOf(__set), (__m, __e) => if(__m < __e) __m else __e) - } + pure def min(__set: Set[int]): int = minBy(__set, __a => __a) - run MinTest = + run minTest = all { - assert(Min(Set(1, 2, 3)) == 1), + assert(min(Set(1, 2, 3)) == 1), } pure def HasSubsequence(__this: List[a], __other: List[a]): bool = { @@ -236,21 +214,21 @@ module extraSpells { // Returns the maximum element of a set, according to a given function. // If two elements are equally large, an arbitrary one will be returned. // If the set is empty, the function call will fail at runtime. - pure def MaxBy(__set: Set[a], __f: a => int): a = { + pure def maxBy(__set: Set[a], __f: a => int): a = { __set.fold( oneOf(__set), (__m, __e) => if(__f(__m) > __f(__e)) {__m } else {__e} ) } - run MaxByTest = + run maxByTest = all { - assert(MaxBy(Set(1, 2, 3), __x => __x) == 3), - assert(MaxBy(Set(1, 2, 3), __x => -__x) == 1), + assert(maxBy(Set(1, 2, 3), __x => __x) == 3), + assert(maxBy(Set(1, 2, 3), __x => -__x) == 1), } - // Like MaxBy, but returns the minimum element. - pure def MinBy(__set: Set[a], __f: a => int): a = { + // Like maxBy, but returns the minimum element. + pure def minBy(__set: Set[a], __f: a => int): a = { __set.fold( oneOf(__set), (__m, __e) => if(__f(__m) < __f(__e)) {__m } else {__e} From 36308469de839dda0b808406385846eb630ff9ed Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Tue, 10 Oct 2023 16:28:09 +0200 Subject: [PATCH 63/80] Remove HasSubsequence --- .../quint_model/libraries/extraSpells.qnt | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/tests/difference/core/quint_model/libraries/extraSpells.qnt b/tests/difference/core/quint_model/libraries/extraSpells.qnt index 414ce8f949..cc20c17aef 100644 --- a/tests/difference/core/quint_model/libraries/extraSpells.qnt +++ b/tests/difference/core/quint_model/libraries/extraSpells.qnt @@ -187,30 +187,6 @@ module extraSpells { assert(min(Set(1, 2, 3)) == 1), } - pure def HasSubsequence(__this: List[a], __other: List[a]): bool = { - if(__other.length() > __this.length()) { - false - } else { - 0.to(__this.length() - __other.length()) // go through all possible starting points of __other in __this - .exists( - __start => __this.slice(__start, __start + __other.length()) == __other - ) - } - } - - run HasSubsequenceTest = - all { - assert(List(1, 2, 3, 4).HasSubsequence(List(1, 2))), - assert(List(1, 2, 3, 4).HasSubsequence(List(2, 3))), - assert(List(1, 2, 3, 4).HasSubsequence(List(3, 4))), - assert(List(1, 2, 3, 4).HasSubsequence(List(1, 2, 3))), - assert(not(List(1, 2, 3, 4).HasSubsequence(List(1, 3)))), - assert(not(List().HasSubsequence(List(1)))), - assert(List().HasSubsequence(List())), - assert(List(1).HasSubsequence(List())), - assert(List(1).HasSubsequence(List(1))), - } - // Returns the maximum element of a set, according to a given function. // If two elements are equally large, an arbitrary one will be returned. // If the set is empty, the function call will fail at runtime. From 90f6652ce1584fa4f02dd6c6bc53597b3b86c178 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Tue, 10 Oct 2023 16:47:39 +0200 Subject: [PATCH 64/80] Run tests before running invariants --- tests/difference/core/quint_model/run_invariants.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/run_invariants.sh b/tests/difference/core/quint_model/run_invariants.sh index 142095682f..5acd79e49c 100755 --- a/tests/difference/core/quint_model/run_invariants.sh +++ b/tests/difference/core/quint_model/run_invariants.sh @@ -1 +1,4 @@ -quint run --invariant "all{ValidatorUpdatesArePropagatedInv,ValidatorSetHasExistedInv,SameVSCPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv}" ccv_statemachine.qnt --main CCVDefaultStateMachine --max-steps 500 --max-samples 200 --out out.log \ No newline at end of file +#! /bin/sh + +quint test ccv_statemachine.qnt --main CCVDefaultStateMachine +quint run --invariant "all{ValidatorUpdatesArePropagatedInv,ValidatorSetHasExistedInv,SameVscPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv}" ccv_statemachine.qnt --main CCVDefaultStateMachine --max-steps 500 --max-samples 200 \ No newline at end of file From 13a32fcb5898d361105cd055600674b629b64000 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Wed, 11 Oct 2023 11:39:06 +0200 Subject: [PATCH 65/80] Rename modules to have same name as files --- tests/difference/core/quint_model/ccv.qnt | 6 +- .../core/quint_model/ccv_statemachine.qnt | 181 +++++++++++------- .../difference/core/quint_model/ccv_test.qnt | 6 +- 3 files changed, 114 insertions(+), 79 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index dd9107695d..2b975d6c53 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -1,5 +1,5 @@ // -*- mode: Bluespec; -*- -module CCVTypes { +module ccv_types { import Time.* from "./libraries/Time" type Node = str @@ -204,7 +204,7 @@ module CCVTypes { pure val PROVIDER_CHAIN = "provider" } -module CCV { +module ccv { // Implements the core logic of the cross-chain validation protocol. // Things that are not modelled: @@ -222,7 +222,7 @@ module CCV { import Time.* from "./libraries/Time" import extraSpells.* from "./libraries/extraSpells" - import CCVTypes.* + import ccv_types.* // =================== diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index a15ed2c830..26e365a398 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -1,7 +1,7 @@ // -*- mode: Bluespec; -*- -module CCVDefaultStateMachine { +module ccv_statemachine { // A basic state machine that utilizes the CCV protocol. - import CCVTypes.* from "./ccv" + import ccv_types.* from "./ccv" import Time.* from "./libraries/Time" import extraSpells.* from "./libraries/extraSpells" @@ -13,13 +13,98 @@ module CCVDefaultStateMachine { pure val nodes = Set("node1", "node2", "node3", "node4", "node5", "node6", "node7", "node8", "node9", "node10") pure val InitialValidatorSet = nodes.mapBy(node => 100) - import CCV(VscTimeout = 5 * Week, CcvTimeout = ccvTimeouts, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = consumerChains).* from "./ccv" + import ccv(VscTimeout = 5 * Week, CcvTimeout = ccvTimeouts, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = consumerChains).* from "./ccv" var currentState: ProtocolState + + + pure def ACTIONS = Set( + "VotingPowerChange", + "DeliverVscPacket", + "DeliverVscMaturedPacket", + "EndAndBeginBlockForProvider", + "EndAndBeginBlockForConsumer" + ) + + // a type storing the parameters used in actions. + // this is used in the trace to store + // the name of the last action, plus the parameters we passed to it. + // Note: This type holds ALL parameters that are used in ANY action, + // so not all of these fields are relevant to each action. + type Action = + { + kind: str, + consumerChain: Chain, + timeAdvancement: Time, + consumersToStart: Set[Chain], + consumersToStop: Set[Chain], + validator: Node, + newVotingPower: int, + } - // bookkeeping - var trace: List[str] + + var trace: List[Action] + + // a few different values for time advancements. + // to keep the number of possible steps small, we only have a few different values. + // Roughly, 1s for very small advances (like between blocks), + // and then longer values for increasingly severe downtime scenarios. + // Note that these can still be combined, so in effect we can get all time advancements by any amount of seconds. + pure val timeAdvancements = Set(1 * Second, 1 * Day, 1 * Week, 4 * Week) + + pure def emptyAction = + { + kind: "", + consumerChain: "", + timeAdvancement: 0 * Second, + consumersToStart: Set(), + consumersToStop: Set(), + validator: "", + newVotingPower: 0, + } + + // step allows the most generic nondeterminism, in particular it becomes relatively likely + // that over a long enough runtime, all consumers would time out by mismatching their time advancements, + // and each endblock has a good chance to stop consumers, ... + // step is thus suited to test also unhappy paths. + action step = any { + all { + runningConsumers.size() > 0, // ensure there is a running consumer, otherwise this action does not make sense + nondet chain = oneOf(runningConsumers) + nondet timeAdvancement = oneOf(timeAdvancements) + EndAndBeginBlockForConsumer(chain, timeAdvancement), + }, + + val consumerStatus = currentState.providerState.consumerStatus + nondet consumersToStart = oneOf(nonConsumers.powerset()) + nondet consumersToStop = oneOf(runningConsumers.powerset()) + nondet timeAdvancement = oneOf(timeAdvancements) + EndAndBeginBlockForProvider(timeAdvancement, consumersToStart, consumersToStop), + + nondet node = oneOf(nodes) + // very restricted set of voting powers. exact values are not important, + // and this keeps the state space smaller. + // 0 for getting a validator out of the validator set, and two non-zero values + nondet newVotingPower = oneOf(Set(0, 50, 100)) + VotingPowerChange(node, newVotingPower), + + // try to send a packet. we could filter by chains that can actually send, + // but it's probably not much faster than just trying and failing. + all { + runningConsumers.size() > 0, // ensure there is a running consumer, otherwise this action does not make sense + nondet sender = oneOf(runningConsumers) + DeliverVscMaturedPacket(sender), + }, + + // again, we could filter by chains that can actually receive, + // but it's probably not much faster than just trying and failing. + all { + runningConsumers.size() > 0, // ensure there is a running consumer, otherwise this action does not make sense + nondet recciver = oneOf(runningConsumers) + DeliverVscPacket(recciver), + }, + } // some utility stateful vals to make invariants easier to define val providerValidatorHistory = currentState.providerState.chainState.votingPowerHistory @@ -50,7 +135,7 @@ module CCVDefaultStateMachine { providerState: providerStateWithConsumers, consumerStates: consumerStates }, - trace' = List("init") + trace' = List(emptyAction.with("kind", "init")), } action VotingPowerChange(validator: Node, newVotingPower: int): bool = @@ -58,7 +143,7 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, - trace' = trace.append("VotingPowerChange") + trace' = trace.append(emptyAction.with("kind", "VotingPowerChange").with("validator", validator).with("newVotingPower", newVotingPower)) } // The receiver receives the next outstanding VscPacket from the provider. @@ -69,7 +154,7 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, - trace' = trace.append("DeliverVscPacket") + trace' = trace.append(emptyAction.with("kind", "DeliverVscPacket").with("consumerChain", receiver)) } // The provider receives the next outstanding VscMaturedPacket from the sender. @@ -80,7 +165,7 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, - trace' = trace.append("DeliverVscMaturedPacket") + trace' = trace.append(emptyAction.with("kind", "DeliverVscMaturedPacket").with("consumerChain", sender)) } action EndAndBeginBlockForProvider( @@ -91,7 +176,7 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, - trace' = trace.append("EndAndBeginBlockForProvider") + trace' = trace.append(emptyAction.with("kind", "EndAndBeginBlockForProvider").with("timeAdvancement", timeAdvancement).with("consumersToStart", consumersToStart).with("consumersToStop", consumersToStop)) } action EndAndBeginBlockForConsumer( @@ -101,58 +186,9 @@ module CCVDefaultStateMachine { all { result.hasError == false, currentState' = result.newState, - trace' = trace.append("EndAndBeginBlockForConsumer") + trace' = trace.append(emptyAction.with("kind", "EndAndBeginBlockForConsumer").with("consumerChain", chain).with("timeAdvancement", timeAdvancement)) } - // a few different values for time advancements. - // to keep the number of possible steps small, we only have a few different values. - // Roughly, 1s for very small advances (like between blocks), - // and then longer values for increasingly severe downtime scenarios. - // Note that these can still be combined, so in effect we can get all time advancements by any amount of seconds. - pure val timeAdvancements = Set(1 * Second, 1 * Day, 1 * Week, 4 * Week) - - // step allows the most generic nondeterminism, in particular it becomes relatively likely - // that over a long enough runtime, all consumers would time out by mismatching their time advancements, - // and each endblock has a good chance to stop consumers, ... - // step is thus suited to test also unhappy paths. - action step = any { - all { - runningConsumers.size() > 0, // ensure there is a running consumer, otherwise this action does not make sense - nondet chain = oneOf(runningConsumers) - nondet timeAdvancement = oneOf(timeAdvancements) - EndAndBeginBlockForConsumer(chain, timeAdvancement), - }, - - val consumerStatus = currentState.providerState.consumerStatus - nondet consumersToStart = oneOf(nonConsumers.powerset()) - nondet consumersToStop = oneOf(runningConsumers.powerset()) - nondet timeAdvancement = oneOf(timeAdvancements) - EndAndBeginBlockForProvider(timeAdvancement, consumersToStart, consumersToStop), - - nondet node = oneOf(nodes) - // very restricted set of voting powers. exact values are not important, - // and this keeps the state space smaller. - // 0 for getting a validator out of the validator set, and two non-zero values - nondet newVotingPower = oneOf(Set(0, 50, 100)) - VotingPowerChange(node, newVotingPower), - - // try to send a packet. we could filter by chains that can actually send, - // but it's probably not much faster than just trying and failing. - all { - runningConsumers.size() > 0, // ensure there is a running consumer, otherwise this action does not make sense - nondet sender = oneOf(runningConsumers) - DeliverVscMaturedPacket(sender), - }, - - // again, we could filter by chains that can actually receive, - // but it's probably not much faster than just trying and failing. - all { - runningConsumers.size() > 0, // ensure there is a running consumer, otherwise this action does not make sense - nondet recciver = oneOf(runningConsumers) - DeliverVscPacket(recciver), - }, - } - // ================== // INVARIANT CHECKS // ================== @@ -169,7 +205,7 @@ module CCVDefaultStateMachine { // Any update in the power of a validator on the provider // MUST be present in a ValidatorSetChangePacket that is sent to all registered consumer chains - val ValUpdatePrecondition = trace[trace.length()-1] == "EndAndBeginBlockForProvider" + val ValUpdatePrecondition = trace[trace.length()-1].kind == "EndAndBeginBlockForProvider" val ValidatorUpdatesArePropagatedInv = // when the provider has just entered a validator set into a block... if (ValUpdatePrecondition and currentState.providerState.providerValidatorSetChangedInThisBlock) { @@ -389,8 +425,7 @@ module CCVDefaultStateMachine { assert(currentState.providerState.receivedMaturations.size() == 1), // the packet was removed from the consumer assert(currentState.consumerStates.get("consumer1").outstandingPacketsToProvider.length() == 0), - currentState' = currentState, // just so this still has an effect - trace' = trace.append("HappyPathTest") + VotingPowerChange("node1", 50) // just so this still has an effect } ) } @@ -436,7 +471,7 @@ module CCVDefaultStateMachine { all { assert(SameVscPacketsInv), // action does not matter, but needed to have uniform effect - step + VotingPowerChange("node1", 50) } ) @@ -459,13 +494,13 @@ module CCVDefaultStateMachine { // advance time on provider by VscTimeout + 1 Second EndAndBeginBlockForProvider(VscTimeout + 5 * Second, Set(), Set()) ) - // .then( - // all { - // // the consumer chains should have timed out - // assert(ConsumerChains.forall( - // chain => currentState.providerState.consumerStatus.get(chain) == TIMEDOUT - // )), - // VotingPowerChange("node2", 50)// action needs to be there but does not matter - // } - // ) + .then( + all { + // the consumer chains should have timed out + assert(ConsumerChains.forall( + chain => currentState.providerState.consumerStatus.get(chain) == TIMEDOUT + )), + VotingPowerChange("node1", 50) // action needs to be there but does not matter what it is + } + ) } \ No newline at end of file diff --git a/tests/difference/core/quint_model/ccv_test.qnt b/tests/difference/core/quint_model/ccv_test.qnt index 9493e69d6a..b21653ae6f 100644 --- a/tests/difference/core/quint_model/ccv_test.qnt +++ b/tests/difference/core/quint_model/ccv_test.qnt @@ -1,8 +1,8 @@ // -*- mode: Bluespec; -*- // contains test logic for the stateless functions in the CCV module -module CCVTest { - import CCVTypes.* from "./ccv" +module ccv_test { + import ccv_types.* from "./ccv" import Time.* from "./libraries/Time" import extraSpells.* from "./libraries/extraSpells" @@ -11,7 +11,7 @@ module CCVTest { pure val unbondingPeriods = chains.mapBy(chain => 2 * Week) pure val ccvTimeouts = chains.mapBy(chain => 3 * Week) - import CCV(VscTimeout = 5 * Week, CcvTimeout = ccvTimeouts, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = consumerChains).* from "./ccv" + import ccv(VscTimeout = 5 * Week, CcvTimeout = ccvTimeouts, UnbondingPeriodPerChain = unbondingPeriods, ConsumerChains = consumerChains).* from "./ccv" // negative voting powers give an error run VotingPowerNegativeTest = From 852dac496aa747800f9af4d3761fd88bdcac4205 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Wed, 11 Oct 2023 11:40:18 +0200 Subject: [PATCH 66/80] Adjust module name in README and invariant script --- tests/difference/core/quint_model/README.md | 10 +++++----- tests/difference/core/quint_model/run_invariants.sh | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 9213b091c3..235372cc1c 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -22,18 +22,18 @@ The parameters of the protocol are defined as consts in [ccv.qnt](ccv.qnt). To run unit tests, run ``` -quint test ccv_test.qnt --main CCVTest +quint test ccv_test. ``` and ``` -quint test ccv_statemachine.qnt --main CCVDefaultStateMachine +quint test ccv_statemachine.qnt ``` ### Invariants The invariants to check are in [ccv_statemachine.qnt](ccv_statemachine.qnt). Check a single invariant by running -`quint run --invariant INVARIANT_NAME ccv_statemachine.qnt --main CCVDefaultStateMachine`, +`quint run --invariant INVARIANT_NAME ccv_statemachine.qnt`, or all invariants one after another with the help of the script `run_invariants.sh`. Each invariant takes about a minute to run. @@ -53,7 +53,7 @@ that were running at the time the packet was sent (and are still running). Invariants can also be model-checked by Apalache, using this command: ``` quint verify --invariant ValidatorUpdatesArePropagatedInv,ValidatorSetHasExistedInv,SameVscPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv \ ---main CCVDefaultStateMachine ccv_statemachine.qnt + ccv_statemachine.qnt ``` ### Sanity Checks @@ -63,7 +63,7 @@ In detail, they are invariant checks that we expect to fail. They usually negate the appearance of some behaviour, i.e. `not(DesirableBehaviour)`. Then, a counterexample for this is an example trace exhibiting the behaviour. -They are run like invariant checks, i.e. `quint run --invariant SANITY_CHECK_NAME ccv_statemachine.qnt --main CCVDefaultStateMachine`. +They are run like invariant checks, i.e. `quint run --invariant SANITY_CHECK_NAME ccv_statemachine.qnt`. The available sanity checks are: - CanRunConsumer - CanStopConsumer diff --git a/tests/difference/core/quint_model/run_invariants.sh b/tests/difference/core/quint_model/run_invariants.sh index 5acd79e49c..ae94dcbd2d 100755 --- a/tests/difference/core/quint_model/run_invariants.sh +++ b/tests/difference/core/quint_model/run_invariants.sh @@ -1,4 +1,4 @@ #! /bin/sh -quint test ccv_statemachine.qnt --main CCVDefaultStateMachine -quint run --invariant "all{ValidatorUpdatesArePropagatedInv,ValidatorSetHasExistedInv,SameVscPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv}" ccv_statemachine.qnt --main CCVDefaultStateMachine --max-steps 500 --max-samples 200 \ No newline at end of file +quint test ccv_statemachine.qnt +quint run --invariant "all{ValidatorUpdatesArePropagatedInv,ValidatorSetHasExistedInv,SameVscPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv}" ccv_statemachine.qnt --max-steps 500 --max-samples 200 \ No newline at end of file From 8aee401634dfafc918044a8ce459898f02b562a9 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Wed, 11 Oct 2023 11:48:46 +0200 Subject: [PATCH 67/80] Fix voting power change behaviour around 0 --- tests/difference/core/quint_model/ccv.qnt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 2b975d6c53..606574c42b 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -250,8 +250,8 @@ module ccv { // the power of a validator on the provider chain is changed to the given amount. We do not care how this happens, // e.g. via undelegations, or delegations, ... pure def votingPowerChange(currentState: ProtocolState, validator: Node, amount: int): Result = { - if (amount <= 0) { - Err("Voting power changes must be positive") + if (amount < 0) { + Err("Voting power changes must be nonnegative") } else { pure val currentValidatorSet = currentState.providerState.chainState.currentValidatorSet pure val newValidatorSet = getUpdatedValidatorSet(currentValidatorSet, validator, amount) From d75d5c51ad57c62e085d942580996bf78997863a Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Wed, 11 Oct 2023 11:50:34 +0200 Subject: [PATCH 68/80] Adjust error message in test --- tests/difference/core/quint_model/ccv_test.qnt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/ccv_test.qnt b/tests/difference/core/quint_model/ccv_test.qnt index b21653ae6f..4262c4c386 100644 --- a/tests/difference/core/quint_model/ccv_test.qnt +++ b/tests/difference/core/quint_model/ccv_test.qnt @@ -218,7 +218,7 @@ module ccv_test { Set("chain3"), Set() ) - res._2 == "cannot start a consumer that is stopped or running" + res._2 == "cannot start a consumer that is stopped or already a consumer" } run ConsumerStatusMapAlreadyStoppedTest = From f294eecabb5a3aee2b592316d4df353645311a9d Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Wed, 11 Oct 2023 14:45:32 +0200 Subject: [PATCH 69/80] Remove special treatment of 0 voting power --- tests/difference/core/quint_model/ccv.qnt | 10 +--------- tests/difference/core/quint_model/ccv_test.qnt | 4 ++-- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 606574c42b..ac1f1f4959 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -254,7 +254,7 @@ module ccv { Err("Voting power changes must be nonnegative") } else { pure val currentValidatorSet = currentState.providerState.chainState.currentValidatorSet - pure val newValidatorSet = getUpdatedValidatorSet(currentValidatorSet, validator, amount) + pure val newValidatorSet = currentValidatorSet.put(validator, amount) // set the validator set changed flag val newProviderState = currentState.providerState.with( "providerValidatorSetChangedInThisBlock", true @@ -737,14 +737,6 @@ module ccv { newState } - // Updates the given oldValidatorSet by setting the validator to newVotingPower. - // If newVotingPower is zero, the validator is removed. - pure def getUpdatedValidatorSet(oldValidatorSet: ValidatorSet, validator: Node, newVotingPower: int): ValidatorSet = - if (newVotingPower > 0) - oldValidatorSet.put(validator, newVotingPower) - else - oldValidatorSet.mapRemove(validator) - // Returns a ProtocolState where the current validator set on the provider is set to // newValidatorSet. pure def setProviderValidatorSet(currentState: ProtocolState, newValidatorSet: ValidatorSet): ProtocolState = { diff --git a/tests/difference/core/quint_model/ccv_test.qnt b/tests/difference/core/quint_model/ccv_test.qnt index 4262c4c386..eb832603e6 100644 --- a/tests/difference/core/quint_model/ccv_test.qnt +++ b/tests/difference/core/quint_model/ccv_test.qnt @@ -35,7 +35,7 @@ module ccv_test { result.newState.providerState.chainState.currentValidatorSet.get("validator") == 5 } - // validators that get zero voting power are removed + // voting power of 0 is allowed and applied as usual run VotingPowerZeroTest = { val tmpResult = votingPowerChange( @@ -49,7 +49,7 @@ module ccv_test { 0 ) not(finalResult.hasError) and - not(finalResult.newState.providerState.chainState.currentValidatorSet.keys().contains("validator")) + finalResult.newState.providerState.chainState.currentValidatorSet.get("validator") == 0 } run VotingPowerSetsFlagTest = From 4d873721481f47eb1873b8e3dd0e2200b19f6162 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 12 Oct 2023 14:17:05 +0200 Subject: [PATCH 70/80] Rename sentVscPackets to sentVscPacketsToConsumer --- tests/difference/core/quint_model/ccv.qnt | 20 +++++++++---------- .../core/quint_model/ccv_statemachine.qnt | 10 +++++----- .../difference/core/quint_model/ccv_test.qnt | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index ac1f1f4959..e23bbb8532 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -69,7 +69,7 @@ module ccv_types { receivedMaturations: Set[VscMaturedPacket], // Stores VscPackets which have been sent but where the provider has *not received a response yet*. - sentVscPackets: Chain -> List[VscPacket], + sentVscPacketsToConsumer: Chain -> List[VscPacket], // stores whether, in this block, the validator set has changed. // this is needed because the validator set might be considered to have changed, even though @@ -92,7 +92,7 @@ module ccv_types { chainState: GetEmptyChainState, outstandingPacketsToConsumer: Map(), receivedMaturations: Set(), - sentVscPackets: Map(), + sentVscPacketsToConsumer: Map(), providerValidatorSetChangedInThisBlock: false, consumerStatus: Map(), runningVscId: 0, @@ -178,7 +178,7 @@ module ccv_types { }, outstandingPacketsToConsumer: Map(), receivedMaturations: Set(), - sentVscPackets: Map(), + sentVscPacketsToConsumer: Map(), providerValidatorSetChangedInThisBlock: false, consumerStatus: Map(), runningVscId: 0, @@ -634,10 +634,10 @@ module ccv { ) ).with( // update the sent VscPackets - "sentVscPackets", + "sentVscPacketsToConsumer", ConsumerChains.mapBy( (consumer) => - providerState.sentVscPackets.get(consumer).concat( + providerState.sentVscPacketsToConsumer.get(consumer).concat( newSentPacketsPerConsumer.get(consumer) ) ) @@ -688,7 +688,7 @@ module ccv { pure def recvPacketOnProvider(currentState: ProtocolState, sender: Chain, packet: VscMaturedPacket): Result = { if (not(isRunningConsumer(sender, currentState.providerState))) { Err("Sender is not currently a consumer - must have 'running' status!") - } else if (currentState.providerState.sentVscPackets.get(sender).head().id != packet.id) { + } else if (currentState.providerState.sentVscPacketsToConsumer.get(sender).head().id != packet.id) { // the packet is not the oldest sentVscPacket, something went wrong Err("Received maturation is not for the oldest sentVscPacket") } else { @@ -698,7 +698,7 @@ module ccv { "receivedMaturations", newReceivedMaturations ) // prune the sentVscPacket - val newSentVscPacket = currentState.providerState.sentVscPackets.get(sender).tail() + val newSentVscPacket = currentState.providerState.sentVscPacketsToConsumer.get(sender).tail() val newState = currentState.with( "providerState", newProviderState ) @@ -784,9 +784,9 @@ module ccv { val consumerState = currentState.consumerStates.get(consumer) // has a packet been sent on the provider more than VscTimeout ago, but we have not received an answer since then? - val sentVscPackets = providerState.sentVscPackets.get(consumer) - if(sentVscPackets.length() > 0) { - val oldestSentVscPacket = sentVscPackets.head() // if length is 0, this is undefined, but we check for this before we use it + val sentVscPacketsToConsumer = providerState.sentVscPacketsToConsumer.get(consumer) + if(sentVscPacketsToConsumer.length() > 0) { + val oldestSentVscPacket = sentVscPacketsToConsumer.head() // if length is 0, this is undefined, but we check for this before we use it if(oldestSentVscPacket.sendingTime + VscTimeout < providerState.chainState.lastTimestamp) { (true, "") } else { diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 26e365a398..52c4bc83c9 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -121,7 +121,7 @@ module ccv_statemachine { "outstandingPacketsToConsumer", ConsumerChains.mapBy(chain => List()) ).with( - "sentVscPackets", + "sentVscPacketsToConsumer", ConsumerChains.mapBy(chain => List()) ).with( // set the validator set to be the initial validator set in the history @@ -213,7 +213,7 @@ module ccv_statemachine { // ... for each consumer that is running then ... runningConsumers.forall( // ...the validator set is in a sent packet - consumer => currentState.providerState.sentVscPackets.get(consumer).toSet().exists( + consumer => currentState.providerState.sentVscPacketsToConsumer.get(consumer).toSet().exists( packet => packet.validatorSet == providerValSetInCurBlock ) ) @@ -272,14 +272,14 @@ module ccv_statemachine { // If we send a VscPacket, this is eventually responded to by all consumers // that were running at the time the packet was sent (and are still running). - // Since we remove sentVscPackets when we receive responses for them, + // Since we remove sentVscPacketsToConsumer when we receive responses for them, // we just check that if a sentVscPacket has been sent more than // VscTimeout ago, the consumer must have been dropped. // In practice, when this is true, a pending unbonding can mature. val EventuallyMatureOnProviderInv = runningConsumers.forall( consumer => { - val sentPackets = currentState.providerState.sentVscPackets.get(consumer).toSet() + val sentPackets = currentState.providerState.sentVscPacketsToConsumer.get(consumer).toSet() sentPackets.forall( packet => // consumer still has time to respond @@ -363,7 +363,7 @@ module ccv_statemachine { "consumer2" -> List(), "consumer3" -> List() )), - assert(currentState.providerState.sentVscPackets == Map( + assert(currentState.providerState.sentVscPacketsToConsumer == Map( "consumer1" -> List(), "consumer2" -> List(), "consumer3" -> List() diff --git a/tests/difference/core/quint_model/ccv_test.qnt b/tests/difference/core/quint_model/ccv_test.qnt index eb832603e6..4f49f5ff4d 100644 --- a/tests/difference/core/quint_model/ccv_test.qnt +++ b/tests/difference/core/quint_model/ccv_test.qnt @@ -121,7 +121,7 @@ module ccv_test { ).with( // put an entry into sentVscPacket on the provider that corresponds to the packet we put on the consumer "providerState", _DeliverPacketToProvider_TestState.providerState.with( - "sentVscPackets", _DeliverPacketToProvider_TestState.providerState.sentVscPackets.put( + "sentVscPacketsToConsumer", _DeliverPacketToProvider_TestState.providerState.sentVscPacketsToConsumer.put( "sender", List({ id: 0, validatorSet: _DeliverPacketToProvider_TestState.providerState.chainState.currentValidatorSet, From 53d5bff2b89008e6bb53bd7057809a4c87a7cdd0 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com> Date: Thu, 12 Oct 2023 17:03:41 +0200 Subject: [PATCH 71/80] Update tests/difference/core/quint_model/README.md Co-authored-by: insumity --- tests/difference/core/quint_model/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 235372cc1c..54251a7544 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -22,7 +22,7 @@ The parameters of the protocol are defined as consts in [ccv.qnt](ccv.qnt). To run unit tests, run ``` -quint test ccv_test. +quint test ccv_test.qnt ``` and ``` From 738a3479b9ef088e39e3aed61ec002782b25599b Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 12 Oct 2023 18:21:38 +0200 Subject: [PATCH 72/80] Resolve comments --- tests/difference/core/quint_model/ccv_statemachine.qnt | 10 ---------- tests/difference/core/quint_model/ccv_test.qnt | 6 ++---- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 52c4bc83c9..93ee8f6fe3 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -18,15 +18,6 @@ module ccv_statemachine { var currentState: ProtocolState - - pure def ACTIONS = Set( - "VotingPowerChange", - "DeliverVscPacket", - "DeliverVscMaturedPacket", - "EndAndBeginBlockForProvider", - "EndAndBeginBlockForConsumer" - ) - // a type storing the parameters used in actions. // this is used in the trace to store // the name of the last action, plus the parameters we passed to it. @@ -85,7 +76,6 @@ module ccv_statemachine { nondet node = oneOf(nodes) // very restricted set of voting powers. exact values are not important, // and this keeps the state space smaller. - // 0 for getting a validator out of the validator set, and two non-zero values nondet newVotingPower = oneOf(Set(0, 50, 100)) VotingPowerChange(node, newVotingPower), diff --git a/tests/difference/core/quint_model/ccv_test.qnt b/tests/difference/core/quint_model/ccv_test.qnt index 4f49f5ff4d..621df175c2 100644 --- a/tests/difference/core/quint_model/ccv_test.qnt +++ b/tests/difference/core/quint_model/ccv_test.qnt @@ -145,7 +145,6 @@ module ccv_test { run StateModificationOK_DeliverPacketToProviderHappyPathTest = { val result = DeliverPacketToProviderHappyPathTest_resultAndTimeout._1 - val timedOut = DeliverPacketToProviderHappyPathTest_resultAndTimeout._2 val newProviderState = result.newState.providerState val newConsumerState = result.newState.consumerStates.get("sender") not(result.hasError) and @@ -168,17 +167,16 @@ module ccv_test { run DidTimeOut_DeliverPacketToProviderTimeoutTest = { val result = DeliverPacketToProviderTimeoutTest_resultAndTimeout._1 - val timedOut = DeliverPacketToProviderTimeoutTest_resultAndTimeout._2 + val timeout = DeliverPacketToProviderTimeoutTest_resultAndTimeout._2 val newProviderState = result.newState.providerState val newConsumerState = result.newState.consumerStates.get("sender") not(result.hasError) and - timedOut + timeout } run StateModificationOK_DeliverPacketToProviderTimeoutTest = { val result = DeliverPacketToProviderTimeoutTest_resultAndTimeout._1 - val timedOut = DeliverPacketToProviderTimeoutTest_resultAndTimeout._2 val newProviderState = result.newState.providerState val newConsumerState = result.newState.consumerStates.get("sender") not(result.hasError) and From 3a03fcdccdd5dfc2f7118723a19be4f631d67628 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 12 Oct 2023 18:34:15 +0200 Subject: [PATCH 73/80] Adjust comment to fit actual time advancement --- tests/difference/core/quint_model/ccv_statemachine.qnt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 93ee8f6fe3..9585073224 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -482,7 +482,7 @@ module ccv_statemachine { ) .then( // advance time on provider by VscTimeout + 1 Second - EndAndBeginBlockForProvider(VscTimeout + 5 * Second, Set(), Set()) + EndAndBeginBlockForProvider(VscTimeout + 1 * Second, Set(), Set()) ) .then( all { From d71dad347a3a9d39b135e6d2e9479fffb0eba64d Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 13 Oct 2023 10:18:49 +0200 Subject: [PATCH 74/80] Remove hasError field and make it a function --- tests/difference/core/quint_model/ccv.qnt | 13 ++++++------- .../core/quint_model/ccv_statemachine.qnt | 10 +++++----- tests/difference/core/quint_model/ccv_test.qnt | 18 +++++++++--------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index e23bbb8532..e1d78c273b 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -148,17 +148,15 @@ module ccv_types { } // we return either a result or an error. - // if hasError is true, newState may be arbitrary, but the error will be meaningful. - // if hasError is false, error may be arbitrary, but newState will be meaningful. + // if hasError() is true, newState may be arbitrary, but the error will be meaningful. + // if hasError() is false, error may be arbitrary, but newState will be meaningful. type Result = { - hasError: bool, newState: ProtocolState, error: Error } pure def Ok(newState: ProtocolState): Result = { { - hasError: false, newState: newState, error: { message: "" @@ -168,7 +166,6 @@ module ccv_types { pure def Err(msg: str): Result = { { - hasError: true, newState: { providerState: { chainState: { @@ -191,6 +188,8 @@ module ccv_types { } } + pure def hasError(result: Result): bool = result.error.message != "" + // possible consumer statuses pure val STOPPED = "stopped" // the chain was once a consumer chain, but has been voluntarily dropped by the provider. pure val TIMEDOUT = "timedout" // the chain has timed out and was dropped by the provider. This is only used for involuntary drops. @@ -308,7 +307,7 @@ module ccv { // the packet has not timed out, so receive it on the provider val result = recvPacketOnProvider(currentState, sender, packet) val tmpState = result.newState - if (result.hasError) { + if (result.hasError()) { (Err(result.error.message), false) } else { (Ok(removeOutstandingPacketFromConsumer(tmpState, sender)), false) // false because the packet did not time out @@ -357,7 +356,7 @@ module ccv { // the packet has not timed out, so receive it on the consumer val result = recvPacketOnConsumer(currentState, receiver, packet) val tmpState = result.newState - if (result.hasError) { + if (result.hasError()) { (Err(result.error.message), false) } else { (Ok(removeOutstandingPacketFromProvider(tmpState, receiver)), false) // false because the packet did not time out diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_statemachine.qnt index 9585073224..cb62f560ee 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_statemachine.qnt @@ -131,7 +131,7 @@ module ccv_statemachine { action VotingPowerChange(validator: Node, newVotingPower: int): bool = val result = votingPowerChange(currentState, validator, newVotingPower) all { - result.hasError == false, + result.hasError() == false, currentState' = result.newState, trace' = trace.append(emptyAction.with("kind", "VotingPowerChange").with("validator", validator).with("newVotingPower", newVotingPower)) } @@ -142,7 +142,7 @@ module ccv_statemachine { val resultAndTimeout = deliverPacketToConsumer(currentState, receiver) val result = resultAndTimeout._1 all { - result.hasError == false, + result.hasError() == false, currentState' = result.newState, trace' = trace.append(emptyAction.with("kind", "DeliverVscPacket").with("consumerChain", receiver)) } @@ -153,7 +153,7 @@ module ccv_statemachine { val resultAndTimeout = deliverPacketToProvider(currentState, sender) val result = resultAndTimeout._1 all { - result.hasError == false, + result.hasError() == false, currentState' = result.newState, trace' = trace.append(emptyAction.with("kind", "DeliverVscMaturedPacket").with("consumerChain", sender)) } @@ -164,7 +164,7 @@ module ccv_statemachine { consumersToStop: Set[Chain]): bool = val result = endAndBeginBlockForProvider(currentState, timeAdvancement, consumersToStart, consumersToStop) all { - result.hasError == false, + result.hasError() == false, currentState' = result.newState, trace' = trace.append(emptyAction.with("kind", "EndAndBeginBlockForProvider").with("timeAdvancement", timeAdvancement).with("consumersToStart", consumersToStart).with("consumersToStop", consumersToStop)) } @@ -174,7 +174,7 @@ module ccv_statemachine { timeAdvancement: Time): bool = val result = endAndBeginBlockForConsumer(currentState, chain, timeAdvancement) all { - result.hasError == false, + result.hasError() == false, currentState' = result.newState, trace' = trace.append(emptyAction.with("kind", "EndAndBeginBlockForConsumer").with("consumerChain", chain).with("timeAdvancement", timeAdvancement)) } diff --git a/tests/difference/core/quint_model/ccv_test.qnt b/tests/difference/core/quint_model/ccv_test.qnt index 621df175c2..6bbe884d52 100644 --- a/tests/difference/core/quint_model/ccv_test.qnt +++ b/tests/difference/core/quint_model/ccv_test.qnt @@ -20,7 +20,7 @@ module ccv_test { GetEmptyProtocolState, "validator", -1 - ).hasError + ).hasError() } run VotingPowerOkTest = @@ -30,7 +30,7 @@ module ccv_test { "validator", 5 ) - not(result.hasError) and + not(result.hasError()) and result.newState.providerState.chainState.currentValidatorSet.keys().contains("validator") and result.newState.providerState.chainState.currentValidatorSet.get("validator") == 5 } @@ -48,7 +48,7 @@ module ccv_test { "validator", 0 ) - not(finalResult.hasError) and + not(finalResult.hasError()) and finalResult.newState.providerState.chainState.currentValidatorSet.get("validator") == 0 } @@ -67,7 +67,7 @@ module ccv_test { 0 ) // still should set the flag - not(finalResult.hasError) and + not(finalResult.hasError()) and finalResult.newState.providerState.providerValidatorSetChangedInThisBlock } @@ -80,7 +80,7 @@ module ccv_test { "validator", 0 ) - not(result.hasError) and + not(result.hasError()) and result.newState.providerState.chainState.votingPowerHistory == List() } @@ -138,7 +138,7 @@ module ccv_test { { val result = DeliverPacketToProviderHappyPathTest_resultAndTimeout._1 val timeout = DeliverPacketToProviderHappyPathTest_resultAndTimeout._2 - not(result.hasError) and + not(result.hasError()) and not(timeout) } @@ -147,7 +147,7 @@ module ccv_test { val result = DeliverPacketToProviderHappyPathTest_resultAndTimeout._1 val newProviderState = result.newState.providerState val newConsumerState = result.newState.consumerStates.get("sender") - not(result.hasError) and + not(result.hasError()) and newProviderState.receivedMaturations.size() == 1 and newConsumerState.outstandingPacketsToProvider.length() == 0 } @@ -170,7 +170,7 @@ module ccv_test { val timeout = DeliverPacketToProviderTimeoutTest_resultAndTimeout._2 val newProviderState = result.newState.providerState val newConsumerState = result.newState.consumerStates.get("sender") - not(result.hasError) and + not(result.hasError()) and timeout } @@ -179,7 +179,7 @@ module ccv_test { val result = DeliverPacketToProviderTimeoutTest_resultAndTimeout._1 val newProviderState = result.newState.providerState val newConsumerState = result.newState.consumerStates.get("sender") - not(result.hasError) and + not(result.hasError()) and newProviderState.receivedMaturations.size() == 0 and newProviderState.consumerStatus.get("sender") == TIMEDOUT } From 455696a14fb6d1e1301112c540f44de421ecd480 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 13 Oct 2023 15:32:30 +0200 Subject: [PATCH 75/80] Adjust docstring --- tests/difference/core/quint_model/ccv.qnt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index e1d78c273b..a11852294c 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -267,7 +267,7 @@ module ccv { } // Delivers the next queued VscMaturedPacket from a consumer chain to the provider chain. - // Only argument is the consumer chain, from which the packet will be delivered. + // Arguments are the currentState and the the consumer chain, from which the packet will be delivered. // If this packet will time out on the provider on delivery, // the consumer will be dropped. // The first return is the result of the operation, the second result is a boolean From d422cb49b90a50ee6502c5e9daa31ce5e12790af Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 13 Oct 2023 15:36:04 +0200 Subject: [PATCH 76/80] Remove unused timedout val --- tests/difference/core/quint_model/ccv.qnt | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index a11852294c..9a17510bfe 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -280,8 +280,6 @@ module ccv { (Err("No outstanding packets to deliver"), false) } else { val packet = currentState.consumerStates.get(sender).outstandingPacketsToProvider.head() - // if the packet has timed out, drop the consumer. its state doesn't matter anymore - val timeout = CcvTimeout.get(sender) if(packet.sendingTime + CcvTimeout.get(sender) < currentState.providerState.chainState.lastTimestamp) { // drop consumer val result = stopConsumers( From 6ed82c847d92bec121dfdd7c2cd54854bd77d76d Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 13 Oct 2023 15:37:11 +0200 Subject: [PATCH 77/80] Update doc --- tests/difference/core/quint_model/ccv.qnt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 9a17510bfe..5ea3d8f4a7 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -315,7 +315,7 @@ module ccv { } // Delivers the next queued VscPacket from the provider chain to a consumer chain. - // Only argument is the consumer chain, to which the packet will be delivered. + // Arguments are the current state and the consumer chain, to which the packet will be delivered. // If this packet will time out on the consumer on delivery, // the consumer will be dropped. // The first return is the result of the operation, the second result is a boolean From b817f431e2b981850771a60afcd3cd16d2cac952 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 16 Oct 2023 10:36:32 +0200 Subject: [PATCH 78/80] Rename statemachine to model --- tests/difference/core/quint_model/README.md | 12 ++++++------ .../{ccv_statemachine.qnt => ccv_model.qnt} | 4 ++-- tests/difference/core/quint_model/run_invariants.sh | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) rename tests/difference/core/quint_model/{ccv_statemachine.qnt => ccv_model.qnt} (99%) diff --git a/tests/difference/core/quint_model/README.md b/tests/difference/core/quint_model/README.md index 54251a7544..0cef3bc632 100644 --- a/tests/difference/core/quint_model/README.md +++ b/tests/difference/core/quint_model/README.md @@ -4,7 +4,7 @@ This folder contains a Quint model for the core logic of Cross-Chain Validation The files are as follows: - ccv.qnt: Contains the type definitions, data structures, functional logic for CCV. The core of the protocol. -- ccv_statemachine.qnt: Contains the state machine layer for CCV. Very roughly speaking, this could be seen as "e2e tests". +- ccv_model.qnt: Contains the stateful part of the model for CCV. Very roughly speaking, this could be seen as "e2e tests". Also contains invariants. - ccv_test.qnt: Contains unit tests for the functional layer of CCV. - libraries/*: Libraries that don't belong to CCV, but are used by it. @@ -26,14 +26,14 @@ quint test ccv_test.qnt ``` and ``` -quint test ccv_statemachine.qnt +quint test ccv_model.qnt ``` ### Invariants -The invariants to check are in [ccv_statemachine.qnt](ccv_statemachine.qnt). +The invariants to check are in [ccv_model.qnt](ccv_model.qnt). Check a single invariant by running -`quint run --invariant INVARIANT_NAME ccv_statemachine.qnt`, +`quint run --invariant INVARIANT_NAME ccv_model.qnt`, or all invariants one after another with the help of the script `run_invariants.sh`. Each invariant takes about a minute to run. @@ -53,7 +53,7 @@ that were running at the time the packet was sent (and are still running). Invariants can also be model-checked by Apalache, using this command: ``` quint verify --invariant ValidatorUpdatesArePropagatedInv,ValidatorSetHasExistedInv,SameVscPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv \ - ccv_statemachine.qnt + ccv_model.qnt ``` ### Sanity Checks @@ -63,7 +63,7 @@ In detail, they are invariant checks that we expect to fail. They usually negate the appearance of some behaviour, i.e. `not(DesirableBehaviour)`. Then, a counterexample for this is an example trace exhibiting the behaviour. -They are run like invariant checks, i.e. `quint run --invariant SANITY_CHECK_NAME ccv_statemachine.qnt`. +They are run like invariant checks, i.e. `quint run --invariant SANITY_CHECK_NAME ccv_model.qnt`. The available sanity checks are: - CanRunConsumer - CanStopConsumer diff --git a/tests/difference/core/quint_model/ccv_statemachine.qnt b/tests/difference/core/quint_model/ccv_model.qnt similarity index 99% rename from tests/difference/core/quint_model/ccv_statemachine.qnt rename to tests/difference/core/quint_model/ccv_model.qnt index cb62f560ee..300c543d40 100644 --- a/tests/difference/core/quint_model/ccv_statemachine.qnt +++ b/tests/difference/core/quint_model/ccv_model.qnt @@ -1,6 +1,6 @@ // -*- mode: Bluespec; -*- -module ccv_statemachine { - // A basic state machine that utilizes the CCV protocol. +module ccv_model { + // A basic stateful model that utilizes the CCV protocol. import ccv_types.* from "./ccv" import Time.* from "./libraries/Time" import extraSpells.* from "./libraries/extraSpells" diff --git a/tests/difference/core/quint_model/run_invariants.sh b/tests/difference/core/quint_model/run_invariants.sh index ae94dcbd2d..4c65693cc0 100755 --- a/tests/difference/core/quint_model/run_invariants.sh +++ b/tests/difference/core/quint_model/run_invariants.sh @@ -1,4 +1,4 @@ #! /bin/sh -quint test ccv_statemachine.qnt -quint run --invariant "all{ValidatorUpdatesArePropagatedInv,ValidatorSetHasExistedInv,SameVscPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv}" ccv_statemachine.qnt --max-steps 500 --max-samples 200 \ No newline at end of file +quint test ccv_model.qnt +quint run --invariant "all{ValidatorUpdatesArePropagatedInv,ValidatorSetHasExistedInv,SameVscPacketsInv,MatureOnTimeInv,EventuallyMatureOnProviderInv}" ccv_model.qnt --max-steps 500 --max-samples 200 \ No newline at end of file From 70cd7742ee74295ea07124fdd169d194038f1ded Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 16 Oct 2023 10:40:47 +0200 Subject: [PATCH 79/80] Use ... syntax --- tests/difference/core/quint_model/ccv.qnt | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 5ea3d8f4a7..8cab951c99 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -620,30 +620,25 @@ module ccv { List() } ) - providerState.with( - // send VscPackets to consumers - "outstandingPacketsToConsumer", - ConsumerChains.mapBy( + val newOutstandingPacketsToConsumer = ConsumerChains.mapBy( (consumer) => providerState.outstandingPacketsToConsumer.get(consumer).concat( newSentPacketsPerConsumer.get(consumer) ) ) - ).with( - // update the sent VscPackets - "sentVscPacketsToConsumer", - ConsumerChains.mapBy( + val newSentVscPackets = ConsumerChains.mapBy( (consumer) => providerState.sentVscPacketsToConsumer.get(consumer).concat( newSentPacketsPerConsumer.get(consumer) ) ) - ).with( - // the validator set has not changed yet in the new block - "providerValidatorSetChangedInThisBlock", false - ).with( - "runningVscId", providerState.runningVscId + 1 - ) + { + ...providerState, + outstandingPacketsToConsumer: newOutstandingPacketsToConsumer, + sentVscPacketsToConsumer: newSentVscPackets, + providerValidatorSetChangedInThisBlock: false, + runningVscId: providerState.runningVscId + 1, + } } // receives a given packet (sent by the provider) on the consumer. The arguments are the consumer chain that is receiving the packet, and the packet itself. From 86324b71a9449d24e48601d47db34b3501e13a3c Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Mon, 16 Oct 2023 11:17:47 +0200 Subject: [PATCH 80/80] Change Error type to string --- tests/difference/core/quint_model/ccv.qnt | 45 ++++++++----------- .../difference/core/quint_model/ccv_model.qnt | 20 ++++----- 2 files changed, 27 insertions(+), 38 deletions(-) diff --git a/tests/difference/core/quint_model/ccv.qnt b/tests/difference/core/quint_model/ccv.qnt index 8cab951c99..0e07b4476c 100644 --- a/tests/difference/core/quint_model/ccv.qnt +++ b/tests/difference/core/quint_model/ccv.qnt @@ -143,9 +143,7 @@ module ccv_types { consumerStates: Map(), } - type Error = { - message: str - } + type Error = str // we return either a result or an error. // if hasError() is true, newState may be arbitrary, but the error will be meaningful. @@ -158,9 +156,7 @@ module ccv_types { pure def Ok(newState: ProtocolState): Result = { { newState: newState, - error: { - message: "" - } + error: "" } } @@ -182,13 +178,11 @@ module ccv_types { }, consumerStates: Map(), }, - error: { - message: msg - } + error: msg } } - pure def hasError(result: Result): bool = result.error.message != "" + pure def hasError(result: Result): bool = result.error != "" // possible consumer statuses pure val STOPPED = "stopped" // the chain was once a consumer chain, but has been voluntarily dropped by the provider. @@ -306,7 +300,7 @@ module ccv { val result = recvPacketOnProvider(currentState, sender, packet) val tmpState = result.newState if (result.hasError()) { - (Err(result.error.message), false) + (result, false) } else { (Ok(removeOutstandingPacketFromConsumer(tmpState, sender)), false) // false because the packet did not time out } @@ -355,7 +349,7 @@ module ccv { val result = recvPacketOnConsumer(currentState, receiver, packet) val tmpState = result.newState if (result.hasError()) { - (Err(result.error.message), false) + (result, false) } else { (Ok(removeOutstandingPacketFromProvider(tmpState, receiver)), false) // false because the packet did not time out } @@ -652,21 +646,18 @@ module ccv { // update the running validator set, but not the history yet, // as that only happens when the next block is started val currentConsumerState = currentState.consumerStates.get(receiver) - val newConsumerState = currentConsumerState.with( - "chainState", - currentConsumerState.chainState.with( - "currentValidatorSet", packet.validatorSet - ) - ).with( - "maturationTimes", - currentConsumerState.maturationTimes.put( - packet, - currentConsumerState.chainState.lastTimestamp + UnbondingPeriodPerChain.get(receiver) - ) - ).with( - "receivedVscPackets", - currentConsumerState.receivedVscPackets.prepend(packet) - ) + val newConsumerState = + { + ...currentConsumerState, + chainState: currentConsumerState.chainState.with( + "currentValidatorSet", packet.validatorSet + ), + maturationTimes: currentConsumerState.maturationTimes.put( + packet, + currentConsumerState.chainState.lastTimestamp + UnbondingPeriodPerChain.get(receiver) + ), + receivedVscPackets: currentConsumerState.receivedVscPackets.prepend(packet) + } val newConsumerStates = currentState.consumerStates.set(receiver, newConsumerState) val newState = currentState.with( "consumerStates", newConsumerStates diff --git a/tests/difference/core/quint_model/ccv_model.qnt b/tests/difference/core/quint_model/ccv_model.qnt index 300c543d40..f886fe9e85 100644 --- a/tests/difference/core/quint_model/ccv_model.qnt +++ b/tests/difference/core/quint_model/ccv_model.qnt @@ -198,18 +198,16 @@ module ccv_model { val ValUpdatePrecondition = trace[trace.length()-1].kind == "EndAndBeginBlockForProvider" val ValidatorUpdatesArePropagatedInv = // when the provider has just entered a validator set into a block... - if (ValUpdatePrecondition and currentState.providerState.providerValidatorSetChangedInThisBlock) { - val providerValSetInCurBlock = providerValidatorHistory.head() - // ... for each consumer that is running then ... - runningConsumers.forall( - // ...the validator set is in a sent packet - consumer => currentState.providerState.sentVscPacketsToConsumer.get(consumer).toSet().exists( - packet => packet.validatorSet == providerValSetInCurBlock - ) + ValUpdatePrecondition and currentState.providerState.providerValidatorSetChangedInThisBlock + implies + val providerValSetInCurBlock = providerValidatorHistory.head() + // ... for each consumer that is running then ... + runningConsumers.forall( + // ...the validator set is in a sent packet + consumer => currentState.providerState.sentVscPacketsToConsumer.get(consumer).toSet().exists( + packet => packet.validatorSet == providerValSetInCurBlock ) - } else { - true - } + ) // Every consumer chain receives the same sequence of // ValidatorSetChangePackets in the same order.